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