IImage.h 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424
  1. // Copyright (C) 2002-2012 Nikolaus Gebhardt
  2. // This file is part of the "Irrlicht Engine".
  3. // For conditions of distribution and use, see copyright notice in irrlicht.h
  4. #pragma once
  5. #include "IReferenceCounted.h"
  6. #include "position2d.h"
  7. #include "rect.h"
  8. #include "SColor.h"
  9. #include <cstring>
  10. namespace irr
  11. {
  12. namespace video
  13. {
  14. //! Interface for software image data.
  15. /** Image loaders create these images from files. IVideoDrivers convert
  16. these images into their (hardware) textures.
  17. NOTE: Floating point formats are not well supported yet. Basically only getData() works for them.
  18. */
  19. class IImage : public virtual IReferenceCounted
  20. {
  21. public:
  22. //! constructor
  23. IImage(ECOLOR_FORMAT format, const core::dimension2d<u32> &size, bool deleteMemory) :
  24. Format(format), Size(size), Data(0), MipMapsData(0), BytesPerPixel(0), Pitch(0), DeleteMemory(deleteMemory), DeleteMipMapsMemory(false)
  25. {
  26. BytesPerPixel = getBitsPerPixelFromFormat(Format) / 8;
  27. Pitch = BytesPerPixel * Size.Width;
  28. }
  29. //! destructor
  30. virtual ~IImage()
  31. {
  32. if (DeleteMemory)
  33. delete[] Data;
  34. if (DeleteMipMapsMemory)
  35. delete[] MipMapsData;
  36. }
  37. //! Returns the color format
  38. ECOLOR_FORMAT getColorFormat() const
  39. {
  40. return Format;
  41. }
  42. //! Returns width and height of image data.
  43. const core::dimension2d<u32> &getDimension() const
  44. {
  45. return Size;
  46. }
  47. //! Returns bits per pixel.
  48. u32 getBitsPerPixel() const
  49. {
  50. return getBitsPerPixelFromFormat(Format);
  51. }
  52. //! Returns bytes per pixel
  53. u32 getBytesPerPixel() const
  54. {
  55. return BytesPerPixel;
  56. }
  57. //! Returns image data size in bytes
  58. u32 getImageDataSizeInBytes() const
  59. {
  60. return getDataSizeFromFormat(Format, Size.Width, Size.Height);
  61. }
  62. //! Returns image data size in pixels
  63. u32 getImageDataSizeInPixels() const
  64. {
  65. return Size.Width * Size.Height;
  66. }
  67. //! Returns pitch of image
  68. u32 getPitch() const
  69. {
  70. return Pitch;
  71. }
  72. //! Returns mask for red value of a pixel
  73. u32 getRedMask() const
  74. {
  75. switch (Format) {
  76. case ECF_A1R5G5B5:
  77. return 0x1F << 10;
  78. case ECF_R5G6B5:
  79. return 0x1F << 11;
  80. case ECF_R8G8B8:
  81. return 0x00FF0000;
  82. case ECF_A8R8G8B8:
  83. return 0x00FF0000;
  84. default:
  85. return 0x0;
  86. }
  87. }
  88. //! Returns mask for green value of a pixel
  89. u32 getGreenMask() const
  90. {
  91. switch (Format) {
  92. case ECF_A1R5G5B5:
  93. return 0x1F << 5;
  94. case ECF_R5G6B5:
  95. return 0x3F << 5;
  96. case ECF_R8G8B8:
  97. return 0x0000FF00;
  98. case ECF_A8R8G8B8:
  99. return 0x0000FF00;
  100. default:
  101. return 0x0;
  102. }
  103. }
  104. //! Returns mask for blue value of a pixel
  105. u32 getBlueMask() const
  106. {
  107. switch (Format) {
  108. case ECF_A1R5G5B5:
  109. return 0x1F;
  110. case ECF_R5G6B5:
  111. return 0x1F;
  112. case ECF_R8G8B8:
  113. return 0x000000FF;
  114. case ECF_A8R8G8B8:
  115. return 0x000000FF;
  116. default:
  117. return 0x0;
  118. }
  119. }
  120. //! Returns mask for alpha value of a pixel
  121. u32 getAlphaMask() const
  122. {
  123. switch (Format) {
  124. case ECF_A1R5G5B5:
  125. return 0x1 << 15;
  126. case ECF_R5G6B5:
  127. return 0x0;
  128. case ECF_R8G8B8:
  129. return 0x0;
  130. case ECF_A8R8G8B8:
  131. return 0xFF000000;
  132. default:
  133. return 0x0;
  134. }
  135. }
  136. //! Use this to get a pointer to the image data.
  137. /**
  138. \return Pointer to the image data. What type of data is pointed to
  139. depends on the color format of the image. For example if the color
  140. format is ECF_A8R8G8B8, it is of u32. */
  141. void *getData() const
  142. {
  143. return Data;
  144. }
  145. //! Get the mipmap size for this image for a certain mipmap level
  146. /** level 0 will be full image size. Every further level is half the size.
  147. Doesn't care if the image actually has mipmaps, just which size would be needed. */
  148. core::dimension2du getMipMapsSize(u32 mipmapLevel) const
  149. {
  150. return getMipMapsSize(Size, mipmapLevel);
  151. }
  152. //! Calculate mipmap size for a certain level
  153. /** level 0 will be full image size. Every further level is half the size. */
  154. static core::dimension2du getMipMapsSize(const core::dimension2du &sizeLevel0, u32 mipmapLevel)
  155. {
  156. core::dimension2du result(sizeLevel0);
  157. u32 i = 0;
  158. while (i != mipmapLevel) {
  159. if (result.Width > 1)
  160. result.Width >>= 1;
  161. if (result.Height > 1)
  162. result.Height >>= 1;
  163. ++i;
  164. if (result.Width == 1 && result.Height == 1 && i < mipmapLevel)
  165. return core::dimension2du(0, 0);
  166. }
  167. return result;
  168. }
  169. //! Get mipmaps data.
  170. /** Note that different mip levels are just behind each other in memory block.
  171. So if you just get level 1 you also have the data for all other levels.
  172. There is no level 0 - use getData to get the original image data.
  173. */
  174. void *getMipMapsData(irr::u32 mipLevel = 1) const
  175. {
  176. if (MipMapsData && mipLevel > 0) {
  177. size_t dataSize = 0;
  178. core::dimension2du mipSize(Size);
  179. u32 i = 1; // We want the start of data for this level, not end.
  180. while (i != mipLevel) {
  181. if (mipSize.Width > 1)
  182. mipSize.Width >>= 1;
  183. if (mipSize.Height > 1)
  184. mipSize.Height >>= 1;
  185. dataSize += getDataSizeFromFormat(Format, mipSize.Width, mipSize.Height);
  186. ++i;
  187. if (mipSize.Width == 1 && mipSize.Height == 1 && i < mipLevel)
  188. return 0;
  189. }
  190. return MipMapsData + dataSize;
  191. }
  192. return 0;
  193. }
  194. //! Set mipmaps data.
  195. /** This method allows you to put custom mipmaps data for
  196. image.
  197. \param data A byte array with pixel color information
  198. \param ownForeignMemory If true, the image will use the data
  199. pointer directly and own it afterward. If false, the memory
  200. will by copied internally.
  201. \param deleteMemory Whether the memory is deallocated upon
  202. destruction. */
  203. void setMipMapsData(void *data, bool ownForeignMemory)
  204. {
  205. if (data != MipMapsData) {
  206. if (DeleteMipMapsMemory) {
  207. delete[] MipMapsData;
  208. DeleteMipMapsMemory = false;
  209. }
  210. if (data) {
  211. if (ownForeignMemory) {
  212. MipMapsData = static_cast<u8 *>(data);
  213. DeleteMipMapsMemory = false;
  214. } else {
  215. u32 dataSize = 0;
  216. u32 width = Size.Width;
  217. u32 height = Size.Height;
  218. do {
  219. if (width > 1)
  220. width >>= 1;
  221. if (height > 1)
  222. height >>= 1;
  223. dataSize += getDataSizeFromFormat(Format, width, height);
  224. } while (width != 1 || height != 1);
  225. MipMapsData = new u8[dataSize];
  226. memcpy(MipMapsData, data, dataSize);
  227. DeleteMipMapsMemory = true;
  228. }
  229. } else {
  230. MipMapsData = 0;
  231. }
  232. }
  233. }
  234. //! Returns a pixel
  235. virtual SColor getPixel(u32 x, u32 y) const = 0;
  236. //! Sets a pixel
  237. virtual void setPixel(u32 x, u32 y, const SColor &color, bool blend = false) = 0;
  238. //! Copies this surface into another, if it has the exact same size and format.
  239. /** NOTE: mipmaps are ignored
  240. \return True if it was copied, false otherwise.
  241. */
  242. virtual bool copyToNoScaling(void *target, u32 width, u32 height, ECOLOR_FORMAT format = ECF_A8R8G8B8, u32 pitch = 0) const = 0;
  243. //! Copies the image into the target, scaling the image to fit
  244. /** NOTE: mipmaps are ignored */
  245. virtual void copyToScaling(void *target, u32 width, u32 height, ECOLOR_FORMAT format = ECF_A8R8G8B8, u32 pitch = 0) = 0;
  246. //! Copies the image into the target, scaling the image to fit
  247. /** NOTE: mipmaps are ignored */
  248. virtual void copyToScaling(IImage *target) = 0;
  249. //! copies this surface into another
  250. /** NOTE: mipmaps are ignored */
  251. virtual void copyTo(IImage *target, const core::position2d<s32> &pos = core::position2d<s32>(0, 0)) = 0;
  252. //! copies this surface into another
  253. /** NOTE: mipmaps are ignored */
  254. virtual void copyTo(IImage *target, const core::position2d<s32> &pos, const core::rect<s32> &sourceRect, const core::rect<s32> *clipRect = 0) = 0;
  255. //! copies this surface into another, using the alpha mask and cliprect and a color to add with
  256. /** NOTE: mipmaps are ignored
  257. \param combineAlpha - When true then combine alpha channels. When false replace target image alpha with source image alpha.
  258. */
  259. virtual void copyToWithAlpha(IImage *target, const core::position2d<s32> &pos,
  260. const core::rect<s32> &sourceRect, const SColor &color,
  261. const core::rect<s32> *clipRect = 0,
  262. bool combineAlpha = false) = 0;
  263. //! copies this surface into another, scaling it to fit, applying a box filter
  264. /** NOTE: mipmaps are ignored */
  265. virtual void copyToScalingBoxFilter(IImage *target, s32 bias = 0, bool blend = false) = 0;
  266. //! fills the surface with given color
  267. virtual void fill(const SColor &color) = 0;
  268. //! get the amount of Bits per Pixel of the given color format
  269. static u32 getBitsPerPixelFromFormat(const ECOLOR_FORMAT format)
  270. {
  271. switch (format) {
  272. case ECF_A1R5G5B5:
  273. return 16;
  274. case ECF_R5G6B5:
  275. return 16;
  276. case ECF_R8G8B8:
  277. return 24;
  278. case ECF_A8R8G8B8:
  279. return 32;
  280. case ECF_D16:
  281. return 16;
  282. case ECF_D32:
  283. return 32;
  284. case ECF_D24S8:
  285. return 32;
  286. case ECF_R8:
  287. return 8;
  288. case ECF_R8G8:
  289. return 16;
  290. case ECF_R16:
  291. return 16;
  292. case ECF_R16G16:
  293. return 32;
  294. case ECF_R16F:
  295. return 16;
  296. case ECF_G16R16F:
  297. return 32;
  298. case ECF_A16B16G16R16F:
  299. return 64;
  300. case ECF_R32F:
  301. return 32;
  302. case ECF_G32R32F:
  303. return 64;
  304. case ECF_A32B32G32R32F:
  305. return 128;
  306. default:
  307. return 0;
  308. }
  309. }
  310. //! calculate image data size in bytes for selected format, width and height.
  311. static u32 getDataSizeFromFormat(ECOLOR_FORMAT format, u32 width, u32 height)
  312. {
  313. // non-compressed formats
  314. u32 imageSize = getBitsPerPixelFromFormat(format) / 8 * width;
  315. imageSize *= height;
  316. return imageSize;
  317. }
  318. //! check if this is compressed color format
  319. static bool isCompressedFormat(const ECOLOR_FORMAT format)
  320. {
  321. return false;
  322. }
  323. //! check if the color format is only viable for depth/stencil textures
  324. static bool isDepthFormat(const ECOLOR_FORMAT format)
  325. {
  326. switch (format) {
  327. case ECF_D16:
  328. case ECF_D32:
  329. case ECF_D24S8:
  330. return true;
  331. default:
  332. return false;
  333. }
  334. }
  335. //! Check if the color format uses floating point values for pixels
  336. static bool isFloatingPointFormat(const ECOLOR_FORMAT format)
  337. {
  338. if (isCompressedFormat(format))
  339. return false;
  340. switch (format) {
  341. case ECF_R16F:
  342. case ECF_G16R16F:
  343. case ECF_A16B16G16R16F:
  344. case ECF_R32F:
  345. case ECF_G32R32F:
  346. case ECF_A32B32G32R32F:
  347. return true;
  348. default:
  349. break;
  350. }
  351. return false;
  352. }
  353. protected:
  354. ECOLOR_FORMAT Format;
  355. core::dimension2d<u32> Size;
  356. u8 *Data;
  357. u8 *MipMapsData;
  358. u32 BytesPerPixel;
  359. u32 Pitch;
  360. bool DeleteMemory;
  361. bool DeleteMipMapsMemory;
  362. };
  363. } // end namespace video
  364. } // end namespace irr