summaryrefslogtreecommitdiff
path: root/core/image.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'core/image.cpp')
-rw-r--r--core/image.cpp1176
1 files changed, 621 insertions, 555 deletions
diff --git a/core/image.cpp b/core/image.cpp
index 2c39c9b882..0f15574053 100644
--- a/core/image.cpp
+++ b/core/image.cpp
@@ -37,8 +37,6 @@
#include "core/os/copymem.h"
#include "core/print_string.h"
-#include "thirdparty/misc/hq2x.h"
-
#include <stdio.h>
const char *Image::format_names[Image::FORMAT_MAX] = {
@@ -84,13 +82,12 @@ const char *Image::format_names[Image::FORMAT_MAX] = {
};
-SavePNGFunc Image::save_png_func = NULL;
-SaveEXRFunc Image::save_exr_func = NULL;
+SavePNGFunc Image::save_png_func = nullptr;
+SaveEXRFunc Image::save_exr_func = nullptr;
-SavePNGBufferFunc Image::save_png_buffer_func = NULL;
+SavePNGBufferFunc Image::save_png_buffer_func = nullptr;
void Image::_put_pixelb(int p_x, int p_y, uint32_t p_pixelsize, uint8_t *p_data, const uint8_t *p_pixel) {
-
uint32_t ofs = (p_y * width + p_x) * p_pixelsize;
for (uint32_t i = 0; i < p_pixelsize; i++) {
@@ -99,7 +96,6 @@ void Image::_put_pixelb(int p_x, int p_y, uint32_t p_pixelsize, uint8_t *p_data,
}
void Image::_get_pixelb(int p_x, int p_y, uint32_t p_pixelsize, const uint8_t *p_data, uint8_t *p_pixel) {
-
uint32_t ofs = (p_y * width + p_x) * p_pixelsize;
for (uint32_t i = 0; i < p_pixelsize; i++) {
@@ -108,29 +104,41 @@ void Image::_get_pixelb(int p_x, int p_y, uint32_t p_pixelsize, const uint8_t *p
}
int Image::get_format_pixel_size(Format p_format) {
-
switch (p_format) {
case FORMAT_L8:
return 1; //luminance
case FORMAT_LA8:
return 2; //luminance-alpha
- case FORMAT_R8: return 1;
- case FORMAT_RG8: return 2;
- case FORMAT_RGB8: return 3;
- case FORMAT_RGBA8: return 4;
- case FORMAT_RGBA4444: return 2;
- case FORMAT_RGB565: return 2;
+ case FORMAT_R8:
+ return 1;
+ case FORMAT_RG8:
+ return 2;
+ case FORMAT_RGB8:
+ return 3;
+ case FORMAT_RGBA8:
+ return 4;
+ case FORMAT_RGBA4444:
+ return 2;
+ case FORMAT_RGB565:
+ return 2;
case FORMAT_RF:
return 4; //float
- case FORMAT_RGF: return 8;
- case FORMAT_RGBF: return 12;
- case FORMAT_RGBAF: return 16;
+ case FORMAT_RGF:
+ return 8;
+ case FORMAT_RGBF:
+ return 12;
+ case FORMAT_RGBAF:
+ return 16;
case FORMAT_RH:
return 2; //half float
- case FORMAT_RGH: return 4;
- case FORMAT_RGBH: return 6;
- case FORMAT_RGBAH: return 8;
- case FORMAT_RGBE9995: return 4;
+ case FORMAT_RGH:
+ return 4;
+ case FORMAT_RGBH:
+ return 6;
+ case FORMAT_RGBAH:
+ return 8;
+ case FORMAT_RGBE9995:
+ return 4;
case FORMAT_DXT1:
return 1; //s3tc bc1
case FORMAT_DXT3:
@@ -149,22 +157,32 @@ int Image::get_format_pixel_size(Format p_format) {
return 1; //unsigned float
case FORMAT_PVRTC2:
return 1; //pvrtc
- case FORMAT_PVRTC2A: return 1;
- case FORMAT_PVRTC4: return 1;
- case FORMAT_PVRTC4A: return 1;
+ case FORMAT_PVRTC2A:
+ return 1;
+ case FORMAT_PVRTC4:
+ return 1;
+ case FORMAT_PVRTC4A:
+ return 1;
case FORMAT_ETC:
return 1; //etc1
case FORMAT_ETC2_R11:
return 1; //etc2
case FORMAT_ETC2_R11S:
return 1; //signed: return 1; NOT srgb.
- case FORMAT_ETC2_RG11: return 1;
- case FORMAT_ETC2_RG11S: return 1;
- case FORMAT_ETC2_RGB8: return 1;
- case FORMAT_ETC2_RGBA8: return 1;
- case FORMAT_ETC2_RGB8A1: return 1;
- case FORMAT_ETC2_RA_AS_RG: return 1;
- case FORMAT_DXT5_RA_AS_RG: return 1;
+ case FORMAT_ETC2_RG11:
+ return 1;
+ case FORMAT_ETC2_RG11S:
+ return 1;
+ case FORMAT_ETC2_RGB8:
+ return 1;
+ case FORMAT_ETC2_RGBA8:
+ return 1;
+ case FORMAT_ETC2_RGB8A1:
+ return 1;
+ case FORMAT_ETC2_RA_AS_RG:
+ return 1;
+ case FORMAT_DXT5_RA_AS_RG:
+ return 1;
case FORMAT_MAX: {
}
}
@@ -172,7 +190,6 @@ 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
@@ -185,25 +202,21 @@ void Image::get_format_min_pixel_size(Format p_format, int &r_w, int &r_h) {
} break;
case FORMAT_PVRTC2:
case FORMAT_PVRTC2A: {
-
r_w = 16;
r_h = 8;
} break;
case FORMAT_PVRTC4A:
case FORMAT_PVRTC4: {
-
r_w = 8;
r_h = 8;
} break;
case FORMAT_ETC: {
-
r_w = 4;
r_h = 4;
} break;
case FORMAT_BPTC_RGBA:
case FORMAT_BPTC_RGBF:
case FORMAT_BPTC_RGBFU: {
-
r_w = 4;
r_h = 4;
} break;
@@ -216,7 +229,6 @@ void Image::get_format_min_pixel_size(Format p_format, int &r_w, int &r_h) {
case FORMAT_ETC2_RGB8A1:
case FORMAT_ETC2_RA_AS_RG:
case FORMAT_DXT5_RA_AS_RG: {
-
r_w = 4;
r_h = 4;
@@ -230,17 +242,16 @@ void Image::get_format_min_pixel_size(Format p_format, int &r_w, int &r_h) {
}
int Image::get_format_pixel_rshift(Format p_format) {
-
- if (p_format == FORMAT_DXT1 || p_format == FORMAT_RGTC_R || p_format == FORMAT_PVRTC4 || p_format == FORMAT_PVRTC4A || p_format == FORMAT_ETC || p_format == FORMAT_ETC2_R11 || p_format == FORMAT_ETC2_R11S || p_format == FORMAT_ETC2_RGB8 || p_format == FORMAT_ETC2_RGB8A1)
+ if (p_format == FORMAT_DXT1 || p_format == FORMAT_RGTC_R || p_format == FORMAT_PVRTC4 || p_format == FORMAT_PVRTC4A || p_format == FORMAT_ETC || p_format == FORMAT_ETC2_R11 || p_format == FORMAT_ETC2_R11S || p_format == FORMAT_ETC2_RGB8 || p_format == FORMAT_ETC2_RGB8A1) {
return 1;
- else if (p_format == FORMAT_PVRTC2 || p_format == FORMAT_PVRTC2A)
+ } else if (p_format == FORMAT_PVRTC2 || p_format == FORMAT_PVRTC2A) {
return 2;
- else
+ } else {
return 0;
+ }
}
int Image::get_format_block_size(Format p_format) {
-
switch (p_format) {
case FORMAT_DXT1: //s3tc bc1
case FORMAT_DXT3: //bc2
@@ -252,22 +263,18 @@ int Image::get_format_block_size(Format p_format) {
}
case FORMAT_PVRTC2:
case FORMAT_PVRTC2A: {
-
return 4;
}
case FORMAT_PVRTC4A:
case FORMAT_PVRTC4: {
-
return 4;
}
case FORMAT_ETC: {
-
return 4;
}
case FORMAT_BPTC_RGBA:
case FORMAT_BPTC_RGBF:
case FORMAT_BPTC_RGBFU: {
-
return 4;
}
case FORMAT_ETC2_R11: //etc2
@@ -281,7 +288,6 @@ int Image::get_format_block_size(Format p_format) {
case FORMAT_DXT5_RA_AS_RG: //used to make basis universal happy
{
-
return 4;
}
default: {
@@ -292,7 +298,6 @@ int Image::get_format_block_size(Format p_format) {
}
void Image::_get_mipmap_offset_and_size(int p_mipmap, int &r_offset, int &r_width, int &r_height) const {
-
int w = width;
int h = height;
int ofs = 0;
@@ -322,7 +327,6 @@ void Image::_get_mipmap_offset_and_size(int p_mipmap, int &r_offset, int &r_widt
}
int Image::get_mipmap_offset(int p_mipmap) const {
-
ERR_FAIL_INDEX_V(p_mipmap, get_mipmap_count() + 1, -1);
int ofs, w, h;
@@ -331,7 +335,6 @@ int Image::get_mipmap_offset(int p_mipmap) const {
}
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;
@@ -342,7 +345,6 @@ int Image::get_mipmap_byte_size(int p_mipmap) const {
}
void Image::get_mipmap_offset_and_size(int p_mipmap, int &r_ofs, int &r_size) const {
-
int ofs, w, h;
_get_mipmap_offset_and_size(p_mipmap, ofs, w, h);
int ofs2;
@@ -352,7 +354,6 @@ void Image::get_mipmap_offset_and_size(int p_mipmap, int &r_ofs, int &r_size) co
}
void Image::get_mipmap_offset_size_and_dimensions(int p_mipmap, int &r_ofs, int &r_size, int &w, int &h) const {
-
int ofs;
_get_mipmap_offset_and_size(p_mipmap, ofs, w, h);
int ofs2, w2, h2;
@@ -362,42 +363,36 @@ void Image::get_mipmap_offset_size_and_dimensions(int p_mipmap, int &r_ofs, int
}
int Image::get_width() const {
-
return width;
}
int Image::get_height() const {
-
return height;
}
Vector2 Image::get_size() const {
-
return Vector2(width, height);
}
bool Image::has_mipmaps() const {
-
return mipmaps;
}
int Image::get_mipmap_count() const {
-
- if (mipmaps)
+ if (mipmaps) {
return get_image_required_mipmaps(width, height, format);
- else
+ } else {
return 0;
+ }
}
//using template generates perfectly optimized code due to constant expression reduction and unused variable removal present in all compilers
template <uint32_t read_bytes, bool read_alpha, uint32_t write_bytes, bool write_alpha, bool read_gray, bool write_gray>
static void _convert(int p_width, int p_height, const uint8_t *p_src, uint8_t *p_dst) {
-
uint32_t max_bytes = MAX(read_bytes, write_bytes);
for (int y = 0; y < p_height; y++) {
for (int x = 0; x < p_width; x++) {
-
const uint8_t *rofs = &p_src[((y * p_width) + x) * (read_bytes + (read_alpha ? 1 : 0))];
uint8_t *wofs = &p_dst[((y * p_width) + x) * (write_bytes + (write_alpha ? 1 : 0))];
@@ -408,9 +403,7 @@ static void _convert(int p_width, int p_height, const uint8_t *p_src, uint8_t *p
rgba[1] = rofs[0];
rgba[2] = rofs[0];
} else {
-
for (uint32_t i = 0; i < max_bytes; i++) {
-
rgba[i] = (i < read_bytes) ? rofs[i] : 0;
}
}
@@ -424,7 +417,6 @@ static void _convert(int p_width, int p_height, const uint8_t *p_src, uint8_t *p
wofs[0] = uint8_t((uint16_t(rofs[0]) + uint16_t(rofs[1]) + uint16_t(rofs[2])) / 3);
} else {
for (uint32_t i = 0; i < write_bytes; i++) {
-
wofs[i] = rgba[i];
}
}
@@ -437,25 +429,23 @@ static void _convert(int p_width, int p_height, const uint8_t *p_src, uint8_t *p
}
void Image::convert(Format p_new_format) {
-
- if (data.size() == 0)
+ if (data.size() == 0) {
return;
+ }
- if (p_new_format == format)
+ if (p_new_format == format) {
return;
+ }
if (format > FORMAT_RGBE9995 || p_new_format > FORMAT_RGBE9995) {
-
ERR_FAIL_MSG("Cannot convert to <-> from compressed formats. Use compress() and decompress() instead.");
} else if (format > FORMAT_RGBA8 || p_new_format > FORMAT_RGBA8) {
-
//use put/set pixel which is slower but works with non byte formats
- Image new_img(width, height, 0, p_new_format);
+ Image new_img(width, height, false, p_new_format);
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
-
new_img.set_pixel(i, j, get_pixel(i, j));
}
}
@@ -469,7 +459,7 @@ void Image::convert(Format p_new_format) {
return;
}
- Image new_img(width, height, 0, p_new_format);
+ Image new_img(width, height, false, p_new_format);
const uint8_t *rptr = data.ptr();
uint8_t *wptr = new_img.data.ptrw();
@@ -477,69 +467,127 @@ void Image::convert(Format p_new_format) {
int conversion_type = format | p_new_format << 8;
switch (conversion_type) {
-
- case FORMAT_L8 | (FORMAT_LA8 << 8): _convert<1, false, 1, true, true, true>(width, height, rptr, wptr); break;
- case FORMAT_L8 | (FORMAT_R8 << 8): _convert<1, false, 1, false, true, false>(width, height, rptr, wptr); break;
- case FORMAT_L8 | (FORMAT_RG8 << 8): _convert<1, false, 2, false, true, false>(width, height, rptr, wptr); break;
- case FORMAT_L8 | (FORMAT_RGB8 << 8): _convert<1, false, 3, false, true, false>(width, height, rptr, wptr); break;
- case FORMAT_L8 | (FORMAT_RGBA8 << 8): _convert<1, false, 3, true, true, false>(width, height, rptr, wptr); break;
- case FORMAT_LA8 | (FORMAT_L8 << 8): _convert<1, true, 1, false, true, true>(width, height, rptr, wptr); break;
- case FORMAT_LA8 | (FORMAT_R8 << 8): _convert<1, true, 1, false, true, false>(width, height, rptr, wptr); break;
- case FORMAT_LA8 | (FORMAT_RG8 << 8): _convert<1, true, 2, false, true, false>(width, height, rptr, wptr); break;
- case FORMAT_LA8 | (FORMAT_RGB8 << 8): _convert<1, true, 3, false, true, false>(width, height, rptr, wptr); break;
- case FORMAT_LA8 | (FORMAT_RGBA8 << 8): _convert<1, true, 3, true, true, false>(width, height, rptr, wptr); break;
- case FORMAT_R8 | (FORMAT_L8 << 8): _convert<1, false, 1, false, false, true>(width, height, rptr, wptr); break;
- case FORMAT_R8 | (FORMAT_LA8 << 8): _convert<1, false, 1, true, false, true>(width, height, rptr, wptr); break;
- case FORMAT_R8 | (FORMAT_RG8 << 8): _convert<1, false, 2, false, false, false>(width, height, rptr, wptr); break;
- case FORMAT_R8 | (FORMAT_RGB8 << 8): _convert<1, false, 3, false, false, false>(width, height, rptr, wptr); break;
- case FORMAT_R8 | (FORMAT_RGBA8 << 8): _convert<1, false, 3, true, false, false>(width, height, rptr, wptr); break;
- case FORMAT_RG8 | (FORMAT_L8 << 8): _convert<2, false, 1, false, false, true>(width, height, rptr, wptr); break;
- case FORMAT_RG8 | (FORMAT_LA8 << 8): _convert<2, false, 1, true, false, true>(width, height, rptr, wptr); break;
- case FORMAT_RG8 | (FORMAT_R8 << 8): _convert<2, false, 1, false, false, false>(width, height, rptr, wptr); break;
- case FORMAT_RG8 | (FORMAT_RGB8 << 8): _convert<2, false, 3, false, false, false>(width, height, rptr, wptr); break;
- case FORMAT_RG8 | (FORMAT_RGBA8 << 8): _convert<2, false, 3, true, false, false>(width, height, rptr, wptr); break;
- case FORMAT_RGB8 | (FORMAT_L8 << 8): _convert<3, false, 1, false, false, true>(width, height, rptr, wptr); break;
- case FORMAT_RGB8 | (FORMAT_LA8 << 8): _convert<3, false, 1, true, false, true>(width, height, rptr, wptr); break;
- case FORMAT_RGB8 | (FORMAT_R8 << 8): _convert<3, false, 1, false, false, false>(width, height, rptr, wptr); break;
- case FORMAT_RGB8 | (FORMAT_RG8 << 8): _convert<3, false, 2, false, false, false>(width, height, rptr, wptr); break;
- case FORMAT_RGB8 | (FORMAT_RGBA8 << 8): _convert<3, false, 3, true, false, false>(width, height, rptr, wptr); break;
- case FORMAT_RGBA8 | (FORMAT_L8 << 8): _convert<3, true, 1, false, false, true>(width, height, rptr, wptr); break;
- case FORMAT_RGBA8 | (FORMAT_LA8 << 8): _convert<3, true, 1, true, false, true>(width, height, rptr, wptr); break;
- case FORMAT_RGBA8 | (FORMAT_R8 << 8): _convert<3, true, 1, false, false, false>(width, height, rptr, wptr); break;
- case FORMAT_RGBA8 | (FORMAT_RG8 << 8): _convert<3, true, 2, false, false, false>(width, height, rptr, wptr); break;
- case FORMAT_RGBA8 | (FORMAT_RGB8 << 8): _convert<3, true, 3, false, false, false>(width, height, rptr, wptr); break;
+ case FORMAT_L8 | (FORMAT_LA8 << 8):
+ _convert<1, false, 1, true, true, true>(width, height, rptr, wptr);
+ break;
+ case FORMAT_L8 | (FORMAT_R8 << 8):
+ _convert<1, false, 1, false, true, false>(width, height, rptr, wptr);
+ break;
+ case FORMAT_L8 | (FORMAT_RG8 << 8):
+ _convert<1, false, 2, false, true, false>(width, height, rptr, wptr);
+ break;
+ case FORMAT_L8 | (FORMAT_RGB8 << 8):
+ _convert<1, false, 3, false, true, false>(width, height, rptr, wptr);
+ break;
+ case FORMAT_L8 | (FORMAT_RGBA8 << 8):
+ _convert<1, false, 3, true, true, false>(width, height, rptr, wptr);
+ break;
+ case FORMAT_LA8 | (FORMAT_L8 << 8):
+ _convert<1, true, 1, false, true, true>(width, height, rptr, wptr);
+ break;
+ case FORMAT_LA8 | (FORMAT_R8 << 8):
+ _convert<1, true, 1, false, true, false>(width, height, rptr, wptr);
+ break;
+ case FORMAT_LA8 | (FORMAT_RG8 << 8):
+ _convert<1, true, 2, false, true, false>(width, height, rptr, wptr);
+ break;
+ case FORMAT_LA8 | (FORMAT_RGB8 << 8):
+ _convert<1, true, 3, false, true, false>(width, height, rptr, wptr);
+ break;
+ case FORMAT_LA8 | (FORMAT_RGBA8 << 8):
+ _convert<1, true, 3, true, true, false>(width, height, rptr, wptr);
+ break;
+ case FORMAT_R8 | (FORMAT_L8 << 8):
+ _convert<1, false, 1, false, false, true>(width, height, rptr, wptr);
+ break;
+ case FORMAT_R8 | (FORMAT_LA8 << 8):
+ _convert<1, false, 1, true, false, true>(width, height, rptr, wptr);
+ break;
+ case FORMAT_R8 | (FORMAT_RG8 << 8):
+ _convert<1, false, 2, false, false, false>(width, height, rptr, wptr);
+ break;
+ case FORMAT_R8 | (FORMAT_RGB8 << 8):
+ _convert<1, false, 3, false, false, false>(width, height, rptr, wptr);
+ break;
+ case FORMAT_R8 | (FORMAT_RGBA8 << 8):
+ _convert<1, false, 3, true, false, false>(width, height, rptr, wptr);
+ break;
+ case FORMAT_RG8 | (FORMAT_L8 << 8):
+ _convert<2, false, 1, false, false, true>(width, height, rptr, wptr);
+ break;
+ case FORMAT_RG8 | (FORMAT_LA8 << 8):
+ _convert<2, false, 1, true, false, true>(width, height, rptr, wptr);
+ break;
+ case FORMAT_RG8 | (FORMAT_R8 << 8):
+ _convert<2, false, 1, false, false, false>(width, height, rptr, wptr);
+ break;
+ case FORMAT_RG8 | (FORMAT_RGB8 << 8):
+ _convert<2, false, 3, false, false, false>(width, height, rptr, wptr);
+ break;
+ case FORMAT_RG8 | (FORMAT_RGBA8 << 8):
+ _convert<2, false, 3, true, false, false>(width, height, rptr, wptr);
+ break;
+ case FORMAT_RGB8 | (FORMAT_L8 << 8):
+ _convert<3, false, 1, false, false, true>(width, height, rptr, wptr);
+ break;
+ case FORMAT_RGB8 | (FORMAT_LA8 << 8):
+ _convert<3, false, 1, true, false, true>(width, height, rptr, wptr);
+ break;
+ case FORMAT_RGB8 | (FORMAT_R8 << 8):
+ _convert<3, false, 1, false, false, false>(width, height, rptr, wptr);
+ break;
+ case FORMAT_RGB8 | (FORMAT_RG8 << 8):
+ _convert<3, false, 2, false, false, false>(width, height, rptr, wptr);
+ break;
+ case FORMAT_RGB8 | (FORMAT_RGBA8 << 8):
+ _convert<3, false, 3, true, false, false>(width, height, rptr, wptr);
+ break;
+ case FORMAT_RGBA8 | (FORMAT_L8 << 8):
+ _convert<3, true, 1, false, false, true>(width, height, rptr, wptr);
+ break;
+ case FORMAT_RGBA8 | (FORMAT_LA8 << 8):
+ _convert<3, true, 1, true, false, true>(width, height, rptr, wptr);
+ break;
+ case FORMAT_RGBA8 | (FORMAT_R8 << 8):
+ _convert<3, true, 1, false, false, false>(width, height, rptr, wptr);
+ break;
+ case FORMAT_RGBA8 | (FORMAT_RG8 << 8):
+ _convert<3, true, 2, false, false, false>(width, height, rptr, wptr);
+ break;
+ case FORMAT_RGBA8 | (FORMAT_RGB8 << 8):
+ _convert<3, true, 3, false, false, false>(width, height, rptr, wptr);
+ break;
}
bool gen_mipmaps = mipmaps;
_copy_internals_from(new_img);
- if (gen_mipmaps)
+ if (gen_mipmaps) {
generate_mipmaps();
+ }
}
Image::Format Image::get_format() const {
-
return format;
}
static double _bicubic_interp_kernel(double x) {
-
x = ABS(x);
double bc = 0;
- if (x <= 1)
+ if (x <= 1) {
bc = (1.5 * x - 2.5) * x * x + 1;
- else if (x < 2)
+ } else if (x < 2) {
bc = ((-0.5 * x + 2.5) * x - 4) * x + 2;
+ }
return bc;
}
template <int CC, class T>
static void _scale_cubic(const uint8_t *__restrict p_src, uint8_t *__restrict p_dst, uint32_t p_src_width, uint32_t p_src_height, uint32_t p_dst_width, uint32_t p_dst_height) {
-
// get source image size
int width = p_src_width;
int height = p_src_height;
@@ -580,20 +628,24 @@ static void _scale_cubic(const uint8_t *__restrict p_src, uint8_t *__restrict p_
k1 = _bicubic_interp_kernel(dy - (double)n);
oy2 = oy1 + n;
- if (oy2 < 0)
+ if (oy2 < 0) {
oy2 = 0;
- if (oy2 > ymax)
+ }
+ if (oy2 > ymax) {
oy2 = ymax;
+ }
for (int m = -1; m < 3; m++) {
// get X coefficient
k2 = k1 * _bicubic_interp_kernel((double)m - dx);
ox2 = ox1 + m;
- if (ox2 < 0)
+ if (ox2 < 0) {
ox2 = 0;
- if (ox2 > xmax)
+ }
+ if (ox2 > xmax) {
ox2 = xmax;
+ }
// get pixel of original image
const T *__restrict p = ((T *)p_src) + (oy2 * p_src_width + ox2) * CC;
@@ -623,7 +675,6 @@ static void _scale_cubic(const uint8_t *__restrict p_src, uint8_t *__restrict p_
template <int CC, class T>
static void _scale_bilinear(const uint8_t *__restrict p_src, uint8_t *__restrict p_dst, uint32_t p_src_width, uint32_t p_src_height, uint32_t p_dst_width, uint32_t p_dst_height) {
-
enum {
FRAC_BITS = 8,
FRAC_LEN = (1 << FRAC_BITS),
@@ -632,14 +683,14 @@ static void _scale_bilinear(const uint8_t *__restrict p_src, uint8_t *__restrict
};
for (uint32_t i = 0; i < p_dst_height; i++) {
-
uint32_t src_yofs_up_fp = (i * p_src_height * FRAC_LEN / p_dst_height);
uint32_t src_yofs_frac = src_yofs_up_fp & FRAC_MASK;
uint32_t src_yofs_up = src_yofs_up_fp >> FRAC_BITS;
uint32_t src_yofs_down = (i + 1) * p_src_height / p_dst_height;
- if (src_yofs_down >= p_src_height)
+ if (src_yofs_down >= p_src_height) {
src_yofs_down = p_src_height - 1;
+ }
//src_yofs_up*=CC;
//src_yofs_down*=CC;
@@ -648,19 +699,18 @@ static void _scale_bilinear(const uint8_t *__restrict p_src, uint8_t *__restrict
uint32_t y_ofs_down = src_yofs_down * p_src_width * CC;
for (uint32_t j = 0; j < p_dst_width; j++) {
-
uint32_t src_xofs_left_fp = (j * p_src_width * FRAC_LEN / p_dst_width);
uint32_t src_xofs_frac = src_xofs_left_fp & FRAC_MASK;
uint32_t src_xofs_left = src_xofs_left_fp >> FRAC_BITS;
uint32_t src_xofs_right = (j + 1) * p_src_width / p_dst_width;
- if (src_xofs_right >= p_src_width)
+ if (src_xofs_right >= p_src_width) {
src_xofs_right = p_src_width - 1;
+ }
src_xofs_left *= CC;
src_xofs_right *= CC;
for (uint32_t l = 0; l < CC; l++) {
-
if (sizeof(T) == 1) { //uint8
uint32_t p00 = p_src[y_ofs_up + src_xofs_left + l] << FRAC_BITS;
uint32_t p10 = p_src[y_ofs_up + src_xofs_right + l] << FRAC_BITS;
@@ -714,19 +764,15 @@ static void _scale_bilinear(const uint8_t *__restrict p_src, uint8_t *__restrict
template <int CC, class T>
static void _scale_nearest(const uint8_t *__restrict p_src, uint8_t *__restrict p_dst, uint32_t p_src_width, uint32_t p_src_height, uint32_t p_dst_width, uint32_t p_dst_height) {
-
for (uint32_t i = 0; i < p_dst_height; i++) {
-
uint32_t src_yofs = i * p_src_height / p_dst_height;
uint32_t y_ofs = src_yofs * p_src_width * CC;
for (uint32_t j = 0; j < p_dst_width; j++) {
-
uint32_t src_xofs = j * p_src_width / p_dst_width;
src_xofs *= CC;
for (uint32_t l = 0; l < CC; l++) {
-
const T *src = ((const T *)p_src);
T *dst = ((T *)p_dst);
@@ -745,7 +791,6 @@ static float _lanczos(float p_x) {
template <int CC, class T>
static void _scale_lanczos(const uint8_t *__restrict p_src, uint8_t *__restrict p_dst, uint32_t p_src_width, uint32_t p_src_height, uint32_t p_dst_width, uint32_t p_dst_height) {
-
int32_t src_width = p_src_width;
int32_t src_height = p_src_height;
int32_t dst_height = p_dst_height;
@@ -764,40 +809,40 @@ static void _scale_lanczos(const uint8_t *__restrict p_src, uint8_t *__restrict
float *kernel = memnew_arr(float, half_kernel * 2);
for (int32_t buffer_x = 0; buffer_x < dst_width; buffer_x++) {
-
// The corresponding point on the source image
float src_x = (buffer_x + 0.5f) * x_scale; // Offset by 0.5 so it uses the pixel's center
int32_t start_x = MAX(0, int32_t(src_x) - half_kernel + 1);
int32_t end_x = MIN(src_width - 1, int32_t(src_x) + half_kernel);
// Create the kernel used by all the pixels of the column
- for (int32_t target_x = start_x; target_x <= end_x; target_x++)
+ for (int32_t target_x = start_x; target_x <= end_x; target_x++) {
kernel[target_x - start_x] = _lanczos((target_x + 0.5f - src_x) / scale_factor);
+ }
for (int32_t buffer_y = 0; buffer_y < src_height; buffer_y++) {
-
float pixel[CC] = { 0 };
float weight = 0;
for (int32_t target_x = start_x; target_x <= end_x; target_x++) {
-
float lanczos_val = kernel[target_x - start_x];
weight += lanczos_val;
const T *__restrict src_data = ((const T *)p_src) + (buffer_y * src_width + target_x) * CC;
for (uint32_t i = 0; i < CC; i++) {
- if (sizeof(T) == 2) //half float
+ if (sizeof(T) == 2) { //half float
pixel[i] += Math::half_to_float(src_data[i]) * lanczos_val;
- else
+ } else {
pixel[i] += src_data[i] * lanczos_val;
+ }
}
}
float *dst_data = ((float *)buffer) + (buffer_y * dst_width + buffer_x) * CC;
- for (uint32_t i = 0; i < CC; i++)
+ for (uint32_t i = 0; i < CC; i++) {
dst_data[i] = pixel[i] / weight; // Normalize the sum of all the samples
+ }
}
}
@@ -814,28 +859,27 @@ static void _scale_lanczos(const uint8_t *__restrict p_src, uint8_t *__restrict
float *kernel = memnew_arr(float, half_kernel * 2);
for (int32_t dst_y = 0; dst_y < dst_height; dst_y++) {
-
float buffer_y = (dst_y + 0.5f) * y_scale;
int32_t start_y = MAX(0, int32_t(buffer_y) - half_kernel + 1);
int32_t end_y = MIN(src_height - 1, int32_t(buffer_y) + half_kernel);
- for (int32_t target_y = start_y; target_y <= end_y; target_y++)
+ for (int32_t target_y = start_y; target_y <= end_y; target_y++) {
kernel[target_y - start_y] = _lanczos((target_y + 0.5f - buffer_y) / scale_factor);
+ }
for (int32_t dst_x = 0; dst_x < dst_width; dst_x++) {
-
float pixel[CC] = { 0 };
float weight = 0;
for (int32_t target_y = start_y; target_y <= end_y; target_y++) {
-
float lanczos_val = kernel[target_y - start_y];
weight += lanczos_val;
float *buffer_data = ((float *)buffer) + (target_y * dst_width + dst_x) * CC;
- for (uint32_t i = 0; i < CC; i++)
+ for (uint32_t i = 0; i < CC; i++) {
pixel[i] += buffer_data[i] * lanczos_val;
+ }
}
T *dst_data = ((T *)p_dst) + (dst_y * dst_width + dst_x) * CC;
@@ -843,12 +887,13 @@ static void _scale_lanczos(const uint8_t *__restrict p_src, uint8_t *__restrict
for (uint32_t i = 0; i < CC; i++) {
pixel[i] /= weight;
- if (sizeof(T) == 1) //byte
+ if (sizeof(T) == 1) { //byte
dst_data[i] = CLAMP(Math::fast_ftoi(pixel[i]), 0, 255);
- else if (sizeof(T) == 2) //half float
+ } else if (sizeof(T) == 2) { //half float
dst_data[i] = Math::make_half_float(pixel[i]);
- else // float
+ } else { // float
dst_data[i] = pixel[i];
+ }
}
}
}
@@ -860,11 +905,9 @@ static void _scale_lanczos(const uint8_t *__restrict p_src, uint8_t *__restrict
}
static void _overlay(const uint8_t *__restrict p_src, uint8_t *__restrict p_dst, float p_alpha, uint32_t p_width, uint32_t p_height, uint32_t p_pixel_size) {
-
uint16_t alpha = MIN((uint16_t)(p_alpha * 256.0f), 256);
for (uint32_t i = 0; i < p_width * p_height * p_pixel_size; i++) {
-
p_dst[i] = (p_dst[i] * (256 - alpha) + p_src[i] * alpha) >> 8;
}
}
@@ -874,23 +917,24 @@ bool Image::is_size_po2() const {
}
void Image::resize_to_po2(bool p_square) {
-
ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot resize in compressed or custom image formats.");
int w = next_power_of_2(width);
int h = next_power_of_2(height);
+ if (p_square) {
+ w = h = MAX(w, h);
+ }
if (w == width && h == height) {
-
- if (!p_square || w == h)
+ if (!p_square || w == h) {
return; //nothing to do
+ }
}
resize(w, h);
}
void Image::resize(int p_width, int p_height, Interpolation p_interpolation) {
-
ERR_FAIL_COND_MSG(data.size() == 0, "Cannot resize image before creating it, use create() or create_from_data() first.");
ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot resize in compressed or custom image formats.");
@@ -902,10 +946,11 @@ void Image::resize(int p_width, int p_height, Interpolation p_interpolation) {
ERR_FAIL_COND_MSG(p_height > MAX_HEIGHT, "Image height cannot be greater than " + itos(MAX_HEIGHT) + ".");
ERR_FAIL_COND_MSG(p_width * p_height > MAX_PIXELS, "Too many pixels for image, maximum is " + itos(MAX_PIXELS));
- if (p_width == width && p_height == height)
+ if (p_width == width && p_height == height) {
return;
+ }
- Image dst(p_width, p_height, 0, format);
+ Image dst(p_width, p_height, false, format);
// Setup mipmap-aware scaling
Image dst2;
@@ -925,7 +970,7 @@ void Image::resize(int p_width, int p_height, Interpolation p_interpolation) {
}
bool interpolate_mipmaps = mipmap_aware && mip1 != mip2;
if (interpolate_mipmaps) {
- dst2.create(p_width, p_height, 0, format);
+ dst2.create(p_width, p_height, false, format);
}
bool had_mipmaps = mipmaps;
@@ -941,37 +986,58 @@ void Image::resize(int p_width, int p_height, Interpolation p_interpolation) {
unsigned char *w_ptr = w;
switch (p_interpolation) {
-
case INTERPOLATE_NEAREST: {
-
if (format >= FORMAT_L8 && format <= FORMAT_RGBA8) {
switch (get_format_pixel_size(format)) {
- case 1: _scale_nearest<1, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height); break;
- case 2: _scale_nearest<2, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height); break;
- case 3: _scale_nearest<3, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height); break;
- case 4: _scale_nearest<4, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height); break;
+ case 1:
+ _scale_nearest<1, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height);
+ break;
+ case 2:
+ _scale_nearest<2, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height);
+ break;
+ case 3:
+ _scale_nearest<3, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height);
+ break;
+ case 4:
+ _scale_nearest<4, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height);
+ break;
}
} else if (format >= FORMAT_RF && format <= FORMAT_RGBAF) {
switch (get_format_pixel_size(format)) {
- case 4: _scale_nearest<1, float>(r_ptr, w_ptr, width, height, p_width, p_height); break;
- case 8: _scale_nearest<2, float>(r_ptr, w_ptr, width, height, p_width, p_height); break;
- case 12: _scale_nearest<3, float>(r_ptr, w_ptr, width, height, p_width, p_height); break;
- case 16: _scale_nearest<4, float>(r_ptr, w_ptr, width, height, p_width, p_height); break;
+ case 4:
+ _scale_nearest<1, float>(r_ptr, w_ptr, width, height, p_width, p_height);
+ break;
+ case 8:
+ _scale_nearest<2, float>(r_ptr, w_ptr, width, height, p_width, p_height);
+ break;
+ case 12:
+ _scale_nearest<3, float>(r_ptr, w_ptr, width, height, p_width, p_height);
+ break;
+ case 16:
+ _scale_nearest<4, float>(r_ptr, w_ptr, width, height, p_width, p_height);
+ break;
}
} else if (format >= FORMAT_RH && format <= FORMAT_RGBAH) {
switch (get_format_pixel_size(format)) {
- case 2: _scale_nearest<1, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); break;
- case 4: _scale_nearest<2, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); break;
- case 6: _scale_nearest<3, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); break;
- case 8: _scale_nearest<4, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); break;
+ case 2:
+ _scale_nearest<1, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
+ break;
+ case 4:
+ _scale_nearest<2, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
+ break;
+ case 6:
+ _scale_nearest<3, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
+ break;
+ case 8:
+ _scale_nearest<4, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
+ break;
}
}
} break;
case INTERPOLATE_BILINEAR:
case INTERPOLATE_TRILINEAR: {
-
for (int i = 0; i < 2; ++i) {
int src_width;
int src_height;
@@ -1010,24 +1076,48 @@ void Image::resize(int p_width, int p_height, Interpolation p_interpolation) {
if (format >= FORMAT_L8 && format <= FORMAT_RGBA8) {
switch (get_format_pixel_size(format)) {
- case 1: _scale_bilinear<1, uint8_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); break;
- case 2: _scale_bilinear<2, uint8_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); break;
- case 3: _scale_bilinear<3, uint8_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); break;
- case 4: _scale_bilinear<4, uint8_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); break;
+ case 1:
+ _scale_bilinear<1, uint8_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
+ break;
+ case 2:
+ _scale_bilinear<2, uint8_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
+ break;
+ case 3:
+ _scale_bilinear<3, uint8_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
+ break;
+ case 4:
+ _scale_bilinear<4, uint8_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
+ break;
}
} else if (format >= FORMAT_RF && format <= FORMAT_RGBAF) {
switch (get_format_pixel_size(format)) {
- case 4: _scale_bilinear<1, float>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); break;
- case 8: _scale_bilinear<2, float>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); break;
- case 12: _scale_bilinear<3, float>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); break;
- case 16: _scale_bilinear<4, float>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); break;
+ case 4:
+ _scale_bilinear<1, float>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
+ break;
+ case 8:
+ _scale_bilinear<2, float>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
+ break;
+ case 12:
+ _scale_bilinear<3, float>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
+ break;
+ case 16:
+ _scale_bilinear<4, float>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
+ break;
}
} else if (format >= FORMAT_RH && format <= FORMAT_RGBAH) {
switch (get_format_pixel_size(format)) {
- case 2: _scale_bilinear<1, uint16_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); break;
- case 4: _scale_bilinear<2, uint16_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); break;
- case 6: _scale_bilinear<3, uint16_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); break;
- case 8: _scale_bilinear<4, uint16_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); break;
+ case 2:
+ _scale_bilinear<1, uint16_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
+ break;
+ case 4:
+ _scale_bilinear<2, uint16_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
+ break;
+ case 6:
+ _scale_bilinear<3, uint16_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
+ break;
+ case 8:
+ _scale_bilinear<4, uint16_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
+ break;
}
}
}
@@ -1040,52 +1130,98 @@ void Image::resize(int p_width, int p_height, Interpolation p_interpolation) {
} break;
case INTERPOLATE_CUBIC: {
-
if (format >= FORMAT_L8 && format <= FORMAT_RGBA8) {
switch (get_format_pixel_size(format)) {
- case 1: _scale_cubic<1, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height); break;
- case 2: _scale_cubic<2, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height); break;
- case 3: _scale_cubic<3, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height); break;
- case 4: _scale_cubic<4, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height); break;
+ case 1:
+ _scale_cubic<1, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height);
+ break;
+ case 2:
+ _scale_cubic<2, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height);
+ break;
+ case 3:
+ _scale_cubic<3, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height);
+ break;
+ case 4:
+ _scale_cubic<4, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height);
+ break;
}
} else if (format >= FORMAT_RF && format <= FORMAT_RGBAF) {
switch (get_format_pixel_size(format)) {
- case 4: _scale_cubic<1, float>(r_ptr, w_ptr, width, height, p_width, p_height); break;
- case 8: _scale_cubic<2, float>(r_ptr, w_ptr, width, height, p_width, p_height); break;
- case 12: _scale_cubic<3, float>(r_ptr, w_ptr, width, height, p_width, p_height); break;
- case 16: _scale_cubic<4, float>(r_ptr, w_ptr, width, height, p_width, p_height); break;
+ case 4:
+ _scale_cubic<1, float>(r_ptr, w_ptr, width, height, p_width, p_height);
+ break;
+ case 8:
+ _scale_cubic<2, float>(r_ptr, w_ptr, width, height, p_width, p_height);
+ break;
+ case 12:
+ _scale_cubic<3, float>(r_ptr, w_ptr, width, height, p_width, p_height);
+ break;
+ case 16:
+ _scale_cubic<4, float>(r_ptr, w_ptr, width, height, p_width, p_height);
+ break;
}
} else if (format >= FORMAT_RH && format <= FORMAT_RGBAH) {
switch (get_format_pixel_size(format)) {
- case 2: _scale_cubic<1, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); break;
- case 4: _scale_cubic<2, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); break;
- case 6: _scale_cubic<3, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); break;
- case 8: _scale_cubic<4, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); break;
+ case 2:
+ _scale_cubic<1, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
+ break;
+ case 4:
+ _scale_cubic<2, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
+ break;
+ case 6:
+ _scale_cubic<3, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
+ break;
+ case 8:
+ _scale_cubic<4, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
+ break;
}
}
} break;
case INTERPOLATE_LANCZOS: {
-
if (format >= FORMAT_L8 && format <= FORMAT_RGBA8) {
switch (get_format_pixel_size(format)) {
- case 1: _scale_lanczos<1, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height); break;
- case 2: _scale_lanczos<2, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height); break;
- case 3: _scale_lanczos<3, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height); break;
- case 4: _scale_lanczos<4, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height); break;
+ case 1:
+ _scale_lanczos<1, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height);
+ break;
+ case 2:
+ _scale_lanczos<2, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height);
+ break;
+ case 3:
+ _scale_lanczos<3, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height);
+ break;
+ case 4:
+ _scale_lanczos<4, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height);
+ break;
}
} else if (format >= FORMAT_RF && format <= FORMAT_RGBAF) {
switch (get_format_pixel_size(format)) {
- case 4: _scale_lanczos<1, float>(r_ptr, w_ptr, width, height, p_width, p_height); break;
- case 8: _scale_lanczos<2, float>(r_ptr, w_ptr, width, height, p_width, p_height); break;
- case 12: _scale_lanczos<3, float>(r_ptr, w_ptr, width, height, p_width, p_height); break;
- case 16: _scale_lanczos<4, float>(r_ptr, w_ptr, width, height, p_width, p_height); break;
+ case 4:
+ _scale_lanczos<1, float>(r_ptr, w_ptr, width, height, p_width, p_height);
+ break;
+ case 8:
+ _scale_lanczos<2, float>(r_ptr, w_ptr, width, height, p_width, p_height);
+ break;
+ case 12:
+ _scale_lanczos<3, float>(r_ptr, w_ptr, width, height, p_width, p_height);
+ break;
+ case 16:
+ _scale_lanczos<4, float>(r_ptr, w_ptr, width, height, p_width, p_height);
+ break;
}
} else if (format >= FORMAT_RH && format <= FORMAT_RGBAH) {
switch (get_format_pixel_size(format)) {
- case 2: _scale_lanczos<1, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); break;
- case 4: _scale_lanczos<2, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); break;
- case 6: _scale_lanczos<3, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); break;
- case 8: _scale_lanczos<4, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); break;
+ case 2:
+ _scale_lanczos<1, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
+ break;
+ case 4:
+ _scale_lanczos<2, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
+ break;
+ case 6:
+ _scale_lanczos<3, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
+ break;
+ case 8:
+ _scale_lanczos<4, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
+ break;
}
}
} break;
@@ -1095,14 +1231,14 @@ void Image::resize(int p_width, int p_height, Interpolation p_interpolation) {
dst._copy_internals_from(dst2);
}
- if (had_mipmaps)
+ if (had_mipmaps) {
dst.generate_mipmaps();
+ }
_copy_internals_from(dst);
}
void Image::crop_from_point(int p_x, int p_y, int p_width, int p_height) {
-
ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot crop in compressed or custom image formats.");
ERR_FAIL_COND_MSG(p_x < 0, "Start x position cannot be smaller than 0.");
@@ -1116,13 +1252,14 @@ void Image::crop_from_point(int p_x, int p_y, int p_width, int p_height) {
will most likely either not be used much, or in critical areas, for now it won't, because
it's a waste of time. */
- if (p_width == width && p_height == height && p_x == 0 && p_y == 0)
+ if (p_width == width && p_height == height && p_x == 0 && p_y == 0) {
return;
+ }
uint8_t pdata[16]; //largest is 16
uint32_t pixel_size = get_format_pixel_size(format);
- Image dst(p_width, p_height, 0, format);
+ Image dst(p_width, p_height, false, format);
{
const uint8_t *r = data.ptr();
@@ -1131,12 +1268,11 @@ void Image::crop_from_point(int p_x, int p_y, int p_width, int p_height) {
int m_h = p_y + p_height;
int m_w = p_x + p_width;
for (int y = p_y; y < m_h; y++) {
-
for (int x = p_x; x < m_w; x++) {
-
if ((x >= width || y >= height)) {
- for (uint32_t i = 0; i < pixel_size; i++)
+ for (uint32_t i = 0; i < pixel_size; i++) {
pdata[i] = 0;
+ }
} else {
_get_pixelb(x, y, pixel_size, r, pdata);
}
@@ -1146,18 +1282,17 @@ void Image::crop_from_point(int p_x, int p_y, int p_width, int p_height) {
}
}
- if (has_mipmaps())
+ if (has_mipmaps()) {
dst.generate_mipmaps();
+ }
_copy_internals_from(dst);
}
void Image::crop(int p_width, int p_height) {
-
crop_from_point(0, 0, p_width, p_height);
}
void Image::flip_y() {
-
ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot flip_y in compressed or custom image formats.");
bool used_mipmaps = has_mipmaps();
@@ -1172,9 +1307,7 @@ void Image::flip_y() {
uint32_t pixel_size = get_format_pixel_size(format);
for (int y = 0; y < height / 2; y++) {
-
for (int x = 0; x < width; x++) {
-
_get_pixelb(x, y, pixel_size, w, up);
_get_pixelb(x, height - y - 1, pixel_size, w, down);
@@ -1190,7 +1323,6 @@ void Image::flip_y() {
}
void Image::flip_x() {
-
ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot flip_x in compressed or custom image formats.");
bool used_mipmaps = has_mipmaps();
@@ -1205,9 +1337,7 @@ void Image::flip_x() {
uint32_t pixel_size = get_format_pixel_size(format);
for (int y = 0; y < height; y++) {
-
for (int x = 0; x < width / 2; x++) {
-
_get_pixelb(x, y, pixel_size, w, up);
_get_pixelb(width - x - 1, y, pixel_size, w, down);
@@ -1223,7 +1353,6 @@ void Image::flip_x() {
}
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) {
-
int size = 0;
int w = p_width;
int h = p_height;
@@ -1238,7 +1367,6 @@ int Image::_get_dst_image_size(int p_width, int p_height, Format p_format, int &
int minw = 1, minh = 1;
while (true) {
-
int bw = w % block != 0 ? w + (block - w % block) : w;
int bh = h % block != 0 ? h + (block - h % block) : h;
@@ -1256,28 +1384,28 @@ int Image::_get_dst_image_size(int p_width, int p_height, Format p_format, int &
*r_mm_height = bh;
}
- if (p_mipmaps >= 0 && mm == p_mipmaps)
+ if (p_mipmaps >= 0 && mm == p_mipmaps) {
break;
+ }
if (p_mipmaps >= 0) {
-
w = MAX(minw, w >> 1);
h = MAX(minh, h >> 1);
} else {
- if (w == minw && h == minh)
+ if (w == minw && h == minh) {
break;
+ }
w = MAX(minw, w >> 1);
h = MAX(minh, h >> 1);
}
mm++;
- };
+ }
r_mipmaps = mm;
return size;
}
bool Image::_can_modify(Format p_format) const {
-
return p_format <= FORMAT_RGBE9995;
}
@@ -1285,7 +1413,6 @@ template <class Component, int CC, bool renormalize,
void (*average_func)(Component &, const Component &, const Component &, const Component &, const Component &),
void (*renormalize_func)(Component *)>
static void _generate_po2_mipmap(const Component *p_src, Component *p_dst, uint32_t p_width, uint32_t p_height) {
-
//fast power of 2 mipmap generation
uint32_t dst_w = MAX(p_width >> 1, 1);
uint32_t dst_h = MAX(p_height >> 1, 1);
@@ -1294,7 +1421,6 @@ static void _generate_po2_mipmap(const Component *p_src, Component *p_dst, uint3
int down_step = (p_height == 1) ? 0 : (p_width * CC);
for (uint32_t i = 0; i < dst_h; i++) {
-
const Component *rup_ptr = &p_src[i * 2 * down_step];
const Component *rdown_ptr = rup_ptr + down_step;
Component *dst_ptr = &p_dst[i * dst_w * CC];
@@ -1317,52 +1443,10 @@ static void _generate_po2_mipmap(const Component *p_src, Component *p_dst, uint3
}
}
-void Image::expand_x2_hq2x() {
-
- ERR_FAIL_COND(!_can_modify(format));
-
- bool used_mipmaps = has_mipmaps();
- if (used_mipmaps) {
- clear_mipmaps();
- }
-
- Format current = format;
-
- if (current != FORMAT_RGBA8)
- convert(FORMAT_RGBA8);
-
- Vector<uint8_t> dest;
- dest.resize(width * 2 * height * 2 * 4);
-
- {
- const uint8_t *r = data.ptr();
- uint8_t *w = dest.ptrw();
-
- ERR_FAIL_COND(!r);
-
- hq2x_resize((const uint32_t *)r, width, height, (uint32_t *)w);
- }
-
- width *= 2;
- height *= 2;
- data = dest;
-
- if (current != FORMAT_RGBA8)
- convert(current);
-
- // FIXME: This is likely meant to use "used_mipmaps" as defined above, but if we do,
- // we end up with a regression: GH-22747
- if (mipmaps) {
- generate_mipmaps();
- }
-}
-
void Image::shrink_x2() {
-
ERR_FAIL_COND(data.size() == 0);
if (mipmaps) {
-
//just use the lower mipmap as base and copy all
Vector<uint8_t> new_img;
@@ -1384,7 +1468,6 @@ void Image::shrink_x2() {
data = new_img;
} else {
-
Vector<uint8_t> new_img;
ERR_FAIL_COND(!_can_modify(format));
@@ -1398,25 +1481,52 @@ void Image::shrink_x2() {
const uint8_t *r = data.ptr();
switch (format) {
-
case FORMAT_L8:
- case FORMAT_R8: _generate_po2_mipmap<uint8_t, 1, false, Image::average_4_uint8, Image::renormalize_uint8>(r, w, width, height); break;
- case FORMAT_LA8: _generate_po2_mipmap<uint8_t, 2, false, Image::average_4_uint8, Image::renormalize_uint8>(r, w, width, height); break;
- case FORMAT_RG8: _generate_po2_mipmap<uint8_t, 2, false, Image::average_4_uint8, Image::renormalize_uint8>(r, w, width, height); break;
- case FORMAT_RGB8: _generate_po2_mipmap<uint8_t, 3, false, Image::average_4_uint8, Image::renormalize_uint8>(r, w, width, height); break;
- case FORMAT_RGBA8: _generate_po2_mipmap<uint8_t, 4, false, Image::average_4_uint8, Image::renormalize_uint8>(r, w, width, height); break;
-
- case FORMAT_RF: _generate_po2_mipmap<float, 1, false, Image::average_4_float, Image::renormalize_float>(reinterpret_cast<const float *>(r), reinterpret_cast<float *>(w), width, height); break;
- case FORMAT_RGF: _generate_po2_mipmap<float, 2, false, Image::average_4_float, Image::renormalize_float>(reinterpret_cast<const float *>(r), reinterpret_cast<float *>(w), width, height); break;
- case FORMAT_RGBF: _generate_po2_mipmap<float, 3, false, Image::average_4_float, Image::renormalize_float>(reinterpret_cast<const float *>(r), reinterpret_cast<float *>(w), width, height); break;
- case FORMAT_RGBAF: _generate_po2_mipmap<float, 4, false, Image::average_4_float, Image::renormalize_float>(reinterpret_cast<const float *>(r), reinterpret_cast<float *>(w), width, height); break;
-
- case FORMAT_RH: _generate_po2_mipmap<uint16_t, 1, false, Image::average_4_half, Image::renormalize_half>(reinterpret_cast<const uint16_t *>(r), reinterpret_cast<uint16_t *>(w), width, height); break;
- case FORMAT_RGH: _generate_po2_mipmap<uint16_t, 2, false, Image::average_4_half, Image::renormalize_half>(reinterpret_cast<const uint16_t *>(r), reinterpret_cast<uint16_t *>(w), width, height); break;
- case FORMAT_RGBH: _generate_po2_mipmap<uint16_t, 3, false, Image::average_4_half, Image::renormalize_half>(reinterpret_cast<const uint16_t *>(r), reinterpret_cast<uint16_t *>(w), width, height); break;
- case FORMAT_RGBAH: _generate_po2_mipmap<uint16_t, 4, false, Image::average_4_half, Image::renormalize_half>(reinterpret_cast<const uint16_t *>(r), reinterpret_cast<uint16_t *>(w), width, height); break;
-
- case FORMAT_RGBE9995: _generate_po2_mipmap<uint32_t, 1, false, Image::average_4_rgbe9995, Image::renormalize_rgbe9995>(reinterpret_cast<const uint32_t *>(r), reinterpret_cast<uint32_t *>(w), width, height); break;
+ case FORMAT_R8:
+ _generate_po2_mipmap<uint8_t, 1, false, Image::average_4_uint8, Image::renormalize_uint8>(r, w, width, height);
+ break;
+ case FORMAT_LA8:
+ _generate_po2_mipmap<uint8_t, 2, false, Image::average_4_uint8, Image::renormalize_uint8>(r, w, width, height);
+ break;
+ case FORMAT_RG8:
+ _generate_po2_mipmap<uint8_t, 2, false, Image::average_4_uint8, Image::renormalize_uint8>(r, w, width, height);
+ break;
+ case FORMAT_RGB8:
+ _generate_po2_mipmap<uint8_t, 3, false, Image::average_4_uint8, Image::renormalize_uint8>(r, w, width, height);
+ break;
+ case FORMAT_RGBA8:
+ _generate_po2_mipmap<uint8_t, 4, false, Image::average_4_uint8, Image::renormalize_uint8>(r, w, width, height);
+ break;
+
+ case FORMAT_RF:
+ _generate_po2_mipmap<float, 1, false, Image::average_4_float, Image::renormalize_float>(reinterpret_cast<const float *>(r), reinterpret_cast<float *>(w), width, height);
+ break;
+ case FORMAT_RGF:
+ _generate_po2_mipmap<float, 2, false, Image::average_4_float, Image::renormalize_float>(reinterpret_cast<const float *>(r), reinterpret_cast<float *>(w), width, height);
+ break;
+ case FORMAT_RGBF:
+ _generate_po2_mipmap<float, 3, false, Image::average_4_float, Image::renormalize_float>(reinterpret_cast<const float *>(r), reinterpret_cast<float *>(w), width, height);
+ break;
+ case FORMAT_RGBAF:
+ _generate_po2_mipmap<float, 4, false, Image::average_4_float, Image::renormalize_float>(reinterpret_cast<const float *>(r), reinterpret_cast<float *>(w), width, height);
+ break;
+
+ case FORMAT_RH:
+ _generate_po2_mipmap<uint16_t, 1, false, Image::average_4_half, Image::renormalize_half>(reinterpret_cast<const uint16_t *>(r), reinterpret_cast<uint16_t *>(w), width, height);
+ break;
+ case FORMAT_RGH:
+ _generate_po2_mipmap<uint16_t, 2, false, Image::average_4_half, Image::renormalize_half>(reinterpret_cast<const uint16_t *>(r), reinterpret_cast<uint16_t *>(w), width, height);
+ break;
+ case FORMAT_RGBH:
+ _generate_po2_mipmap<uint16_t, 3, false, Image::average_4_half, Image::renormalize_half>(reinterpret_cast<const uint16_t *>(r), reinterpret_cast<uint16_t *>(w), width, height);
+ break;
+ case FORMAT_RGBAH:
+ _generate_po2_mipmap<uint16_t, 4, false, Image::average_4_half, Image::renormalize_half>(reinterpret_cast<const uint16_t *>(r), reinterpret_cast<uint16_t *>(w), width, height);
+ break;
+
+ case FORMAT_RGBE9995:
+ _generate_po2_mipmap<uint32_t, 1, false, Image::average_4_rgbe9995, Image::renormalize_rgbe9995>(reinterpret_cast<const uint32_t *>(r), reinterpret_cast<uint32_t *>(w), width, height);
+ break;
default: {
}
}
@@ -1429,16 +1539,13 @@ void Image::shrink_x2() {
}
void Image::normalize() {
-
bool used_mipmaps = has_mipmaps();
if (used_mipmaps) {
clear_mipmaps();
}
for (int y = 0; y < height; y++) {
-
for (int x = 0; x < width; x++) {
-
Color c = get_pixel(x, y);
Vector3 v(c.r * 2.0 - 1.0, c.g * 2.0 - 1.0, c.b * 2.0 - 1.0);
v.normalize();
@@ -1455,7 +1562,6 @@ void Image::normalize() {
}
Error Image::generate_mipmaps(bool p_renormalize) {
-
ERR_FAIL_COND_V_MSG(!_can_modify(format), ERR_UNAVAILABLE, "Cannot generate mipmaps in compressed or custom image formats.");
ERR_FAIL_COND_V_MSG(format == FORMAT_RGBA4444, ERR_UNAVAILABLE, "Cannot generate mipmaps from RGBA4444 format.");
@@ -1475,28 +1581,32 @@ Error Image::generate_mipmaps(bool p_renormalize) {
int prev_w = width;
for (int i = 1; i <= mmcount; i++) {
-
int ofs, w, h;
_get_mipmap_offset_and_size(i, ofs, w, h);
switch (format) {
-
case FORMAT_L8:
- case FORMAT_R8: _generate_po2_mipmap<uint8_t, 1, false, Image::average_4_uint8, Image::renormalize_uint8>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h); break;
+ case FORMAT_R8:
+ _generate_po2_mipmap<uint8_t, 1, false, Image::average_4_uint8, Image::renormalize_uint8>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h);
+ break;
case FORMAT_LA8:
- case FORMAT_RG8: _generate_po2_mipmap<uint8_t, 2, false, Image::average_4_uint8, Image::renormalize_uint8>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h); break;
+ case FORMAT_RG8:
+ _generate_po2_mipmap<uint8_t, 2, false, Image::average_4_uint8, Image::renormalize_uint8>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h);
+ break;
case FORMAT_RGB8:
- if (p_renormalize)
+ if (p_renormalize) {
_generate_po2_mipmap<uint8_t, 3, true, Image::average_4_uint8, Image::renormalize_uint8>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h);
- else
+ } else {
_generate_po2_mipmap<uint8_t, 3, false, Image::average_4_uint8, Image::renormalize_uint8>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h);
+ }
break;
case FORMAT_RGBA8:
- if (p_renormalize)
+ if (p_renormalize) {
_generate_po2_mipmap<uint8_t, 4, true, Image::average_4_uint8, Image::renormalize_uint8>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h);
- else
+ } else {
_generate_po2_mipmap<uint8_t, 4, false, Image::average_4_uint8, Image::renormalize_uint8>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h);
+ }
break;
case FORMAT_RF:
_generate_po2_mipmap<float, 1, false, Image::average_4_float, Image::renormalize_float>(reinterpret_cast<const float *>(&wp[prev_ofs]), reinterpret_cast<float *>(&wp[ofs]), prev_w, prev_h);
@@ -1505,17 +1615,19 @@ Error Image::generate_mipmaps(bool p_renormalize) {
_generate_po2_mipmap<float, 2, false, Image::average_4_float, Image::renormalize_float>(reinterpret_cast<const float *>(&wp[prev_ofs]), reinterpret_cast<float *>(&wp[ofs]), prev_w, prev_h);
break;
case FORMAT_RGBF:
- if (p_renormalize)
+ if (p_renormalize) {
_generate_po2_mipmap<float, 3, true, Image::average_4_float, Image::renormalize_float>(reinterpret_cast<const float *>(&wp[prev_ofs]), reinterpret_cast<float *>(&wp[ofs]), prev_w, prev_h);
- else
+ } else {
_generate_po2_mipmap<float, 3, false, Image::average_4_float, Image::renormalize_float>(reinterpret_cast<const float *>(&wp[prev_ofs]), reinterpret_cast<float *>(&wp[ofs]), prev_w, prev_h);
+ }
break;
case FORMAT_RGBAF:
- if (p_renormalize)
+ if (p_renormalize) {
_generate_po2_mipmap<float, 4, true, Image::average_4_float, Image::renormalize_float>(reinterpret_cast<const float *>(&wp[prev_ofs]), reinterpret_cast<float *>(&wp[ofs]), prev_w, prev_h);
- else
+ } else {
_generate_po2_mipmap<float, 4, false, Image::average_4_float, Image::renormalize_float>(reinterpret_cast<const float *>(&wp[prev_ofs]), reinterpret_cast<float *>(&wp[ofs]), prev_w, prev_h);
+ }
break;
case FORMAT_RH:
@@ -1525,24 +1637,27 @@ Error Image::generate_mipmaps(bool p_renormalize) {
_generate_po2_mipmap<uint16_t, 2, false, Image::average_4_half, Image::renormalize_half>(reinterpret_cast<const uint16_t *>(&wp[prev_ofs]), reinterpret_cast<uint16_t *>(&wp[ofs]), prev_w, prev_h);
break;
case FORMAT_RGBH:
- if (p_renormalize)
+ if (p_renormalize) {
_generate_po2_mipmap<uint16_t, 3, true, Image::average_4_half, Image::renormalize_half>(reinterpret_cast<const uint16_t *>(&wp[prev_ofs]), reinterpret_cast<uint16_t *>(&wp[ofs]), prev_w, prev_h);
- else
+ } else {
_generate_po2_mipmap<uint16_t, 3, false, Image::average_4_half, Image::renormalize_half>(reinterpret_cast<const uint16_t *>(&wp[prev_ofs]), reinterpret_cast<uint16_t *>(&wp[ofs]), prev_w, prev_h);
+ }
break;
case FORMAT_RGBAH:
- if (p_renormalize)
+ if (p_renormalize) {
_generate_po2_mipmap<uint16_t, 4, true, Image::average_4_half, Image::renormalize_half>(reinterpret_cast<const uint16_t *>(&wp[prev_ofs]), reinterpret_cast<uint16_t *>(&wp[ofs]), prev_w, prev_h);
- else
+ } else {
_generate_po2_mipmap<uint16_t, 4, false, Image::average_4_half, Image::renormalize_half>(reinterpret_cast<const uint16_t *>(&wp[prev_ofs]), reinterpret_cast<uint16_t *>(&wp[ofs]), prev_w, prev_h);
+ }
break;
case FORMAT_RGBE9995:
- if (p_renormalize)
+ if (p_renormalize) {
_generate_po2_mipmap<uint32_t, 1, true, Image::average_4_rgbe9995, Image::renormalize_rgbe9995>(reinterpret_cast<const uint32_t *>(&wp[prev_ofs]), reinterpret_cast<uint32_t *>(&wp[ofs]), prev_w, prev_h);
- else
+ } else {
_generate_po2_mipmap<uint32_t, 1, false, Image::average_4_rgbe9995, Image::renormalize_rgbe9995>(reinterpret_cast<const uint32_t *>(&wp[prev_ofs]), reinterpret_cast<uint32_t *>(&wp[ofs]), prev_w, prev_h);
+ }
break;
default: {
@@ -1560,7 +1675,6 @@ Error Image::generate_mipmaps(bool p_renormalize) {
}
Error Image::generate_mipmap_roughness(RoughnessChannel p_roughness_channel, const Ref<Image> &p_normal_map) {
-
Vector<double> normal_sat_vec; //summed area table
double *normal_sat = nullptr; //summed area table for normalmap
int normal_w = 0, normal_h = 0;
@@ -1625,7 +1739,6 @@ 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;
_get_mipmap_offset_and_size(i, ofs, w, h);
uint8_t *ptr = &base_ptr[ofs];
@@ -1680,7 +1793,7 @@ Error Image::generate_mipmap_roughness(RoughnessChannel p_roughness_channel, con
int pixel_ofs = y * w + x;
Color c = _get_color_at_ofs(ptr, pixel_ofs);
- float roughness;
+ float roughness = 0;
switch (p_roughness_channel) {
case ROUGHNESS_CHANNEL_R: {
@@ -1756,12 +1869,13 @@ Error Image::generate_mipmap_roughness(RoughnessChannel p_roughness_channel, con
}
void Image::clear_mipmaps() {
-
- if (!mipmaps)
+ if (!mipmaps) {
return;
+ }
- if (empty())
+ if (empty()) {
return;
+ }
int ofs, w, h;
_get_mipmap_offset_and_size(1, ofs, w, h);
@@ -1771,17 +1885,14 @@ void Image::clear_mipmaps() {
}
bool Image::empty() const {
-
return (data.size() == 0);
}
Vector<uint8_t> Image::get_data() const {
-
return data;
}
void Image::create(int p_width, int p_height, bool p_use_mipmaps, Format p_format) {
-
ERR_FAIL_INDEX(p_width - 1, MAX_WIDTH);
ERR_FAIL_INDEX(p_height - 1, MAX_HEIGHT);
ERR_FAIL_COND_MSG(p_width * p_height > MAX_PIXELS, "Too many pixels for image, maximum is " + itos(MAX_PIXELS));
@@ -1802,7 +1913,6 @@ void Image::create(int p_width, int p_height, bool p_use_mipmaps, Format p_forma
}
void Image::create(int p_width, int p_height, bool p_use_mipmaps, Format p_format, const Vector<uint8_t> &p_data) {
-
ERR_FAIL_INDEX(p_width - 1, MAX_WIDTH);
ERR_FAIL_INDEX(p_height - 1, MAX_HEIGHT);
ERR_FAIL_COND_MSG(p_width * p_height > MAX_PIXELS, "Too many pixels for image, maximum is " + itos(MAX_PIXELS));
@@ -1821,7 +1931,6 @@ void Image::create(int p_width, int p_height, bool p_use_mipmaps, Format p_forma
}
void Image::create(const char **p_xpm) {
-
int size_width = 0;
int size_height = 0;
int pixelchars = 0;
@@ -1841,16 +1950,13 @@ void Image::create(const char **p_xpm) {
HashMap<String, Color> colormap;
int colormap_size = 0;
uint32_t pixel_size = 0;
- uint8_t *w;
+ uint8_t *data_write = nullptr;
while (status != DONE) {
-
const char *line_ptr = p_xpm[line];
switch (status) {
-
case READING_HEADER: {
-
String line_str = line_ptr;
line_str.replace("\t", " ");
@@ -1865,25 +1971,24 @@ void Image::create(const char **p_xpm) {
status = READING_COLORS;
} break;
case READING_COLORS: {
-
String colorstring;
for (int i = 0; i < pixelchars; i++) {
-
colorstring += *line_ptr;
line_ptr++;
}
//skip spaces
while (*line_ptr == ' ' || *line_ptr == '\t' || *line_ptr == 0) {
- if (*line_ptr == 0)
+ if (*line_ptr == 0) {
break;
+ }
line_ptr++;
}
if (*line_ptr == 'c') {
-
line_ptr++;
while (*line_ptr == ' ' || *line_ptr == '\t' || *line_ptr == 0) {
- if (*line_ptr == 0)
+ if (*line_ptr == 0) {
break;
+ }
line_ptr++;
}
@@ -1895,55 +2000,63 @@ void Image::create(const char **p_xpm) {
//uint8_t col_a=255;
for (int i = 0; i < 6; i++) {
-
char v = line_ptr[i];
- if (v >= '0' && v <= '9')
+ if (v >= '0' && v <= '9') {
v -= '0';
- else if (v >= 'A' && v <= 'F')
+ } else if (v >= 'A' && v <= 'F') {
v = (v - 'A') + 10;
- else if (v >= 'a' && v <= 'f')
+ } else if (v >= 'a' && v <= 'f') {
v = (v - 'a') + 10;
- else
+ } else {
break;
+ }
switch (i) {
- case 0: col_r = v << 4; break;
- case 1: col_r |= v; break;
- case 2: col_g = v << 4; break;
- case 3: col_g |= v; break;
- case 4: col_b = v << 4; break;
- case 5: col_b |= v; break;
- };
+ case 0:
+ col_r = v << 4;
+ break;
+ case 1:
+ col_r |= v;
+ break;
+ case 2:
+ col_g = v << 4;
+ break;
+ case 3:
+ col_g |= v;
+ break;
+ case 4:
+ col_b = v << 4;
+ break;
+ case 5:
+ col_b |= v;
+ break;
+ }
}
// magenta mask
if (col_r == 255 && col_g == 0 && col_b == 255) {
-
colormap[colorstring] = Color(0, 0, 0, 0);
has_alpha = true;
} else {
-
colormap[colorstring] = Color(col_r / 255.0, col_g / 255.0, col_b / 255.0, 1.0);
}
}
}
if (line == colormap_size) {
-
status = READING_PIXELS;
- create(size_width, size_height, 0, has_alpha ? FORMAT_RGBA8 : FORMAT_RGB8);
- w = data.ptrw();
+ create(size_width, size_height, false, has_alpha ? FORMAT_RGBA8 : FORMAT_RGB8);
+ data_write = data.ptrw();
pixel_size = has_alpha ? 4 : 3;
}
} break;
case READING_PIXELS: {
-
int y = line - colormap_size - 1;
for (int x = 0; x < size_width; x++) {
-
char pixelstr[6] = { 0, 0, 0, 0, 0, 0 };
- for (int i = 0; i < pixelchars; i++)
+ for (int i = 0; i < pixelchars; i++) {
pixelstr[i] = line_ptr[x * pixelchars + i];
+ }
Color *colorptr = colormap.getptr(pixelstr);
ERR_FAIL_COND(!colorptr);
@@ -1951,11 +2064,12 @@ void Image::create(const char **p_xpm) {
for (uint32_t i = 0; i < pixel_size; i++) {
pixel[i] = CLAMP((*colorptr)[i] * 255, 0, 255);
}
- _put_pixelb(x, y, pixel_size, w, pixel);
+ _put_pixelb(x, y, pixel_size, data_write, pixel);
}
- if (y == (size_height - 1))
+ if (y == (size_height - 1)) {
status = DONE;
+ }
} break;
default: {
}
@@ -1973,7 +2087,6 @@ void Image::create(const char **p_xpm) {
if (value < DETECT_ALPHA_MIN_THRESHOLD) \
bit = true; \
else if (value < DETECT_ALPHA_MAX_THRESHOLD) { \
- \
detected = true; \
break; \
} \
@@ -1983,22 +2096,22 @@ void Image::create(const char **p_xpm) {
{ \
uint8_t value = m_value; \
if (value > 0) { \
- \
detected = true; \
break; \
} \
}
bool Image::is_invisible() const {
-
if (format == FORMAT_L8 ||
- format == FORMAT_RGB8 || format == FORMAT_RG8)
+ format == FORMAT_RGB8 || format == FORMAT_RG8) {
return false;
+ }
int len = data.size();
- if (len == 0)
+ if (len == 0) {
return true;
+ }
int w, h;
_get_mipmap_offset_and_size(1, len, w, h);
@@ -2009,16 +2122,13 @@ bool Image::is_invisible() const {
bool detected = false;
switch (format) {
-
case FORMAT_LA8: {
-
for (int i = 0; i < (len >> 1); i++) {
DETECT_NON_ALPHA(data_ptr[(i << 1) + 1]);
}
} break;
case FORMAT_RGBA8: {
-
for (int i = 0; i < (len >> 2); i++) {
DETECT_NON_ALPHA(data_ptr[(i << 2) + 3])
}
@@ -2039,11 +2149,11 @@ bool Image::is_invisible() const {
}
Image::AlphaMode Image::detect_alpha() const {
-
int len = data.size();
- if (len == 0)
+ if (len == 0) {
return ALPHA_NONE;
+ }
int w, h;
_get_mipmap_offset_and_size(1, len, w, h);
@@ -2055,16 +2165,13 @@ Image::AlphaMode Image::detect_alpha() const {
bool detected = false;
switch (format) {
-
case FORMAT_LA8: {
-
for (int i = 0; i < (len >> 1); i++) {
DETECT_ALPHA(data_ptr[(i << 1) + 1]);
}
} break;
case FORMAT_RGBA8: {
-
for (int i = 0; i < (len >> 2); i++) {
DETECT_ALPHA(data_ptr[(i << 2) + 3])
}
@@ -2080,12 +2187,13 @@ Image::AlphaMode Image::detect_alpha() const {
}
}
- if (detected)
+ if (detected) {
return ALPHA_BLEND;
- else if (bit)
+ } else if (bit) {
return ALPHA_BIT;
- else
+ } else {
return ALPHA_NONE;
+ }
}
Error Image::load(const String &p_path) {
@@ -2098,15 +2206,15 @@ Error Image::load(const String &p_path) {
}
Error Image::save_png(const String &p_path) const {
-
- if (save_png_func == NULL)
+ if (save_png_func == nullptr) {
return ERR_UNAVAILABLE;
+ }
return save_png_func(p_path, Ref<Image>((Image *)this));
}
Vector<uint8_t> Image::save_png_to_buffer() const {
- if (save_png_buffer_func == NULL) {
+ if (save_png_buffer_func == nullptr) {
return Vector<uint8_t>();
}
@@ -2114,21 +2222,19 @@ Vector<uint8_t> Image::save_png_to_buffer() const {
}
Error Image::save_exr(const String &p_path, bool p_grayscale) const {
-
- if (save_exr_func == NULL)
+ if (save_exr_func == nullptr) {
return ERR_UNAVAILABLE;
+ }
return save_exr_func(p_path, Ref<Image>((Image *)this), p_grayscale);
}
int 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);
}
int Image::get_image_required_mipmaps(int p_width, int p_height, Format p_format) {
-
int mm;
_get_dst_image_size(p_width, p_height, p_format, mm, -1);
return mm;
@@ -2142,7 +2248,6 @@ Size2i Image::get_image_mipmap_size(int p_width, int p_height, Format p_format,
}
int Image::get_image_mipmap_offset(int p_width, int p_height, Format p_format, int p_mipmap) {
-
if (p_mipmap <= 0) {
return 0;
}
@@ -2151,7 +2256,6 @@ int Image::get_image_mipmap_offset(int p_width, int p_height, Format p_format, i
}
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) {
-
if (p_mipmap <= 0) {
r_w = p_width;
r_h = p_height;
@@ -2166,57 +2270,49 @@ bool Image::is_compressed() const {
}
Error Image::decompress() {
-
- if (((format >= FORMAT_DXT1 && format <= FORMAT_RGTC_RG) || (format == FORMAT_DXT5_RA_AS_RG)) && _image_decompress_bc)
+ if (((format >= FORMAT_DXT1 && format <= FORMAT_RGTC_RG) || (format == FORMAT_DXT5_RA_AS_RG)) && _image_decompress_bc) {
_image_decompress_bc(this);
- else if (format >= FORMAT_BPTC_RGBA && format <= FORMAT_BPTC_RGBFU && _image_decompress_bptc)
+ } else if (format >= FORMAT_BPTC_RGBA && format <= FORMAT_BPTC_RGBFU && _image_decompress_bptc) {
_image_decompress_bptc(this);
- else if (format >= FORMAT_PVRTC2 && format <= FORMAT_PVRTC4A && _image_decompress_pvrtc)
+ } else if (format >= FORMAT_PVRTC2 && format <= FORMAT_PVRTC4A && _image_decompress_pvrtc) {
_image_decompress_pvrtc(this);
- else if (format == FORMAT_ETC && _image_decompress_etc1)
+ } else if (format == FORMAT_ETC && _image_decompress_etc1) {
_image_decompress_etc1(this);
- else if (format >= FORMAT_ETC2_R11 && format <= FORMAT_ETC2_RA_AS_RG && _image_decompress_etc2)
+ } else if (format >= FORMAT_ETC2_R11 && format <= FORMAT_ETC2_RA_AS_RG && _image_decompress_etc2) {
_image_decompress_etc2(this);
- else
+ } else {
return ERR_UNAVAILABLE;
+ }
return OK;
}
Error Image::compress(CompressMode p_mode, CompressSource p_source, float p_lossy_quality) {
-
return compress_from_channels(p_mode, detect_used_channels(p_source), p_lossy_quality);
}
-Error Image::compress_from_channels(CompressMode p_mode, UsedChannels p_channels, float p_lossy_quality) {
+Error Image::compress_from_channels(CompressMode p_mode, UsedChannels p_channels, float p_lossy_quality) {
switch (p_mode) {
-
case COMPRESS_S3TC: {
-
ERR_FAIL_COND_V(!_image_compress_bc_func, ERR_UNAVAILABLE);
_image_compress_bc_func(this, p_lossy_quality, p_channels);
} break;
case COMPRESS_PVRTC2: {
-
ERR_FAIL_COND_V(!_image_compress_pvrtc2_func, ERR_UNAVAILABLE);
_image_compress_pvrtc2_func(this);
} break;
case COMPRESS_PVRTC4: {
-
ERR_FAIL_COND_V(!_image_compress_pvrtc4_func, ERR_UNAVAILABLE);
_image_compress_pvrtc4_func(this);
} break;
case COMPRESS_ETC: {
-
ERR_FAIL_COND_V(!_image_compress_etc1_func, ERR_UNAVAILABLE);
_image_compress_etc1_func(this, p_lossy_quality);
} break;
case COMPRESS_ETC2: {
-
ERR_FAIL_COND_V(!_image_compress_etc2_func, ERR_UNAVAILABLE);
_image_compress_etc2_func(this, p_lossy_quality, p_channels);
} break;
case COMPRESS_BPTC: {
-
ERR_FAIL_COND_V(!_image_compress_bptc_func, ERR_UNAVAILABLE);
_image_compress_bptc_func(this, p_lossy_quality, p_channels);
} break;
@@ -2226,7 +2322,6 @@ Error Image::compress_from_channels(CompressMode p_mode, UsedChannels p_channels
}
Image::Image(const char **p_xpm) {
-
width = 0;
height = 0;
mipmaps = false;
@@ -2236,7 +2331,6 @@ Image::Image(const char **p_xpm) {
}
Image::Image(int p_width, int p_height, bool p_use_mipmaps, Format p_format) {
-
width = 0;
height = 0;
mipmaps = p_use_mipmaps;
@@ -2246,7 +2340,6 @@ Image::Image(int p_width, int p_height, bool p_use_mipmaps, Format p_format) {
}
Image::Image(int p_width, int p_height, bool p_mipmaps, Format p_format, const Vector<uint8_t> &p_data) {
-
width = 0;
height = 0;
mipmaps = p_mipmaps;
@@ -2256,48 +2349,52 @@ Image::Image(int p_width, int p_height, bool p_mipmaps, Format p_format, const V
}
Rect2 Image::get_used_rect() const {
-
- if (format != FORMAT_LA8 && format != FORMAT_RGBA8 && format != FORMAT_RGBAF && format != FORMAT_RGBAH && format != FORMAT_RGBA4444 && format != FORMAT_RGB565)
+ if (format != FORMAT_LA8 && format != FORMAT_RGBA8 && format != FORMAT_RGBAF && format != FORMAT_RGBAH && format != FORMAT_RGBA4444 && format != FORMAT_RGB565) {
return Rect2(Point2(), Size2(width, height));
+ }
int len = data.size();
- if (len == 0)
+ if (len == 0) {
return Rect2();
+ }
int minx = 0xFFFFFF, miny = 0xFFFFFFF;
int maxx = -1, maxy = -1;
for (int j = 0; j < height; j++) {
for (int i = 0; i < width; i++) {
-
- if (!(get_pixel(i, j).a > 0))
+ if (!(get_pixel(i, j).a > 0)) {
continue;
- if (i > maxx)
+ }
+ if (i > maxx) {
maxx = i;
- if (j > maxy)
+ }
+ if (j > maxy) {
maxy = j;
- if (i < minx)
+ }
+ if (i < minx) {
minx = i;
- if (j < miny)
+ }
+ if (j < miny) {
miny = j;
+ }
}
}
- if (maxx == -1)
+ if (maxx == -1) {
return Rect2();
- else
+ } else {
return Rect2(minx, miny, maxx - minx + 1, maxy - miny + 1);
+ }
}
Ref<Image> Image::get_rect(const Rect2 &p_area) const {
-
Ref<Image> img = memnew(Image(p_area.size.x, p_area.size.y, mipmaps, format));
img->blit_rect(Ref<Image>((Image *)this), p_area, Point2(0, 0));
return img;
}
void Image::blit_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const Point2 &p_dest) {
-
ERR_FAIL_COND_MSG(p_src.is_null(), "It's not a reference to a valid Image object.");
int dsize = data.size();
int srcdsize = p_src->data.size();
@@ -2308,13 +2405,16 @@ void Image::blit_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const Po
Rect2i clipped_src_rect = Rect2i(0, 0, p_src->width, p_src->height).clip(p_src_rect);
- if (p_dest.x < 0)
+ if (p_dest.x < 0) {
clipped_src_rect.position.x = ABS(p_dest.x);
- if (p_dest.y < 0)
+ }
+ if (p_dest.y < 0) {
clipped_src_rect.position.y = ABS(p_dest.y);
+ }
- if (clipped_src_rect.size.x <= 0 || clipped_src_rect.size.y <= 0)
+ if (clipped_src_rect.size.x <= 0 || clipped_src_rect.size.y <= 0) {
return;
+ }
Point2 src_underscan = Point2(MIN(0, p_src_rect.position.x), MIN(0, p_src_rect.position.y));
Rect2i dest_rect = Rect2i(0, 0, width, height).clip(Rect2i(p_dest - src_underscan, clipped_src_rect.size));
@@ -2328,9 +2428,7 @@ void Image::blit_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const Po
int pixel_size = get_format_pixel_size(format);
for (int i = 0; i < dest_rect.size.y; i++) {
-
for (int j = 0; j < dest_rect.size.x; j++) {
-
int src_x = clipped_src_rect.position.x + j;
int src_y = clipped_src_rect.position.y + i;
@@ -2348,7 +2446,6 @@ void Image::blit_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const Po
}
void Image::blit_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, const Rect2 &p_src_rect, const Point2 &p_dest) {
-
ERR_FAIL_COND_MSG(p_src.is_null(), "It's not a reference to a valid Image object.");
ERR_FAIL_COND_MSG(p_mask.is_null(), "It's not a reference to a valid Image object.");
int dsize = data.size();
@@ -2363,13 +2460,16 @@ void Image::blit_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, co
Rect2i clipped_src_rect = Rect2i(0, 0, p_src->width, p_src->height).clip(p_src_rect);
- if (p_dest.x < 0)
+ if (p_dest.x < 0) {
clipped_src_rect.position.x = ABS(p_dest.x);
- if (p_dest.y < 0)
+ }
+ if (p_dest.y < 0) {
clipped_src_rect.position.y = ABS(p_dest.y);
+ }
- if (clipped_src_rect.size.x <= 0 || clipped_src_rect.size.y <= 0)
+ if (clipped_src_rect.size.x <= 0 || clipped_src_rect.size.y <= 0) {
return;
+ }
Point2 src_underscan = Point2(MIN(0, p_src_rect.position.x), MIN(0, p_src_rect.position.y));
Rect2i dest_rect = Rect2i(0, 0, width, height).clip(Rect2i(p_dest - src_underscan, clipped_src_rect.size));
@@ -2385,14 +2485,11 @@ void Image::blit_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, co
Ref<Image> msk = p_mask;
for (int i = 0; i < dest_rect.size.y; i++) {
-
for (int j = 0; j < dest_rect.size.x; j++) {
-
int src_x = clipped_src_rect.position.x + j;
int src_y = clipped_src_rect.position.y + i;
if (msk->get_pixel(src_x, src_y).a != 0) {
-
int dst_x = dest_rect.position.x + j;
int dst_y = dest_rect.position.y + i;
@@ -2408,7 +2505,6 @@ void Image::blit_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, co
}
void Image::blend_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const Point2 &p_dest) {
-
ERR_FAIL_COND_MSG(p_src.is_null(), "It's not a reference to a valid Image object.");
int dsize = data.size();
int srcdsize = p_src->data.size();
@@ -2418,13 +2514,16 @@ void Image::blend_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const P
Rect2i clipped_src_rect = Rect2i(0, 0, p_src->width, p_src->height).clip(p_src_rect);
- if (p_dest.x < 0)
+ if (p_dest.x < 0) {
clipped_src_rect.position.x = ABS(p_dest.x);
- if (p_dest.y < 0)
+ }
+ if (p_dest.y < 0) {
clipped_src_rect.position.y = ABS(p_dest.y);
+ }
- if (clipped_src_rect.size.x <= 0 || clipped_src_rect.size.y <= 0)
+ if (clipped_src_rect.size.x <= 0 || clipped_src_rect.size.y <= 0) {
return;
+ }
Point2 src_underscan = Point2(MIN(0, p_src_rect.position.x), MIN(0, p_src_rect.position.y));
Rect2i dest_rect = Rect2i(0, 0, width, height).clip(Rect2i(p_dest - src_underscan, clipped_src_rect.size));
@@ -2432,9 +2531,7 @@ void Image::blend_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const P
Ref<Image> img = p_src;
for (int i = 0; i < dest_rect.size.y; i++) {
-
for (int j = 0; j < dest_rect.size.x; j++) {
-
int src_x = clipped_src_rect.position.x + j;
int src_y = clipped_src_rect.position.y + i;
@@ -2442,18 +2539,16 @@ void Image::blend_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const P
int dst_y = dest_rect.position.y + i;
Color sc = img->get_pixel(src_x, src_y);
- Color dc = get_pixel(dst_x, dst_y);
- dc.r = (double)(sc.a * sc.r + dc.a * (1.0 - sc.a) * dc.r);
- dc.g = (double)(sc.a * sc.g + dc.a * (1.0 - sc.a) * dc.g);
- dc.b = (double)(sc.a * sc.b + dc.a * (1.0 - sc.a) * dc.b);
- dc.a = (double)(sc.a + dc.a * (1.0 - sc.a));
- set_pixel(dst_x, dst_y, dc);
+ if (sc.a != 0) {
+ Color dc = get_pixel(dst_x, dst_y);
+ dc = dc.blend(sc);
+ set_pixel(dst_x, dst_y, dc);
+ }
}
}
}
void Image::blend_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, const Rect2 &p_src_rect, const Point2 &p_dest) {
-
ERR_FAIL_COND_MSG(p_src.is_null(), "It's not a reference to a valid Image object.");
ERR_FAIL_COND_MSG(p_mask.is_null(), "It's not a reference to a valid Image object.");
int dsize = data.size();
@@ -2468,13 +2563,16 @@ void Image::blend_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, c
Rect2i clipped_src_rect = Rect2i(0, 0, p_src->width, p_src->height).clip(p_src_rect);
- if (p_dest.x < 0)
+ if (p_dest.x < 0) {
clipped_src_rect.position.x = ABS(p_dest.x);
- if (p_dest.y < 0)
+ }
+ if (p_dest.y < 0) {
clipped_src_rect.position.y = ABS(p_dest.y);
+ }
- if (clipped_src_rect.size.x <= 0 || clipped_src_rect.size.y <= 0)
+ if (clipped_src_rect.size.x <= 0 || clipped_src_rect.size.y <= 0) {
return;
+ }
Point2 src_underscan = Point2(MIN(0, p_src_rect.position.x), MIN(0, p_src_rect.position.y));
Rect2i dest_rect = Rect2i(0, 0, width, height).clip(Rect2i(p_dest - src_underscan, clipped_src_rect.size));
@@ -2483,9 +2581,7 @@ void Image::blend_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, c
Ref<Image> msk = p_mask;
for (int i = 0; i < dest_rect.size.y; i++) {
-
for (int j = 0; j < dest_rect.size.x; j++) {
-
int src_x = clipped_src_rect.position.x + j;
int src_y = clipped_src_rect.position.y + i;
@@ -2493,17 +2589,15 @@ void Image::blend_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, c
//Color c = msk->get_pixel(src_x, src_y);
//if (c.a == 0) continue;
if (msk->get_pixel(src_x, src_y).a != 0) {
-
int dst_x = dest_rect.position.x + j;
int dst_y = dest_rect.position.y + i;
Color sc = img->get_pixel(src_x, src_y);
- Color dc = get_pixel(dst_x, dst_y);
- dc.r = (double)(sc.a * sc.r + dc.a * (1.0 - sc.a) * dc.r);
- dc.g = (double)(sc.a * sc.g + dc.a * (1.0 - sc.a) * dc.g);
- dc.b = (double)(sc.a * sc.b + dc.a * (1.0 - sc.a) * dc.b);
- dc.a = (double)(sc.a + dc.a * (1.0 - sc.a));
- set_pixel(dst_x, dst_y, dc);
+ if (sc.a != 0) {
+ Color dc = get_pixel(dst_x, dst_y);
+ dc = dc.blend(sc);
+ set_pixel(dst_x, dst_y, dc);
+ }
}
}
}
@@ -2521,9 +2615,7 @@ void Image::fill(const Color &c) {
set_pixel(0, 0, c);
for (int y = 0; y < height; y++) {
-
for (int x = 0; x < width; x++) {
-
uint8_t *dst = &dst_data_ptr[(y * width + x) * pixel_size];
for (int k = 0; k < pixel_size; k++) {
@@ -2533,31 +2625,30 @@ void Image::fill(const Color &c) {
}
}
-ImageMemLoadFunc Image::_png_mem_loader_func = NULL;
-ImageMemLoadFunc Image::_jpg_mem_loader_func = NULL;
-ImageMemLoadFunc Image::_webp_mem_loader_func = NULL;
+ImageMemLoadFunc Image::_png_mem_loader_func = nullptr;
+ImageMemLoadFunc Image::_jpg_mem_loader_func = nullptr;
+ImageMemLoadFunc Image::_webp_mem_loader_func = nullptr;
-void (*Image::_image_compress_bc_func)(Image *, float, Image::UsedChannels) = NULL;
-void (*Image::_image_compress_bptc_func)(Image *, float, Image::UsedChannels) = NULL;
-void (*Image::_image_compress_pvrtc2_func)(Image *) = NULL;
-void (*Image::_image_compress_pvrtc4_func)(Image *) = NULL;
-void (*Image::_image_compress_etc1_func)(Image *, float) = NULL;
-void (*Image::_image_compress_etc2_func)(Image *, float, Image::UsedChannels) = NULL;
-void (*Image::_image_decompress_pvrtc)(Image *) = NULL;
-void (*Image::_image_decompress_bc)(Image *) = NULL;
-void (*Image::_image_decompress_bptc)(Image *) = NULL;
-void (*Image::_image_decompress_etc1)(Image *) = NULL;
-void (*Image::_image_decompress_etc2)(Image *) = NULL;
+void (*Image::_image_compress_bc_func)(Image *, float, Image::UsedChannels) = nullptr;
+void (*Image::_image_compress_bptc_func)(Image *, float, Image::UsedChannels) = nullptr;
+void (*Image::_image_compress_pvrtc2_func)(Image *) = nullptr;
+void (*Image::_image_compress_pvrtc4_func)(Image *) = nullptr;
+void (*Image::_image_compress_etc1_func)(Image *, float) = nullptr;
+void (*Image::_image_compress_etc2_func)(Image *, float, Image::UsedChannels) = nullptr;
+void (*Image::_image_decompress_pvrtc)(Image *) = 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;
-Vector<uint8_t> (*Image::lossy_packer)(const Ref<Image> &, float) = NULL;
-Ref<Image> (*Image::lossy_unpacker)(const Vector<uint8_t> &) = NULL;
-Vector<uint8_t> (*Image::lossless_packer)(const Ref<Image> &) = NULL;
-Ref<Image> (*Image::lossless_unpacker)(const Vector<uint8_t> &) = NULL;
-Vector<uint8_t> (*Image::basis_universal_packer)(const Ref<Image> &, Image::UsedChannels) = NULL;
-Ref<Image> (*Image::basis_universal_unpacker)(const Vector<uint8_t> &) = NULL;
+Vector<uint8_t> (*Image::lossy_packer)(const Ref<Image> &, float) = nullptr;
+Ref<Image> (*Image::lossy_unpacker)(const Vector<uint8_t> &) = nullptr;
+Vector<uint8_t> (*Image::lossless_packer)(const Ref<Image> &) = nullptr;
+Ref<Image> (*Image::lossless_unpacker)(const Vector<uint8_t> &) = nullptr;
+Vector<uint8_t> (*Image::basis_universal_packer)(const Ref<Image> &, Image::UsedChannels) = nullptr;
+Ref<Image> (*Image::basis_universal_unpacker)(const Vector<uint8_t> &) = nullptr;
void Image::_set_data(const Dictionary &p_data) {
-
ERR_FAIL_COND(!p_data.has("width"));
ERR_FAIL_COND(!p_data.has("height"));
ERR_FAIL_COND(!p_data.has("format"));
@@ -2583,7 +2674,6 @@ void Image::_set_data(const Dictionary &p_data) {
}
Dictionary Image::_get_data() const {
-
Dictionary d;
d["width"] = width;
d["height"] = height;
@@ -2598,7 +2688,6 @@ Color Image::get_pixelv(const Point2 &p_src) const {
}
Color Image::_get_color_at_ofs(const uint8_t *ptr, uint32_t ofs) const {
-
switch (format) {
case FORMAT_L8: {
float l = ptr[ofs] / 255.0;
@@ -2610,12 +2699,10 @@ Color Image::_get_color_at_ofs(const uint8_t *ptr, uint32_t ofs) const {
return Color(l, l, l, a);
}
case FORMAT_R8: {
-
float r = ptr[ofs] / 255.0;
return Color(r, 0, 0, 1);
}
case FORMAT_RG8: {
-
float r = ptr[ofs * 2 + 0] / 255.0;
float g = ptr[ofs * 2 + 1] / 255.0;
return Color(r, g, 0, 1);
@@ -2642,7 +2729,6 @@ Color Image::_get_color_at_ofs(const uint8_t *ptr, uint32_t ofs) const {
return Color(r, g, b, a);
}
case FORMAT_RGB565: {
-
uint16_t u = ((uint16_t *)ptr)[ofs];
float r = (u & 0x1F) / 31.0;
float g = ((u >> 5) & 0x3F) / 63.0;
@@ -2650,25 +2736,21 @@ Color Image::_get_color_at_ofs(const uint8_t *ptr, uint32_t ofs) const {
return Color(r, g, b, 1.0);
}
case FORMAT_RF: {
-
float r = ((float *)ptr)[ofs];
return Color(r, 0, 0, 1);
}
case FORMAT_RGF: {
-
float r = ((float *)ptr)[ofs * 2 + 0];
float g = ((float *)ptr)[ofs * 2 + 1];
return Color(r, g, 0, 1);
}
case FORMAT_RGBF: {
-
float r = ((float *)ptr)[ofs * 3 + 0];
float g = ((float *)ptr)[ofs * 3 + 1];
float b = ((float *)ptr)[ofs * 3 + 2];
return Color(r, g, b, 1);
}
case FORMAT_RGBAF: {
-
float r = ((float *)ptr)[ofs * 4 + 0];
float g = ((float *)ptr)[ofs * 4 + 1];
float b = ((float *)ptr)[ofs * 4 + 2];
@@ -2676,25 +2758,21 @@ Color Image::_get_color_at_ofs(const uint8_t *ptr, uint32_t ofs) const {
return Color(r, g, b, a);
}
case FORMAT_RH: {
-
uint16_t r = ((uint16_t *)ptr)[ofs];
return Color(Math::half_to_float(r), 0, 0, 1);
}
case FORMAT_RGH: {
-
uint16_t r = ((uint16_t *)ptr)[ofs * 2 + 0];
uint16_t g = ((uint16_t *)ptr)[ofs * 2 + 1];
return Color(Math::half_to_float(r), Math::half_to_float(g), 0, 1);
}
case FORMAT_RGBH: {
-
uint16_t r = ((uint16_t *)ptr)[ofs * 3 + 0];
uint16_t g = ((uint16_t *)ptr)[ofs * 3 + 1];
uint16_t b = ((uint16_t *)ptr)[ofs * 3 + 2];
return Color(Math::half_to_float(r), Math::half_to_float(g), Math::half_to_float(b), 1);
}
case FORMAT_RGBAH: {
-
uint16_t r = ((uint16_t *)ptr)[ofs * 4 + 0];
uint16_t g = ((uint16_t *)ptr)[ofs * 4 + 1];
uint16_t b = ((uint16_t *)ptr)[ofs * 4 + 2];
@@ -2720,11 +2798,9 @@ void Image::_set_color_at_ofs(uint8_t *ptr, uint32_t ofs, const Color &p_color)
ptr[ofs * 2 + 1] = uint8_t(CLAMP(p_color.a * 255.0, 0, 255));
} break;
case FORMAT_R8: {
-
ptr[ofs] = uint8_t(CLAMP(p_color.r * 255.0, 0, 255));
} break;
case FORMAT_RG8: {
-
ptr[ofs * 2 + 0] = uint8_t(CLAMP(p_color.r * 255.0, 0, 255));
ptr[ofs * 2 + 1] = uint8_t(CLAMP(p_color.g * 255.0, 0, 255));
} break;
@@ -2741,7 +2817,6 @@ void Image::_set_color_at_ofs(uint8_t *ptr, uint32_t ofs, const Color &p_color)
} break;
case FORMAT_RGBA4444: {
-
uint16_t rgba = 0;
rgba = uint16_t(CLAMP(p_color.r * 15.0, 0, 15)) << 12;
@@ -2753,7 +2828,6 @@ void Image::_set_color_at_ofs(uint8_t *ptr, uint32_t ofs, const Color &p_color)
} break;
case FORMAT_RGB565: {
-
uint16_t rgba = 0;
rgba = uint16_t(CLAMP(p_color.r * 31.0, 0, 31));
@@ -2764,51 +2838,42 @@ void Image::_set_color_at_ofs(uint8_t *ptr, uint32_t ofs, const Color &p_color)
} break;
case FORMAT_RF: {
-
((float *)ptr)[ofs] = p_color.r;
} break;
case FORMAT_RGF: {
-
((float *)ptr)[ofs * 2 + 0] = p_color.r;
((float *)ptr)[ofs * 2 + 1] = p_color.g;
} break;
case FORMAT_RGBF: {
-
((float *)ptr)[ofs * 3 + 0] = p_color.r;
((float *)ptr)[ofs * 3 + 1] = p_color.g;
((float *)ptr)[ofs * 3 + 2] = p_color.b;
} break;
case FORMAT_RGBAF: {
-
((float *)ptr)[ofs * 4 + 0] = p_color.r;
((float *)ptr)[ofs * 4 + 1] = p_color.g;
((float *)ptr)[ofs * 4 + 2] = p_color.b;
((float *)ptr)[ofs * 4 + 3] = p_color.a;
} break;
case FORMAT_RH: {
-
((uint16_t *)ptr)[ofs] = Math::make_half_float(p_color.r);
} break;
case FORMAT_RGH: {
-
((uint16_t *)ptr)[ofs * 2 + 0] = Math::make_half_float(p_color.r);
((uint16_t *)ptr)[ofs * 2 + 1] = Math::make_half_float(p_color.g);
} break;
case FORMAT_RGBH: {
-
((uint16_t *)ptr)[ofs * 3 + 0] = Math::make_half_float(p_color.r);
((uint16_t *)ptr)[ofs * 3 + 1] = Math::make_half_float(p_color.g);
((uint16_t *)ptr)[ofs * 3 + 2] = Math::make_half_float(p_color.b);
} break;
case FORMAT_RGBAH: {
-
((uint16_t *)ptr)[ofs * 4 + 0] = Math::make_half_float(p_color.r);
((uint16_t *)ptr)[ofs * 4 + 1] = Math::make_half_float(p_color.g);
((uint16_t *)ptr)[ofs * 4 + 2] = Math::make_half_float(p_color.b);
((uint16_t *)ptr)[ofs * 4 + 3] = Math::make_half_float(p_color.a);
} break;
case FORMAT_RGBE9995: {
-
((uint32_t *)ptr)[ofs] = p_color.to_rgbe9995();
} break;
@@ -2843,24 +2908,26 @@ void Image::set_pixel(int p_x, int p_y, const Color &p_color) {
}
Image::UsedChannels Image::detect_used_channels(CompressSource p_source) {
-
ERR_FAIL_COND_V(data.size() == 0, USED_CHANNELS_RGBA);
ERR_FAIL_COND_V(is_compressed(), USED_CHANNELS_RGBA);
bool r = false, g = false, b = false, a = false, c = false;
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
-
Color col = get_pixel(i, j);
- if (col.r > 0.001)
+ if (col.r > 0.001) {
r = true;
- if (col.g > 0.001)
+ }
+ if (col.g > 0.001) {
g = true;
- if (col.b > 0.001)
+ }
+ if (col.b > 0.001) {
b = true;
- if (col.a < 0.999)
+ }
+ if (col.a < 0.999) {
a = true;
+ }
if (col.r != col.b || col.r != col.g || col.b != col.g) {
c = true;
@@ -2870,18 +2937,19 @@ Image::UsedChannels Image::detect_used_channels(CompressSource p_source) {
UsedChannels used_channels;
- if (!c && !a)
+ if (!c && !a) {
used_channels = USED_CHANNELS_L;
- else if (!c && a)
+ } else if (!c && a) {
used_channels = USED_CHANNELS_LA;
- else if (r && !g && !b && !a)
+ } else if (r && !g && !b && !a) {
used_channels = USED_CHANNELS_R;
- else if (r && g && !b && !a)
+ } else if (r && g && !b && !a) {
used_channels = USED_CHANNELS_RG;
- else if (r && g && b && !a)
+ } else if (r && g && b && !a) {
used_channels = USED_CHANNELS_RGB;
- else
+ } else {
used_channels = USED_CHANNELS_RGBA;
+ }
if (p_source == COMPRESS_SOURCE_SRGB && (used_channels == USED_CHANNELS_R || used_channels == USED_CHANNELS_RG)) {
//R and RG do not support SRGB
@@ -2898,17 +2966,28 @@ Image::UsedChannels Image::detect_used_channels(CompressSource p_source) {
void Image::optimize_channels() {
switch (detect_used_channels()) {
- case USED_CHANNELS_L: convert(FORMAT_L8); break;
- case USED_CHANNELS_LA: convert(FORMAT_LA8); break;
- case USED_CHANNELS_R: convert(FORMAT_R8); break;
- case USED_CHANNELS_RG: convert(FORMAT_RG8); break;
- case USED_CHANNELS_RGB: convert(FORMAT_RGB8); break;
- case USED_CHANNELS_RGBA: convert(FORMAT_RGBA8); break;
+ case USED_CHANNELS_L:
+ convert(FORMAT_L8);
+ break;
+ case USED_CHANNELS_LA:
+ convert(FORMAT_LA8);
+ break;
+ case USED_CHANNELS_R:
+ convert(FORMAT_R8);
+ break;
+ case USED_CHANNELS_RG:
+ convert(FORMAT_RG8);
+ break;
+ case USED_CHANNELS_RGB:
+ convert(FORMAT_RGB8);
+ break;
+ case USED_CHANNELS_RGBA:
+ convert(FORMAT_RGBA8);
+ break;
}
}
void Image::_bind_methods() {
-
ClassDB::bind_method(D_METHOD("get_width"), &Image::get_width);
ClassDB::bind_method(D_METHOD("get_height"), &Image::get_height);
ClassDB::bind_method(D_METHOD("get_size"), &Image::get_size);
@@ -2923,7 +3002,6 @@ void Image::_bind_methods() {
ClassDB::bind_method(D_METHOD("resize_to_po2", "square"), &Image::resize_to_po2, DEFVAL(false));
ClassDB::bind_method(D_METHOD("resize", "width", "height", "interpolation"), &Image::resize, DEFVAL(INTERPOLATE_BILINEAR));
ClassDB::bind_method(D_METHOD("shrink_x2"), &Image::shrink_x2);
- ClassDB::bind_method(D_METHOD("expand_x2_hq2x"), &Image::expand_x2_hq2x);
ClassDB::bind_method(D_METHOD("crop", "width", "height"), &Image::crop);
ClassDB::bind_method(D_METHOD("flip_x"), &Image::flip_x);
@@ -2938,6 +3016,7 @@ void Image::_bind_methods() {
ClassDB::bind_method(D_METHOD("load", "path"), &Image::load);
ClassDB::bind_method(D_METHOD("save_png", "path"), &Image::save_png);
+ ClassDB::bind_method(D_METHOD("save_png_to_buffer"), &Image::save_png_to_buffer);
ClassDB::bind_method(D_METHOD("save_exr", "path", "grayscale"), &Image::save_exr, DEFVAL(false));
ClassDB::bind_method(D_METHOD("detect_alpha"), &Image::detect_alpha);
@@ -2945,7 +3024,7 @@ void Image::_bind_methods() {
ClassDB::bind_method(D_METHOD("detect_used_channels", "source"), &Image::detect_used_channels, DEFVAL(COMPRESS_SOURCE_GENERIC));
ClassDB::bind_method(D_METHOD("compress", "mode", "source", "lossy_quality"), &Image::compress, DEFVAL(COMPRESS_SOURCE_GENERIC), DEFVAL(0.7));
- ClassDB::bind_method(D_METHOD("compress_from_channels", "mode", "channels", "lossy_quality"), &Image::compress, DEFVAL(0.7));
+ ClassDB::bind_method(D_METHOD("compress_from_channels", "mode", "channels", "lossy_quality"), &Image::compress_from_channels, DEFVAL(0.7));
ClassDB::bind_method(D_METHOD("decompress"), &Image::decompress);
ClassDB::bind_method(D_METHOD("is_compressed"), &Image::is_compressed);
@@ -3054,17 +3133,14 @@ void Image::_bind_methods() {
}
void Image::set_compress_bc_func(void (*p_compress_func)(Image *, float, UsedChannels)) {
-
_image_compress_bc_func = p_compress_func;
}
void Image::set_compress_bptc_func(void (*p_compress_func)(Image *, float, UsedChannels)) {
-
_image_compress_bptc_func = p_compress_func;
}
void Image::normalmap_to_xy() {
-
convert(Image::FORMAT_RGBA8);
{
@@ -3072,7 +3148,6 @@ void Image::normalmap_to_xy() {
uint8_t *data_ptr = data.ptrw();
for (int i = 0; i < len; i++) {
-
data_ptr[(i << 2) + 3] = data_ptr[(i << 2) + 0]; //x to w
data_ptr[(i << 2) + 0] = data_ptr[(i << 2) + 1]; //y to xz
data_ptr[(i << 2) + 2] = data_ptr[(i << 2) + 1];
@@ -3083,15 +3158,15 @@ void Image::normalmap_to_xy() {
}
Ref<Image> Image::rgbe_to_srgb() {
-
- if (data.size() == 0)
+ if (data.size() == 0) {
return Ref<Image>();
+ }
ERR_FAIL_COND_V(format != FORMAT_RGBE9995, Ref<Image>());
Ref<Image> new_image;
new_image.instance();
- new_image->create(width, height, 0, Image::FORMAT_RGB8);
+ new_image->create(width, height, false, Image::FORMAT_RGB8);
for (int row = 0; row < height; row++) {
for (int col = 0; col < width; col++) {
@@ -3107,7 +3182,6 @@ Ref<Image> Image::rgbe_to_srgb() {
}
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);
@@ -3149,11 +3223,15 @@ void Image::bumpmap_to_normalmap(float bump_scale) {
for (int ty = 0; ty < height; ty++) {
int py = ty + 1;
- if (py >= height) py -= height;
+ if (py >= height) {
+ py -= height;
+ }
for (int tx = 0; tx < width; tx++) {
int px = tx + 1;
- if (px >= width) px -= width;
+ if (px >= width) {
+ px -= width;
+ }
float here = read_ptr[ty * width + tx];
float to_right = read_ptr[ty * width + px];
float above = read_ptr[py * width + tx];
@@ -3175,33 +3253,29 @@ void Image::bumpmap_to_normalmap(float bump_scale) {
}
void Image::srgb_to_linear() {
-
- if (data.size() == 0)
+ if (data.size() == 0) {
return;
+ }
static const uint8_t srgb2lin[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, 11, 11, 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 22, 22, 23, 23, 24, 24, 25, 26, 26, 27, 27, 28, 29, 29, 30, 31, 31, 32, 33, 33, 34, 35, 36, 36, 37, 38, 38, 39, 40, 41, 42, 42, 43, 44, 45, 46, 47, 47, 48, 49, 50, 51, 52, 53, 54, 55, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 70, 71, 72, 73, 74, 75, 76, 77, 78, 80, 81, 82, 83, 84, 85, 87, 88, 89, 90, 92, 93, 94, 95, 97, 98, 99, 101, 102, 103, 105, 106, 107, 109, 110, 112, 113, 114, 116, 117, 119, 120, 122, 123, 125, 126, 128, 129, 131, 132, 134, 135, 137, 139, 140, 142, 144, 145, 147, 148, 150, 152, 153, 155, 157, 159, 160, 162, 164, 166, 167, 169, 171, 173, 175, 176, 178, 180, 182, 184, 186, 188, 190, 192, 193, 195, 197, 199, 201, 203, 205, 207, 209, 211, 213, 215, 218, 220, 222, 224, 226, 228, 230, 232, 235, 237, 239, 241, 243, 245, 248, 250, 252, 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] = srgb2lin[data_ptr[(i << 2) + 0]];
data_ptr[(i << 2) + 1] = srgb2lin[data_ptr[(i << 2) + 1]];
data_ptr[(i << 2) + 2] = srgb2lin[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] = srgb2lin[data_ptr[(i * 3) + 0]];
data_ptr[(i * 3) + 1] = srgb2lin[data_ptr[(i * 3) + 1]];
data_ptr[(i * 3) + 2] = srgb2lin[data_ptr[(i * 3) + 2]];
@@ -3210,18 +3284,18 @@ void Image::srgb_to_linear() {
}
void Image::premultiply_alpha() {
-
- if (data.size() == 0)
+ if (data.size() == 0) {
return;
+ }
- if (format != FORMAT_RGBA8)
+ if (format != FORMAT_RGBA8) {
return; //not needed
+ }
uint8_t *data_ptr = data.ptrw();
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
-
uint8_t *ptr = &data_ptr[(i * width + j) * 4];
ptr[0] = (uint16_t(ptr[0]) * uint16_t(ptr[3])) >> 8;
@@ -3232,12 +3306,13 @@ void Image::premultiply_alpha() {
}
void Image::fix_alpha_edges() {
-
- if (data.size() == 0)
+ if (data.size() == 0) {
return;
+ }
- if (format != FORMAT_RGBA8)
+ if (format != FORMAT_RGBA8) {
return; //not needed
+ }
Vector<uint8_t> dcopy = data;
const uint8_t *srcptr = dcopy.ptr();
@@ -3250,12 +3325,12 @@ void Image::fix_alpha_edges() {
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
-
const uint8_t *rptr = &srcptr[(i * width + j) * 4];
uint8_t *wptr = &data_ptr[(i * width + j) * 4];
- if (rptr[3] >= alpha_threshold)
+ if (rptr[3] >= alpha_threshold) {
continue;
+ }
int closest_dist = max_dist;
uint8_t closest_color[3];
@@ -3267,17 +3342,18 @@ void Image::fix_alpha_edges() {
for (int k = from_y; k <= to_y; k++) {
for (int l = from_x; l <= to_x; l++) {
-
int dy = i - k;
int dx = j - l;
int dist = dy * dy + dx * dx;
- if (dist >= closest_dist)
+ if (dist >= closest_dist) {
continue;
+ }
const uint8_t *rp2 = &srcptr[(k * width + l) << 2];
- if (rp2[3] < alpha_threshold)
+ if (rp2[3] < alpha_threshold) {
continue;
+ }
closest_dist = dist;
closest_color[0] = rp2[0];
@@ -3287,7 +3363,6 @@ void Image::fix_alpha_edges() {
}
if (closest_dist != max_dist) {
-
wptr[0] = closest_color[0];
wptr[1] = closest_color[1];
wptr[2] = closest_color[2];
@@ -3297,7 +3372,6 @@ void Image::fix_alpha_edges() {
}
String Image::get_format_name(Format p_format) {
-
ERR_FAIL_INDEX_V(p_format, FORMAT_MAX, String());
return format_names[p_format];
}
@@ -3326,6 +3400,7 @@ void Image::convert_rg_to_ra_rgba8() {
w[i + 2] = 0;
}
}
+
void Image::convert_ra_rgba8_to_rg() {
ERR_FAIL_COND(format != FORMAT_RGBA8);
ERR_FAIL_COND(!data.size());
@@ -3405,7 +3480,6 @@ void Image::renormalize_rgbe9995(uint32_t *p_rgb) {
}
Image::Image(const uint8_t *p_mem_png_jpg, int p_len) {
-
width = 0;
height = 0;
mipmaps = false;
@@ -3421,20 +3495,12 @@ Image::Image(const uint8_t *p_mem_png_jpg, int p_len) {
}
Ref<Resource> Image::duplicate(bool p_subresources) const {
-
Ref<Image> copy;
copy.instance();
copy->_copy_internals_from(*this);
return copy;
}
-Image::Image() {
-
- width = 0;
- height = 0;
- mipmaps = false;
- format = FORMAT_L8;
-}
-
-Image::~Image() {
+void Image::set_as_black() {
+ zeromem(data.ptrw(), data.size());
}