1 // 2 // Copyright (c) 2008-2017 the Urho3D project. 3 // 4 // Permission is hereby granted, free of charge, to any person obtaining a copy 5 // of this software and associated documentation files (the "Software"), to deal 6 // in the Software without restriction, including without limitation the rights 7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 // copies of the Software, and to permit persons to whom the Software is 9 // furnished to do so, subject to the following conditions: 10 // 11 // The above copyright notice and this permission notice shall be included in 12 // all copies or substantial portions of the Software. 13 // 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 // THE SOFTWARE. 21 // 22 23 #pragma once 24 25 #include "../Container/ArrayPtr.h" 26 #include "../Resource/Resource.h" 27 28 struct SDL_Surface; 29 30 namespace Urho3D 31 { 32 33 static const int COLOR_LUT_SIZE = 16; 34 35 /// Supported compressed image formats. 36 enum CompressedFormat 37 { 38 CF_NONE = 0, 39 CF_RGBA, 40 CF_DXT1, 41 CF_DXT3, 42 CF_DXT5, 43 CF_ETC1, 44 CF_PVRTC_RGB_2BPP, 45 CF_PVRTC_RGBA_2BPP, 46 CF_PVRTC_RGB_4BPP, 47 CF_PVRTC_RGBA_4BPP, 48 }; 49 50 /// Compressed image mip level. 51 struct CompressedLevel 52 { 53 /// Construct empty. CompressedLevelCompressedLevel54 CompressedLevel() : 55 data_(0), 56 format_(CF_NONE), 57 width_(0), 58 height_(0), 59 depth_(0), 60 blockSize_(0), 61 dataSize_(0), 62 rowSize_(0), 63 rows_(0) 64 { 65 } 66 67 /// Decompress to RGBA. The destination buffer required is width * height * 4 bytes. Return true if successful. 68 bool Decompress(unsigned char* dest); 69 70 /// Compressed image data. 71 unsigned char* data_; 72 /// Compression format. 73 CompressedFormat format_; 74 /// Width. 75 int width_; 76 /// Height. 77 int height_; 78 /// Depth. 79 int depth_; 80 /// Block size in bytes. 81 unsigned blockSize_; 82 /// Total data size in bytes. 83 unsigned dataSize_; 84 /// Row size in bytes. 85 unsigned rowSize_; 86 /// Number of rows. 87 unsigned rows_; 88 }; 89 90 /// %Image resource. 91 class URHO3D_API Image : public Resource 92 { 93 URHO3D_OBJECT(Image, Resource); 94 95 public: 96 /// Construct empty. 97 Image(Context* context); 98 /// Destruct. 99 virtual ~Image(); 100 /// Register object factory. 101 static void RegisterObject(Context* context); 102 103 /// Load resource from stream. May be called from a worker thread. Return true if successful. 104 virtual bool BeginLoad(Deserializer& source); 105 /// Save the image to a stream. Regardless of original format, the image is saved as png. Compressed image data is not supported. Return true if successful. 106 virtual bool Save(Serializer& dest) const; 107 /// Save the image to a file. Format of the image is determined by file extension. JPG is saved with maximum quality. 108 virtual bool SaveFile(const String& fileName) const; 109 110 /// Set 2D size and number of color components. Old image data will be destroyed and new data is undefined. Return true if successful. 111 bool SetSize(int width, int height, unsigned components); 112 /// Set 3D size and number of color components. Old image data will be destroyed and new data is undefined. Return true if successful. 113 bool SetSize(int width, int height, int depth, unsigned components); 114 /// Set new image data. 115 void SetData(const unsigned char* pixelData); 116 /// Set a 2D pixel. 117 void SetPixel(int x, int y, const Color& color); 118 /// Set a 3D pixel. 119 void SetPixel(int x, int y, int z, const Color& color); 120 /// Set a 2D pixel with an integer color. R component is in the 8 lowest bits. 121 void SetPixelInt(int x, int y, unsigned uintColor); 122 /// Set a 3D pixel with an integer color. R component is in the 8 lowest bits. 123 void SetPixelInt(int x, int y, int z, unsigned uintColor); 124 /// Load as color LUT. Return true if successful. 125 bool LoadColorLUT(Deserializer& source); 126 /// Flip image horizontally. Return true if successful. 127 bool FlipHorizontal(); 128 /// Flip image vertically. Return true if successful. 129 bool FlipVertical(); 130 /// Resize image by bilinear resampling. Return true if successful. 131 bool Resize(int width, int height); 132 /// Clear the image with a color. 133 void Clear(const Color& color); 134 /// Clear the image with an integer color. R component is in the 8 lowest bits. 135 void ClearInt(unsigned uintColor); 136 /// Save in BMP format. Return true if successful. 137 bool SaveBMP(const String& fileName) const; 138 /// Save in PNG format. Return true if successful. 139 bool SavePNG(const String& fileName) const; 140 /// Save in TGA format. Return true if successful. 141 bool SaveTGA(const String& fileName) const; 142 /// Save in JPG format with specified quality. Return true if successful. 143 bool SaveJPG(const String& fileName, int quality) const; 144 /// Save in DDS format. Only uncompressed RGBA images are supported. Return true if successful. 145 bool SaveDDS(const String& fileName) const; 146 /// Save in WebP format with minimum (fastest) or specified compression. Return true if successful. Fails always if WebP support is not compiled in. 147 bool SaveWEBP(const String& fileName, float compression = 0.0f) const; 148 /// Whether this texture is detected as a cubemap, only relevant for DDS. IsCubemap()149 bool IsCubemap() const { return cubemap_; } 150 /// Whether this texture has been detected as a volume, only relevant for DDS. IsArray()151 bool IsArray() const { return array_; } 152 /// Whether this texture is in sRGB, only relevant for DDS. IsSRGB()153 bool IsSRGB() const { return sRGB_; } 154 155 /// Return a 2D pixel color. 156 Color GetPixel(int x, int y) const; 157 /// Return a 3D pixel color. 158 Color GetPixel(int x, int y, int z) const; 159 /// Return a 2D pixel integer color. R component is in the 8 lowest bits. 160 unsigned GetPixelInt(int x, int y) const; 161 /// Return a 3D pixel integer color. R component is in the 8 lowest bits. 162 unsigned GetPixelInt(int x, int y, int z) const; 163 /// Return a bilinearly sampled 2D pixel color. X and Y have the range 0-1. 164 Color GetPixelBilinear(float x, float y) const; 165 /// Return a trilinearly sampled 3D pixel color. X, Y and Z have the range 0-1. 166 Color GetPixelTrilinear(float x, float y, float z) const; 167 168 /// Return width. GetWidth()169 int GetWidth() const { return width_; } 170 171 /// Return height. GetHeight()172 int GetHeight() const { return height_; } 173 174 /// Return depth. GetDepth()175 int GetDepth() const { return depth_; } 176 177 /// Return number of color components. GetComponents()178 unsigned GetComponents() const { return components_; } 179 180 /// Return pixel data. GetData()181 unsigned char* GetData() const { return data_; } 182 183 /// Return whether is compressed. IsCompressed()184 bool IsCompressed() const { return compressedFormat_ != CF_NONE; } 185 186 /// Return compressed format. GetCompressedFormat()187 CompressedFormat GetCompressedFormat() const { return compressedFormat_; } 188 189 /// Return number of compressed mip levels. Returns 0 if the image is has not been loaded from a source file containing multiple mip levels. GetNumCompressedLevels()190 unsigned GetNumCompressedLevels() const { return numCompressedLevels_; } 191 192 /// Return next mip level by bilinear filtering. Note that if the image is already 1x1x1, will keep returning an image of that size. 193 SharedPtr<Image> GetNextLevel() const; 194 /// Return the next sibling image of an array or cubemap. GetNextSibling()195 SharedPtr<Image> GetNextSibling() const { return nextSibling_; } 196 /// Return image converted to 4-component (RGBA) to circumvent modern rendering API's not supporting e.g. the luminance-alpha format. 197 SharedPtr<Image> ConvertToRGBA() const; 198 /// Return a compressed mip level. 199 CompressedLevel GetCompressedLevel(unsigned index) const; 200 /// Return subimage from the image by the defined rect or null if failed. 3D images are not supported. You must free the subimage yourself. 201 Image* GetSubimage(const IntRect& rect) const; 202 /// Return an SDL surface from the image, or null if failed. Only RGB images are supported. Specify rect to only return partial image. You must free the surface yourself. 203 SDL_Surface* GetSDLSurface(const IntRect& rect = IntRect::ZERO) const; 204 /// Precalculate the mip levels. Used by asynchronous texture loading. 205 void PrecalculateLevels(); 206 /// Clean up the mip levels. 207 void CleanupLevels(); 208 /// Get all stored mip levels starting from this. 209 void GetLevels(PODVector<Image*>& levels); 210 /// Get all stored mip levels starting from this. 211 void GetLevels(PODVector<const Image*>& levels) const; 212 213 private: 214 /// Decode an image using stb_image. 215 static unsigned char* GetImageData(Deserializer& source, int& width, int& height, unsigned& components); 216 /// Free an image file's pixel data. 217 static void FreeImageData(unsigned char* pixelData); 218 219 /// Width. 220 int width_; 221 /// Height. 222 int height_; 223 /// Depth. 224 int depth_; 225 /// Number of color components. 226 unsigned components_; 227 /// Number of compressed mip levels. 228 unsigned numCompressedLevels_; 229 /// Cubemap status if DDS. 230 bool cubemap_; 231 /// Texture array status if DDS. 232 bool array_; 233 /// Data is sRGB. 234 bool sRGB_; 235 /// Compressed format. 236 CompressedFormat compressedFormat_; 237 /// Pixel data. 238 SharedArrayPtr<unsigned char> data_; 239 /// Precalculated mip level image. 240 SharedPtr<Image> nextLevel_; 241 /// Next texture array or cube map image. 242 SharedPtr<Image> nextSibling_; 243 }; 244 245 } 246