diff options
Diffstat (limited to 'core/io/image.cpp')
-rw-r--r-- | core/io/image.cpp | 286 |
1 files changed, 227 insertions, 59 deletions
diff --git a/core/io/image.cpp b/core/io/image.cpp index 4b1188ad47..f6065d984b 100644 --- a/core/io/image.cpp +++ b/core/io/image.cpp @@ -30,6 +30,7 @@ #include "image.h" +#include "core/config/project_settings.h" #include "core/error/error_list.h" #include "core/error/error_macros.h" #include "core/io/image_loader.h" @@ -300,10 +301,10 @@ int Image::get_format_block_size(Format p_format) { return 1; } -void Image::_get_mipmap_offset_and_size(int p_mipmap, int &r_offset, int &r_width, int &r_height) const { +void Image::_get_mipmap_offset_and_size(int p_mipmap, int64_t &r_offset, int &r_width, int &r_height) const { int w = width; int h = height; - int ofs = 0; + int64_t ofs = 0; int pixel_size = get_format_pixel_size(format); int pixel_rshift = get_format_pixel_rshift(format); @@ -315,7 +316,7 @@ void Image::_get_mipmap_offset_and_size(int p_mipmap, int &r_offset, int &r_widt int bw = w % block != 0 ? w + (block - w % block) : w; int bh = h % block != 0 ? h + (block - h % block) : h; - int s = bw * bh; + int64_t s = bw * bh; s *= pixel_size; s >>= pixel_rshift; @@ -329,37 +330,30 @@ void Image::_get_mipmap_offset_and_size(int p_mipmap, int &r_offset, int &r_widt r_height = h; } -int Image::get_mipmap_offset(int p_mipmap) const { +int64_t Image::get_mipmap_offset(int p_mipmap) const { ERR_FAIL_INDEX_V(p_mipmap, get_mipmap_count() + 1, -1); - int ofs, w, h; + int64_t ofs; + int w, h; _get_mipmap_offset_and_size(p_mipmap, ofs, w, h); return ofs; } -int Image::get_mipmap_byte_size(int p_mipmap) const { - ERR_FAIL_INDEX_V(p_mipmap, get_mipmap_count() + 1, -1); - - int ofs, w, h; - _get_mipmap_offset_and_size(p_mipmap, ofs, w, h); - int ofs2; - _get_mipmap_offset_and_size(p_mipmap + 1, ofs2, w, h); - return ofs2 - ofs; -} - -void Image::get_mipmap_offset_and_size(int p_mipmap, int &r_ofs, int &r_size) const { - int ofs, w, h; +void Image::get_mipmap_offset_and_size(int p_mipmap, int64_t &r_ofs, int64_t &r_size) const { + int64_t ofs; + int w, h; _get_mipmap_offset_and_size(p_mipmap, ofs, w, h); - int ofs2; + int64_t ofs2; _get_mipmap_offset_and_size(p_mipmap + 1, ofs2, w, h); r_ofs = ofs; r_size = ofs2 - ofs; } -void Image::get_mipmap_offset_size_and_dimensions(int p_mipmap, int &r_ofs, int &r_size, int &w, int &h) const { - int ofs; +void Image::get_mipmap_offset_size_and_dimensions(int p_mipmap, int64_t &r_ofs, int64_t &r_size, int &w, int &h) const { + int64_t ofs; _get_mipmap_offset_and_size(p_mipmap, ofs, w, h); - int ofs2, w2, h2; + int64_t ofs2; + int w2, h2; _get_mipmap_offset_and_size(p_mipmap + 1, ofs2, w2, h2); r_ofs = ofs; r_size = ofs2 - ofs; @@ -508,6 +502,38 @@ static void _convert(int p_width, int p_height, const uint8_t *p_src, uint8_t *p } } +template <typename T, uint32_t read_channels, uint32_t write_channels, T def_zero, T def_one> +static void _convert_fast(int p_width, int p_height, const T *p_src, T *p_dst) { + uint32_t dst_count = 0; + uint32_t src_count = 0; + + const int resolution = p_width * p_height; + + for (int i = 0; i < resolution; i++) { + memcpy(p_dst + dst_count, p_src + src_count, MIN(read_channels, write_channels) * sizeof(T)); + + if constexpr (write_channels > read_channels) { + const T def_value[4] = { def_zero, def_zero, def_zero, def_one }; + memcpy(p_dst + dst_count + read_channels, &def_value[read_channels], (write_channels - read_channels) * sizeof(T)); + } + + dst_count += write_channels; + src_count += read_channels; + } +} + +static bool _are_formats_compatible(Image::Format p_format0, Image::Format p_format1) { + if (p_format0 <= Image::FORMAT_RGBA8 && p_format1 <= Image::FORMAT_RGBA8) { + return true; + } else if (p_format0 <= Image::FORMAT_RGBAH && p_format0 >= Image::FORMAT_RH && p_format1 <= Image::FORMAT_RGBAH && p_format1 >= Image::FORMAT_RH) { + return true; + } else if (p_format0 <= Image::FORMAT_RGBAF && p_format0 >= Image::FORMAT_RF && p_format1 <= Image::FORMAT_RGBAF && p_format1 >= Image::FORMAT_RF) { + return true; + } + + return false; +} + void Image::convert(Format p_new_format) { ERR_FAIL_INDEX_MSG(p_new_format, FORMAT_MAX, "The Image format specified (" + itos(p_new_format) + ") is out of range. See Image's Format enum."); if (data.size() == 0) { @@ -524,7 +550,7 @@ void Image::convert(Format p_new_format) { if (Image::is_format_compressed(format) || Image::is_format_compressed(p_new_format)) { ERR_FAIL_MSG("Cannot convert to <-> from compressed formats. Use compress() and decompress() instead."); - } else if (format > FORMAT_RGBA8 || p_new_format > FORMAT_RGBA8) { + } else if (!_are_formats_compatible(format, p_new_format)) { //use put/set pixel which is slower but works with non byte formats Image new_img(width, height, mipmaps, p_new_format); @@ -538,8 +564,8 @@ void Image::convert(Format p_new_format) { } } - int mip_offset = 0; - int mip_size = 0; + int64_t mip_offset = 0; + int64_t mip_size = 0; new_img.get_mipmap_offset_and_size(mip, mip_offset, mip_size); memcpy(new_img.data.ptrw() + mip_offset, new_mip->data.ptr(), mip_size); @@ -555,8 +581,8 @@ void Image::convert(Format p_new_format) { int conversion_type = format | p_new_format << 8; for (int mip = 0; mip < mipmap_count; mip++) { - int mip_offset = 0; - int mip_size = 0; + int64_t mip_offset = 0; + int64_t mip_size = 0; int mip_width = 0; int mip_height = 0; get_mipmap_offset_size_and_dimensions(mip, mip_offset, mip_size, mip_width, mip_height); @@ -655,6 +681,78 @@ void Image::convert(Format p_new_format) { case FORMAT_RGBA8 | (FORMAT_RGB8 << 8): _convert<3, true, 3, false, false, false>(mip_width, mip_height, rptr, wptr); break; + case FORMAT_RH | (FORMAT_RGH << 8): + _convert_fast<uint16_t, 1, 2, 0x0000, 0x3C00>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr); + break; + case FORMAT_RH | (FORMAT_RGBH << 8): + _convert_fast<uint16_t, 1, 3, 0x0000, 0x3C00>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr); + break; + case FORMAT_RH | (FORMAT_RGBAH << 8): + _convert_fast<uint16_t, 1, 4, 0x0000, 0x3C00>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr); + break; + case FORMAT_RGH | (FORMAT_RH << 8): + _convert_fast<uint16_t, 2, 1, 0x0000, 0x3C00>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr); + break; + case FORMAT_RGH | (FORMAT_RGBH << 8): + _convert_fast<uint16_t, 2, 3, 0x0000, 0x3C00>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr); + break; + case FORMAT_RGH | (FORMAT_RGBAH << 8): + _convert_fast<uint16_t, 2, 4, 0x0000, 0x3C00>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr); + break; + case FORMAT_RGBH | (FORMAT_RH << 8): + _convert_fast<uint16_t, 3, 1, 0x0000, 0x3C00>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr); + break; + case FORMAT_RGBH | (FORMAT_RGH << 8): + _convert_fast<uint16_t, 3, 2, 0x0000, 0x3C00>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr); + break; + case FORMAT_RGBH | (FORMAT_RGBAH << 8): + _convert_fast<uint16_t, 3, 4, 0x0000, 0x3C00>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr); + break; + case FORMAT_RGBAH | (FORMAT_RH << 8): + _convert_fast<uint16_t, 4, 1, 0x0000, 0x3C00>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr); + break; + case FORMAT_RGBAH | (FORMAT_RGH << 8): + _convert_fast<uint16_t, 4, 2, 0x0000, 0x3C00>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr); + break; + case FORMAT_RGBAH | (FORMAT_RGBH << 8): + _convert_fast<uint16_t, 4, 3, 0x0000, 0x3C00>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr); + break; + case FORMAT_RF | (FORMAT_RGF << 8): + _convert_fast<uint32_t, 1, 2, 0x00000000, 0x3F800000>(mip_width, mip_height, (const uint32_t *)rptr, (uint32_t *)wptr); + break; + case FORMAT_RF | (FORMAT_RGBF << 8): + _convert_fast<uint32_t, 1, 3, 0x00000000, 0x3F800000>(mip_width, mip_height, (const uint32_t *)rptr, (uint32_t *)wptr); + break; + case FORMAT_RF | (FORMAT_RGBAF << 8): + _convert_fast<uint32_t, 1, 4, 0x00000000, 0x3F800000>(mip_width, mip_height, (const uint32_t *)rptr, (uint32_t *)wptr); + break; + case FORMAT_RGF | (FORMAT_RF << 8): + _convert_fast<uint32_t, 2, 1, 0x00000000, 0x3F800000>(mip_width, mip_height, (const uint32_t *)rptr, (uint32_t *)wptr); + break; + case FORMAT_RGF | (FORMAT_RGBF << 8): + _convert_fast<uint32_t, 2, 3, 0x00000000, 0x3F800000>(mip_width, mip_height, (const uint32_t *)rptr, (uint32_t *)wptr); + break; + case FORMAT_RGF | (FORMAT_RGBAF << 8): + _convert_fast<uint32_t, 2, 4, 0x00000000, 0x3F800000>(mip_width, mip_height, (const uint32_t *)rptr, (uint32_t *)wptr); + break; + case FORMAT_RGBF | (FORMAT_RF << 8): + _convert_fast<uint32_t, 3, 1, 0x00000000, 0x3F800000>(mip_width, mip_height, (const uint32_t *)rptr, (uint32_t *)wptr); + break; + case FORMAT_RGBF | (FORMAT_RGF << 8): + _convert_fast<uint32_t, 3, 2, 0x00000000, 0x3F800000>(mip_width, mip_height, (const uint32_t *)rptr, (uint32_t *)wptr); + break; + case FORMAT_RGBF | (FORMAT_RGBAF << 8): + _convert_fast<uint32_t, 3, 4, 0x00000000, 0x3F800000>(mip_width, mip_height, (const uint32_t *)rptr, (uint32_t *)wptr); + break; + case FORMAT_RGBAF | (FORMAT_RF << 8): + _convert_fast<uint32_t, 4, 1, 0x00000000, 0x3F800000>(mip_width, mip_height, (const uint32_t *)rptr, (uint32_t *)wptr); + break; + case FORMAT_RGBAF | (FORMAT_RGF << 8): + _convert_fast<uint32_t, 4, 2, 0x00000000, 0x3F800000>(mip_width, mip_height, (const uint32_t *)rptr, (uint32_t *)wptr); + break; + case FORMAT_RGBAF | (FORMAT_RGBF << 8): + _convert_fast<uint32_t, 4, 3, 0x00000000, 0x3F800000>(mip_width, mip_height, (const uint32_t *)rptr, (uint32_t *)wptr); + break; } } @@ -1151,7 +1249,7 @@ void Image::resize(int p_width, int p_height, Interpolation p_interpolation) { if (i == 0) { // Read from the first mipmap that will be interpolated // (if both levels are the same, we will not interpolate, but at least we'll sample from the right level) - int offs; + int64_t offs; _get_mipmap_offset_and_size(mip1, offs, src_width, src_height); src_ptr = r_ptr + offs; } else if (!interpolate_mipmaps) { @@ -1159,7 +1257,7 @@ void Image::resize(int p_width, int p_height, Interpolation p_interpolation) { break; } else { // Switch to read from the second mipmap that will be interpolated - int offs; + int64_t offs; _get_mipmap_offset_and_size(mip2, offs, src_width, src_height); src_ptr = r_ptr + offs; // Switch to write to the second destination image @@ -1599,9 +1697,9 @@ void Image::flip_x() { } /// Get mipmap size and offset. -int 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) { +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). - int size = 0; + int64_t size = 0; int w = p_width; int h = p_height; @@ -1623,7 +1721,7 @@ int Image::_get_dst_image_size(int p_width, int p_height, Format p_format, int & int bw = w % block != 0 ? w + (block - w % block) : w; int bh = h % block != 0 ? h + (block - h % block) : h; - int s = bw * bh; + int64_t s = bw * bh; s *= pixsize; s >>= pixshift; @@ -1837,7 +1935,8 @@ Error Image::generate_mipmaps(bool p_renormalize) { int prev_w = width; for (int i = 1; i <= mmcount; i++) { - int ofs, w, h; + int64_t ofs; + int w, h; _get_mipmap_offset_and_size(i, ofs, w, h); switch (format) { @@ -1993,7 +2092,8 @@ Error Image::generate_mipmap_roughness(RoughnessChannel p_roughness_channel, con uint8_t *base_ptr = data.ptrw(); for (int i = 1; i <= mmcount; i++) { - int ofs, w, h; + int64_t ofs; + int w, h; _get_mipmap_offset_and_size(i, ofs, w, h); uint8_t *ptr = &base_ptr[ofs]; @@ -2102,21 +2202,6 @@ Error Image::generate_mipmap_roughness(RoughnessChannel p_roughness_channel, con _set_color_at_ofs(ptr, pixel_ofs, c); } } -#if 0 - { - int size = get_mipmap_byte_size(i); - print_line("size for mimpap " + itos(i) + ": " + itos(size)); - Vector<uint8_t> imgdata; - imgdata.resize(size); - - - uint8_t* wr = imgdata.ptrw(); - memcpy(wr.ptr(), ptr, size); - wr = uint8_t*(); - Ref<Image> im = Image::create_from_data(w, h, false, format, imgdata); - im->save_png("res://mipmap_" + itos(i) + ".png"); - } -#endif } return OK; @@ -2131,7 +2216,8 @@ void Image::clear_mipmaps() { return; } - int ofs, w, h; + int64_t ofs; + int w, h; _get_mipmap_offset_and_size(1, ofs, w, h); data.resize(ofs); @@ -2176,7 +2262,7 @@ void Image::initialize_data(int p_width, int p_height, bool p_use_mipmaps, Forma ERR_FAIL_INDEX_MSG(p_format, FORMAT_MAX, "The Image format specified (" + itos(p_format) + ") is out of range. See Image's Format enum."); int mm = 0; - int size = _get_dst_image_size(p_width, p_height, p_format, mm, p_use_mipmaps ? -1 : 0); + int64_t size = _get_dst_image_size(p_width, p_height, p_format, mm, p_use_mipmaps ? -1 : 0); data.resize(size); { @@ -2202,7 +2288,7 @@ void Image::initialize_data(int p_width, int p_height, bool p_use_mipmaps, Forma ERR_FAIL_INDEX_MSG(p_format, FORMAT_MAX, "The Image format specified (" + itos(p_format) + ") is out of range. See Image's Format enum."); int mm; - int size = _get_dst_image_size(p_width, p_height, p_format, mm, p_use_mipmaps ? -1 : 0); + int64_t size = _get_dst_image_size(p_width, p_height, p_format, mm, p_use_mipmaps ? -1 : 0); if (unlikely(p_data.size() != size)) { String description_mipmaps = get_format_name(p_format) + " "; @@ -2405,7 +2491,7 @@ bool Image::is_invisible() const { return false; } - int len = data.size(); + int64_t len = data.size(); if (len == 0) { return true; @@ -2445,7 +2531,7 @@ bool Image::is_invisible() const { } Image::AlphaMode Image::detect_alpha() const { - int len = data.size(); + int64_t len = data.size(); if (len == 0) { return ALPHA_NONE; @@ -2579,7 +2665,7 @@ Vector<uint8_t> Image::save_webp_to_buffer(const bool p_lossy, const float p_qua return save_webp_buffer_func(Ref<Image>((Image *)this), p_lossy, p_quality); } -int Image::get_image_data_size(int p_width, int p_height, Format p_format, bool p_mipmaps) { +int64_t Image::get_image_data_size(int p_width, int p_height, Format p_format, bool p_mipmaps) { int mm; return _get_dst_image_size(p_width, p_height, p_format, mm, p_mipmaps ? -1 : 0); } @@ -2597,7 +2683,7 @@ Size2i Image::get_image_mipmap_size(int p_width, int p_height, Format p_format, return ret; } -int Image::get_image_mipmap_offset(int p_width, int p_height, Format p_format, int p_mipmap) { +int64_t Image::get_image_mipmap_offset(int p_width, int p_height, Format p_format, int p_mipmap) { if (p_mipmap <= 0) { return 0; } @@ -2605,7 +2691,7 @@ int Image::get_image_mipmap_offset(int p_width, int p_height, Format p_format, i return _get_dst_image_size(p_width, p_height, p_format, mm, p_mipmap - 1); } -int Image::get_image_mipmap_offset_and_dimensions(int p_width, int p_height, Format p_format, int p_mipmap, int &r_w, int &r_h) { +int64_t Image::get_image_mipmap_offset_and_dimensions(int p_width, int p_height, Format p_format, int p_mipmap, int &r_w, int &r_h) { if (p_mipmap <= 0) { r_w = p_width; r_h = p_height; @@ -2649,6 +2735,27 @@ Error Image::compress(CompressMode p_mode, CompressSource p_source, ASTCFormat p Error Image::compress_from_channels(CompressMode p_mode, UsedChannels p_channels, ASTCFormat p_astc_format) { ERR_FAIL_COND_V(data.is_empty(), ERR_INVALID_DATA); + // RenderingDevice only. + if (GLOBAL_GET("rendering/textures/vram_compression/compress_with_gpu")) { + switch (p_mode) { + case COMPRESS_BPTC: { + // BC7 is unsupported currently. + if ((format >= FORMAT_RF && format <= FORMAT_RGBE9995) && _image_compress_bptc_rd_func) { + Error result = _image_compress_bptc_rd_func(this, p_channels); + + // If the image was compressed successfully, we return here. If not, we fall back to the default compression scheme. + if (result == OK) { + return OK; + } + } + + } break; + + default: { + } + } + } + switch (p_mode) { case COMPRESS_S3TC: { ERR_FAIL_NULL_V(_image_compress_bc_func, ERR_UNAVAILABLE); @@ -3030,6 +3137,7 @@ 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; void (*Image::_image_decompress_bc)(Image *) = nullptr; void (*Image::_image_decompress_bptc)(Image *) = nullptr; void (*Image::_image_decompress_etc1)(Image *) = nullptr; @@ -3479,6 +3587,7 @@ void Image::_bind_methods() { ClassDB::bind_method(D_METHOD("fix_alpha_edges"), &Image::fix_alpha_edges); ClassDB::bind_method(D_METHOD("premultiply_alpha"), &Image::premultiply_alpha); ClassDB::bind_method(D_METHOD("srgb_to_linear"), &Image::srgb_to_linear); + ClassDB::bind_method(D_METHOD("linear_to_srgb"), &Image::linear_to_srgb); ClassDB::bind_method(D_METHOD("normal_map_to_xy"), &Image::normal_map_to_xy); ClassDB::bind_method(D_METHOD("rgbe_to_srgb"), &Image::rgbe_to_srgb); ClassDB::bind_method(D_METHOD("bump_map_to_normal_map", "bump_scale"), &Image::bump_map_to_normal_map, DEFVAL(1.0)); @@ -3642,9 +3751,10 @@ Ref<Image> Image::rgbe_to_srgb() { return new_image; } -Ref<Image> Image::get_image_from_mipmap(int p_mipamp) const { - int ofs, size, w, h; - get_mipmap_offset_size_and_dimensions(p_mipamp, ofs, size, w, h); +Ref<Image> Image::get_image_from_mipmap(int p_mipmap) const { + int64_t ofs, size; + int w, h; + get_mipmap_offset_size_and_dimensions(p_mipmap, ofs, size, w, h); Vector<uint8_t> new_data; new_data.resize(size); @@ -3714,6 +3824,33 @@ void Image::bump_map_to_normal_map(float bump_scale) { data = result_image; } +bool Image::detect_signed(bool p_include_mips) const { + ERR_FAIL_COND_V(is_compressed(), false); + + if (format >= Image::FORMAT_RH && format <= Image::FORMAT_RGBAH) { + const uint16_t *img_data = reinterpret_cast<const uint16_t *>(data.ptr()); + const uint64_t img_size = p_include_mips ? (data.size() / 2) : (width * height * get_format_pixel_size(format) / 2); + + for (uint64_t i = 0; i < img_size; i++) { + if ((img_data[i] & 0x8000) != 0 && (img_data[i] & 0x7fff) != 0) { + return true; + } + } + + } else if (format >= Image::FORMAT_RF && format <= Image::FORMAT_RGBAF) { + const uint32_t *img_data = reinterpret_cast<const uint32_t *>(data.ptr()); + const uint64_t img_size = p_include_mips ? (data.size() / 4) : (width * height * get_format_pixel_size(format) / 4); + + for (uint64_t i = 0; i < img_size; i++) { + if ((img_data[i] & 0x80000000) != 0 && (img_data[i] & 0x7fffffff) != 0) { + return true; + } + } + } + + return false; +} + void Image::srgb_to_linear() { if (data.size() == 0) { return; @@ -3745,6 +3882,37 @@ void Image::srgb_to_linear() { } } +void Image::linear_to_srgb() { + if (data.size() == 0) { + return; + } + + static const uint8_t lin2srgb[256] = { 0, 12, 21, 28, 33, 38, 42, 46, 49, 52, 55, 58, 61, 63, 66, 68, 70, 73, 75, 77, 79, 81, 82, 84, 86, 88, 89, 91, 93, 94, 96, 97, 99, 100, 102, 103, 104, 106, 107, 109, 110, 111, 112, 114, 115, 116, 117, 118, 120, 121, 122, 123, 124, 125, 126, 127, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 151, 152, 153, 154, 155, 156, 157, 157, 158, 159, 160, 161, 161, 162, 163, 164, 165, 165, 166, 167, 168, 168, 169, 170, 171, 171, 172, 173, 174, 174, 175, 176, 176, 177, 178, 179, 179, 180, 181, 181, 182, 183, 183, 184, 185, 185, 186, 187, 187, 188, 189, 189, 190, 191, 191, 192, 193, 193, 194, 194, 195, 196, 196, 197, 197, 198, 199, 199, 200, 201, 201, 202, 202, 203, 204, 204, 205, 205, 206, 206, 207, 208, 208, 209, 209, 210, 210, 211, 212, 212, 213, 213, 214, 214, 215, 215, 216, 217, 217, 218, 218, 219, 219, 220, 220, 221, 221, 222, 222, 223, 223, 224, 224, 225, 226, 226, 227, 227, 228, 228, 229, 229, 230, 230, 231, 231, 232, 232, 233, 233, 234, 234, 235, 235, 236, 236, 237, 237, 237, 238, 238, 239, 239, 240, 240, 241, 241, 242, 242, 243, 243, 244, 244, 245, 245, 245, 246, 246, 247, 247, 248, 248, 249, 249, 250, 250, 251, 251, 251, 252, 252, 253, 253, 254, 254, 255 }; + + ERR_FAIL_COND(format != FORMAT_RGB8 && format != FORMAT_RGBA8); + + if (format == FORMAT_RGBA8) { + int len = data.size() / 4; + uint8_t *data_ptr = data.ptrw(); + + for (int i = 0; i < len; i++) { + data_ptr[(i << 2) + 0] = lin2srgb[data_ptr[(i << 2) + 0]]; + data_ptr[(i << 2) + 1] = lin2srgb[data_ptr[(i << 2) + 1]]; + data_ptr[(i << 2) + 2] = lin2srgb[data_ptr[(i << 2) + 2]]; + } + + } else if (format == FORMAT_RGB8) { + int len = data.size() / 3; + uint8_t *data_ptr = data.ptrw(); + + for (int i = 0; i < len; i++) { + data_ptr[(i * 3) + 0] = lin2srgb[data_ptr[(i * 3) + 0]]; + data_ptr[(i * 3) + 1] = lin2srgb[data_ptr[(i * 3) + 1]]; + data_ptr[(i * 3) + 2] = lin2srgb[data_ptr[(i * 3) + 2]]; + } + } +} + void Image::premultiply_alpha() { if (data.size() == 0) { return; |