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