Skip to content

Commit 7c840fd

Browse files
committed
Image: Support generating mipmaps for all formats
1 parent 6c9aa4c commit 7c840fd

File tree

2 files changed

+55
-8
lines changed

2 files changed

+55
-8
lines changed

core/io/image.cpp

Lines changed: 52 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1782,7 +1782,7 @@ static void _generate_po2_mipmap(const Component *p_src, Component *p_dst, uint3
17821782
average_func(dst_ptr[j], rup_ptr[j], rup_ptr[j + right_step], rdown_ptr[j], rdown_ptr[j + right_step]);
17831783
}
17841784

1785-
if (renormalize) {
1785+
if constexpr (renormalize) {
17861786
renormalize_func(dst_ptr);
17871787
}
17881788

@@ -1828,6 +1828,12 @@ void Image::_generate_mipmap_from_format(Image::Format p_format, const uint8_t *
18281828
_generate_po2_mipmap<uint8_t, 4, false, Image::average_4_uint8, Image::renormalize_uint8>(p_src, p_dst, p_width, p_height);
18291829
}
18301830
} break;
1831+
case Image::FORMAT_RGBA4444: {
1832+
_generate_po2_mipmap<uint16_t, 1, false, Image::average_4_rgba4444, nullptr>(src_u16, dst_u16, p_width, p_height);
1833+
} break;
1834+
case Image::FORMAT_RGB565: {
1835+
_generate_po2_mipmap<uint16_t, 1, false, Image::average_4_rgb565, nullptr>(src_u16, dst_u16, p_width, p_height);
1836+
} break;
18311837
case Image::FORMAT_RF:
18321838
_generate_po2_mipmap<float, 1, false, Image::average_4_float, Image::renormalize_float>(src_float, dst_float, p_width, p_height);
18331839
break;
@@ -1869,7 +1875,7 @@ void Image::_generate_mipmap_from_format(Image::Format p_format, const uint8_t *
18691875
}
18701876
} break;
18711877
case Image::FORMAT_RGBE9995:
1872-
_generate_po2_mipmap<uint32_t, 1, false, Image::average_4_rgbe9995, Image::renormalize_rgbe9995>(src_u32, dst_u32, p_width, p_height);
1878+
_generate_po2_mipmap<uint32_t, 1, false, Image::average_4_rgbe9995, nullptr>(src_u32, dst_u32, p_width, p_height);
18731879
break;
18741880

