summaryrefslogtreecommitdiff
path: root/core/image.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'core/image.cpp')
-rw-r--r--core/image.cpp48
1 files changed, 36 insertions, 12 deletions
diff --git a/core/image.cpp b/core/image.cpp
index 2ac8ffea56..1f4498af9b 100644
--- a/core/image.cpp
+++ b/core/image.cpp
@@ -937,7 +937,7 @@ bool Image::_can_modify(Format p_format) const {
return p_format <= FORMAT_RGBE9995;
}
-template <int CC>
+template <int CC, bool renormalize>
static void _generate_po2_mipmap(const uint8_t *p_src, uint8_t *p_dst, uint32_t p_width, uint32_t p_height) {
//fast power of 2 mipmap generation
@@ -963,6 +963,19 @@ static void _generate_po2_mipmap(const uint8_t *p_src, uint8_t *p_dst, uint32_t
dst_ptr[j] = val >> 2;
}
+ if (renormalize) {
+ Vector3 n(dst_ptr[0] / 255.0, dst_ptr[1] / 255.0, dst_ptr[2] / 255.0);
+ n *= 2.0;
+ n -= Vector3(1, 1, 1);
+ n.normalize();
+ n += Vector3(1, 1, 1);
+ n *= 0.5;
+ n *= 255;
+ dst_ptr[0] = CLAMP(int(n.x), 0, 255);
+ dst_ptr[1] = CLAMP(int(n.y), 0, 255);
+ dst_ptr[2] = CLAMP(int(n.z), 0, 255);
+ }
+
dst_ptr += CC;
rup_ptr += CC * 2;
rdown_ptr += CC * 2;
@@ -1045,11 +1058,11 @@ void Image::shrink_x2() {
switch (format) {
case FORMAT_L8:
- case FORMAT_R8: _generate_po2_mipmap<1>(r.ptr(), w.ptr(), width, height); break;
- case FORMAT_LA8: _generate_po2_mipmap<2>(r.ptr(), w.ptr(), width, height); break;
- case FORMAT_RG8: _generate_po2_mipmap<2>(r.ptr(), w.ptr(), width, height); break;
- case FORMAT_RGB8: _generate_po2_mipmap<3>(r.ptr(), w.ptr(), width, height); break;
- case FORMAT_RGBA8: _generate_po2_mipmap<4>(r.ptr(), w.ptr(), width, height); break;
+ case FORMAT_R8: _generate_po2_mipmap<1, false>(r.ptr(), w.ptr(), width, height); break;
+ case FORMAT_LA8: _generate_po2_mipmap<2, false>(r.ptr(), w.ptr(), width, height); break;
+ case FORMAT_RG8: _generate_po2_mipmap<2, false>(r.ptr(), w.ptr(), width, height); break;
+ case FORMAT_RGB8: _generate_po2_mipmap<3, false>(r.ptr(), w.ptr(), width, height); break;
+ case FORMAT_RGBA8: _generate_po2_mipmap<4, false>(r.ptr(), w.ptr(), width, height); break;
default: {}
}
}
@@ -1060,7 +1073,7 @@ void Image::shrink_x2() {
}
}
-Error Image::generate_mipmaps() {
+Error Image::generate_mipmaps(bool p_renormalize) {
if (!_can_modify(format)) {
ERR_EXPLAIN("Cannot generate mipmaps in indexed, compressed or custom image formats.");
@@ -1089,11 +1102,22 @@ Error Image::generate_mipmaps() {
switch (format) {
case FORMAT_L8:
- case FORMAT_R8: _generate_po2_mipmap<1>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h); break;
+ case FORMAT_R8: _generate_po2_mipmap<1, false>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h); break;
case FORMAT_LA8:
- case FORMAT_RG8: _generate_po2_mipmap<2>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h); break;
- case FORMAT_RGB8: _generate_po2_mipmap<3>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h); break;
- case FORMAT_RGBA8: _generate_po2_mipmap<4>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h); break;
+ case FORMAT_RG8: _generate_po2_mipmap<2, false>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h); break;
+ case FORMAT_RGB8:
+ if (p_renormalize)
+ _generate_po2_mipmap<3, true>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h);
+ else
+ _generate_po2_mipmap<3, false>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h);
+
+ break;
+ case FORMAT_RGBA8:
+ if (p_renormalize)
+ _generate_po2_mipmap<4, true>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h);
+ else
+ _generate_po2_mipmap<4, false>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h);
+ break;
default: {}
}
@@ -2217,7 +2241,7 @@ void Image::_bind_methods() {
ClassDB::bind_method(D_METHOD("crop", "width", "height"), &Image::crop);
ClassDB::bind_method(D_METHOD("flip_x"), &Image::flip_x);
ClassDB::bind_method(D_METHOD("flip_y"), &Image::flip_y);
- ClassDB::bind_method(D_METHOD("generate_mipmaps"), &Image::generate_mipmaps);
+ ClassDB::bind_method(D_METHOD("generate_mipmaps", "renormalize"), &Image::generate_mipmaps, DEFVAL(false));
ClassDB::bind_method(D_METHOD("clear_mipmaps"), &Image::clear_mipmaps);
ClassDB::bind_method(D_METHOD("create", "width", "height", "use_mipmaps", "format"), &Image::_create_empty);