]> git.lizzy.rs Git - irrlicht.git/blob - include/IImage.h
Merging r6039 through r6072 from trunk to ogl-es branch.
[irrlicht.git] / include / IImage.h
1 // Copyright (C) 2002-2012 Nikolaus Gebhardt\r
2 // This file is part of the "Irrlicht Engine".\r
3 // For conditions of distribution and use, see copyright notice in irrlicht.h\r
4 \r
5 #ifndef __I_IMAGE_H_INCLUDED__\r
6 #define __I_IMAGE_H_INCLUDED__\r
7 \r
8 #include "IReferenceCounted.h"\r
9 #include "position2d.h"\r
10 #include "rect.h"\r
11 #include "SColor.h"\r
12 #include "irrAllocator.h"\r
13 #include <string.h>\r
14 \r
15 namespace irr\r
16 {\r
17 namespace video\r
18 {\r
19 \r
20 //! Interface for software image data.\r
21 /** Image loaders create these images from files. IVideoDrivers convert\r
22 these images into their (hardware) textures.\r
23 NOTE: Floating point formats are not well supported yet. Basically only getData() works for them.\r
24 */\r
25 class IImage : public virtual IReferenceCounted\r
26 {\r
27 public:\r
28 \r
29         //! constructor\r
30         IImage(ECOLOR_FORMAT format, const core::dimension2d<u32>& size, bool deleteMemory) :\r
31                 Format(format), Size(size), Data(0), MipMapsData(0), BytesPerPixel(0), Pitch(0), DeleteMemory(deleteMemory), DeleteMipMapsMemory(false)\r
32         {\r
33                 BytesPerPixel = getBitsPerPixelFromFormat(Format) / 8;\r
34                 Pitch = BytesPerPixel * Size.Width;\r
35         }\r
36 \r
37         //! destructor\r
38         virtual ~IImage()\r
39         {\r
40                 if (DeleteMemory)\r
41                         delete[] Data;\r
42 \r
43                 if (DeleteMipMapsMemory)\r
44                         Allocator.deallocate(MipMapsData);\r
45         }\r
46 \r
47         //! Returns the color format\r
48         ECOLOR_FORMAT getColorFormat() const\r
49         {\r
50                 return Format;\r
51         }\r
52 \r
53         //! Returns width and height of image data.\r
54         const core::dimension2d<u32>& getDimension() const\r
55         {\r
56                 return Size;\r
57         }\r
58 \r
59         //! Returns bits per pixel.\r
60         u32 getBitsPerPixel() const\r
61         {\r
62 \r
63                 return getBitsPerPixelFromFormat(Format);\r
64         }\r
65 \r
66         //! Returns bytes per pixel\r
67         u32 getBytesPerPixel() const\r
68         {\r
69                 return BytesPerPixel;\r
70         }\r
71 \r
72         //! Returns image data size in bytes\r
73         u32 getImageDataSizeInBytes() const\r
74         {\r
75                 return getDataSizeFromFormat(Format, Size.Width, Size.Height);\r
76         }\r
77 \r
78         //! Returns image data size in pixels\r
79         u32 getImageDataSizeInPixels() const\r
80         {\r
81                 return Size.Width * Size.Height;\r
82         }\r
83 \r
84         //! Returns pitch of image\r
85         u32 getPitch() const\r
86         {\r
87                 return Pitch;\r
88         }\r
89 \r
90         //! Returns mask for red value of a pixel\r
91         u32 getRedMask() const\r
92         {\r
93                 switch (Format)\r
94                 {\r
95                 case ECF_A1R5G5B5:\r
96                         return 0x1F << 10;\r
97                 case ECF_R5G6B5:\r
98                         return 0x1F << 11;\r
99                 case ECF_R8G8B8:\r
100                         return 0x00FF0000;\r
101                 case ECF_A8R8G8B8:\r
102                         return 0x00FF0000;\r
103                 default:\r
104                         return 0x0;\r
105                 }\r
106         }\r
107 \r
108         //! Returns mask for green value of a pixel\r
109         u32 getGreenMask() const\r
110         {\r
111                 switch (Format)\r
112                 {\r
113                 case ECF_A1R5G5B5:\r
114                         return 0x1F << 5;\r
115                 case ECF_R5G6B5:\r
116                         return 0x3F << 5;\r
117                 case ECF_R8G8B8:\r
118                         return 0x0000FF00;\r
119                 case ECF_A8R8G8B8:\r
120                         return 0x0000FF00;\r
121                 default:\r
122                         return 0x0;\r
123                 }\r
124         }\r
125 \r
126         //! Returns mask for blue value of a pixel\r
127         u32 getBlueMask() const\r
128         {\r
129                 switch (Format)\r
130                 {\r
131                 case ECF_A1R5G5B5:\r
132                         return 0x1F;\r
133                 case ECF_R5G6B5:\r
134                         return 0x1F;\r
135                 case ECF_R8G8B8:\r
136                         return 0x000000FF;\r
137                 case ECF_A8R8G8B8:\r
138                         return 0x000000FF;\r
139                 default:\r
140                         return 0x0;\r
141                 }\r
142         }\r
143 \r
144         //! Returns mask for alpha value of a pixel\r
145         u32 getAlphaMask() const\r
146         {\r
147                 switch (Format)\r
148                 {\r
149                 case ECF_A1R5G5B5:\r
150                         return 0x1 << 15;\r
151                 case ECF_R5G6B5:\r
152                         return 0x0;\r
153                 case ECF_R8G8B8:\r
154                         return 0x0;\r
155                 case ECF_A8R8G8B8:\r
156                         return 0xFF000000;\r
157                 default:\r
158                         return 0x0;\r
159                 }\r
160         }\r
161 \r
162         //! Use this to get a pointer to the image data.\r
163         /**\r
164         \return Pointer to the image data. What type of data is pointed to\r
165         depends on the color format of the image. For example if the color\r
166         format is ECF_A8R8G8B8, it is of u32. */\r
167         void* getData() const\r
168         {\r
169                 return Data;\r
170         }\r
171 \r
172         //! Lock function. Use this to get a pointer to the image data.\r
173         /** Use getData instead.\r
174         \return Pointer to the image data. What type of data is pointed to\r
175         depends on the color format of the image. For example if the color\r
176         format is ECF_A8R8G8B8, it is of u32. Be sure to call unlock() after\r
177         you don't need the pointer any more. */\r
178         _IRR_DEPRECATED_ void* lock()\r
179         {\r
180                 return getData();\r
181         }\r
182 \r
183         //! Unlock function.\r
184         /** Should be called after the pointer received by lock() is not\r
185         needed anymore. */\r
186         _IRR_DEPRECATED_ void unlock()\r
187         {\r
188         }\r
189 \r
190         //! Get the mipmap size for this image for a certain mipmap level\r
191         /** level 0 will be full image size. Every further level is half the size.\r
192                 Doesn't care if the image actually has mipmaps, just which size would be needed. */\r
193         core::dimension2du getMipMapsSize(u32 mipmapLevel) const\r
194         {\r
195                 return getMipMapsSize(Size, mipmapLevel);\r
196         }\r
197 \r
198 \r
199         //! Calculate mipmap size for a certain level\r
200         /** level 0 will be full image size. Every further level is half the size.      */\r
201         static core::dimension2du getMipMapsSize(const core::dimension2du& sizeLevel0, u32 mipmapLevel)\r
202         {\r
203                 core::dimension2du result(sizeLevel0);\r
204                 u32 i=0;\r
205                 while (i != mipmapLevel)\r
206                 {\r
207                         if (result.Width>1)\r
208                                 result.Width >>= 1;\r
209                         if (result.Height>1)\r
210                                 result.Height>>=1;\r
211                         ++i;\r
212 \r
213                         if ( result.Width == 1 && result.Height == 1 && i < mipmapLevel )\r
214                                 return core::dimension2du(0,0);\r
215                 }\r
216                 return result;\r
217         }\r
218 \r
219 \r
220         //! Get mipmaps data.\r
221         /** Note that different mip levels are just behind each other in memory block.\r
222                 So if you just get level 1 you also have the data for all other levels.\r
223                 There is no level 0 - use getData to get the original image data.\r
224         */\r
225         void* getMipMapsData(irr::u32 mipLevel=1) const\r
226         {\r
227                 if ( MipMapsData && mipLevel > 0)\r
228                 {\r
229                         size_t dataSize = 0;\r
230                         core::dimension2du mipSize(Size);\r
231                         u32 i = 1;      // We want the start of data for this level, not end.\r
232 \r
233                         while (i != mipLevel)\r
234                         {\r
235                                 if (mipSize.Width > 1)\r
236                                         mipSize.Width >>= 1;\r
237 \r
238                                 if (mipSize.Height > 1)\r
239                                         mipSize.Height >>= 1;\r
240 \r
241                                 dataSize += getDataSizeFromFormat(Format, mipSize.Width, mipSize.Height);\r
242 \r
243                                 ++i;\r
244                                 if ( mipSize.Width == 1 && mipSize.Height == 1 && i < mipLevel)\r
245                                         return 0;\r
246                         }\r
247 \r
248                         return MipMapsData + dataSize;\r
249                 }\r
250 \r
251                 return 0;\r
252         }\r
253 \r
254         //! Set mipmaps data.\r
255         /** This method allows you to put custom mipmaps data for\r
256         image.\r
257         \param data A byte array with pixel color information\r
258         \param ownForeignMemory If true, the image will use the data\r
259         pointer directly and own it afterward. If false, the memory\r
260         will by copied internally.\r
261         \param deleteMemory Whether the memory is deallocated upon\r
262         destruction. */\r
263         void setMipMapsData(void* data, bool ownForeignMemory, bool deleteMemory)\r
264         {\r
265                 if (data != MipMapsData)\r
266                 {\r
267                         if (DeleteMipMapsMemory)\r
268                         {\r
269                                 Allocator.deallocate(MipMapsData);\r
270 \r
271                                 DeleteMipMapsMemory = false;\r
272                         }\r
273 \r
274                         if (data)\r
275                         {\r
276                                 if (ownForeignMemory)\r
277                                 {\r
278                                         MipMapsData = static_cast<u8*>(data);\r
279 \r
280                                         DeleteMipMapsMemory = deleteMemory;\r
281                                 }\r
282                                 else\r
283                                 {\r
284                                         u32 dataSize = 0;\r
285                                         u32 width = Size.Width;\r
286                                         u32 height = Size.Height;\r
287 \r
288                                         do\r
289                                         {\r
290                                                 if (width > 1)\r
291                                                         width >>= 1;\r
292 \r
293                                                 if (height > 1)\r
294                                                         height >>= 1;\r
295 \r
296                                                 dataSize += getDataSizeFromFormat(Format, width, height);\r
297                                         } while (width != 1 || height != 1);\r
298 \r
299                                         MipMapsData = Allocator.allocate(dataSize);\r
300                                         memcpy(MipMapsData, data, dataSize);\r
301 \r
302                                         DeleteMipMapsMemory = true;\r
303                                 }\r
304                         }\r
305                         else\r
306                         {\r
307                                 MipMapsData = 0;\r
308                         }\r
309                 }\r
310         }\r
311 \r
312         //! Returns a pixel\r
313         virtual SColor getPixel(u32 x, u32 y) const = 0;\r
314 \r
315         //! Sets a pixel\r
316         virtual void setPixel(u32 x, u32 y, const SColor &color, bool blend = false ) = 0;\r
317 \r
318         //! Copies the image into the target, scaling the image to fit\r
319         /**     NOTE: mipmaps are ignored */\r
320         virtual void copyToScaling(void* target, u32 width, u32 height, ECOLOR_FORMAT format=ECF_A8R8G8B8, u32 pitch=0) =0;\r
321 \r
322         //! Copies the image into the target, scaling the image to fit\r
323         /**     NOTE: mipmaps are ignored */\r
324         virtual void copyToScaling(IImage* target) =0;\r
325 \r
326         //! copies this surface into another\r
327         /**     NOTE: mipmaps are ignored */\r
328         virtual void copyTo(IImage* target, const core::position2d<s32>& pos=core::position2d<s32>(0,0)) =0;\r
329 \r
330         //! copies this surface into another\r
331         /**     NOTE: mipmaps are ignored */\r
332         virtual void copyTo(IImage* target, const core::position2d<s32>& pos, const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect=0) =0;\r
333 \r
334         //! copies this surface into another, using the alpha mask and cliprect and a color to add with\r
335         /**     NOTE: mipmaps are ignored\r
336         \param combineAlpha - When true then combine alpha channels. When false replace target image alpha with source image alpha.\r
337         */\r
338         virtual void copyToWithAlpha(IImage* target, const core::position2d<s32>& pos,\r
339                         const core::rect<s32>& sourceRect, const SColor &color,\r
340                         const core::rect<s32>* clipRect = 0,\r
341                         bool combineAlpha=false) =0;\r
342 \r
343         //! copies this surface into another, scaling it to fit, applying a box filter\r
344         /**     NOTE: mipmaps are ignored */\r
345         virtual void copyToScalingBoxFilter(IImage* target, s32 bias = 0, bool blend = false) = 0;\r
346 \r
347         //! fills the surface with given color\r
348         virtual void fill(const SColor &color) =0;\r
349 \r
350         //! Inform whether the image is compressed\r
351         _IRR_DEPRECATED_ bool isCompressed() const\r
352         {\r
353                 return IImage::isCompressedFormat(Format);\r
354         }\r
355 \r
356         //! Check whether the image has MipMaps\r
357         /** \return True if image has MipMaps, else false. */\r
358         _IRR_DEPRECATED_ bool hasMipMaps() const\r
359         {\r
360                 return (getMipMapsData() != 0);\r
361         }\r
362 \r
363         //! get the amount of Bits per Pixel of the given color format\r
364         static u32 getBitsPerPixelFromFormat(const ECOLOR_FORMAT format)\r
365         {\r
366                 switch(format)\r
367                 {\r
368                 case ECF_A1R5G5B5:\r
369                         return 16;\r
370                 case ECF_R5G6B5:\r
371                         return 16;\r
372                 case ECF_R8G8B8:\r
373                         return 24;\r
374                 case ECF_A8R8G8B8:\r
375                         return 32;\r
376                 case ECF_DXT1:\r
377                         return 16;\r
378                 case ECF_DXT2:\r
379                 case ECF_DXT3:\r
380                 case ECF_DXT4:\r
381                 case ECF_DXT5:\r
382                         return 32;\r
383                 case ECF_PVRTC_RGB2:\r
384                         return 12;\r
385                 case ECF_PVRTC_ARGB2:\r
386                 case ECF_PVRTC2_ARGB2:\r
387                         return 16;\r
388                 case ECF_PVRTC_RGB4:\r
389                         return 24;\r
390                 case ECF_PVRTC_ARGB4:\r
391                 case ECF_PVRTC2_ARGB4:\r
392                         return 32;\r
393                 case ECF_ETC1:\r
394                 case ECF_ETC2_RGB:\r
395                         return 24;\r
396                 case ECF_ETC2_ARGB:\r
397                         return 32;\r
398                 case ECF_D16:\r
399                         return 16;\r
400                 case ECF_D32:\r
401                         return 32;\r
402                 case ECF_D24S8:\r
403                         return 32;\r
404                 case ECF_R8:\r
405                         return 8;\r
406                 case ECF_R8G8:\r
407                         return 16;\r
408                 case ECF_R16:\r
409                         return 16;\r
410                 case ECF_R16G16:\r
411                         return 32;\r
412                 case ECF_R16F:\r
413                         return 16;\r
414                 case ECF_G16R16F:\r
415                         return 32;\r
416                 case ECF_A16B16G16R16F:\r
417                         return 64;\r
418                 case ECF_R32F:\r
419                         return 32;\r
420                 case ECF_G32R32F:\r
421                         return 64;\r
422                 case ECF_A32B32G32R32F:\r
423                         return 128;\r
424                 default:\r
425                         return 0;\r
426                 }\r
427         }\r
428 \r
429         //! calculate image data size in bytes for selected format, width and height.\r
430         static u32 getDataSizeFromFormat(ECOLOR_FORMAT format, u32 width, u32 height)\r
431         {\r
432                 u32 imageSize = 0;\r
433 \r
434                 switch (format)\r
435                 {\r
436                 case ECF_DXT1:\r
437                         imageSize = ((width + 3) / 4) * ((height + 3) / 4) * 8;\r
438                         break;\r
439                 case ECF_DXT2:\r
440                 case ECF_DXT3:\r
441                 case ECF_DXT4:\r
442                 case ECF_DXT5:\r
443                         imageSize = ((width + 3) / 4) * ((height + 3) / 4) * 16;\r
444                         break;\r
445                 case ECF_PVRTC_RGB2:\r
446                 case ECF_PVRTC_ARGB2:\r
447                         imageSize = (core::max_<u32>(width, 16) * core::max_<u32>(height, 8) * 2 + 7) / 8;\r
448                         break;\r
449                 case ECF_PVRTC_RGB4:\r
450                 case ECF_PVRTC_ARGB4:\r
451                         imageSize = (core::max_<u32>(width, 8) * core::max_<u32>(height, 8) * 4 + 7) / 8;\r
452                         break;\r
453                 case ECF_PVRTC2_ARGB2:\r
454                         imageSize = core::ceil32(width / 8.0f) * core::ceil32(height / 4.0f) * 8;\r
455                         break;\r
456                 case ECF_PVRTC2_ARGB4:\r
457                 case ECF_ETC1:\r
458                 case ECF_ETC2_RGB:\r
459                         imageSize = core::ceil32(width / 4.0f) * core::ceil32(height / 4.0f) * 8;\r
460                         break;\r
461                 case ECF_ETC2_ARGB:\r
462                         imageSize = core::ceil32(width / 4.0f) * core::ceil32(height / 4.0f) * 16;\r
463                         break;\r
464                 default: // uncompressed formats\r
465                         imageSize = getBitsPerPixelFromFormat(format) / 8 * width;\r
466                         imageSize *= height;\r
467                         break;\r
468                 }\r
469 \r
470                 return imageSize;\r
471         }\r
472 \r
473 // Define to check for all compressed image formats cases in a switch\r
474 #define IRR_CASE_IIMAGE_COMPRESSED_FORMAT\\r
475         case ECF_DXT1:\\r
476         case ECF_DXT2:\\r
477         case ECF_DXT3:\\r
478         case ECF_DXT4:\\r
479         case ECF_DXT5:\\r
480         case ECF_PVRTC_RGB2:\\r
481         case ECF_PVRTC_ARGB2:\\r
482         case ECF_PVRTC2_ARGB2:\\r
483         case ECF_PVRTC_RGB4:\\r
484         case ECF_PVRTC_ARGB4:\\r
485         case ECF_PVRTC2_ARGB4:\\r
486         case ECF_ETC1:\\r
487         case ECF_ETC2_RGB:\\r
488         case ECF_ETC2_ARGB:\r
489 \r
490         //! check if this is compressed color format\r
491         static bool isCompressedFormat(const ECOLOR_FORMAT format)\r
492         {\r
493                 switch(format)\r
494                 {\r
495                         IRR_CASE_IIMAGE_COMPRESSED_FORMAT\r
496                                 return true;\r
497                         default:\r
498                                 return false;\r
499                 }\r
500         }\r
501 \r
502         //! check if the color format is only viable for depth/stencil textures\r
503         static bool isDepthFormat(const ECOLOR_FORMAT format)\r
504         {\r
505                 switch(format)\r
506                 {\r
507                         case ECF_D16:\r
508                         case ECF_D32:\r
509                         case ECF_D24S8:\r
510                                 return true;\r
511                         default:\r
512                                 return false;\r
513                 }\r
514         }\r
515 \r
516         //! Check if the color format uses floating point values for pixels\r
517         static bool isFloatingPointFormat(const ECOLOR_FORMAT format)\r
518         {\r
519                 if (isCompressedFormat(format))\r
520                         return false;\r
521 \r
522                 switch(format)\r
523                 {\r
524                 case ECF_R16F:\r
525                 case ECF_G16R16F:\r
526                 case ECF_A16B16G16R16F:\r
527                 case ECF_R32F:\r
528                 case ECF_G32R32F:\r
529                 case ECF_A32B32G32R32F:\r
530                         return true;\r
531                 default:\r
532                         break;\r
533                 }\r
534                 return false;\r
535         }\r
536 \r
537 protected:\r
538         ECOLOR_FORMAT Format;\r
539         core::dimension2d<u32> Size;\r
540 \r
541         u8* Data;\r
542         u8* MipMapsData;\r
543 \r
544         u32 BytesPerPixel;\r
545         u32 Pitch;\r
546 \r
547         bool DeleteMemory;\r
548         bool DeleteMipMapsMemory;\r
549 \r
550         core::irrAllocator<u8> Allocator;\r
551 };\r
552 \r
553 } // end namespace video\r
554 } // end namespace irr\r
555 \r
556 #endif\r
557 \r