18751881
default:
@@ -1930,7 +1936,6 @@ void Image::normalize() {
19301936

19311937
Error Image::generate_mipmaps(bool p_renormalize) {
19321938
ERR_FAIL_COND_V_MSG(is_compressed(), ERR_UNAVAILABLE, "Cannot generate mipmaps from compressed image formats.");
1933-
ERR_FAIL_COND_V_MSG(format == FORMAT_RGBA4444, ERR_UNAVAILABLE, "Cannot generate mipmaps from RGBA4444 format.");
19341939
ERR_FAIL_COND_V_MSG(width == 0 || height == 0, ERR_UNCONFIGURED, "Cannot generate mipmaps with width or height equal to 0.");
19351940

19361941
int gen_mipmap_count;
@@ -4197,6 +4202,42 @@ Error Image::_load_from_buffer(const Vector<uint8_t> &p_array, ImageMemLoadFunc
41974202
return OK;
41984203
}
41994204

4205+
_FORCE_INLINE_ Color col_from_rgba4444(uint16_t p_col) {
4206+
float r = ((p_col >> 12) & 0xF) / 15.0;
4207+
float g = ((p_col >> 8) & 0xF) / 15.0;
4208+
float b = ((p_col >> 4) & 0xF) / 15.0;
4209+
float a = (p_col & 0xF) / 15.0;
4210+
return Color(r, g, b, a);
4211+
}
4212+
4213+
_FORCE_INLINE_ uint16_t col_to_rgba4444(Color p_col) {
4214+
uint16_t rgba = 0;
4215+
4216+
rgba = uint16_t(CLAMP(p_col.r * 15.0, 0, 15)) << 12;
4217+
rgba |= uint16_t(CLAMP(p_col.g * 15.0, 0, 15)) << 8;
4218+
rgba |= uint16_t(CLAMP(p_col.b * 15.0, 0, 15)) << 4;
4219+
rgba |= uint16_t(CLAMP(p_col.a * 15.0, 0, 15));
4220+
4221+
return rgba;
4222+
}
4223+
4224+
_FORCE_INLINE_ Color col_from_rgb565(uint16_t p_col) {
4225+
float r = ((p_col >> 11) & 0x1F) / 31.0;
4226+
float g = ((p_col >> 5) & 0x3F) / 63.0;
4227+
float b = (p_col & 0x1F) / 31.0;
4228+
return Color(r, g, b, 1.0);
4229+
}
4230+
4231+
_FORCE_INLINE_ uint16_t col_to_rgb565(Color p_col) {
4232+
uint16_t rgba = 0;
4233+
4234+
rgba = uint16_t(CLAMP(p_col.r * 31.0, 0, 31)) << 11;
4235+
rgba |= uint16_t(CLAMP(p_col.g * 63.0, 0, 63)) << 5;
4236+
rgba |= uint16_t(CLAMP(p_col.b * 31.0, 0, 31));
4237+
4238+
return rgba;
4239+
}
4240+
42004241
void Image::average_4_uint8(uint8_t &p_out, const uint8_t &p_a, const uint8_t &p_b, const uint8_t &p_c, const uint8_t &p_d) {
42014242
p_out = static_cast<uint8_t>((p_a + p_b + p_c + p_d + 2) >> 2);
42024243
}
@@ -4213,6 +4254,14 @@ void Image::average_4_rgbe9995(uint32_t &p_out, const uint32_t &p_a, const uint3
42134254
p_out = ((Color::from_rgbe9995(p_a) + Color::from_rgbe9995(p_b) + Color::from_rgbe9995(p_c) + Color::from_rgbe9995(p_d)) * 0.25f).to_rgbe9995();
42144255
}
42154256

4257+
void Image::average_4_rgba4444(uint16_t &p_out, const uint16_t &p_a, const uint16_t &p_b, const uint16_t &p_c, const uint16_t &p_d) {
4258+
p_out = col_to_rgba4444((col_from_rgba4444(p_a) + col_from_rgba4444(p_b) + col_from_rgba4444(p_c) + col_from_rgba4444(p_d)) * 0.25f);
4259+
}
4260+
4261+
void Image::average_4_rgb565(uint16_t &p_out, const uint16_t &p_a, const uint16_t &p_b, const uint16_t &p_c, const uint16_t &p_d) {
4262+
p_out = col_to_rgb565((col_from_rgb565(p_a) + col_from_rgb565(p_b) + col_from_rgb565(p_c) + col_from_rgb565(p_d)) * 0.25f);
4263+
}
4264+
42164265
void Image::renormalize_uint8(uint8_t *p_rgb) {
42174266
Vector3 n(p_rgb[0] / 255.0, p_rgb[1] / 255.0, p_rgb[2] / 255.0);
42184267
n *= 2.0;
@@ -4242,10 +4291,6 @@ void Image::renormalize_half(uint16_t *p_rgb) {
42424291
p_rgb[2] = Math::make_half_float(n.z);
42434292
}
42444293

4245-
void Image::renormalize_rgbe9995(uint32_t *p_rgb) {
4246-
// Never used.
4247-
}
4248-
42494294
Image::Image(const uint8_t *p_mem_png_jpg, int p_len) {
42504295
width = 0;
42514296
height = 0;

core/io/image.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,10 +282,12 @@ class Image : public Resource {
282282
static void average_4_float(float &p_out, const float &p_a, const float &p_b, const float &p_c, const float &p_d);
283283
static void average_4_half(uint16_t &p_out, const uint16_t &p_a, const uint16_t &p_b, const uint16_t &p_c, const uint16_t &p_d);
284284
static void average_4_rgbe9995(uint32_t &p_out, const uint32_t &p_a, const uint32_t &p_b, const uint32_t &p_c, const uint32_t &p_d);
285+
static void average_4_rgba4444(uint16_t &p_out, const uint16_t &p_a, const uint16_t &p_b, const uint16_t &p_c, const uint16_t &p_d);
286+
static void average_4_rgb565(uint16_t &p_out, const uint16_t &p_a, const uint16_t &p_b, const uint16_t &p_c, const uint16_t &p_d);
287+
285288
static void renormalize_uint8(uint8_t *p_rgb);
286289
static void renormalize_float(float *p_rgb);
287290
static void renormalize_half(uint16_t *p_rgb);
288-
static void renormalize_rgbe9995(uint32_t *p_rgb);
289291

290292
public:
291293
int get_width() const;

0 commit comments

Comments
 (0)