1 /*************************************************************************/ 2 /* image.h */ 3 /*************************************************************************/ 4 /* This file is part of: */ 5 /* GODOT ENGINE */ 6 /* https://godotengine.org */ 7 /*************************************************************************/ 8 /* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ 9 /* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ 10 /* */ 11 /* Permission is hereby granted, free of charge, to any person obtaining */ 12 /* a copy of this software and associated documentation files (the */ 13 /* "Software"), to deal in the Software without restriction, including */ 14 /* without limitation the rights to use, copy, modify, merge, publish, */ 15 /* distribute, sublicense, and/or sell copies of the Software, and to */ 16 /* permit persons to whom the Software is furnished to do so, subject to */ 17 /* the following conditions: */ 18 /* */ 19 /* The above copyright notice and this permission notice shall be */ 20 /* included in all copies or substantial portions of the Software. */ 21 /* */ 22 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ 23 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ 24 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ 25 /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ 26 /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ 27 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ 28 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 29 /*************************************************************************/ 30 #ifndef IMAGE_H 31 #define IMAGE_H 32 33 #include "color.h" 34 #include "dvector.h" 35 #include "math_2d.h" 36 /** 37 * @author Juan Linietsky <reduzio@gmail.com> 38 * 39 * Image storage class. This is used to store an image in user memory, as well as 40 * providing some basic methods for image manipulation. 41 * Images can be loaded from a file, or registered into the Render object as textures. 42 */ 43 44 class Image; 45 46 typedef Error (*SavePNGFunc)(const String &p_path, Image &p_img); 47 48 class Image { 49 50 enum { 51 MAX_WIDTH = 16384, // force a limit somehow 52 MAX_HEIGHT = 16384 // force a limit somehow 53 }; 54 55 public: 56 static SavePNGFunc save_png_func; 57 58 enum Format { 59 FORMAT_GRAYSCALE, ///< one byte per pixel, 0-255 60 FORMAT_INTENSITY, ///< one byte per pixel, 0-255 61 FORMAT_GRAYSCALE_ALPHA, ///< two bytes per pixel, 0-255. alpha 0-255 62 FORMAT_RGB, ///< one byte R, one byte G, one byte B 63 FORMAT_RGBA, ///< one byte R, one byte G, one byte B, one byte A 64 FORMAT_INDEXED, ///< index byte 0-256, and after image end, 256*3 bytes of palette 65 FORMAT_INDEXED_ALPHA, ///< index byte 0-256, and after image end, 256*4 bytes of palette (alpha) 66 FORMAT_YUV_422, 67 FORMAT_YUV_444, 68 FORMAT_BC1, // DXT1 69 FORMAT_BC2, // DXT3 70 FORMAT_BC3, // DXT5 71 FORMAT_BC4, // ATI1 72 FORMAT_BC5, // ATI2 73 FORMAT_PVRTC2, 74 FORMAT_PVRTC2_ALPHA, 75 FORMAT_PVRTC4, 76 FORMAT_PVRTC4_ALPHA, 77 FORMAT_ETC, // regular ETC, no transparency 78 FORMAT_ATC, 79 FORMAT_ATC_ALPHA_EXPLICIT, 80 FORMAT_ATC_ALPHA_INTERPOLATED, 81 /*FORMAT_ETC2_R, for the future.. 82 FORMAT_ETC2_RG, 83 FORMAT_ETC2_RGB, 84 FORMAT_ETC2_RGBA1, 85 FORMAT_ETC2_RGBA,*/ 86 FORMAT_CUSTOM, 87 88 FORMAT_MAX 89 }; 90 91 static const char *format_names[FORMAT_MAX]; 92 enum Interpolation { 93 94 INTERPOLATE_NEAREST, 95 INTERPOLATE_BILINEAR, 96 INTERPOLATE_CUBIC, 97 /* INTERPOLATE GAUSS */ 98 }; 99 100 static Image (*_png_mem_loader_func)(const uint8_t *p_png, int p_size); 101 static Image (*_jpg_mem_loader_func)(const uint8_t *p_png, int p_size); 102 static void (*_image_compress_bc_func)(Image *); 103 static void (*_image_compress_pvrtc2_func)(Image *); 104 static void (*_image_compress_pvrtc4_func)(Image *); 105 static void (*_image_compress_etc_func)(Image *); 106 static void (*_image_decompress_pvrtc)(Image *); 107 static void (*_image_decompress_bc)(Image *); 108 static void (*_image_decompress_etc)(Image *); 109 110 Error _decompress_bc(); 111 112 static DVector<uint8_t> (*lossy_packer)(const Image &p_image, float p_quality); 113 static Image (*lossy_unpacker)(const DVector<uint8_t> &p_buffer); 114 static DVector<uint8_t> (*lossless_packer)(const Image &p_image); 115 static Image (*lossless_unpacker)(const DVector<uint8_t> &p_buffer); 116 117 private: 118 //internal byte based color 119 struct BColor { 120 union { 121 uint8_t col[4]; 122 struct { 123 uint8_t r, g, b, a; 124 }; 125 }; 126 127 bool operator==(const BColor &p_color) const { 128 for (int i = 0; i < 4; i++) { 129 if (col[i] != p_color.col[i]) return false; 130 } 131 return true; 132 } grayBColor133 _FORCE_INLINE_ uint8_t gray() const { return (uint16_t(col[0]) + uint16_t(col[1]) + uint16_t(col[2])) / 3; } BColorBColor134 _FORCE_INLINE_ BColor() {} 135 BColor(uint8_t p_r, uint8_t p_g, uint8_t p_b, uint8_t p_a = 255) { 136 col[0] = p_r; 137 col[1] = p_g; 138 col[2] = p_b; 139 col[3] = p_a; 140 } 141 }; 142 143 //median cut classes 144 145 struct BColorPos { 146 147 uint32_t index; 148 BColor color; 149 struct SortR { 150 operatorBColorPos::SortR151 bool operator()(const BColorPos &ca, const BColorPos &cb) const { return ca.color.r < cb.color.r; } 152 }; 153 154 struct SortG { 155 operatorBColorPos::SortG156 bool operator()(const BColorPos &ca, const BColorPos &cb) const { return ca.color.g < cb.color.g; } 157 }; 158 159 struct SortB { 160 operatorBColorPos::SortB161 bool operator()(const BColorPos &ca, const BColorPos &cb) const { return ca.color.b < cb.color.b; } 162 }; 163 164 struct SortA { 165 operatorBColorPos::SortA166 bool operator()(const BColorPos &ca, const BColorPos &cb) const { return ca.color.a < cb.color.a; } 167 }; 168 }; 169 170 struct SPTree { 171 172 bool leaf; 173 uint8_t split_plane; 174 uint8_t split_value; 175 union { 176 int left; 177 int color; 178 }; 179 int right; SPTreeSPTree180 SPTree() { 181 leaf = true; 182 left = -1; 183 right = -1; 184 } 185 }; 186 187 struct MCBlock { 188 189 BColorPos min_color, max_color; 190 BColorPos *colors; 191 int sp_idx; 192 int color_count; 193 int get_longest_axis_index() const; 194 int get_longest_axis_length() const; 195 bool operator<(const MCBlock &p_block) const; 196 void shrink(); 197 MCBlock(); 198 MCBlock(BColorPos *p_colors, int p_color_count); 199 }; 200 201 Format format; 202 DVector<uint8_t> data; 203 int width, height, mipmaps; 204 205 _FORCE_INLINE_ BColor _get_pixel(int p_x, int p_y, const unsigned char *p_data, int p_data_size) const; 206 _FORCE_INLINE_ BColor _get_pixelw(int p_x, int p_y, int p_width, const unsigned char *p_data, int p_data_size) const; 207 _FORCE_INLINE_ void _put_pixelw(int p_x, int p_y, int p_width, const BColor &p_color, unsigned char *p_data); 208 _FORCE_INLINE_ void _put_pixel(int p_x, int p_y, const BColor &p_color, unsigned char *p_data); 209 _FORCE_INLINE_ void _get_mipmap_offset_and_size(int p_mipmap, int &r_offset, int &r_width, int &r_height) const; //get where the mipmap begins in data 210 _FORCE_INLINE_ static void _get_format_min_data_size(Format p_format, int &r_w, int &r_h); 211 212 static int _get_dst_image_size(int p_width, int p_height, Format p_format, int &r_mipmaps, int p_mipmaps = -1); 213 bool _can_modify(Format p_format) const; 214 215 public: 216 int get_width() const; ///< Get image width 217 int get_height() const; ///< Get image height 218 int get_mipmaps() const; 219 220 /** 221 * Get a pixel from the image. for grayscale or indexed formats, use Color::gray to obtain the actual 222 * value. 223 */ 224 Color get_pixel(int p_x, int p_y, int p_mipmap = 0) const; 225 /** 226 * Set a pixel into the image. for grayscale or indexed formats, a suitable Color constructor. 227 */ 228 void put_pixel(int p_x, int p_y, const Color &p_color, int p_mipmap = 0); /* alpha and index are averaged */ 229 230 /** 231 * Convert the image to another format, as close as it can be done. 232 */ 233 void convert(Format p_new_format); 234 converted(int p_new_format)235 Image converted(int p_new_format) { 236 ERR_FAIL_INDEX_V(p_new_format, FORMAT_MAX, Image()); 237 238 Image ret = *this; 239 ret.convert((Format)p_new_format); 240 return ret; 241 }; 242 243 /** 244 * Get the current image format. 245 */ 246 Format get_format() const; 247 248 int get_mipmap_offset(int p_mipmap) const; //get where the mipmap begins in data 249 void get_mipmap_offset_and_size(int p_mipmap, int &r_ofs, int &r_size) const; //get where the mipmap begins in data 250 void get_mipmap_offset_size_and_dimensions(int p_mipmap, int &r_ofs, int &r_size, int &w, int &h) const; //get where the mipmap begins in data 251 252 /** 253 * Resize the image, using the prefered interpolation method. 254 * Indexed-Color images always use INTERPOLATE_NEAREST. 255 */ 256 257 void resize_to_po2(bool p_square = false); 258 void resize(int p_width, int p_height, Interpolation p_interpolation = INTERPOLATE_BILINEAR); 259 Image resized(int p_width, int p_height, int p_interpolation = INTERPOLATE_BILINEAR); 260 void shrink_x2(); 261 void expand_x2_hq2x(); 262 /** 263 * Crop the image to a specific size, if larger, then the image is filled by black 264 */ 265 void crop(int p_width, int p_height); 266 267 void flip_x(); 268 void flip_y(); 269 /** 270 * Generate a mipmap to an image (creates an image 1/4 the size, with averaging of 4->1) 271 */ 272 Error generate_mipmaps(int p_amount = -1, bool p_keep_existing = false); 273 274 void clear_mipmaps(); 275 276 /** 277 * Generate a normal map from a grayscale image 278 */ 279 280 void make_normalmap(float p_height_scale = 1.0); 281 282 /** 283 * Create a new image of a given size and format. Current image will be lost 284 */ 285 void create(int p_width, int p_height, bool p_use_mipmaps, Format p_format); 286 void create(int p_width, int p_height, int p_mipmaps, Format p_format, const DVector<uint8_t> &p_data); 287 288 void create(const char **p_xpm); 289 /** 290 * returns true when the image is empty (0,0) in size 291 */ 292 bool empty() const; 293 294 DVector<uint8_t> get_data() const; 295 296 Error load(const String &p_path); 297 Error save_png(const String &p_path) const; 298 299 /** 300 * create an empty image 301 */ 302 Image(); 303 /** 304 * create an empty image of a specific size and format 305 */ 306 Image(int p_width, int p_height, bool p_use_mipmaps, Format p_format); 307 /** 308 * import an image of a specific size and format from a pointer 309 */ 310 Image(int p_width, int p_height, int p_mipmaps, Format p_format, const DVector<uint8_t> &p_data); 311 312 enum AlphaMode { 313 ALPHA_NONE, 314 ALPHA_BIT, 315 ALPHA_BLEND 316 }; 317 318 AlphaMode detect_alpha() const; 319 bool is_invisible() const; 320 321 void put_indexed_pixel(int p_x, int p_y, uint8_t p_idx, int p_mipmap = 0); 322 uint8_t get_indexed_pixel(int p_x, int p_y, int p_mipmap = 0) const; 323 void set_pallete(const DVector<uint8_t> &p_data); 324 325 static int get_format_pixel_size(Format p_format); 326 static int get_format_pixel_rshift(Format p_format); 327 static int get_format_pallete_size(Format p_format); 328 static int get_image_data_size(int p_width, int p_height, Format p_format, int p_mipmaps = 0); 329 static int get_image_required_mipmaps(int p_width, int p_height, Format p_format); 330 331 bool operator==(const Image &p_image) const; 332 333 void quantize(); 334 335 enum CompressMode { 336 COMPRESS_BC, 337 COMPRESS_PVRTC2, 338 COMPRESS_PVRTC4, 339 COMPRESS_ETC 340 }; 341 342 Error compress(CompressMode p_mode = COMPRESS_BC); 343 Image compressed(int p_mode); /* from the Image::CompressMode enum */ 344 Error decompress(); 345 Image decompressed() const; 346 bool is_compressed() const; 347 348 void fix_alpha_edges(); 349 void premultiply_alpha(); 350 void srgb_to_linear(); 351 void normalmap_to_xy(); 352 353 void blit_rect(const Image &p_src, const Rect2 &p_src_rect, const Point2 &p_dest); 354 void blit_rect_mask(const Image &p_src, const Image &p_mask, const Rect2 &p_src_rect, const Point2 &p_dest); 355 void blend_rect(const Image &p_src, const Rect2 &p_src_rect, const Point2 &p_dest); 356 void blend_rect_mask(const Image &p_src, const Image &p_mask, const Rect2 &p_src_rect, const Point2 &p_dest); 357 358 void fill(const Color &p_color); 359 360 void brush_transfer(const Image &p_src, const Image &p_brush, const Point2 &p_dest); 361 Image brushed(const Image &p_src, const Image &p_brush, const Point2 &p_dest) const; 362 363 Rect2 get_used_rect() const; 364 Image get_rect(const Rect2 &p_area) const; 365 366 static void set_compress_bc_func(void (*p_compress_func)(Image *)); 367 static String get_format_name(Format p_format); 368 369 Image(const uint8_t *p_mem_png_jpg, int p_len = -1); 370 Image(const char **p_xpm); 371 ~Image(); 372 }; 373 374 #endif 375