From 4f9e101cf64df1ffa8f6e12785fe814de4e11790 Mon Sep 17 00:00:00 2001 From: BlueCube3310 <53150244+BlueCube3310@users.noreply.github.com> Date: Fri, 11 Oct 2024 11:51:44 +0200 Subject: [PATCH] Clean up Image --- core/io/image.cpp | 220 ++++++++++++++++++++++------------------ core/io/image.h | 251 +++++++++++++++++++++------------------------- 2 files changed, 235 insertions(+), 236 deletions(-) diff --git a/core/io/image.cpp b/core/io/image.cpp index aa391b77dd4..2617514fa87 100644 --- a/core/io/image.cpp +++ b/core/io/image.cpp @@ -44,24 +44,24 @@ #include const char *Image::format_names[Image::FORMAT_MAX] = { - "Lum8", //luminance - "LumAlpha8", //luminance-alpha + "Lum8", + "LumAlpha8", "Red8", "RedGreen", "RGB8", "RGBA8", "RGBA4444", - "RGBA5551", - "RFloat", //float + "RGBA5551", // Actually RGB565, kept as RGBA5551 for compatibility. + "RFloat", "RGFloat", "RGBFloat", "RGBAFloat", - "RHalf", //half float + "RHalf", "RGHalf", "RGBHalf", "RGBAHalf", "RGBE9995", - "DXT1 RGB8", //s3tc + "DXT1 RGB8", "DXT3 RGBA8", "DXT5 RGBA8", "RGTC Red8", @@ -69,9 +69,9 @@ const char *Image::format_names[Image::FORMAT_MAX] = { "BPTC_RGBA", "BPTC_RGBF", "BPTC_RGBFU", - "ETC", //etc1 - "ETC2_R11", //etc2 - "ETC2_R11S", //signed", NOT srgb. + "ETC", + "ETC2_R11", + "ETC2_R11S", "ETC2_RG11", "ETC2_RG11S", "ETC2_RGB8", @@ -85,17 +85,60 @@ const char *Image::format_names[Image::FORMAT_MAX] = { "ASTC_8x8_HDR", }; +// External saver function pointers. + SavePNGFunc Image::save_png_func = nullptr; SaveJPGFunc Image::save_jpg_func = nullptr; SaveEXRFunc Image::save_exr_func = nullptr; +SaveWebPFunc Image::save_webp_func = nullptr; SavePNGBufferFunc Image::save_png_buffer_func = nullptr; -SaveEXRBufferFunc Image::save_exr_buffer_func = nullptr; SaveJPGBufferFunc Image::save_jpg_buffer_func = nullptr; - -SaveWebPFunc Image::save_webp_func = nullptr; +SaveEXRBufferFunc Image::save_exr_buffer_func = nullptr; SaveWebPBufferFunc Image::save_webp_buffer_func = nullptr; +// External loader function pointers. + +ImageMemLoadFunc Image::_png_mem_loader_func = nullptr; +ImageMemLoadFunc Image::_png_mem_unpacker_func = nullptr; +ImageMemLoadFunc Image::_jpg_mem_loader_func = nullptr; +ImageMemLoadFunc Image::_webp_mem_loader_func = nullptr; +ImageMemLoadFunc Image::_tga_mem_loader_func = nullptr; +ImageMemLoadFunc Image::_bmp_mem_loader_func = nullptr; +ScalableImageMemLoadFunc Image::_svg_scalable_mem_loader_func = nullptr; +ImageMemLoadFunc Image::_ktx_mem_loader_func = nullptr; + +// External VRAM compression function pointers. + +void (*Image::_image_compress_bc_func)(Image *, Image::UsedChannels) = nullptr; +void (*Image::_image_compress_bptc_func)(Image *, Image::UsedChannels) = nullptr; +void (*Image::_image_compress_etc1_func)(Image *) = nullptr; +void (*Image::_image_compress_etc2_func)(Image *, Image::UsedChannels) = nullptr; +void (*Image::_image_compress_astc_func)(Image *, Image::ASTCFormat) = nullptr; + +Error (*Image::_image_compress_bptc_rd_func)(Image *, Image::UsedChannels) = nullptr; +Error (*Image::_image_compress_bc_rd_func)(Image *, Image::UsedChannels) = nullptr; + +// External VRAM decompression function pointers. + +void (*Image::_image_decompress_bc)(Image *) = nullptr; +void (*Image::_image_decompress_bptc)(Image *) = nullptr; +void (*Image::_image_decompress_etc1)(Image *) = nullptr; +void (*Image::_image_decompress_etc2)(Image *) = nullptr; +void (*Image::_image_decompress_astc)(Image *) = nullptr; + +// External packer function pointers. + +Vector (*Image::webp_lossy_packer)(const Ref &, float) = nullptr; +Vector (*Image::webp_lossless_packer)(const Ref &) = nullptr; +Vector (*Image::png_packer)(const Ref &) = nullptr; +Vector (*Image::basis_universal_packer)(const Ref &, Image::UsedChannels) = nullptr; + +Ref (*Image::webp_unpacker)(const Vector &) = nullptr; +Ref (*Image::png_unpacker)(const Vector &) = nullptr; +Ref (*Image::basis_universal_unpacker)(const Vector &) = nullptr; +Ref (*Image::basis_universal_unpacker_ptr)(const uint8_t *, int) = nullptr; + void Image::_put_pixelb(int p_x, int p_y, uint32_t p_pixel_size, uint8_t *p_data, const uint8_t *p_pixel) { uint32_t ofs = (p_y * width + p_x) * p_pixel_size; memcpy(p_data + ofs, p_pixel, p_pixel_size); @@ -109,9 +152,9 @@ void Image::_get_pixelb(int p_x, int p_y, uint32_t p_pixel_size, const uint8_t * int Image::get_format_pixel_size(Format p_format) { switch (p_format) { case FORMAT_L8: - return 1; //luminance + return 1; case FORMAT_LA8: - return 2; //luminance-alpha + return 2; case FORMAT_R8: return 1; case FORMAT_RG8: @@ -125,7 +168,7 @@ int Image::get_format_pixel_size(Format p_format) { case FORMAT_RGB565: return 2; case FORMAT_RF: - return 4; //float + return 4; case FORMAT_RGF: return 8; case FORMAT_RGBF: @@ -133,7 +176,7 @@ int Image::get_format_pixel_size(Format p_format) { case FORMAT_RGBAF: return 16; case FORMAT_RH: - return 2; //half float + return 2; case FORMAT_RGH: return 4; case FORMAT_RGBH: @@ -143,27 +186,27 @@ int Image::get_format_pixel_size(Format p_format) { case FORMAT_RGBE9995: return 4; case FORMAT_DXT1: - return 1; //s3tc bc1 + return 1; case FORMAT_DXT3: - return 1; //bc2 + return 1; case FORMAT_DXT5: - return 1; //bc3 + return 1; case FORMAT_RGTC_R: - return 1; //bc4 + return 1; case FORMAT_RGTC_RG: - return 1; //bc5 + return 1; case FORMAT_BPTC_RGBA: - return 1; //btpc bc6h + return 1; case FORMAT_BPTC_RGBF: - return 1; //float / + return 1; case FORMAT_BPTC_RGBFU: - return 1; //unsigned float + return 1; case FORMAT_ETC: - return 1; //etc1 + return 1; case FORMAT_ETC2_R11: - return 1; //etc2 + return 1; case FORMAT_ETC2_R11S: - return 1; //signed: return 1; NOT srgb. + return 1; case FORMAT_ETC2_RG11: return 1; case FORMAT_ETC2_RG11S: @@ -194,12 +237,11 @@ int Image::get_format_pixel_size(Format p_format) { void Image::get_format_min_pixel_size(Format p_format, int &r_w, int &r_h) { switch (p_format) { - case FORMAT_DXT1: //s3tc bc1 - case FORMAT_DXT3: //bc2 - case FORMAT_DXT5: //bc3 - case FORMAT_RGTC_R: //bc4 - case FORMAT_RGTC_RG: { //bc5 case case FORMAT_DXT1: - + case FORMAT_DXT1: + case FORMAT_DXT3: + case FORMAT_DXT5: + case FORMAT_RGTC_R: + case FORMAT_RGTC_RG: { r_w = 4; r_h = 4; } break; @@ -213,8 +255,8 @@ void Image::get_format_min_pixel_size(Format p_format, int &r_w, int &r_h) { r_w = 4; r_h = 4; } break; - case FORMAT_ETC2_R11: //etc2 - case FORMAT_ETC2_R11S: //signed: NOT srgb. + case FORMAT_ETC2_R11: + case FORMAT_ETC2_R11S: case FORMAT_ETC2_RG11: case FORMAT_ETC2_RG11S: case FORMAT_ETC2_RGB8: @@ -224,19 +266,16 @@ void Image::get_format_min_pixel_size(Format p_format, int &r_w, int &r_h) { case FORMAT_DXT5_RA_AS_RG: { r_w = 4; r_h = 4; - } break; case FORMAT_ASTC_4x4: case FORMAT_ASTC_4x4_HDR: { r_w = 4; r_h = 4; - } break; case FORMAT_ASTC_8x8: case FORMAT_ASTC_8x8_HDR: { r_w = 8; r_h = 8; - } break; default: { r_w = 1; @@ -257,12 +296,11 @@ int Image::get_format_pixel_rshift(Format p_format) { int Image::get_format_block_size(Format p_format) { switch (p_format) { - case FORMAT_DXT1: //s3tc bc1 - case FORMAT_DXT3: //bc2 - case FORMAT_DXT5: //bc3 - case FORMAT_RGTC_R: //bc4 - case FORMAT_RGTC_RG: { //bc5 case case FORMAT_DXT1: - + case FORMAT_DXT1: + case FORMAT_DXT3: + case FORMAT_DXT5: + case FORMAT_RGTC_R: + case FORMAT_RGTC_RG: { return 4; } case FORMAT_ETC: { @@ -273,17 +311,15 @@ int Image::get_format_block_size(Format p_format) { case FORMAT_BPTC_RGBFU: { return 4; } - case FORMAT_ETC2_R11: //etc2 - case FORMAT_ETC2_R11S: //signed: NOT srgb. + case FORMAT_ETC2_R11: + case FORMAT_ETC2_R11S: case FORMAT_ETC2_RG11: case FORMAT_ETC2_RG11S: case FORMAT_ETC2_RGB8: case FORMAT_ETC2_RGBA8: case FORMAT_ETC2_RGB8A1: - case FORMAT_ETC2_RA_AS_RG: //used to make basis universal happy - case FORMAT_DXT5_RA_AS_RG: //used to make basis universal happy - - { + case FORMAT_ETC2_RA_AS_RG: + case FORMAT_DXT5_RA_AS_RG: { return 4; } case FORMAT_ASTC_4x4: @@ -459,7 +495,7 @@ int Image::get_mipmap_count() const { } } -//using template generates perfectly optimized code due to constant expression reduction and unused variable removal present in all compilers +// Using template generates perfectly optimized code due to constant expression reduction and unused variable removal present in all compilers. template static void _convert(int p_width, int p_height, const uint8_t *p_src, uint8_t *p_dst) { constexpr uint32_t max_bytes = MAX(read_bytes, write_bytes); @@ -551,7 +587,7 @@ void Image::convert(Format p_new_format) { ERR_FAIL_MSG("Cannot convert to <-> from compressed formats. Use compress() and decompress() instead."); } else if (!_are_formats_compatible(format, p_new_format)) { - //use put/set pixel which is slower but works with non byte formats + // Use put/set pixel which is slower but works with non-byte formats. Image new_img(width, height, mipmaps, p_new_format); for (int mip = 0; mip < mipmap_count; mip++) { @@ -1694,7 +1730,7 @@ void Image::flip_x() { } } -/// Get mipmap size and offset. +// Get mipmap size and offset. int64_t Image::_get_dst_image_size(int p_width, int p_height, Format p_format, int &r_mipmaps, int p_mipmaps, int *r_mm_width, int *r_mm_height) { // Data offset in mipmaps (including the original texture). int64_t size = 0; @@ -3134,37 +3170,6 @@ void Image::fill_rect(const Rect2i &p_rect, const Color &p_color) { } } -ImageMemLoadFunc Image::_png_mem_loader_func = nullptr; -ImageMemLoadFunc Image::_png_mem_unpacker_func = nullptr; -ImageMemLoadFunc Image::_jpg_mem_loader_func = nullptr; -ImageMemLoadFunc Image::_webp_mem_loader_func = nullptr; -ImageMemLoadFunc Image::_tga_mem_loader_func = nullptr; -ImageMemLoadFunc Image::_bmp_mem_loader_func = nullptr; -ScalableImageMemLoadFunc Image::_svg_scalable_mem_loader_func = nullptr; -ImageMemLoadFunc Image::_ktx_mem_loader_func = nullptr; - -void (*Image::_image_compress_bc_func)(Image *, Image::UsedChannels) = nullptr; -void (*Image::_image_compress_bptc_func)(Image *, Image::UsedChannels) = nullptr; -void (*Image::_image_compress_etc1_func)(Image *) = nullptr; -void (*Image::_image_compress_etc2_func)(Image *, Image::UsedChannels) = nullptr; -void (*Image::_image_compress_astc_func)(Image *, Image::ASTCFormat) = nullptr; -Error (*Image::_image_compress_bptc_rd_func)(Image *, Image::UsedChannels) = nullptr; -Error (*Image::_image_compress_bc_rd_func)(Image *, Image::UsedChannels) = nullptr; -void (*Image::_image_decompress_bc)(Image *) = nullptr; -void (*Image::_image_decompress_bptc)(Image *) = nullptr; -void (*Image::_image_decompress_etc1)(Image *) = nullptr; -void (*Image::_image_decompress_etc2)(Image *) = nullptr; -void (*Image::_image_decompress_astc)(Image *) = nullptr; - -Vector (*Image::webp_lossy_packer)(const Ref &, float) = nullptr; -Vector (*Image::webp_lossless_packer)(const Ref &) = nullptr; -Ref (*Image::webp_unpacker)(const Vector &) = nullptr; -Vector (*Image::png_packer)(const Ref &) = nullptr; -Ref (*Image::png_unpacker)(const Vector &) = nullptr; -Vector (*Image::basis_universal_packer)(const Ref &, Image::UsedChannels) = nullptr; -Ref (*Image::basis_universal_unpacker)(const Vector &) = nullptr; -Ref (*Image::basis_universal_unpacker_ptr)(const uint8_t *, int) = nullptr; - void Image::_set_data(const Dictionary &p_data) { ERR_FAIL_COND(!p_data.has("width")); ERR_FAIL_COND(!p_data.has("height")); @@ -3204,6 +3209,14 @@ Color Image::get_pixelv(const Point2i &p_point) const { return get_pixel(p_point.x, p_point.y); } +void Image::_copy_internals_from(const Image &p_image) { + format = p_image.format; + width = p_image.width; + height = p_image.height; + mipmaps = p_image.mipmaps; + data = p_image.data; +} + Color Image::_get_color_at_ofs(const uint8_t *ptr, uint32_t ofs) const { switch (format) { case FORMAT_L8: { @@ -3643,34 +3656,34 @@ void Image::_bind_methods() { BIND_CONSTANT(MAX_WIDTH); BIND_CONSTANT(MAX_HEIGHT); - BIND_ENUM_CONSTANT(FORMAT_L8); //luminance - BIND_ENUM_CONSTANT(FORMAT_LA8); //luminance-alpha + BIND_ENUM_CONSTANT(FORMAT_L8); + BIND_ENUM_CONSTANT(FORMAT_LA8); BIND_ENUM_CONSTANT(FORMAT_R8); BIND_ENUM_CONSTANT(FORMAT_RG8); BIND_ENUM_CONSTANT(FORMAT_RGB8); BIND_ENUM_CONSTANT(FORMAT_RGBA8); BIND_ENUM_CONSTANT(FORMAT_RGBA4444); BIND_ENUM_CONSTANT(FORMAT_RGB565); - BIND_ENUM_CONSTANT(FORMAT_RF); //float + BIND_ENUM_CONSTANT(FORMAT_RF); BIND_ENUM_CONSTANT(FORMAT_RGF); BIND_ENUM_CONSTANT(FORMAT_RGBF); BIND_ENUM_CONSTANT(FORMAT_RGBAF); - BIND_ENUM_CONSTANT(FORMAT_RH); //half float + BIND_ENUM_CONSTANT(FORMAT_RH); BIND_ENUM_CONSTANT(FORMAT_RGH); BIND_ENUM_CONSTANT(FORMAT_RGBH); BIND_ENUM_CONSTANT(FORMAT_RGBAH); BIND_ENUM_CONSTANT(FORMAT_RGBE9995); - BIND_ENUM_CONSTANT(FORMAT_DXT1); //s3tc bc1 - BIND_ENUM_CONSTANT(FORMAT_DXT3); //bc2 - BIND_ENUM_CONSTANT(FORMAT_DXT5); //bc3 + BIND_ENUM_CONSTANT(FORMAT_DXT1); + BIND_ENUM_CONSTANT(FORMAT_DXT3); + BIND_ENUM_CONSTANT(FORMAT_DXT5); BIND_ENUM_CONSTANT(FORMAT_RGTC_R); BIND_ENUM_CONSTANT(FORMAT_RGTC_RG); - BIND_ENUM_CONSTANT(FORMAT_BPTC_RGBA); //btpc bc6h - BIND_ENUM_CONSTANT(FORMAT_BPTC_RGBF); //float / - BIND_ENUM_CONSTANT(FORMAT_BPTC_RGBFU); //unsigned float - BIND_ENUM_CONSTANT(FORMAT_ETC); //etc1 - BIND_ENUM_CONSTANT(FORMAT_ETC2_R11); //etc2 - BIND_ENUM_CONSTANT(FORMAT_ETC2_R11S); //signed ); NOT srgb. + BIND_ENUM_CONSTANT(FORMAT_BPTC_RGBA); + BIND_ENUM_CONSTANT(FORMAT_BPTC_RGBF); + BIND_ENUM_CONSTANT(FORMAT_BPTC_RGBFU); + BIND_ENUM_CONSTANT(FORMAT_ETC); + BIND_ENUM_CONSTANT(FORMAT_ETC2_R11); + BIND_ENUM_CONSTANT(FORMAT_ETC2_R11S); BIND_ENUM_CONSTANT(FORMAT_ETC2_RG11); BIND_ENUM_CONSTANT(FORMAT_ETC2_RG11S); BIND_ENUM_CONSTANT(FORMAT_ETC2_RGB8); @@ -4177,7 +4190,7 @@ void Image::renormalize_half(uint16_t *p_rgb) { } void Image::renormalize_rgbe9995(uint32_t *p_rgb) { - // Never used + // Never used. } Image::Image(const uint8_t *p_mem_png_jpg, int p_len) { @@ -4210,6 +4223,15 @@ void Image::set_as_black() { memset(data.ptrw(), 0, data.size()); } +void Image::copy_internals_from(const Ref &p_image) { + ERR_FAIL_COND_MSG(p_image.is_null(), "Cannot copy image internals: invalid Image object."); + format = p_image->format; + width = p_image->width; + height = p_image->height; + mipmaps = p_image->mipmaps; + data = p_image->data; +} + Dictionary Image::compute_image_metrics(const Ref p_compared_image, bool p_luma_metric) { // https://github.com/richgel999/bc7enc_rdo/blob/master/LICENSE // @@ -4250,8 +4272,6 @@ Dictionary Image::compute_image_metrics(const Ref p_compared_image, bool } ERR_FAIL_COND_V(err != OK, result); - ERR_FAIL_COND_V(err != OK, result); - ERR_FAIL_COND_V_MSG((compared_image->get_format() >= Image::FORMAT_RH) && (compared_image->get_format() <= Image::FORMAT_RGBE9995), result, "Metrics on HDR images are not supported."); ERR_FAIL_COND_V_MSG((source_image->get_format() >= Image::FORMAT_RH) && (source_image->get_format() <= Image::FORMAT_RGBE9995), result, "Metrics on HDR images are not supported."); diff --git a/core/io/image.h b/core/io/image.h index 78757246e06..3149314ad88 100644 --- a/core/io/image.h +++ b/core/io/image.h @@ -43,12 +43,17 @@ class Image; +// Function pointer prototypes. + typedef Error (*SavePNGFunc)(const String &p_path, const Ref &p_img); typedef Vector (*SavePNGBufferFunc)(const Ref &p_img); + typedef Error (*SaveJPGFunc)(const String &p_path, const Ref &p_img, float p_quality); typedef Vector (*SaveJPGBufferFunc)(const Ref &p_img, float p_quality); + typedef Ref (*ImageMemLoadFunc)(const uint8_t *p_png, int p_size); typedef Ref (*ScalableImageMemLoadFunc)(const uint8_t *p_data, int p_size, float p_scale); + typedef Error (*SaveWebPFunc)(const String &p_path, const Ref &p_img, const bool p_lossy, const float p_quality); typedef Vector (*SaveWebPBufferFunc)(const Ref &p_img, const bool p_lossy, const float p_quality); @@ -59,57 +64,48 @@ class Image : public Resource { GDCLASS(Image, Resource); public: - static SavePNGFunc save_png_func; - static SaveJPGFunc save_jpg_func; - static SaveEXRFunc save_exr_func; - static SavePNGBufferFunc save_png_buffer_func; - static SaveEXRBufferFunc save_exr_buffer_func; - static SaveJPGBufferFunc save_jpg_buffer_func; - static SaveWebPFunc save_webp_func; - static SaveWebPBufferFunc save_webp_buffer_func; - enum { - MAX_WIDTH = (1 << 24), // force a limit somehow - MAX_HEIGHT = (1 << 24), // force a limit somehow - MAX_PIXELS = 268435456 + MAX_WIDTH = (1 << 24), // Force a limit somehow. + MAX_HEIGHT = (1 << 24), // Force a limit somehow. + MAX_PIXELS = 268435456 // 16384 ^ 2 }; enum Format { - FORMAT_L8, //luminance - FORMAT_LA8, //luminance-alpha + FORMAT_L8, // Luminance + FORMAT_LA8, // Luminance-Alpha FORMAT_R8, FORMAT_RG8, FORMAT_RGB8, FORMAT_RGBA8, FORMAT_RGBA4444, FORMAT_RGB565, - FORMAT_RF, //float + FORMAT_RF, // Float FORMAT_RGF, FORMAT_RGBF, FORMAT_RGBAF, - FORMAT_RH, //half float + FORMAT_RH, // Half FORMAT_RGH, FORMAT_RGBH, FORMAT_RGBAH, FORMAT_RGBE9995, - FORMAT_DXT1, //s3tc bc1 - FORMAT_DXT3, //bc2 - FORMAT_DXT5, //bc3 - FORMAT_RGTC_R, - FORMAT_RGTC_RG, - FORMAT_BPTC_RGBA, //btpc bc7 - FORMAT_BPTC_RGBF, //float bc6h - FORMAT_BPTC_RGBFU, //unsigned float bc6hu - FORMAT_ETC, //etc1 - FORMAT_ETC2_R11, //etc2 - FORMAT_ETC2_R11S, //signed, NOT srgb. + FORMAT_DXT1, // BC1 + FORMAT_DXT3, // BC2 + FORMAT_DXT5, // BC3 + FORMAT_RGTC_R, // BC4 + FORMAT_RGTC_RG, // BC5 + FORMAT_BPTC_RGBA, // BC7 + FORMAT_BPTC_RGBF, // BC6 Signed + FORMAT_BPTC_RGBFU, // BC6 Unsigned + FORMAT_ETC, // ETC1 + FORMAT_ETC2_R11, + FORMAT_ETC2_R11S, // Signed, NOT srgb. FORMAT_ETC2_RG11, - FORMAT_ETC2_RG11S, + FORMAT_ETC2_RG11S, // Signed, NOT srgb. FORMAT_ETC2_RGB8, FORMAT_ETC2_RGBA8, FORMAT_ETC2_RGB8A1, - FORMAT_ETC2_RA_AS_RG, //used to make basis universal happy - FORMAT_DXT5_RA_AS_RG, //used to make basis universal happy + FORMAT_ETC2_RA_AS_RG, // ETC2 RGBA with a RA-RG swizzle for normal maps. + FORMAT_DXT5_RA_AS_RG, // BC3 with a RA-RG swizzle for normal maps. FORMAT_ASTC_4x4, FORMAT_ASTC_4x4_HDR, FORMAT_ASTC_8x8, @@ -118,17 +114,18 @@ public: }; static const char *format_names[FORMAT_MAX]; + enum Interpolation { INTERPOLATE_NEAREST, INTERPOLATE_BILINEAR, INTERPOLATE_CUBIC, INTERPOLATE_TRILINEAR, INTERPOLATE_LANCZOS, - /* INTERPOLATE_TRICUBIC, */ - /* INTERPOLATE GAUSS */ + // INTERPOLATE_TRICUBIC, + // INTERPOLATE_GAUSS }; - //this is used for compression + // Used for obtaining optimal compression quality. enum UsedChannels { USED_CHANNELS_L, USED_CHANNELS_LA, @@ -137,13 +134,66 @@ public: USED_CHANNELS_RGB, USED_CHANNELS_RGBA, }; - //some functions provided by something else + // ASTC supports block formats other than 4x4. enum ASTCFormat { ASTC_FORMAT_4x4, ASTC_FORMAT_8x8, }; + enum RoughnessChannel { + ROUGHNESS_CHANNEL_R, + ROUGHNESS_CHANNEL_G, + ROUGHNESS_CHANNEL_B, + ROUGHNESS_CHANNEL_A, + ROUGHNESS_CHANNEL_L, + }; + + enum Image3DValidateError { + VALIDATE_3D_OK, + VALIDATE_3D_ERR_IMAGE_EMPTY, + VALIDATE_3D_ERR_MISSING_IMAGES, + VALIDATE_3D_ERR_EXTRA_IMAGES, + VALIDATE_3D_ERR_IMAGE_SIZE_MISMATCH, + VALIDATE_3D_ERR_IMAGE_FORMAT_MISMATCH, + VALIDATE_3D_ERR_IMAGE_HAS_MIPMAPS, + }; + + enum CompressMode { + COMPRESS_S3TC, + COMPRESS_ETC, + COMPRESS_ETC2, + COMPRESS_BPTC, + COMPRESS_ASTC, + COMPRESS_MAX, + }; + + enum CompressSource { + COMPRESS_SOURCE_GENERIC, + COMPRESS_SOURCE_SRGB, + COMPRESS_SOURCE_NORMAL, + COMPRESS_SOURCE_MAX, + }; + + enum AlphaMode { + ALPHA_NONE, + ALPHA_BIT, + ALPHA_BLEND + }; + + // External saver function pointers. + + static SavePNGFunc save_png_func; + static SaveJPGFunc save_jpg_func; + static SaveEXRFunc save_exr_func; + static SaveWebPFunc save_webp_func; + static SavePNGBufferFunc save_png_buffer_func; + static SaveEXRBufferFunc save_exr_buffer_func; + static SaveJPGBufferFunc save_jpg_buffer_func; + static SaveWebPBufferFunc save_webp_buffer_func; + + // External loader function pointers. + static ImageMemLoadFunc _png_mem_loader_func; static ImageMemLoadFunc _png_mem_unpacker_func; static ImageMemLoadFunc _jpg_mem_loader_func; @@ -153,6 +203,8 @@ public: static ScalableImageMemLoadFunc _svg_scalable_mem_loader_func; static ImageMemLoadFunc _ktx_mem_loader_func; + // External VRAM compression function pointers. + static void (*_image_compress_bc_func)(Image *, UsedChannels p_channels); static void (*_image_compress_bptc_func)(Image *, UsedChannels p_channels); static void (*_image_compress_etc1_func)(Image *); @@ -162,24 +214,26 @@ public: static Error (*_image_compress_bptc_rd_func)(Image *, UsedChannels p_channels); static Error (*_image_compress_bc_rd_func)(Image *, UsedChannels p_channels); + // External VRAM decompression function pointers. + static void (*_image_decompress_bc)(Image *); static void (*_image_decompress_bptc)(Image *); static void (*_image_decompress_etc1)(Image *); static void (*_image_decompress_etc2)(Image *); static void (*_image_decompress_astc)(Image *); + // External packer function pointers. + static Vector (*webp_lossy_packer)(const Ref &p_image, float p_quality); static Vector (*webp_lossless_packer)(const Ref &p_image); - static Ref (*webp_unpacker)(const Vector &p_buffer); static Vector (*png_packer)(const Ref &p_image); - static Ref (*png_unpacker)(const Vector &p_buffer); static Vector (*basis_universal_packer)(const Ref &p_image, UsedChannels p_channels); + + static Ref (*webp_unpacker)(const Vector &p_buffer); + static Ref (*png_unpacker)(const Vector &p_buffer); static Ref (*basis_universal_unpacker)(const Vector &p_buffer); static Ref (*basis_universal_unpacker_ptr)(const uint8_t *p_data, int p_size); - _FORCE_INLINE_ Color _get_color_at_ofs(const uint8_t *ptr, uint32_t ofs) const; - _FORCE_INLINE_ void _set_color_at_ofs(uint8_t *ptr, uint32_t ofs, const Color &p_color); - protected: static void _bind_methods(); @@ -190,15 +244,12 @@ private: int height = 0; bool mipmaps = false; - void _copy_internals_from(const Image &p_image) { - format = p_image.format; - width = p_image.width; - height = p_image.height; - mipmaps = p_image.mipmaps; - data = p_image.data; - } + void _copy_internals_from(const Image &p_image); - _FORCE_INLINE_ void _get_mipmap_offset_and_size(int p_mipmap, int64_t &r_offset, int &r_width, int &r_height) const; //get where the mipmap begins in data + _FORCE_INLINE_ Color _get_color_at_ofs(const uint8_t *ptr, uint32_t ofs) const; + _FORCE_INLINE_ void _set_color_at_ofs(uint8_t *ptr, uint32_t ofs, const Color &p_color); + + _FORCE_INLINE_ void _get_mipmap_offset_and_size(int p_mipmap, int64_t &r_offset, int &r_width, int &r_height) const; // Get where the mipmap begins in data. static int64_t _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); bool _can_modify(Format p_format) const; @@ -225,52 +276,32 @@ private: static void renormalize_rgbe9995(uint32_t *p_rgb); public: - int get_width() const; ///< Get image width - int get_height() const; ///< Get image height + int get_width() const; + int get_height() const; Size2i get_size() const; bool has_mipmaps() const; int get_mipmap_count() const; - /** - * Convert the image to another format, conversion only to raw byte format - */ + // Convert the image to another format, conversion only to raw byte format. void convert(Format p_new_format); - /** - * Get the current image format. - */ Format get_format() const; - /** - * Get where the mipmap begins in data. - */ + // Get where the mipmap begins in data. int64_t get_mipmap_offset(int p_mipmap) const; void get_mipmap_offset_and_size(int p_mipmap, int64_t &r_ofs, int64_t &r_size) const; void get_mipmap_offset_size_and_dimensions(int p_mipmap, int64_t &r_ofs, int64_t &r_size, int &w, int &h) const; - enum Image3DValidateError { - VALIDATE_3D_OK, - VALIDATE_3D_ERR_IMAGE_EMPTY, - VALIDATE_3D_ERR_MISSING_IMAGES, - VALIDATE_3D_ERR_EXTRA_IMAGES, - VALIDATE_3D_ERR_IMAGE_SIZE_MISMATCH, - VALIDATE_3D_ERR_IMAGE_FORMAT_MISMATCH, - VALIDATE_3D_ERR_IMAGE_HAS_MIPMAPS, - }; - static Image3DValidateError validate_3d_image(Format p_format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector> &p_images); static String get_3d_image_validation_error_text(Image3DValidateError p_error); - /** - * Resize the image, using the preferred interpolation method. - */ + // Resize the image, using the preferred interpolation method. void resize_to_po2(bool p_square = false, Interpolation p_interpolation = INTERPOLATE_BILINEAR); void resize(int p_width, int p_height, Interpolation p_interpolation = INTERPOLATE_BILINEAR); void shrink_x2(); bool is_size_po2() const; - /** - * Crop the image to a specific size, if larger, then the image is filled by black - */ + + // Crop the image to a specific size, if larger, then the image is filled by black. void crop_from_point(int p_x, int p_y, int p_width, int p_height); void crop(int p_width, int p_height); @@ -280,34 +311,20 @@ public: void flip_x(); void flip_y(); - /** - * Generate a mipmap to an image (creates an image 1/4 the size, with averaging of 4->1) - */ + // Generate a mipmap chain of an image (creates an image 1/4 the size, with averaging of 4->1). Error generate_mipmaps(bool p_renormalize = false); - enum RoughnessChannel { - ROUGHNESS_CHANNEL_R, - ROUGHNESS_CHANNEL_G, - ROUGHNESS_CHANNEL_B, - ROUGHNESS_CHANNEL_A, - ROUGHNESS_CHANNEL_L, - }; - Error generate_mipmap_roughness(RoughnessChannel p_roughness_channel, const Ref &p_normal_map); void clear_mipmaps(); - void normalize(); //for normal maps + void normalize(); - /** - * Creates new internal image data of a given size and format. Current image will be lost. - */ + // Creates new internal image data of a given size and format. Current image will be lost. void initialize_data(int p_width, int p_height, bool p_use_mipmaps, Format p_format); void initialize_data(int p_width, int p_height, bool p_use_mipmaps, Format p_format, const Vector &p_data); void initialize_data(const char **p_xpm); - /** - * returns true when the image is empty (0,0) in size - */ + // Returns true when the image is empty (0,0) in size. bool is_empty() const; Vector get_data() const; @@ -327,27 +344,14 @@ public: static Ref create_from_data(int p_width, int p_height, bool p_use_mipmaps, Format p_format, const Vector &p_data); void set_data(int p_width, int p_height, bool p_use_mipmaps, Format p_format, const Vector &p_data); - /** - * create an empty image - */ - Image() {} - /** - * create an empty image of a specific size and format - */ - Image(int p_width, int p_height, bool p_use_mipmaps, Format p_format); - /** - * import an image of a specific size and format from a pointer - */ - Image(int p_width, int p_height, bool p_mipmaps, Format p_format, const Vector &p_data); + Image() = default; // Create an empty image. + Image(int p_width, int p_height, bool p_use_mipmaps, Format p_format); // Create an empty image of a specific size and format. + Image(int p_width, int p_height, bool p_mipmaps, Format p_format, const Vector &p_data); // Import an image of a specific size and format from a byte vector. + Image(const uint8_t *p_mem_png_jpg, int p_len = -1); // Import either a png or jpg from a pointer. + Image(const char **p_xpm); // Import an XPM image. ~Image() {} - enum AlphaMode { - ALPHA_NONE, - ALPHA_BIT, - ALPHA_BLEND - }; - AlphaMode detect_alpha() const; bool is_invisible() const; @@ -362,21 +366,6 @@ public: static int64_t get_image_mipmap_offset(int p_width, int p_height, Format p_format, int p_mipmap); static int64_t get_image_mipmap_offset_and_dimensions(int p_width, int p_height, Format p_format, int p_mipmap, int &r_w, int &r_h); - enum CompressMode { - COMPRESS_S3TC, - COMPRESS_ETC, - COMPRESS_ETC2, - COMPRESS_BPTC, - COMPRESS_ASTC, - COMPRESS_MAX, - }; - enum CompressSource { - COMPRESS_SOURCE_GENERIC, - COMPRESS_SOURCE_SRGB, - COMPRESS_SOURCE_NORMAL, - COMPRESS_SOURCE_MAX, - }; - Error compress(CompressMode p_mode, CompressSource p_source = COMPRESS_SOURCE_GENERIC, ASTCFormat p_astc_format = ASTC_FORMAT_4x4); Error compress_from_channels(CompressMode p_mode, UsedChannels p_channels, ASTCFormat p_astc_format = ASTC_FORMAT_4x4); Error decompress(); @@ -422,9 +411,6 @@ public: void convert_ra_rgba8_to_rg(); void convert_rgba8_to_bgra8(); - Image(const uint8_t *p_mem_png_jpg, int p_len = -1); - Image(const char **p_xpm); - virtual Ref duplicate(bool p_subresources = false) const override; UsedChannels detect_used_channels(CompressSource p_source = COMPRESS_SOURCE_GENERIC) const; @@ -443,14 +429,7 @@ public: void set_as_black(); - void copy_internals_from(const Ref &p_image) { - ERR_FAIL_COND_MSG(p_image.is_null(), "Cannot copy image internals: invalid Image object."); - format = p_image->format; - width = p_image->width; - height = p_image->height; - mipmaps = p_image->mipmaps; - data = p_image->data; - } + void copy_internals_from(const Ref &p_image); Dictionary compute_image_metrics(const Ref p_compared_image, bool p_luma_metric = true); };