mirror of
https://github.com/godotengine/godot.git
synced 2025-03-07 23:32:58 +08:00
Image: More cleanup and reduced code duplication.
This commit is contained in:
parent
0f20e67d8d
commit
335077a03f
@ -572,21 +572,18 @@ static bool _are_formats_compatible(Image::Format p_format0, Image::Format p_for
|
||||
|
||||
void Image::convert(Format p_new_format) {
|
||||
ERR_FAIL_INDEX_MSG(p_new_format, FORMAT_MAX, vformat("The Image format specified (%d) is out of range. See Image's Format enum.", p_new_format));
|
||||
if (data.size() == 0) {
|
||||
|
||||
if (data.size() == 0 || p_new_format == format) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (p_new_format == format) {
|
||||
return;
|
||||
}
|
||||
ERR_FAIL_COND_MSG(Image::is_format_compressed(format) || Image::is_format_compressed(p_new_format),
|
||||
"Cannot convert to (or from) compressed formats. Use compress() and decompress() instead.");
|
||||
|
||||
// Includes the main image.
|
||||
const int mipmap_count = get_mipmap_count() + 1;
|
||||
|
||||
if (Image::is_format_compressed(format) || Image::is_format_compressed(p_new_format)) {
|
||||
ERR_FAIL_MSG("Cannot convert to <-> from compressed formats. Use compress() and decompress() instead.");
|
||||
|
||||
} else if (!_are_formats_compatible(format, p_new_format)) {
|
||||
if (!_are_formats_compatible(format, p_new_format)) {
|
||||
// Use put/set pixel which is slower but works with non-byte formats.
|
||||
Image new_img(width, height, mipmaps, p_new_format);
|
||||
|
||||
@ -612,9 +609,10 @@ void Image::convert(Format p_new_format) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Convert the formats in an optimized way by removing/adding color channels if necessary.
|
||||
Image new_img(width, height, mipmaps, p_new_format);
|
||||
|
||||
int conversion_type = format | p_new_format << 8;
|
||||
const int conversion_type = format | p_new_format << 8;
|
||||
|
||||
for (int mip = 0; mip < mipmap_count; mip++) {
|
||||
int64_t mip_offset = 0;
|
||||
@ -1801,7 +1799,7 @@ template <typename 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
|
||||
// Fast power of 2 mipmap generation.
|
||||
uint32_t dst_w = MAX(p_width >> 1, 1u);
|
||||
uint32_t dst_h = MAX(p_height >> 1, 1u);
|
||||
|
||||
@ -1831,99 +1829,116 @@ static void _generate_po2_mipmap(const Component *p_src, Component *p_dst, uint3
|
||||
}
|
||||
}
|
||||
|
||||
void Image::_generate_mipmap_from_format(Image::Format p_format, const uint8_t *p_src, uint8_t *p_dst, uint32_t p_width, uint32_t p_height, bool p_renormalize) {
|
||||
const float *src_float = reinterpret_cast<const float *>(p_src);
|
||||
float *dst_float = reinterpret_cast<float *>(p_dst);
|
||||
|
||||
const uint16_t *src_u16 = reinterpret_cast<const uint16_t *>(p_src);
|
||||
uint16_t *dst_u16 = reinterpret_cast<uint16_t *>(p_dst);
|
||||
|
||||
const uint32_t *src_u32 = reinterpret_cast<const uint32_t *>(p_src);
|
||||
uint32_t *dst_u32 = reinterpret_cast<uint32_t *>(p_dst);
|
||||
|
||||
switch (p_format) {
|
||||
case Image::FORMAT_L8:
|
||||
case Image::FORMAT_R8:
|
||||
_generate_po2_mipmap<uint8_t, 1, false, Image::average_4_uint8, Image::renormalize_uint8>(p_src, p_dst, p_width, p_height);
|
||||
break;
|
||||
case Image::FORMAT_LA8:
|
||||
_generate_po2_mipmap<uint8_t, 2, false, Image::average_4_uint8, Image::renormalize_uint8>(p_src, p_dst, p_width, p_height);
|
||||
break;
|
||||
case Image::FORMAT_RG8:
|
||||
_generate_po2_mipmap<uint8_t, 2, false, Image::average_4_uint8, Image::renormalize_uint8>(p_src, p_dst, p_width, p_height);
|
||||
break;
|
||||
case Image::FORMAT_RGB8: {
|
||||
if (p_renormalize) {
|
||||
_generate_po2_mipmap<uint8_t, 3, true, Image::average_4_uint8, Image::renormalize_uint8>(p_src, p_dst, p_width, p_height);
|
||||
} else {
|
||||
_generate_po2_mipmap<uint8_t, 3, false, Image::average_4_uint8, Image::renormalize_uint8>(p_src, p_dst, p_width, p_height);
|
||||
}
|
||||
} break;
|
||||
case Image::FORMAT_RGBA8: {
|
||||
if (p_renormalize) {
|
||||
_generate_po2_mipmap<uint8_t, 4, true, Image::average_4_uint8, Image::renormalize_uint8>(p_src, p_dst, p_width, p_height);
|
||||
} else {
|
||||
_generate_po2_mipmap<uint8_t, 4, false, Image::average_4_uint8, Image::renormalize_uint8>(p_src, p_dst, p_width, p_height);
|
||||
}
|
||||
} break;
|
||||
case Image::FORMAT_RF:
|
||||
_generate_po2_mipmap<float, 1, false, Image::average_4_float, Image::renormalize_float>(src_float, dst_float, p_width, p_height);
|
||||
break;
|
||||
case Image::FORMAT_RGF:
|
||||
_generate_po2_mipmap<float, 2, false, Image::average_4_float, Image::renormalize_float>(src_float, dst_float, p_width, p_height);
|
||||
break;
|
||||
case Image::FORMAT_RGBF: {
|
||||
if (p_renormalize) {
|
||||
_generate_po2_mipmap<float, 3, true, Image::average_4_float, Image::renormalize_float>(src_float, dst_float, p_width, p_height);
|
||||
} else {
|
||||
_generate_po2_mipmap<float, 3, false, Image::average_4_float, Image::renormalize_float>(src_float, dst_float, p_width, p_height);
|
||||
}
|
||||
} break;
|
||||
case Image::FORMAT_RGBAF: {
|
||||
if (p_renormalize) {
|
||||
_generate_po2_mipmap<float, 4, true, Image::average_4_float, Image::renormalize_float>(src_float, dst_float, p_width, p_height);
|
||||
} else {
|
||||
_generate_po2_mipmap<float, 4, false, Image::average_4_float, Image::renormalize_float>(src_float, dst_float, p_width, p_height);
|
||||
}
|
||||
} break;
|
||||
case Image::FORMAT_RH:
|
||||
_generate_po2_mipmap<uint16_t, 1, false, Image::average_4_half, Image::renormalize_half>(src_u16, dst_u16, p_width, p_height);
|
||||
break;
|
||||
case Image::FORMAT_RGH:
|
||||
_generate_po2_mipmap<uint16_t, 2, false, Image::average_4_half, Image::renormalize_half>(src_u16, dst_u16, p_width, p_height);
|
||||
break;
|
||||
case Image::FORMAT_RGBH: {
|
||||
if (p_renormalize) {
|
||||
_generate_po2_mipmap<uint16_t, 3, true, Image::average_4_half, Image::renormalize_half>(src_u16, dst_u16, p_width, p_height);
|
||||
} else {
|
||||
_generate_po2_mipmap<uint16_t, 3, false, Image::average_4_half, Image::renormalize_half>(src_u16, dst_u16, p_width, p_height);
|
||||
}
|
||||
} break;
|
||||
case Image::FORMAT_RGBAH: {
|
||||
if (p_renormalize) {
|
||||
_generate_po2_mipmap<uint16_t, 4, true, Image::average_4_half, Image::renormalize_half>(src_u16, dst_u16, p_width, p_height);
|
||||
} else {
|
||||
_generate_po2_mipmap<uint16_t, 4, false, Image::average_4_half, Image::renormalize_half>(src_u16, dst_u16, p_width, p_height);
|
||||
}
|
||||
} break;
|
||||
case Image::FORMAT_RGBE9995:
|
||||
_generate_po2_mipmap<uint32_t, 1, false, Image::average_4_rgbe9995, Image::renormalize_rgbe9995>(src_u32, dst_u32, p_width, p_height);
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void Image::shrink_x2() {
|
||||
ERR_FAIL_COND(data.is_empty());
|
||||
Vector<uint8_t> new_data;
|
||||
|
||||
if (mipmaps) {
|
||||
//just use the lower mipmap as base and copy all
|
||||
Vector<uint8_t> new_img;
|
||||
// Just use the lower mipmap as base and copy all.
|
||||
int64_t ofs = get_mipmap_offset(1);
|
||||
int64_t new_size = data.size() - ofs;
|
||||
|
||||
int ofs = get_mipmap_offset(1);
|
||||
|
||||
int new_size = data.size() - ofs;
|
||||
new_img.resize(new_size);
|
||||
ERR_FAIL_COND(new_img.is_empty());
|
||||
|
||||
{
|
||||
uint8_t *w = new_img.ptrw();
|
||||
const uint8_t *r = data.ptr();
|
||||
|
||||
memcpy(w, &r[ofs], new_size);
|
||||
}
|
||||
|
||||
width = MAX(width / 2, 1);
|
||||
height = MAX(height / 2, 1);
|
||||
data = new_img;
|
||||
new_data.resize(new_size);
|
||||
ERR_FAIL_COND(new_data.is_empty());
|
||||
|
||||
memcpy(new_data.ptrw(), data.ptr() + ofs, new_size);
|
||||
} else {
|
||||
Vector<uint8_t> new_img;
|
||||
|
||||
// Generate a mipmap and replace the original.
|
||||
ERR_FAIL_COND(!_can_modify(format));
|
||||
int ps = get_format_pixel_size(format);
|
||||
new_img.resize((width / 2) * (height / 2) * ps);
|
||||
ERR_FAIL_COND(new_img.is_empty());
|
||||
ERR_FAIL_COND(data.is_empty());
|
||||
|
||||
{
|
||||
uint8_t *w = new_img.ptrw();
|
||||
const uint8_t *r = data.ptr();
|
||||
new_data.resize((width / 2) * (height / 2) * get_format_pixel_size(format));
|
||||
ERR_FAIL_COND(data.is_empty() || new_data.is_empty());
|
||||
|
||||
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;
|
||||
default: {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
width /= 2;
|
||||
height /= 2;
|
||||
data = new_img;
|
||||
_generate_mipmap_from_format(format, data.ptr(), new_data.ptrw(), width, height, false);
|
||||
}
|
||||
|
||||
width = MAX(width / 2, 1);
|
||||
height = MAX(height / 2, 1);
|
||||
data = new_data;
|
||||
}
|
||||
|
||||
void Image::normalize() {
|
||||
@ -1951,107 +1966,25 @@ 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.");
|
||||
|
||||
ERR_FAIL_COND_V_MSG(width == 0 || height == 0, ERR_UNCONFIGURED, "Cannot generate mipmaps with width or height equal to 0.");
|
||||
|
||||
int mmcount;
|
||||
|
||||
int size = _get_dst_image_size(width, height, format, mmcount);
|
||||
int gen_mipmap_count;
|
||||
|
||||
int64_t size = _get_dst_image_size(width, height, format, gen_mipmap_count);
|
||||
data.resize(size);
|
||||
|
||||
uint8_t *wp = data.ptrw();
|
||||
|
||||
int prev_ofs = 0;
|
||||
int prev_h = height;
|
||||
int prev_w = width;
|
||||
|
||||
for (int i = 1; i <= mmcount; i++) {
|
||||
for (int i = 1; i <= gen_mipmap_count; i++) {
|
||||
int64_t ofs;
|
||||
int 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_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_RGB8:
|
||||
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 {
|
||||
_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) {
|
||||
_generate_po2_mipmap<uint8_t, 4, true, Image::average_4_uint8, Image::renormalize_uint8>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h);
|
||||
} 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);
|
||||
break;
|
||||
case FORMAT_RGF:
|
||||
_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) {
|
||||
_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 {
|
||||
_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) {
|
||||
_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 {
|
||||
_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:
|
||||
_generate_po2_mipmap<uint16_t, 1, 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_RGH:
|
||||
_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) {
|
||||
_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 {
|
||||
_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) {
|
||||
_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 {
|
||||
_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) {
|
||||
_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 {
|
||||
_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: {
|
||||
}
|
||||
}
|
||||
_generate_mipmap_from_format(format, wp + prev_ofs, wp + ofs, prev_w, prev_h, p_renormalize);
|
||||
|
||||
prev_ofs = ofs;
|
||||
prev_w = w;
|
||||
@ -2080,8 +2013,7 @@ Error Image::generate_mipmap_roughness(RoughnessChannel p_roughness_channel, con
|
||||
normal_sat_vec.resize(normal_w * normal_h * 3);
|
||||
double *normal_sat = normal_sat_vec.ptr();
|
||||
|
||||
//create summed area table
|
||||
|
||||
// Create summed area table.
|
||||
for (int y = 0; y < normal_h; y++) {
|
||||
double line_sum[3] = { 0, 0, 0 };
|
||||
for (int x = 0; x < normal_w; x++) {
|
||||
@ -2110,15 +2042,6 @@ Error Image::generate_mipmap_roughness(RoughnessChannel p_roughness_channel, con
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
{
|
||||
Vector3 beg(normal_sat_vec[0], normal_sat_vec[1], normal_sat_vec[2]);
|
||||
Vector3 end(normal_sat_vec[normal_sat_vec.size() - 3], normal_sat_vec[normal_sat_vec.size() - 2], normal_sat_vec[normal_sat_vec.size() - 1]);
|
||||
Vector3 avg = (end - beg) / (normal_w * normal_h);
|
||||
print_line("average: " + avg);
|
||||
}
|
||||
#endif
|
||||
|
||||
int mmcount;
|
||||
|
||||
_get_dst_image_size(width, height, format, mmcount);
|
||||
@ -2520,8 +2443,7 @@ void Image::initialize_data(const char **p_xpm) {
|
||||
}
|
||||
|
||||
bool Image::is_invisible() const {
|
||||
if (format == FORMAT_L8 ||
|
||||
format == FORMAT_RGB8 || format == FORMAT_RG8) {
|
||||
if (format == FORMAT_L8 || format == FORMAT_RGB8 || format == FORMAT_RG8) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -2784,9 +2706,7 @@ Error Image::compress_from_channels(CompressMode p_mode, UsedChannels p_channels
|
||||
return OK;
|
||||
}
|
||||
}
|
||||
|
||||
} break;
|
||||
|
||||
case COMPRESS_S3TC: {
|
||||
if (_image_compress_bc_rd_func) {
|
||||
Error result = _image_compress_bc_rd_func(this, p_channels);
|
||||
@ -2796,7 +2716,6 @@ Error Image::compress_from_channels(CompressMode p_mode, UsedChannels p_channels
|
||||
return OK;
|
||||
}
|
||||
}
|
||||
|
||||
} break;
|
||||
|
||||
default: {
|
||||
@ -3313,6 +3232,7 @@ Color Image::_get_color_at_ofs(const uint8_t *ptr, uint32_t ofs) const {
|
||||
case FORMAT_RGBE9995: {
|
||||
return Color::from_rgbe9995(((uint32_t *)ptr)[ofs]);
|
||||
}
|
||||
|
||||
default: {
|
||||
ERR_FAIL_V_MSG(Color(), "Can't get_pixel() on compressed image, sorry.");
|
||||
}
|
||||
@ -3345,7 +3265,6 @@ void Image::_set_color_at_ofs(uint8_t *ptr, uint32_t ofs, const Color &p_color)
|
||||
ptr[ofs * 4 + 1] = uint8_t(CLAMP(p_color.g * 255.0, 0, 255));
|
||||
ptr[ofs * 4 + 2] = uint8_t(CLAMP(p_color.b * 255.0, 0, 255));
|
||||
ptr[ofs * 4 + 3] = uint8_t(CLAMP(p_color.a * 255.0, 0, 255));
|
||||
|
||||
} break;
|
||||
case FORMAT_RGBA4444: {
|
||||
uint16_t rgba = 0;
|
||||
@ -3356,7 +3275,6 @@ void Image::_set_color_at_ofs(uint8_t *ptr, uint32_t ofs, const Color &p_color)
|
||||
rgba |= uint16_t(CLAMP(p_color.a * 15.0, 0, 15));
|
||||
|
||||
((uint16_t *)ptr)[ofs] = rgba;
|
||||
|
||||
} break;
|
||||
case FORMAT_RGB565: {
|
||||
uint16_t rgba = 0;
|
||||
@ -3366,7 +3284,6 @@ void Image::_set_color_at_ofs(uint8_t *ptr, uint32_t ofs, const Color &p_color)
|
||||
rgba |= uint16_t(CLAMP(p_color.b * 31.0, 0, 31)) << 11;
|
||||
|
||||
((uint16_t *)ptr)[ofs] = rgba;
|
||||
|
||||
} break;
|
||||
case FORMAT_RF: {
|
||||
((float *)ptr)[ofs] = p_color.r;
|
||||
@ -3406,8 +3323,8 @@ void Image::_set_color_at_ofs(uint8_t *ptr, uint32_t ofs, const Color &p_color)
|
||||
} break;
|
||||
case FORMAT_RGBE9995: {
|
||||
((uint32_t *)ptr)[ofs] = p_color.to_rgbe9995();
|
||||
|
||||
} break;
|
||||
|
||||
default: {
|
||||
ERR_FAIL_MSG("Can't set_pixel() on compressed image, sorry.");
|
||||
}
|
||||
@ -3475,30 +3392,50 @@ void Image::adjust_bcs(float p_brightness, float p_contrast, float p_saturation)
|
||||
Image::UsedChannels Image::detect_used_channels(CompressSource p_source) const {
|
||||
ERR_FAIL_COND_V(data.is_empty(), USED_CHANNELS_RGBA);
|
||||
ERR_FAIL_COND_V(is_compressed(), USED_CHANNELS_RGBA);
|
||||
|
||||
if (p_source == COMPRESS_SOURCE_NORMAL) {
|
||||
return USED_CHANNELS_RG; // Normal maps only use RG channels.
|
||||
}
|
||||
|
||||
if (format == FORMAT_L8) {
|
||||
return USED_CHANNELS_L; // Grayscale only cannot have any channel less.
|
||||
} else if (format == FORMAT_R8 || format == FORMAT_RH || format == FORMAT_RF) {
|
||||
return USED_CHANNELS_R; // Red only cannot have any channel less.
|
||||
}
|
||||
|
||||
const bool supports_alpha = format == FORMAT_RGBA8 || format == FORMAT_RGBA4444 || format == FORMAT_RGBAH || format == FORMAT_RGBAF;
|
||||
bool r = false, g = false, b = false, a = false, c = false;
|
||||
|
||||
const uint8_t *data_ptr = data.ptr();
|
||||
|
||||
uint32_t data_total = width * height;
|
||||
const uint32_t data_total = width * height;
|
||||
|
||||
for (uint32_t i = 0; i < data_total; i++) {
|
||||
Color col = _get_color_at_ofs(data_ptr, i);
|
||||
|
||||
if (col.r > 0.001) {
|
||||
if (!r && col.r > 0.001) {
|
||||
r = true;
|
||||
}
|
||||
if (col.g > 0.001) {
|
||||
if (!g && col.g > 0.001) {
|
||||
g = true;
|
||||
}
|
||||
if (col.b > 0.001) {
|
||||
if (!b && col.b > 0.001) {
|
||||
b = true;
|
||||
}
|
||||
if (col.a < 0.999) {
|
||||
if (!a && col.a < 0.999) {
|
||||
a = true;
|
||||
}
|
||||
|
||||
if (col.r != col.b || col.r != col.g || col.b != col.g) {
|
||||
c = true;
|
||||
c = true; // The image is not grayscale.
|
||||
}
|
||||
|
||||
if (r && g && b && c) {
|
||||
// All channels are used, no need to continue.
|
||||
if (!supports_alpha) {
|
||||
break;
|
||||
} else if (a) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -3519,13 +3456,7 @@ Image::UsedChannels Image::detect_used_channels(CompressSource p_source) const {
|
||||
}
|
||||
|
||||
if (p_source == COMPRESS_SOURCE_SRGB && (used_channels == USED_CHANNELS_R || used_channels == USED_CHANNELS_RG)) {
|
||||
//R and RG do not support SRGB
|
||||
used_channels = USED_CHANNELS_RGB;
|
||||
}
|
||||
|
||||
if (p_source == COMPRESS_SOURCE_NORMAL) {
|
||||
//use RG channels only for normal
|
||||
used_channels = USED_CHANNELS_RG;
|
||||
used_channels = USED_CHANNELS_RGB; // R and RG do not support SRGB.
|
||||
}
|
||||
|
||||
return used_channels;
|
||||
@ -3730,14 +3661,6 @@ void Image::_bind_methods() {
|
||||
BIND_ENUM_CONSTANT(ASTC_FORMAT_8x8);
|
||||
}
|
||||
|
||||
void Image::set_compress_bc_func(void (*p_compress_func)(Image *, UsedChannels)) {
|
||||
_image_compress_bc_func = p_compress_func;
|
||||
}
|
||||
|
||||
void Image::set_compress_bptc_func(void (*p_compress_func)(Image *, UsedChannels)) {
|
||||
_image_compress_bptc_func = p_compress_func;
|
||||
}
|
||||
|
||||
void Image::normal_map_to_xy() {
|
||||
convert(Image::FORMAT_RGBA8);
|
||||
|
||||
|
@ -266,6 +266,8 @@ private:
|
||||
|
||||
Error _load_from_buffer(const Vector<uint8_t> &p_array, ImageMemLoadFunc p_loader);
|
||||
|
||||
_FORCE_INLINE_ void _generate_mipmap_from_format(Image::Format p_format, const uint8_t *p_src, uint8_t *p_dst, uint32_t p_width, uint32_t p_height, bool p_renormalize = false);
|
||||
|
||||
static void 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);
|
||||
static void average_4_float(float &p_out, const float &p_a, const float &p_b, const float &p_c, const float &p_d);
|
||||
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);
|
||||
@ -393,8 +395,6 @@ public:
|
||||
Rect2i get_used_rect() const;
|
||||
Ref<Image> get_region(const Rect2i &p_area) const;
|
||||
|
||||
static void set_compress_bc_func(void (*p_compress_func)(Image *, UsedChannels));
|
||||
static void set_compress_bptc_func(void (*p_compress_func)(Image *, UsedChannels));
|
||||
static String get_format_name(Format p_format);
|
||||
|
||||
Error load_png_from_buffer(const Vector<uint8_t> &p_array);
|
||||
|
@ -39,7 +39,7 @@ void initialize_cvtt_module(ModuleInitializationLevel p_level) {
|
||||
return;
|
||||
}
|
||||
|
||||
Image::set_compress_bptc_func(image_compress_cvtt);
|
||||
Image::_image_compress_bptc_func = image_compress_cvtt;
|
||||
}
|
||||
|
||||
void uninitialize_cvtt_module(ModuleInitializationLevel p_level) {
|
||||
|
Loading…
Reference in New Issue
Block a user