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
12 #include "irrAllocator.h"
\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
25 class IImage : public virtual IReferenceCounted
\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 #if defined(IRRLICHT_sRGB)
\r
36 BytesPerPixel = getBitsPerPixelFromFormat(Format) / 8;
\r
37 Pitch = BytesPerPixel * Size.Width;
\r
46 if (DeleteMipMapsMemory)
\r
47 Allocator.deallocate(MipMapsData);
\r
50 //! Returns the color format
\r
51 ECOLOR_FORMAT getColorFormat() const
\r
56 #if defined(IRRLICHT_sRGB)
\r
57 //! Texture is linear/sRGB (should be part of ColorFormat: default yes)
\r
58 int get_sRGB() const
\r
62 void set_sRGB(int val)
\r
68 //! Returns width and height of image data.
\r
69 const core::dimension2d<u32>& getDimension() const
\r
74 //! Returns bits per pixel.
\r
75 u32 getBitsPerPixel() const
\r
78 return getBitsPerPixelFromFormat(Format);
\r
81 //! Returns bytes per pixel
\r
82 u32 getBytesPerPixel() const
\r
84 return BytesPerPixel;
\r
87 //! Returns image data size in bytes
\r
88 u32 getImageDataSizeInBytes() const
\r
90 return getDataSizeFromFormat(Format, Size.Width, Size.Height);
\r
93 //! Returns image data size in pixels
\r
94 u32 getImageDataSizeInPixels() const
\r
96 return Size.Width * Size.Height;
\r
99 //! Returns pitch of image
\r
100 u32 getPitch() const
\r
105 //! Returns mask for red value of a pixel
\r
106 u32 getRedMask() const
\r
123 //! Returns mask for green value of a pixel
\r
124 u32 getGreenMask() const
\r
141 //! Returns mask for blue value of a pixel
\r
142 u32 getBlueMask() const
\r
159 //! Returns mask for alpha value of a pixel
\r
160 u32 getAlphaMask() const
\r
177 //! Use this to get a pointer to the image data.
\r
179 \return Pointer to the image data. What type of data is pointed to
\r
180 depends on the color format of the image. For example if the color
\r
181 format is ECF_A8R8G8B8, it is of u32. */
\r
182 void* getData() const
\r
187 //! Lock function. Use this to get a pointer to the image data.
\r
188 /** Use getData instead.
\r
189 \return Pointer to the image data. What type of data is pointed to
\r
190 depends on the color format of the image. For example if the color
\r
191 format is ECF_A8R8G8B8, it is of u32. Be sure to call unlock() after
\r
192 you don't need the pointer any more. */
\r
193 _IRR_DEPRECATED_ void* lock()
\r
198 //! Unlock function.
\r
199 /** Should be called after the pointer received by lock() is not
\r
201 _IRR_DEPRECATED_ void unlock()
\r
205 //! Get the mipmap size for this image for a certain mipmap level
\r
206 /** level 0 will be full image size. Every further level is half the size.
\r
207 Doesn't care if the image actually has mipmaps, just which size would be needed. */
\r
208 core::dimension2du getMipMapsSize(u32 mipmapLevel) const
\r
210 return getMipMapsSize(Size, mipmapLevel);
\r
214 //! Calculate mipmap size for a certain level
\r
215 /** level 0 will be full image size. Every further level is half the size. */
\r
216 static core::dimension2du getMipMapsSize(const core::dimension2du& sizeLevel0, u32 mipmapLevel)
\r
218 core::dimension2du result(sizeLevel0);
\r
220 while (i != mipmapLevel)
\r
222 if (result.Width>1)
\r
223 result.Width >>= 1;
\r
224 if (result.Height>1)
\r
228 if ( result.Width == 1 && result.Height == 1 && i < mipmapLevel )
\r
229 return core::dimension2du(0,0);
\r
235 //! Get mipmaps data.
\r
236 /** Note that different mip levels are just behind each other in memory block.
\r
237 So if you just get level 1 you also have the data for all other levels.
\r
238 There is no level 0 - use getData to get the original image data.
\r
240 void* getMipMapsData(irr::u32 mipLevel=1) const
\r
242 if ( MipMapsData && mipLevel > 0)
\r
244 size_t dataSize = 0;
\r
245 core::dimension2du mipSize(Size);
\r
246 u32 i = 1; // We want the start of data for this level, not end.
\r
248 while (i != mipLevel)
\r
250 if (mipSize.Width > 1)
\r
251 mipSize.Width >>= 1;
\r
253 if (mipSize.Height > 1)
\r
254 mipSize.Height >>= 1;
\r
256 dataSize += getDataSizeFromFormat(Format, mipSize.Width, mipSize.Height);
\r
259 if ( mipSize.Width == 1 && mipSize.Height == 1 && i < mipLevel)
\r
263 return MipMapsData + dataSize;
\r
269 //! Set mipmaps data.
\r
270 /** This method allows you to put custom mipmaps data for
\r
272 \param data A byte array with pixel color information
\r
273 \param ownForeignMemory If true, the image will use the data
\r
274 pointer directly and own it afterward. If false, the memory
\r
275 will by copied internally.
\r
276 \param deleteMemory Whether the memory is deallocated upon
\r
278 void setMipMapsData(void* data, bool ownForeignMemory, bool deleteMemory)
\r
280 if (data != MipMapsData)
\r
282 if (DeleteMipMapsMemory)
\r
284 Allocator.deallocate(MipMapsData);
\r
286 DeleteMipMapsMemory = false;
\r
291 if (ownForeignMemory)
\r
293 MipMapsData = static_cast<u8*>(data);
\r
295 DeleteMipMapsMemory = deleteMemory;
\r
300 u32 width = Size.Width;
\r
301 u32 height = Size.Height;
\r
311 dataSize += getDataSizeFromFormat(Format, width, height);
\r
312 } while (width != 1 || height != 1);
\r
314 MipMapsData = Allocator.allocate(dataSize);
\r
315 memcpy(MipMapsData, data, dataSize);
\r
317 DeleteMipMapsMemory = true;
\r
327 //! Returns a pixel
\r
328 virtual SColor getPixel(u32 x, u32 y) const = 0;
\r
331 virtual void setPixel(u32 x, u32 y, const SColor &color, bool blend = false ) = 0;
\r
333 //! Copies the image into the target, scaling the image to fit
\r
334 /** NOTE: mipmaps are ignored */
\r
335 virtual void copyToScaling(void* target, u32 width, u32 height, ECOLOR_FORMAT format=ECF_A8R8G8B8, u32 pitch=0) =0;
\r
337 //! Copies the image into the target, scaling the image to fit
\r
338 /** NOTE: mipmaps are ignored */
\r
339 virtual void copyToScaling(IImage* target) =0;
\r
341 //! copies this surface into another
\r
342 /** NOTE: mipmaps are ignored */
\r
343 virtual void copyTo(IImage* target, const core::position2d<s32>& pos=core::position2d<s32>(0,0)) =0;
\r
345 //! copies this surface into another
\r
346 /** NOTE: mipmaps are ignored */
\r
347 virtual void copyTo(IImage* target, const core::position2d<s32>& pos, const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect=0) =0;
\r
349 //! copies this surface into another, using the alpha mask and cliprect and a color to add with
\r
350 /** NOTE: mipmaps are ignored
\r
351 \param combineAlpha - When true then combine alpha channels. When false replace target image alpha with source image alpha.
\r
353 virtual void copyToWithAlpha(IImage* target, const core::position2d<s32>& pos,
\r
354 const core::rect<s32>& sourceRect, const SColor &color,
\r
355 const core::rect<s32>* clipRect = 0,
\r
356 bool combineAlpha=false) =0;
\r
358 //! copies this surface into another, scaling it to fit, applying a box filter
\r
359 /** NOTE: mipmaps are ignored */
\r
360 virtual void copyToScalingBoxFilter(IImage* target, s32 bias = 0, bool blend = false) = 0;
\r
362 //! fills the surface with given color
\r
363 virtual void fill(const SColor &color) =0;
\r
365 //! Inform whether the image is compressed
\r
366 _IRR_DEPRECATED_ bool isCompressed() const
\r
368 return IImage::isCompressedFormat(Format);
\r
371 //! Check whether the image has MipMaps
\r
372 /** \return True if image has MipMaps, else false. */
\r
373 _IRR_DEPRECATED_ bool hasMipMaps() const
\r
375 return (getMipMapsData() != 0);
\r
378 //! get the amount of Bits per Pixel of the given color format
\r
379 static u32 getBitsPerPixelFromFormat(const ECOLOR_FORMAT format)
\r
398 case ECF_PVRTC_RGB2:
\r
400 case ECF_PVRTC_ARGB2:
\r
401 case ECF_PVRTC2_ARGB2:
\r
403 case ECF_PVRTC_RGB4:
\r
405 case ECF_PVRTC_ARGB4:
\r
406 case ECF_PVRTC2_ARGB4:
\r
411 case ECF_ETC2_ARGB:
\r
431 case ECF_A16B16G16R16F:
\r
437 case ECF_A32B32G32R32F:
\r
444 //! calculate image data size in bytes for selected format, width and height.
\r
445 static u32 getDataSizeFromFormat(ECOLOR_FORMAT format, u32 width, u32 height)
\r
452 imageSize = ((width + 3) / 4) * ((height + 3) / 4) * 8;
\r
458 imageSize = ((width + 3) / 4) * ((height + 3) / 4) * 16;
\r
460 case ECF_PVRTC_RGB2:
\r
461 case ECF_PVRTC_ARGB2:
\r
462 imageSize = (core::max_<u32>(width, 16) * core::max_<u32>(height, 8) * 2 + 7) / 8;
\r
464 case ECF_PVRTC_RGB4:
\r
465 case ECF_PVRTC_ARGB4:
\r
466 imageSize = (core::max_<u32>(width, 8) * core::max_<u32>(height, 8) * 4 + 7) / 8;
\r
468 case ECF_PVRTC2_ARGB2:
\r
469 imageSize = core::ceil32(width / 8.0f) * core::ceil32(height / 4.0f) * 8;
\r
471 case ECF_PVRTC2_ARGB4:
\r
474 imageSize = core::ceil32(width / 4.0f) * core::ceil32(height / 4.0f) * 8;
\r
476 case ECF_ETC2_ARGB:
\r
477 imageSize = core::ceil32(width / 4.0f) * core::ceil32(height / 4.0f) * 16;
\r
479 default: // uncompressed formats
\r
480 imageSize = getBitsPerPixelFromFormat(format) / 8 * width;
\r
481 imageSize *= height;
\r
488 // Define to check for all compressed image formats cases in a switch
\r
489 #define IRR_CASE_IIMAGE_COMPRESSED_FORMAT\
\r
495 case ECF_PVRTC_RGB2:\
\r
496 case ECF_PVRTC_ARGB2:\
\r
497 case ECF_PVRTC2_ARGB2:\
\r
498 case ECF_PVRTC_RGB4:\
\r
499 case ECF_PVRTC_ARGB4:\
\r
500 case ECF_PVRTC2_ARGB4:\
\r
502 case ECF_ETC2_RGB:\
\r
503 case ECF_ETC2_ARGB:
\r
505 //! check if this is compressed color format
\r
506 static bool isCompressedFormat(const ECOLOR_FORMAT format)
\r
510 IRR_CASE_IIMAGE_COMPRESSED_FORMAT
\r
517 //! check if the color format is only viable for depth/stencil textures
\r
518 static bool isDepthFormat(const ECOLOR_FORMAT format)
\r
531 //! Check if the color format uses floating point values for pixels
\r
532 static bool isFloatingPointFormat(const ECOLOR_FORMAT format)
\r
534 if (isCompressedFormat(format))
\r
541 case ECF_A16B16G16R16F:
\r
544 case ECF_A32B32G32R32F:
\r
552 #if defined(PATCH_SUPERTUX_8_0_1_with_1_9_0)
\r
553 static bool isRenderTargetOnlyFormat(const ECOLOR_FORMAT format)
\r
569 ECOLOR_FORMAT Format;
\r
570 core::dimension2d<u32> Size;
\r
579 bool DeleteMipMapsMemory;
\r
581 core::irrAllocator<u8> Allocator;
\r
582 #if defined(IRRLICHT_sRGB)
\r
588 } // end namespace video
\r
589 } // end namespace irr
\r