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
5 #ifndef __I_IMAGE_H_INCLUDED__
\r
6 #define __I_IMAGE_H_INCLUDED__
\r
8 #include "IReferenceCounted.h"
\r
9 #include "position2d.h"
\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
24 class IImage : public virtual IReferenceCounted
\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
35 BytesPerPixel = getBitsPerPixelFromFormat(Format) / 8;
\r
36 Pitch = BytesPerPixel * Size.Width;
\r
45 if (DeleteMipMapsMemory)
\r
46 delete[] MipMapsData;
\r
49 //! Returns the color format
\r
50 ECOLOR_FORMAT getColorFormat() const
\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
61 void set_sRGB(int val)
\r
67 //! Returns width and height of image data.
\r
68 const core::dimension2d<u32>& getDimension() const
\r
73 //! Returns bits per pixel.
\r
74 u32 getBitsPerPixel() const
\r
77 return getBitsPerPixelFromFormat(Format);
\r
80 //! Returns bytes per pixel
\r
81 u32 getBytesPerPixel() const
\r
83 return BytesPerPixel;
\r
86 //! Returns image data size in bytes
\r
87 u32 getImageDataSizeInBytes() const
\r
89 return getDataSizeFromFormat(Format, Size.Width, Size.Height);
\r
92 //! Returns image data size in pixels
\r
93 u32 getImageDataSizeInPixels() const
\r
95 return Size.Width * Size.Height;
\r
98 //! Returns pitch of image
\r
99 u32 getPitch() const
\r
104 //! Returns mask for red value of a pixel
\r
105 u32 getRedMask() const
\r
122 //! Returns mask for green value of a pixel
\r
123 u32 getGreenMask() const
\r
140 //! Returns mask for blue value of a pixel
\r
141 u32 getBlueMask() const
\r
158 //! Returns mask for alpha value of a pixel
\r
159 u32 getAlphaMask() const
\r
176 //! Use this to get a pointer to the image data.
\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
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
197 //! Unlock function.
\r
198 /** Should be called after the pointer received by lock() is not
\r
200 _IRR_DEPRECATED_ void unlock()
\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
209 return getMipMapsSize(Size, mipmapLevel);
\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
217 core::dimension2du result(sizeLevel0);
\r
219 while (i != mipmapLevel)
\r
221 if (result.Width>1)
\r
222 result.Width >>= 1;
\r
223 if (result.Height>1)
\r
227 if ( result.Width == 1 && result.Height == 1 && i < mipmapLevel )
\r
228 return core::dimension2du(0,0);
\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
239 void* getMipMapsData(irr::u32 mipLevel=1) const
\r
241 if ( MipMapsData && mipLevel > 0)
\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
247 while (i != mipLevel)
\r
249 if (mipSize.Width > 1)
\r
250 mipSize.Width >>= 1;
\r
252 if (mipSize.Height > 1)
\r
253 mipSize.Height >>= 1;
\r
255 dataSize += getDataSizeFromFormat(Format, mipSize.Width, mipSize.Height);
\r
258 if ( mipSize.Width == 1 && mipSize.Height == 1 && i < mipLevel)
\r
262 return MipMapsData + dataSize;
\r
268 //! Set mipmaps data.
\r
269 /** This method allows you to put custom mipmaps data for
\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
277 void setMipMapsData(void* data, bool ownForeignMemory)
\r
279 if (data != MipMapsData)
\r
281 if (DeleteMipMapsMemory)
\r
283 delete[] MipMapsData;
\r
285 DeleteMipMapsMemory = false;
\r
290 if (ownForeignMemory)
\r
292 MipMapsData = static_cast<u8*>(data);
\r
294 DeleteMipMapsMemory = false;
\r
299 u32 width = Size.Width;
\r
300 u32 height = Size.Height;
\r
310 dataSize += getDataSizeFromFormat(Format, width, height);
\r
311 } while (width != 1 || height != 1);
\r
313 MipMapsData = new u8[dataSize];
\r
314 memcpy(MipMapsData, data, dataSize);
\r
316 DeleteMipMapsMemory = true;
\r
326 //! Returns a pixel
\r
327 virtual SColor getPixel(u32 x, u32 y) const = 0;
\r
330 virtual void setPixel(u32 x, u32 y, const SColor &color, bool blend = false ) = 0;
\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
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
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
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
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
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
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
361 //! fills the surface with given color
\r
362 virtual void fill(const SColor &color) =0;
\r
364 //! Inform whether the image is compressed
\r
365 _IRR_DEPRECATED_ bool isCompressed() const
\r
367 return IImage::isCompressedFormat(Format);
\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
374 return (getMipMapsData() != 0);
\r
377 //! get the amount of Bits per Pixel of the given color format
\r
378 static u32 getBitsPerPixelFromFormat(const ECOLOR_FORMAT format)
\r
397 case ECF_PVRTC_RGB2:
\r
399 case ECF_PVRTC_ARGB2:
\r
400 case ECF_PVRTC2_ARGB2:
\r
402 case ECF_PVRTC_RGB4:
\r
404 case ECF_PVRTC_ARGB4:
\r
405 case ECF_PVRTC2_ARGB4:
\r
410 case ECF_ETC2_ARGB:
\r
430 case ECF_A16B16G16R16F:
\r
436 case ECF_A32B32G32R32F:
\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
451 imageSize = ((width + 3) / 4) * ((height + 3) / 4) * 8;
\r
457 imageSize = ((width + 3) / 4) * ((height + 3) / 4) * 16;
\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
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
467 case ECF_PVRTC2_ARGB2:
\r
468 imageSize = core::ceil32(width / 8.0f) * core::ceil32(height / 4.0f) * 8;
\r
470 case ECF_PVRTC2_ARGB4:
\r
473 imageSize = core::ceil32(width / 4.0f) * core::ceil32(height / 4.0f) * 8;
\r
475 case ECF_ETC2_ARGB:
\r
476 imageSize = core::ceil32(width / 4.0f) * core::ceil32(height / 4.0f) * 16;
\r
478 default: // uncompressed formats
\r
479 imageSize = getBitsPerPixelFromFormat(format) / 8 * width;
\r
480 imageSize *= height;
\r
487 // Define to check for all compressed image formats cases in a switch
\r
488 #define IRR_CASE_IIMAGE_COMPRESSED_FORMAT\
\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
501 case ECF_ETC2_RGB:\
\r
502 case ECF_ETC2_ARGB:
\r
504 //! check if this is compressed color format
\r
505 static bool isCompressedFormat(const ECOLOR_FORMAT format)
\r
509 IRR_CASE_IIMAGE_COMPRESSED_FORMAT
\r
516 //! check if the color format is only viable for depth/stencil textures
\r
517 static bool isDepthFormat(const ECOLOR_FORMAT format)
\r
530 //! Check if the color format uses floating point values for pixels
\r
531 static bool isFloatingPointFormat(const ECOLOR_FORMAT format)
\r
533 if (isCompressedFormat(format))
\r
540 case ECF_A16B16G16R16F:
\r
543 case ECF_A32B32G32R32F:
\r
551 #if defined(PATCH_SUPERTUX_8_0_1_with_1_9_0)
\r
552 static bool isRenderTargetOnlyFormat(const ECOLOR_FORMAT format)
\r
568 ECOLOR_FORMAT Format;
\r
569 core::dimension2d<u32> Size;
\r
578 bool DeleteMipMapsMemory;
\r
580 #if defined(IRRLICHT_sRGB)
\r
586 } // end namespace video
\r
587 } // end namespace irr
\r