1 | /**************************************************************************/ |
2 | /* image.h */ |
3 | /**************************************************************************/ |
4 | /* This file is part of: */ |
5 | /* GODOT ENGINE */ |
6 | /* https://godotengine.org */ |
7 | /**************************************************************************/ |
8 | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ |
9 | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ |
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 | |
31 | #ifndef IMAGE_H |
32 | #define IMAGE_H |
33 | |
34 | #include "core/io/resource.h" |
35 | #include "core/math/color.h" |
36 | #include "core/math/rect2.h" |
37 | |
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, const Ref<Image> &p_img); |
47 | typedef Vector<uint8_t> (*SavePNGBufferFunc)(const Ref<Image> &p_img); |
48 | typedef Error (*SaveJPGFunc)(const String &p_path, const Ref<Image> &p_img, float p_quality); |
49 | typedef Vector<uint8_t> (*SaveJPGBufferFunc)(const Ref<Image> &p_img, float p_quality); |
50 | typedef Ref<Image> (*ImageMemLoadFunc)(const uint8_t *p_png, int p_size); |
51 | typedef Ref<Image> (*ScalableImageMemLoadFunc)(const uint8_t *p_data, int p_size, float p_scale); |
52 | typedef Error (*SaveWebPFunc)(const String &p_path, const Ref<Image> &p_img, const bool p_lossy, const float p_quality); |
53 | typedef Vector<uint8_t> (*SaveWebPBufferFunc)(const Ref<Image> &p_img, const bool p_lossy, const float p_quality); |
54 | |
55 | typedef Error (*SaveEXRFunc)(const String &p_path, const Ref<Image> &p_img, bool p_grayscale); |
56 | typedef Vector<uint8_t> (*SaveEXRBufferFunc)(const Ref<Image> &p_img, bool p_grayscale); |
57 | |
58 | class Image : public Resource { |
59 | GDCLASS(Image, Resource); |
60 | |
61 | public: |
62 | static SavePNGFunc save_png_func; |
63 | static SaveJPGFunc save_jpg_func; |
64 | static SaveEXRFunc save_exr_func; |
65 | static SavePNGBufferFunc save_png_buffer_func; |
66 | static SaveEXRBufferFunc save_exr_buffer_func; |
67 | static SaveJPGBufferFunc save_jpg_buffer_func; |
68 | static SaveWebPFunc save_webp_func; |
69 | static SaveWebPBufferFunc save_webp_buffer_func; |
70 | |
71 | enum { |
72 | MAX_WIDTH = (1 << 24), // force a limit somehow |
73 | MAX_HEIGHT = (1 << 24), // force a limit somehow |
74 | MAX_PIXELS = 268435456 |
75 | }; |
76 | |
77 | enum Format { |
78 | FORMAT_L8, //luminance |
79 | FORMAT_LA8, //luminance-alpha |
80 | FORMAT_R8, |
81 | FORMAT_RG8, |
82 | FORMAT_RGB8, |
83 | FORMAT_RGBA8, |
84 | FORMAT_RGBA4444, |
85 | FORMAT_RGB565, |
86 | FORMAT_RF, //float |
87 | FORMAT_RGF, |
88 | FORMAT_RGBF, |
89 | FORMAT_RGBAF, |
90 | FORMAT_RH, //half float |
91 | FORMAT_RGH, |
92 | FORMAT_RGBH, |
93 | FORMAT_RGBAH, |
94 | FORMAT_RGBE9995, |
95 | FORMAT_DXT1, //s3tc bc1 |
96 | FORMAT_DXT3, //bc2 |
97 | FORMAT_DXT5, //bc3 |
98 | FORMAT_RGTC_R, |
99 | FORMAT_RGTC_RG, |
100 | FORMAT_BPTC_RGBA, //btpc bc7 |
101 | FORMAT_BPTC_RGBF, //float bc6h |
102 | FORMAT_BPTC_RGBFU, //unsigned float bc6hu |
103 | FORMAT_ETC, //etc1 |
104 | FORMAT_ETC2_R11, //etc2 |
105 | FORMAT_ETC2_R11S, //signed, NOT srgb. |
106 | FORMAT_ETC2_RG11, |
107 | FORMAT_ETC2_RG11S, |
108 | FORMAT_ETC2_RGB8, |
109 | FORMAT_ETC2_RGBA8, |
110 | FORMAT_ETC2_RGB8A1, |
111 | FORMAT_ETC2_RA_AS_RG, //used to make basis universal happy |
112 | FORMAT_DXT5_RA_AS_RG, //used to make basis universal happy |
113 | FORMAT_ASTC_4x4, |
114 | FORMAT_ASTC_4x4_HDR, |
115 | FORMAT_ASTC_8x8, |
116 | FORMAT_ASTC_8x8_HDR, |
117 | FORMAT_MAX |
118 | }; |
119 | |
120 | static const char *format_names[FORMAT_MAX]; |
121 | enum Interpolation { |
122 | INTERPOLATE_NEAREST, |
123 | INTERPOLATE_BILINEAR, |
124 | INTERPOLATE_CUBIC, |
125 | INTERPOLATE_TRILINEAR, |
126 | INTERPOLATE_LANCZOS, |
127 | /* INTERPOLATE_TRICUBIC, */ |
128 | /* INTERPOLATE GAUSS */ |
129 | }; |
130 | |
131 | //this is used for compression |
132 | enum UsedChannels { |
133 | USED_CHANNELS_L, |
134 | USED_CHANNELS_LA, |
135 | USED_CHANNELS_R, |
136 | USED_CHANNELS_RG, |
137 | USED_CHANNELS_RGB, |
138 | USED_CHANNELS_RGBA, |
139 | }; |
140 | //some functions provided by something else |
141 | |
142 | enum ASTCFormat { |
143 | ASTC_FORMAT_4x4, |
144 | ASTC_FORMAT_8x8, |
145 | }; |
146 | |
147 | static ImageMemLoadFunc _png_mem_loader_func; |
148 | static ImageMemLoadFunc _jpg_mem_loader_func; |
149 | static ImageMemLoadFunc _webp_mem_loader_func; |
150 | static ImageMemLoadFunc _tga_mem_loader_func; |
151 | static ImageMemLoadFunc _bmp_mem_loader_func; |
152 | static ScalableImageMemLoadFunc _svg_scalable_mem_loader_func; |
153 | static ImageMemLoadFunc _ktx_mem_loader_func; |
154 | |
155 | static void (*_image_compress_bc_func)(Image *, UsedChannels p_channels); |
156 | static void (*_image_compress_bptc_func)(Image *, UsedChannels p_channels); |
157 | static void (*_image_compress_etc1_func)(Image *); |
158 | static void (*_image_compress_etc2_func)(Image *, UsedChannels p_channels); |
159 | static void (*_image_compress_astc_func)(Image *, ASTCFormat p_format); |
160 | |
161 | static void (*_image_decompress_bc)(Image *); |
162 | static void (*_image_decompress_bptc)(Image *); |
163 | static void (*_image_decompress_etc1)(Image *); |
164 | static void (*_image_decompress_etc2)(Image *); |
165 | static void (*_image_decompress_astc)(Image *); |
166 | |
167 | static Vector<uint8_t> (*webp_lossy_packer)(const Ref<Image> &p_image, float p_quality); |
168 | static Vector<uint8_t> (*webp_lossless_packer)(const Ref<Image> &p_image); |
169 | static Ref<Image> (*webp_unpacker)(const Vector<uint8_t> &p_buffer); |
170 | static Vector<uint8_t> (*png_packer)(const Ref<Image> &p_image); |
171 | static Ref<Image> (*png_unpacker)(const Vector<uint8_t> &p_buffer); |
172 | static Vector<uint8_t> (*basis_universal_packer)(const Ref<Image> &p_image, UsedChannels p_channels); |
173 | static Ref<Image> (*basis_universal_unpacker)(const Vector<uint8_t> &p_buffer); |
174 | static Ref<Image> (*basis_universal_unpacker_ptr)(const uint8_t *p_data, int p_size); |
175 | |
176 | _FORCE_INLINE_ Color _get_color_at_ofs(const uint8_t *ptr, uint32_t ofs) const; |
177 | _FORCE_INLINE_ void _set_color_at_ofs(uint8_t *ptr, uint32_t ofs, const Color &p_color); |
178 | |
179 | protected: |
180 | static void _bind_methods(); |
181 | |
182 | private: |
183 | Format format = FORMAT_L8; |
184 | Vector<uint8_t> data; |
185 | int width = 0; |
186 | int height = 0; |
187 | bool mipmaps = false; |
188 | |
189 | void _copy_internals_from(const Image &p_image) { |
190 | format = p_image.format; |
191 | width = p_image.width; |
192 | height = p_image.height; |
193 | mipmaps = p_image.mipmaps; |
194 | data = p_image.data; |
195 | } |
196 | |
197 | _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 |
198 | |
199 | static int _get_dst_image_size(int p_width, int p_height, Format p_format, int &r_mipmaps, int p_mipmaps = -1, int *r_mm_width = nullptr, int *r_mm_height = nullptr); |
200 | bool _can_modify(Format p_format) const; |
201 | |
202 | _FORCE_INLINE_ void _get_clipped_src_and_dest_rects(const Ref<Image> &p_src, const Rect2i &p_src_rect, const Point2i &p_dest, Rect2i &r_clipped_src_rect, Rect2i &r_clipped_dest_rect) const; |
203 | |
204 | _FORCE_INLINE_ void _put_pixelb(int p_x, int p_y, uint32_t p_pixel_size, uint8_t *p_data, const uint8_t *p_pixel); |
205 | _FORCE_INLINE_ void _get_pixelb(int p_x, int p_y, uint32_t p_pixel_size, const uint8_t *p_data, uint8_t *p_pixel); |
206 | |
207 | _FORCE_INLINE_ void _repeat_pixel_over_subsequent_memory(uint8_t *p_pixel, int p_pixel_size, int p_count); |
208 | |
209 | void _set_data(const Dictionary &p_data); |
210 | Dictionary _get_data() const; |
211 | |
212 | Error _load_from_buffer(const Vector<uint8_t> &p_array, ImageMemLoadFunc p_loader); |
213 | |
214 | static void average_4_uint8(uint8_t &p_out, const uint8_t &p_a, const uint8_t &p_b, const uint8_t &p_c, const uint8_t &p_d); |
215 | static void average_4_float(float &p_out, const float &p_a, const float &p_b, const float &p_c, const float &p_d); |
216 | static void average_4_half(uint16_t &p_out, const uint16_t &p_a, const uint16_t &p_b, const uint16_t &p_c, const uint16_t &p_d); |
217 | static void average_4_rgbe9995(uint32_t &p_out, const uint32_t &p_a, const uint32_t &p_b, const uint32_t &p_c, const uint32_t &p_d); |
218 | static void renormalize_uint8(uint8_t *p_rgb); |
219 | static void renormalize_float(float *p_rgb); |
220 | static void renormalize_half(uint16_t *p_rgb); |
221 | static void renormalize_rgbe9995(uint32_t *p_rgb); |
222 | |
223 | public: |
224 | int get_width() const; ///< Get image width |
225 | int get_height() const; ///< Get image height |
226 | Size2i get_size() const; |
227 | bool has_mipmaps() const; |
228 | int get_mipmap_count() const; |
229 | |
230 | /** |
231 | * Convert the image to another format, conversion only to raw byte format |
232 | */ |
233 | void convert(Format p_new_format); |
234 | |
235 | /** |
236 | * Get the current image format. |
237 | */ |
238 | Format get_format() const; |
239 | |
240 | int get_mipmap_byte_size(int p_mipmap) const; //get where the mipmap begins in data |
241 | int get_mipmap_offset(int p_mipmap) const; //get where the mipmap begins in data |
242 | void get_mipmap_offset_and_size(int p_mipmap, int &r_ofs, int &r_size) const; //get where the mipmap begins in data |
243 | 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 |
244 | |
245 | enum Image3DValidateError { |
246 | VALIDATE_3D_OK, |
247 | VALIDATE_3D_ERR_IMAGE_EMPTY, |
248 | VALIDATE_3D_ERR_MISSING_IMAGES, |
249 | , |
250 | VALIDATE_3D_ERR_IMAGE_SIZE_MISMATCH, |
251 | VALIDATE_3D_ERR_IMAGE_FORMAT_MISMATCH, |
252 | VALIDATE_3D_ERR_IMAGE_HAS_MIPMAPS, |
253 | }; |
254 | |
255 | static Image3DValidateError validate_3d_image(Format p_format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_images); |
256 | static String get_3d_image_validation_error_text(Image3DValidateError p_error); |
257 | |
258 | /** |
259 | * Resize the image, using the preferred interpolation method. |
260 | */ |
261 | void resize_to_po2(bool p_square = false, Interpolation p_interpolation = INTERPOLATE_BILINEAR); |
262 | void resize(int p_width, int p_height, Interpolation p_interpolation = INTERPOLATE_BILINEAR); |
263 | void shrink_x2(); |
264 | bool is_size_po2() const; |
265 | /** |
266 | * Crop the image to a specific size, if larger, then the image is filled by black |
267 | */ |
268 | void crop_from_point(int p_x, int p_y, int p_width, int p_height); |
269 | void crop(int p_width, int p_height); |
270 | |
271 | void rotate_90(ClockDirection p_direction); |
272 | void rotate_180(); |
273 | |
274 | void flip_x(); |
275 | void flip_y(); |
276 | |
277 | /** |
278 | * Generate a mipmap to an image (creates an image 1/4 the size, with averaging of 4->1) |
279 | */ |
280 | Error generate_mipmaps(bool p_renormalize = false); |
281 | |
282 | enum RoughnessChannel { |
283 | ROUGHNESS_CHANNEL_R, |
284 | ROUGHNESS_CHANNEL_G, |
285 | ROUGHNESS_CHANNEL_B, |
286 | ROUGHNESS_CHANNEL_A, |
287 | ROUGHNESS_CHANNEL_L, |
288 | }; |
289 | |
290 | Error generate_mipmap_roughness(RoughnessChannel p_roughness_channel, const Ref<Image> &p_normal_map); |
291 | |
292 | void clear_mipmaps(); |
293 | void normalize(); //for normal maps |
294 | |
295 | /** |
296 | * Creates new internal image data of a given size and format. Current image will be lost. |
297 | */ |
298 | void initialize_data(int p_width, int p_height, bool p_use_mipmaps, Format p_format); |
299 | void initialize_data(int p_width, int p_height, bool p_use_mipmaps, Format p_format, const Vector<uint8_t> &p_data); |
300 | void initialize_data(const char **p_xpm); |
301 | |
302 | /** |
303 | * returns true when the image is empty (0,0) in size |
304 | */ |
305 | bool is_empty() const; |
306 | |
307 | Vector<uint8_t> get_data() const; |
308 | |
309 | Error load(const String &p_path); |
310 | static Ref<Image> load_from_file(const String &p_path); |
311 | Error save_png(const String &p_path) const; |
312 | Error save_jpg(const String &p_path, float p_quality = 0.75) const; |
313 | Vector<uint8_t> save_png_to_buffer() const; |
314 | Vector<uint8_t> save_jpg_to_buffer(float p_quality = 0.75) const; |
315 | Vector<uint8_t> save_exr_to_buffer(bool p_grayscale) const; |
316 | Error save_exr(const String &p_path, bool p_grayscale) const; |
317 | Error save_webp(const String &p_path, const bool p_lossy = false, const float p_quality = 0.75f) const; |
318 | Vector<uint8_t> save_webp_to_buffer(const bool p_lossy = false, const float p_quality = 0.75f) const; |
319 | |
320 | static Ref<Image> create_empty(int p_width, int p_height, bool p_use_mipmaps, Format p_format); |
321 | static Ref<Image> create_from_data(int p_width, int p_height, bool p_use_mipmaps, Format p_format, const Vector<uint8_t> &p_data); |
322 | void set_data(int p_width, int p_height, bool p_use_mipmaps, Format p_format, const Vector<uint8_t> &p_data); |
323 | |
324 | /** |
325 | * create an empty image |
326 | */ |
327 | Image() {} |
328 | /** |
329 | * create an empty image of a specific size and format |
330 | */ |
331 | Image(int p_width, int p_height, bool p_use_mipmaps, Format p_format); |
332 | /** |
333 | * import an image of a specific size and format from a pointer |
334 | */ |
335 | Image(int p_width, int p_height, bool p_mipmaps, Format p_format, const Vector<uint8_t> &p_data); |
336 | |
337 | ~Image() {} |
338 | |
339 | enum AlphaMode { |
340 | ALPHA_NONE, |
341 | ALPHA_BIT, |
342 | ALPHA_BLEND |
343 | }; |
344 | |
345 | AlphaMode detect_alpha() const; |
346 | bool is_invisible() const; |
347 | |
348 | static int get_format_pixel_size(Format p_format); |
349 | static int get_format_pixel_rshift(Format p_format); |
350 | static int get_format_block_size(Format p_format); |
351 | static void get_format_min_pixel_size(Format p_format, int &r_w, int &r_h); |
352 | |
353 | static int get_image_data_size(int p_width, int p_height, Format p_format, bool p_mipmaps = false); |
354 | static int get_image_required_mipmaps(int p_width, int p_height, Format p_format); |
355 | static Size2i get_image_mipmap_size(int p_width, int p_height, Format p_format, int p_mipmap); |
356 | static int get_image_mipmap_offset(int p_width, int p_height, Format p_format, int p_mipmap); |
357 | static int get_image_mipmap_offset_and_dimensions(int p_width, int p_height, Format p_format, int p_mipmap, int &r_w, int &r_h); |
358 | |
359 | enum CompressMode { |
360 | COMPRESS_S3TC, |
361 | COMPRESS_ETC, |
362 | COMPRESS_ETC2, |
363 | COMPRESS_BPTC, |
364 | COMPRESS_ASTC, |
365 | COMPRESS_MAX, |
366 | }; |
367 | enum CompressSource { |
368 | COMPRESS_SOURCE_GENERIC, |
369 | COMPRESS_SOURCE_SRGB, |
370 | COMPRESS_SOURCE_NORMAL, |
371 | COMPRESS_SOURCE_MAX, |
372 | }; |
373 | |
374 | Error compress(CompressMode p_mode, CompressSource p_source = COMPRESS_SOURCE_GENERIC, ASTCFormat p_astc_format = ASTC_FORMAT_4x4); |
375 | Error compress_from_channels(CompressMode p_mode, UsedChannels p_channels, ASTCFormat p_astc_format = ASTC_FORMAT_4x4); |
376 | Error decompress(); |
377 | bool is_compressed() const; |
378 | |
379 | void fix_alpha_edges(); |
380 | void premultiply_alpha(); |
381 | void srgb_to_linear(); |
382 | void normal_map_to_xy(); |
383 | Ref<Image> rgbe_to_srgb(); |
384 | Ref<Image> get_image_from_mipmap(int p_mipamp) const; |
385 | void bump_map_to_normal_map(float bump_scale = 1.0); |
386 | |
387 | void blit_rect(const Ref<Image> &p_src, const Rect2i &p_src_rect, const Point2i &p_dest); |
388 | void blit_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, const Rect2i &p_src_rect, const Point2i &p_dest); |
389 | void blend_rect(const Ref<Image> &p_src, const Rect2i &p_src_rect, const Point2i &p_dest); |
390 | void blend_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, const Rect2i &p_src_rect, const Point2i &p_dest); |
391 | void fill(const Color &p_color); |
392 | void fill_rect(const Rect2i &p_rect, const Color &p_color); |
393 | |
394 | Rect2i get_used_rect() const; |
395 | Ref<Image> get_region(const Rect2i &p_area) const; |
396 | |
397 | static void set_compress_bc_func(void (*p_compress_func)(Image *, UsedChannels)); |
398 | static void set_compress_bptc_func(void (*p_compress_func)(Image *, UsedChannels)); |
399 | static String get_format_name(Format p_format); |
400 | |
401 | Error load_png_from_buffer(const Vector<uint8_t> &p_array); |
402 | Error load_jpg_from_buffer(const Vector<uint8_t> &p_array); |
403 | Error load_webp_from_buffer(const Vector<uint8_t> &p_array); |
404 | Error load_tga_from_buffer(const Vector<uint8_t> &p_array); |
405 | Error load_bmp_from_buffer(const Vector<uint8_t> &p_array); |
406 | Error load_ktx_from_buffer(const Vector<uint8_t> &p_array); |
407 | |
408 | Error load_svg_from_buffer(const Vector<uint8_t> &p_array, float scale = 1.0); |
409 | Error load_svg_from_string(const String &p_svg_str, float scale = 1.0); |
410 | |
411 | void convert_rg_to_ra_rgba8(); |
412 | void convert_ra_rgba8_to_rg(); |
413 | void convert_rgba8_to_bgra8(); |
414 | |
415 | Image(const uint8_t *p_mem_png_jpg, int p_len = -1); |
416 | Image(const char **p_xpm); |
417 | |
418 | virtual Ref<Resource> duplicate(bool p_subresources = false) const override; |
419 | |
420 | UsedChannels detect_used_channels(CompressSource p_source = COMPRESS_SOURCE_GENERIC) const; |
421 | void optimize_channels(); |
422 | |
423 | Color get_pixelv(const Point2i &p_point) const; |
424 | Color get_pixel(int p_x, int p_y) const; |
425 | void set_pixelv(const Point2i &p_point, const Color &p_color); |
426 | void set_pixel(int p_x, int p_y, const Color &p_color); |
427 | |
428 | void adjust_bcs(float p_brightness, float p_contrast, float p_saturation); |
429 | |
430 | void set_as_black(); |
431 | |
432 | void copy_internals_from(const Ref<Image> &p_image) { |
433 | ERR_FAIL_COND_MSG(p_image.is_null(), "It's not a reference to a valid Image object." ); |
434 | format = p_image->format; |
435 | width = p_image->width; |
436 | height = p_image->height; |
437 | mipmaps = p_image->mipmaps; |
438 | data = p_image->data; |
439 | } |
440 | |
441 | Dictionary compute_image_metrics(const Ref<Image> p_compared_image, bool p_luma_metric = true); |
442 | }; |
443 | |
444 | VARIANT_ENUM_CAST(Image::Format) |
445 | VARIANT_ENUM_CAST(Image::Interpolation) |
446 | VARIANT_ENUM_CAST(Image::CompressMode) |
447 | VARIANT_ENUM_CAST(Image::CompressSource) |
448 | VARIANT_ENUM_CAST(Image::UsedChannels) |
449 | VARIANT_ENUM_CAST(Image::AlphaMode) |
450 | VARIANT_ENUM_CAST(Image::RoughnessChannel) |
451 | VARIANT_ENUM_CAST(Image::ASTCFormat) |
452 | |
453 | #endif // IMAGE_H |
454 | |