|
|
@@ -78,6 +78,14 @@ const char *Image::format_names[Image::FORMAT_MAX] = {
|
|
|
"ASTC_4x4_HDR",
|
|
|
"ASTC_8x8",
|
|
|
"ASTC_8x8_HDR",
|
|
|
+ "R16",
|
|
|
+ "RG16",
|
|
|
+ "RGB16",
|
|
|
+ "RGBA16",
|
|
|
+ "R16Int",
|
|
|
+ "RG16Int",
|
|
|
+ "RGB16Int",
|
|
|
+ "RGBA16Int",
|
|
|
};
|
|
|
|
|
|
// External VRAM compression function pointers.
|
|
|
@@ -201,6 +209,22 @@ int Image::get_format_pixel_size(Format p_format) {
|
|
|
return 1;
|
|
|
case FORMAT_ASTC_8x8_HDR:
|
|
|
return 1;
|
|
|
+ case FORMAT_R16:
|
|
|
+ return 2;
|
|
|
+ case FORMAT_RG16:
|
|
|
+ return 4;
|
|
|
+ case FORMAT_RGB16:
|
|
|
+ return 6;
|
|
|
+ case FORMAT_RGBA16:
|
|
|
+ return 8;
|
|
|
+ case FORMAT_R16I:
|
|
|
+ return 2;
|
|
|
+ case FORMAT_RG16I:
|
|
|
+ return 4;
|
|
|
+ case FORMAT_RGB16I:
|
|
|
+ return 6;
|
|
|
+ case FORMAT_RGBA16I:
|
|
|
+ return 8;
|
|
|
case FORMAT_MAX: {
|
|
|
}
|
|
|
}
|
|
|
@@ -759,6 +783,78 @@ void Image::convert(Format p_new_format) {
|
|
|
case FORMAT_RGBAF | (FORMAT_RGBF << 8):
|
|
|
_convert_fast<uint32_t, 4, 3, 0x00000000, 0x3F800000>(mip_width, mip_height, (const uint32_t *)rptr, (uint32_t *)wptr);
|
|
|
break;
|
|
|
+ case FORMAT_R16 | (FORMAT_RG16 << 8):
|
|
|
+ _convert_fast<uint16_t, 1, 2, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
|
|
+ break;
|
|
|
+ case FORMAT_R16 | (FORMAT_RGB16 << 8):
|
|
|
+ _convert_fast<uint16_t, 1, 3, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
|
|
+ break;
|
|
|
+ case FORMAT_R16 | (FORMAT_RGBA16 << 8):
|
|
|
+ _convert_fast<uint16_t, 1, 4, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
|
|
+ break;
|
|
|
+ case FORMAT_RG16 | (FORMAT_R16 << 8):
|
|
|
+ _convert_fast<uint16_t, 2, 1, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
|
|
+ break;
|
|
|
+ case FORMAT_RG16 | (FORMAT_RGB16 << 8):
|
|
|
+ _convert_fast<uint16_t, 2, 3, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
|
|
+ break;
|
|
|
+ case FORMAT_RG16 | (FORMAT_RGBA16 << 8):
|
|
|
+ _convert_fast<uint16_t, 2, 4, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
|
|
+ break;
|
|
|
+ case FORMAT_RGB16 | (FORMAT_R16 << 8):
|
|
|
+ _convert_fast<uint16_t, 3, 1, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
|
|
+ break;
|
|
|
+ case FORMAT_RGB16 | (FORMAT_RG16 << 8):
|
|
|
+ _convert_fast<uint16_t, 3, 2, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
|
|
+ break;
|
|
|
+ case FORMAT_RGB16 | (FORMAT_RGBA16 << 8):
|
|
|
+ _convert_fast<uint16_t, 3, 4, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
|
|
+ break;
|
|
|
+ case FORMAT_RGBA16 | (FORMAT_R16 << 8):
|
|
|
+ _convert_fast<uint16_t, 4, 1, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
|
|
+ break;
|
|
|
+ case FORMAT_RGBA16 | (FORMAT_RG16 << 8):
|
|
|
+ _convert_fast<uint16_t, 4, 2, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
|
|
+ break;
|
|
|
+ case FORMAT_RGBA16 | (FORMAT_RGB16 << 8):
|
|
|
+ _convert_fast<uint16_t, 4, 3, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
|
|
+ break;
|
|
|
+ case FORMAT_R16I | (FORMAT_RG16I << 8):
|
|
|
+ _convert_fast<uint16_t, 1, 2, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
|
|
+ break;
|
|
|
+ case FORMAT_R16I | (FORMAT_RGB16I << 8):
|
|
|
+ _convert_fast<uint16_t, 1, 3, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
|
|
+ break;
|
|
|
+ case FORMAT_R16I | (FORMAT_RGBA16I << 8):
|
|
|
+ _convert_fast<uint16_t, 1, 4, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
|
|
+ break;
|
|
|
+ case FORMAT_RG16I | (FORMAT_R16I << 8):
|
|
|
+ _convert_fast<uint16_t, 2, 1, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
|
|
+ break;
|
|
|
+ case FORMAT_RG16I | (FORMAT_RGB16I << 8):
|
|
|
+ _convert_fast<uint16_t, 2, 3, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
|
|
+ break;
|
|
|
+ case FORMAT_RG16I | (FORMAT_RGBA16I << 8):
|
|
|
+ _convert_fast<uint16_t, 2, 4, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
|
|
+ break;
|
|
|
+ case FORMAT_RGB16I | (FORMAT_R16I << 8):
|
|
|
+ _convert_fast<uint16_t, 3, 1, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
|
|
+ break;
|
|
|
+ case FORMAT_RGB16I | (FORMAT_RG16I << 8):
|
|
|
+ _convert_fast<uint16_t, 3, 2, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
|
|
+ break;
|
|
|
+ case FORMAT_RGB16I | (FORMAT_RGBA16I << 8):
|
|
|
+ _convert_fast<uint16_t, 3, 4, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
|
|
+ break;
|
|
|
+ case FORMAT_RGBA16I | (FORMAT_R16I << 8):
|
|
|
+ _convert_fast<uint16_t, 4, 1, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
|
|
+ break;
|
|
|
+ case FORMAT_RGBA16I | (FORMAT_RG16I << 8):
|
|
|
+ _convert_fast<uint16_t, 4, 2, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
|
|
+ break;
|
|
|
+ case FORMAT_RGBA16I | (FORMAT_RGB16I << 8):
|
|
|
+ _convert_fast<uint16_t, 4, 3, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
|
|
+ break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -769,6 +865,11 @@ Image::Format Image::get_format() const {
|
|
|
return format;
|
|
|
}
|
|
|
|
|
|
+enum ImageScaleType {
|
|
|
+ IMAGE_SCALING_INT,
|
|
|
+ IMAGE_SCALING_FLOAT,
|
|
|
+};
|
|
|
+
|
|
|
static double _bicubic_interp_kernel(double x) {
|
|
|
x = Math::abs(x);
|
|
|
|
|
|
@@ -783,7 +884,7 @@ static double _bicubic_interp_kernel(double x) {
|
|
|
return bc;
|
|
|
}
|
|
|
|
|
|
-template <int CC, typename T>
|
|
|
+template <int CC, typename T, ImageScaleType TYPE>
|
|
|
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;
|
|
|
@@ -848,7 +949,7 @@ static void _scale_cubic(const uint8_t *__restrict p_src, uint8_t *__restrict p_
|
|
|
const T *__restrict p = ((T *)p_src) + (oy2 * p_src_width + ox2) * CC;
|
|
|
|
|
|
for (int i = 0; i < CC; i++) {
|
|
|
- if constexpr (sizeof(T) == 2) { //half float
|
|
|
+ if constexpr (sizeof(T) == 2 && TYPE == IMAGE_SCALING_FLOAT) { //half float
|
|
|
color[i] = Math::half_to_float(p[i]);
|
|
|
} else {
|
|
|
color[i] += p[i] * k2;
|
|
|
@@ -860,8 +961,12 @@ static void _scale_cubic(const uint8_t *__restrict p_src, uint8_t *__restrict p_
|
|
|
for (int i = 0; i < CC; i++) {
|
|
|
if constexpr (sizeof(T) == 1) { //byte
|
|
|
dst[i] = CLAMP(Math::fast_ftoi(color[i]), 0, 255);
|
|
|
- } else if constexpr (sizeof(T) == 2) { //half float
|
|
|
- dst[i] = Math::make_half_float(color[i]);
|
|
|
+ } else if constexpr (sizeof(T) == 2) {
|
|
|
+ if constexpr (TYPE == IMAGE_SCALING_FLOAT) {
|
|
|
+ dst[i] = Math::make_half_float(color[i]); //half float
|
|
|
+ } else {
|
|
|
+ dst[i] = CLAMP(Math::fast_ftoi(color[i]), 0, 65535); // uint16
|
|
|
+ }
|
|
|
} else {
|
|
|
dst[i] = color[i];
|
|
|
}
|
|
|
@@ -870,7 +975,7 @@ static void _scale_cubic(const uint8_t *__restrict p_src, uint8_t *__restrict p_
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-template <int CC, typename T>
|
|
|
+template <int CC, typename T, ImageScaleType TYPE>
|
|
|
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) {
|
|
|
constexpr uint32_t FRAC_BITS = 8;
|
|
|
constexpr uint32_t FRAC_LEN = (1 << FRAC_BITS);
|
|
|
@@ -918,23 +1023,40 @@ static void _scale_bilinear(const uint8_t *__restrict p_src, uint8_t *__restrict
|
|
|
uint32_t interp = interp_up + (((interp_down - interp_up) * src_yofs_frac) >> FRAC_BITS);
|
|
|
interp >>= FRAC_BITS;
|
|
|
p_dst[i * p_dst_width * CC + j * CC + l] = uint8_t(interp);
|
|
|
- } else if constexpr (sizeof(T) == 2) { //half float
|
|
|
-
|
|
|
- float xofs_frac = float(src_xofs_frac) / (1 << FRAC_BITS);
|
|
|
- float yofs_frac = float(src_yofs_frac) / (1 << FRAC_BITS);
|
|
|
- const T *src = ((const T *)p_src);
|
|
|
- T *dst = ((T *)p_dst);
|
|
|
-
|
|
|
- float p00 = Math::half_to_float(src[y_ofs_up + src_xofs_left + l]);
|
|
|
- float p10 = Math::half_to_float(src[y_ofs_up + src_xofs_right + l]);
|
|
|
- float p01 = Math::half_to_float(src[y_ofs_down + src_xofs_left + l]);
|
|
|
- float p11 = Math::half_to_float(src[y_ofs_down + src_xofs_right + l]);
|
|
|
-
|
|
|
- float interp_up = p00 + (p10 - p00) * xofs_frac;
|
|
|
- float interp_down = p01 + (p11 - p01) * xofs_frac;
|
|
|
- float interp = interp_up + ((interp_down - interp_up) * yofs_frac);
|
|
|
-
|
|
|
- dst[i * p_dst_width * CC + j * CC + l] = Math::make_half_float(interp);
|
|
|
+ } else if constexpr (sizeof(T) == 2) {
|
|
|
+ if constexpr (TYPE == IMAGE_SCALING_FLOAT) { //half float
|
|
|
+ float xofs_frac = float(src_xofs_frac) / (1 << FRAC_BITS);
|
|
|
+ float yofs_frac = float(src_yofs_frac) / (1 << FRAC_BITS);
|
|
|
+ const T *src = ((const T *)p_src);
|
|
|
+ T *dst = ((T *)p_dst);
|
|
|
+
|
|
|
+ float p00 = Math::half_to_float(src[y_ofs_up + src_xofs_left + l]);
|
|
|
+ float p10 = Math::half_to_float(src[y_ofs_up + src_xofs_right + l]);
|
|
|
+ float p01 = Math::half_to_float(src[y_ofs_down + src_xofs_left + l]);
|
|
|
+ float p11 = Math::half_to_float(src[y_ofs_down + src_xofs_right + l]);
|
|
|
+
|
|
|
+ float interp_up = p00 + (p10 - p00) * xofs_frac;
|
|
|
+ float interp_down = p01 + (p11 - p01) * xofs_frac;
|
|
|
+ float interp = interp_up + ((interp_down - interp_up) * yofs_frac);
|
|
|
+
|
|
|
+ dst[i * p_dst_width * CC + j * CC + l] = Math::make_half_float(interp);
|
|
|
+ } else { //uint16
|
|
|
+ float xofs_frac = float(src_xofs_frac) / (1 << FRAC_BITS);
|
|
|
+ float yofs_frac = float(src_yofs_frac) / (1 << FRAC_BITS);
|
|
|
+ const T *src = ((const T *)p_src);
|
|
|
+ T *dst = ((T *)p_dst);
|
|
|
+
|
|
|
+ float p00 = src[y_ofs_up + src_xofs_left + l];
|
|
|
+ float p10 = src[y_ofs_up + src_xofs_right + l];
|
|
|
+ float p01 = src[y_ofs_down + src_xofs_left + l];
|
|
|
+ float p11 = src[y_ofs_down + src_xofs_right + l];
|
|
|
+
|
|
|
+ float interp_up = p00 + (p10 - p00) * xofs_frac;
|
|
|
+ float interp_down = p01 + (p11 - p01) * xofs_frac;
|
|
|
+ float interp = interp_up + ((interp_down - interp_up) * yofs_frac);
|
|
|
+
|
|
|
+ dst[i * p_dst_width * CC + j * CC + l] = uint16_t(interp);
|
|
|
+ }
|
|
|
} else if constexpr (sizeof(T) == 4) { //float
|
|
|
|
|
|
float xofs_frac = float(src_xofs_frac) / (1 << FRAC_BITS);
|
|
|
@@ -985,7 +1107,7 @@ static float _lanczos(float p_x) {
|
|
|
return Math::abs(p_x) >= LANCZOS_TYPE ? 0 : Math::sincn(p_x) * Math::sincn(p_x / LANCZOS_TYPE);
|
|
|
}
|
|
|
|
|
|
-template <int CC, typename T>
|
|
|
+template <int CC, typename T, ImageScaleType TYPE>
|
|
|
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;
|
|
|
@@ -1026,7 +1148,7 @@ static void _scale_lanczos(const uint8_t *__restrict p_src, uint8_t *__restrict
|
|
|
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 constexpr (sizeof(T) == 2) { //half float
|
|
|
+ if constexpr (sizeof(T) == 2 && TYPE == IMAGE_SCALING_FLOAT) { //half float
|
|
|
pixel[i] += Math::half_to_float(src_data[i]) * lanczos_val;
|
|
|
} else {
|
|
|
pixel[i] += src_data[i] * lanczos_val;
|
|
|
@@ -1085,8 +1207,13 @@ static void _scale_lanczos(const uint8_t *__restrict p_src, uint8_t *__restrict
|
|
|
|
|
|
if constexpr (sizeof(T) == 1) { //byte
|
|
|
dst_data[i] = CLAMP(Math::fast_ftoi(pixel[i]), 0, 255);
|
|
|
- } else if constexpr (sizeof(T) == 2) { //half float
|
|
|
- dst_data[i] = Math::make_half_float(pixel[i]);
|
|
|
+ } else if constexpr (sizeof(T) == 2) {
|
|
|
+ if constexpr (TYPE == IMAGE_SCALING_FLOAT) { //half float
|
|
|
+ dst_data[i] = Math::make_half_float(pixel[i]);
|
|
|
+ } else { //uint16
|
|
|
+ dst_data[i] = CLAMP(Math::fast_ftoi(pixel[i]), 0, 65535);
|
|
|
+ }
|
|
|
+
|
|
|
} else { // float
|
|
|
dst_data[i] = pixel[i];
|
|
|
}
|
|
|
@@ -1229,6 +1356,21 @@ void Image::resize(int p_width, int p_height, Interpolation p_interpolation) {
|
|
|
_scale_nearest<4, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
|
|
|
break;
|
|
|
}
|
|
|
+ } else if (format >= FORMAT_R16 && format <= FORMAT_RGBA16I) {
|
|
|
+ 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;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
} break;
|
|
|
@@ -1273,46 +1415,61 @@ 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);
|
|
|
+ _scale_bilinear<1, uint8_t, IMAGE_SCALING_INT>(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);
|
|
|
+ _scale_bilinear<2, uint8_t, IMAGE_SCALING_INT>(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);
|
|
|
+ _scale_bilinear<3, uint8_t, IMAGE_SCALING_INT>(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);
|
|
|
+ _scale_bilinear<4, uint8_t, IMAGE_SCALING_INT>(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);
|
|
|
+ _scale_bilinear<1, float, IMAGE_SCALING_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);
|
|
|
+ _scale_bilinear<2, float, IMAGE_SCALING_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);
|
|
|
+ _scale_bilinear<3, float, IMAGE_SCALING_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);
|
|
|
+ _scale_bilinear<4, float, IMAGE_SCALING_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);
|
|
|
+ _scale_bilinear<1, uint16_t, IMAGE_SCALING_FLOAT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
|
|
+ break;
|
|
|
+ case 4:
|
|
|
+ _scale_bilinear<2, uint16_t, IMAGE_SCALING_FLOAT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
|
|
+ break;
|
|
|
+ case 6:
|
|
|
+ _scale_bilinear<3, uint16_t, IMAGE_SCALING_FLOAT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
|
|
+ break;
|
|
|
+ case 8:
|
|
|
+ _scale_bilinear<4, uint16_t, IMAGE_SCALING_FLOAT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ } else if (format >= FORMAT_R16 && format <= FORMAT_RGBA16I) {
|
|
|
+ switch (get_format_pixel_size(format)) {
|
|
|
+ case 2:
|
|
|
+ _scale_bilinear<1, uint16_t, IMAGE_SCALING_INT>(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);
|
|
|
+ _scale_bilinear<2, uint16_t, IMAGE_SCALING_INT>(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);
|
|
|
+ _scale_bilinear<3, uint16_t, IMAGE_SCALING_INT>(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);
|
|
|
+ _scale_bilinear<4, uint16_t, IMAGE_SCALING_INT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
@@ -1329,46 +1486,61 @@ 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_cubic<1, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height);
|
|
|
+ _scale_cubic<1, uint8_t, IMAGE_SCALING_INT>(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);
|
|
|
+ _scale_cubic<2, uint8_t, IMAGE_SCALING_INT>(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);
|
|
|
+ _scale_cubic<3, uint8_t, IMAGE_SCALING_INT>(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);
|
|
|
+ _scale_cubic<4, uint8_t, IMAGE_SCALING_INT>(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);
|
|
|
+ _scale_cubic<1, float, IMAGE_SCALING_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);
|
|
|
+ _scale_cubic<2, float, IMAGE_SCALING_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);
|
|
|
+ _scale_cubic<3, float, IMAGE_SCALING_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);
|
|
|
+ _scale_cubic<4, float, IMAGE_SCALING_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);
|
|
|
+ _scale_cubic<1, uint16_t, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
|
|
+ break;
|
|
|
+ case 4:
|
|
|
+ _scale_cubic<2, uint16_t, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
|
|
+ break;
|
|
|
+ case 6:
|
|
|
+ _scale_cubic<3, uint16_t, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
|
|
+ break;
|
|
|
+ case 8:
|
|
|
+ _scale_cubic<4, uint16_t, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ } else if (format >= FORMAT_R16 && format <= FORMAT_RGBA16I) {
|
|
|
+ switch (get_format_pixel_size(format)) {
|
|
|
+ case 2:
|
|
|
+ _scale_cubic<1, uint16_t, IMAGE_SCALING_INT>(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);
|
|
|
+ _scale_cubic<2, uint16_t, IMAGE_SCALING_INT>(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);
|
|
|
+ _scale_cubic<3, uint16_t, IMAGE_SCALING_INT>(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);
|
|
|
+ _scale_cubic<4, uint16_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
@@ -1377,46 +1549,61 @@ 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_lanczos<1, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height);
|
|
|
+ _scale_lanczos<1, uint8_t, IMAGE_SCALING_INT>(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);
|
|
|
+ _scale_lanczos<2, uint8_t, IMAGE_SCALING_INT>(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);
|
|
|
+ _scale_lanczos<3, uint8_t, IMAGE_SCALING_INT>(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);
|
|
|
+ _scale_lanczos<4, uint8_t, IMAGE_SCALING_INT>(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);
|
|
|
+ _scale_lanczos<1, float, IMAGE_SCALING_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);
|
|
|
+ _scale_lanczos<2, float, IMAGE_SCALING_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);
|
|
|
+ _scale_lanczos<3, float, IMAGE_SCALING_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);
|
|
|
+ _scale_lanczos<4, float, IMAGE_SCALING_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);
|
|
|
+ _scale_lanczos<1, uint16_t, IMAGE_SCALING_FLOAT>(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);
|
|
|
+ _scale_lanczos<2, uint16_t, IMAGE_SCALING_FLOAT>(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);
|
|
|
+ _scale_lanczos<3, uint16_t, IMAGE_SCALING_FLOAT>(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);
|
|
|
+ _scale_lanczos<4, uint16_t, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ } else if (format >= FORMAT_R16 && format <= FORMAT_RGBA16I) {
|
|
|
+ switch (get_format_pixel_size(format)) {
|
|
|
+ case 2:
|
|
|
+ _scale_lanczos<1, uint16_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
|
|
+ break;
|
|
|
+ case 4:
|
|
|
+ _scale_lanczos<2, uint16_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
|
|
+ break;
|
|
|
+ case 6:
|
|
|
+ _scale_lanczos<3, uint16_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
|
|
+ break;
|
|
|
+ case 8:
|
|
|
+ _scale_lanczos<4, uint16_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
@@ -1874,6 +2061,30 @@ void Image::_generate_mipmap_from_format(Image::Format p_format, const uint8_t *
|
|
|
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;
|
|
|
+ case Image::FORMAT_R16:
|
|
|
+ case Image::FORMAT_R16I:
|
|
|
+ _generate_po2_mipmap<uint16_t, 1, false, Image::average_4_uint16, Image::renormalize_uint16>(src_u16, dst_u16, p_width, p_height);
|
|
|
+ break;
|
|
|
+ case Image::FORMAT_RG16:
|
|
|
+ case Image::FORMAT_RG16I:
|
|
|
+ _generate_po2_mipmap<uint16_t, 2, false, Image::average_4_uint16, Image::renormalize_uint16>(src_u16, dst_u16, p_width, p_height);
|
|
|
+ break;
|
|
|
+ case Image::FORMAT_RGB16:
|
|
|
+ case Image::FORMAT_RGB16I: {
|
|
|
+ if (p_renormalize) {
|
|
|
+ _generate_po2_mipmap<uint16_t, 3, true, Image::average_4_uint16, Image::renormalize_uint16>(src_u16, dst_u16, p_width, p_height);
|
|
|
+ } else {
|
|
|
+ _generate_po2_mipmap<uint16_t, 3, false, Image::average_4_uint16, Image::renormalize_uint16>(src_u16, dst_u16, p_width, p_height);
|
|
|
+ }
|
|
|
+ } break;
|
|
|
+ case Image::FORMAT_RGBA16:
|
|
|
+ case Image::FORMAT_RGBA16I: {
|
|
|
+ if (p_renormalize) {
|
|
|
+ _generate_po2_mipmap<uint16_t, 4, true, Image::average_4_uint16, Image::renormalize_uint16>(src_u16, dst_u16, p_width, p_height);
|
|
|
+ } else {
|
|
|
+ _generate_po2_mipmap<uint16_t, 4, false, Image::average_4_uint16, Image::renormalize_uint16>(src_u16, dst_u16, p_width, p_height);
|
|
|
+ }
|
|
|
+ } break;
|
|
|
|
|
|
default:
|
|
|
return;
|
|
|
@@ -2471,6 +2682,17 @@ bool Image::is_invisible() const {
|
|
|
}
|
|
|
}
|
|
|
} break;
|
|
|
+ case FORMAT_RGBA16:
|
|
|
+ case FORMAT_RGBA16I: {
|
|
|
+ const int pixel_count = len / 8;
|
|
|
+ const uint16_t *pixeldata = reinterpret_cast<const uint16_t *>(data.ptr());
|
|
|
+
|
|
|
+ for (int i = 0; i < pixel_count; i++) {
|
|
|
+ if (pixeldata[i * 4 + 3] != 0) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } break;
|
|
|
default: {
|
|
|
// Formats that are compressed or don't support alpha channels are presumed to be visible.
|
|
|
return false;
|
|
|
@@ -2674,7 +2896,7 @@ bool Image::is_compressed() const {
|
|
|
}
|
|
|
|
|
|
bool Image::is_format_compressed(Format p_format) {
|
|
|
- return p_format > FORMAT_RGBE9995;
|
|
|
+ return p_format > FORMAT_RGBE9995 && p_format < FORMAT_R16;
|
|
|
}
|
|
|
|
|
|
Error Image::decompress() {
|
|
|
@@ -3255,6 +3477,50 @@ 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]);
|
|
|
}
|
|
|
+ case FORMAT_R16: {
|
|
|
+ float r = ((uint16_t *)ptr)[ofs] / 65535.0f;
|
|
|
+ return Color(r, 0, 0, 1);
|
|
|
+ }
|
|
|
+ case FORMAT_RG16: {
|
|
|
+ float r = ((uint16_t *)ptr)[ofs * 2 + 0] / 65535.0f;
|
|
|
+ float g = ((uint16_t *)ptr)[ofs * 2 + 1] / 65535.0f;
|
|
|
+ return Color(r, g, 0, 1);
|
|
|
+ }
|
|
|
+ case FORMAT_RGB16: {
|
|
|
+ float r = ((uint16_t *)ptr)[ofs * 3 + 0] / 65535.0f;
|
|
|
+ float g = ((uint16_t *)ptr)[ofs * 3 + 1] / 65535.0f;
|
|
|
+ float b = ((uint16_t *)ptr)[ofs * 3 + 2] / 65535.0f;
|
|
|
+ return Color(r, g, b, 1);
|
|
|
+ }
|
|
|
+ case FORMAT_RGBA16: {
|
|
|
+ float r = ((uint16_t *)ptr)[ofs * 4 + 0] / 65535.0f;
|
|
|
+ float g = ((uint16_t *)ptr)[ofs * 4 + 1] / 65535.0f;
|
|
|
+ float b = ((uint16_t *)ptr)[ofs * 4 + 2] / 65535.0f;
|
|
|
+ float a = ((uint16_t *)ptr)[ofs * 4 + 3] / 65535.0f;
|
|
|
+ return Color(r, g, b, a);
|
|
|
+ }
|
|
|
+ case FORMAT_R16I: {
|
|
|
+ uint16_t r = ((uint16_t *)ptr)[ofs];
|
|
|
+ return Color(r, 0, 0, 1);
|
|
|
+ }
|
|
|
+ case FORMAT_RG16I: {
|
|
|
+ uint16_t r = ((uint16_t *)ptr)[ofs * 2 + 0];
|
|
|
+ uint16_t g = ((uint16_t *)ptr)[ofs * 2 + 1];
|
|
|
+ return Color(r, g, 0, 1);
|
|
|
+ }
|
|
|
+ case FORMAT_RGB16I: {
|
|
|
+ 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(r, g, b, 1);
|
|
|
+ }
|
|
|
+ case FORMAT_RGBA16I: {
|
|
|
+ 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];
|
|
|
+ uint16_t a = ((uint16_t *)ptr)[ofs * 4 + 3];
|
|
|
+ return Color(r, g, b, a);
|
|
|
+ }
|
|
|
|
|
|
default: {
|
|
|
ERR_FAIL_V_MSG(Color(), "Can't get_pixel() on compressed image, sorry.");
|
|
|
@@ -3347,6 +3613,42 @@ void Image::_set_color_at_ofs(uint8_t *ptr, uint32_t ofs, const Color &p_color)
|
|
|
case FORMAT_RGBE9995: {
|
|
|
((uint32_t *)ptr)[ofs] = p_color.to_rgbe9995();
|
|
|
} break;
|
|
|
+ case FORMAT_R16: {
|
|
|
+ ((uint16_t *)ptr)[ofs] = uint16_t(CLAMP(p_color.r * 65535.0, 0, 65535));
|
|
|
+ } break;
|
|
|
+ case FORMAT_RG16: {
|
|
|
+ ((uint16_t *)ptr)[ofs * 2 + 0] = uint16_t(CLAMP(p_color.r * 65535.0, 0, 65535));
|
|
|
+ ((uint16_t *)ptr)[ofs * 2 + 1] = uint16_t(CLAMP(p_color.g * 65535.0, 0, 65535));
|
|
|
+ } break;
|
|
|
+ case FORMAT_RGB16: {
|
|
|
+ ((uint16_t *)ptr)[ofs * 3 + 0] = uint16_t(CLAMP(p_color.r * 65535.0, 0, 65535));
|
|
|
+ ((uint16_t *)ptr)[ofs * 3 + 1] = uint16_t(CLAMP(p_color.g * 65535.0, 0, 65535));
|
|
|
+ ((uint16_t *)ptr)[ofs * 3 + 2] = uint16_t(CLAMP(p_color.b * 65535.0, 0, 65535));
|
|
|
+ } break;
|
|
|
+ case FORMAT_RGBA16: {
|
|
|
+ ((uint16_t *)ptr)[ofs * 4 + 0] = uint16_t(CLAMP(p_color.r * 65535.0, 0, 65535));
|
|
|
+ ((uint16_t *)ptr)[ofs * 4 + 1] = uint16_t(CLAMP(p_color.g * 65535.0, 0, 65535));
|
|
|
+ ((uint16_t *)ptr)[ofs * 4 + 2] = uint16_t(CLAMP(p_color.b * 65535.0, 0, 65535));
|
|
|
+ ((uint16_t *)ptr)[ofs * 4 + 3] = uint16_t(CLAMP(p_color.a * 65535.0, 0, 65535));
|
|
|
+ } break;
|
|
|
+ case FORMAT_R16I: {
|
|
|
+ ((uint16_t *)ptr)[ofs] = uint16_t(CLAMP(p_color.r, 0, 65535));
|
|
|
+ } break;
|
|
|
+ case FORMAT_RG16I: {
|
|
|
+ ((uint16_t *)ptr)[ofs * 2 + 0] = uint16_t(CLAMP(p_color.r, 0, 65535));
|
|
|
+ ((uint16_t *)ptr)[ofs * 2 + 1] = uint16_t(CLAMP(p_color.g, 0, 65535));
|
|
|
+ } break;
|
|
|
+ case FORMAT_RGB16I: {
|
|
|
+ ((uint16_t *)ptr)[ofs * 3 + 0] = uint16_t(CLAMP(p_color.r, 0, 65535));
|
|
|
+ ((uint16_t *)ptr)[ofs * 3 + 1] = uint16_t(CLAMP(p_color.g, 0, 65535));
|
|
|
+ ((uint16_t *)ptr)[ofs * 3 + 2] = uint16_t(CLAMP(p_color.b, 0, 65535));
|
|
|
+ } break;
|
|
|
+ case FORMAT_RGBA16I: {
|
|
|
+ ((uint16_t *)ptr)[ofs * 4 + 0] = uint16_t(CLAMP(p_color.r, 0, 65535));
|
|
|
+ ((uint16_t *)ptr)[ofs * 4 + 1] = uint16_t(CLAMP(p_color.g, 0, 65535));
|
|
|
+ ((uint16_t *)ptr)[ofs * 4 + 2] = uint16_t(CLAMP(p_color.b, 0, 65535));
|
|
|
+ ((uint16_t *)ptr)[ofs * 4 + 3] = uint16_t(CLAMP(p_color.a, 0, 65535));
|
|
|
+ } break;
|
|
|
|
|
|
default: {
|
|
|
ERR_FAIL_MSG("Can't set_pixel() on compressed image, sorry.");
|
|
|
@@ -3422,11 +3724,11 @@ Image::UsedChannels Image::detect_used_channels(CompressSource p_source) const {
|
|
|
|
|
|
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) {
|
|
|
+ } else if (format == FORMAT_R8 || format == FORMAT_RH || format == FORMAT_RF || format == FORMAT_R16 || format == FORMAT_R16I) {
|
|
|
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;
|
|
|
+ const bool supports_alpha = format == FORMAT_RGBA8 || format == FORMAT_RGBA4444 || format == FORMAT_RGBAH || format == FORMAT_RGBAF || format == FORMAT_RGBA16 || format == FORMAT_RGBA16I;
|
|
|
bool r = false, g = false, b = false, a = false, c = false;
|
|
|
|
|
|
const uint8_t *data_ptr = data.ptr();
|
|
|
@@ -3660,6 +3962,14 @@ void Image::_bind_methods() {
|
|
|
BIND_ENUM_CONSTANT(FORMAT_ASTC_4x4_HDR);
|
|
|
BIND_ENUM_CONSTANT(FORMAT_ASTC_8x8);
|
|
|
BIND_ENUM_CONSTANT(FORMAT_ASTC_8x8_HDR);
|
|
|
+ BIND_ENUM_CONSTANT(FORMAT_R16);
|
|
|
+ BIND_ENUM_CONSTANT(FORMAT_RG16);
|
|
|
+ BIND_ENUM_CONSTANT(FORMAT_RGB16);
|
|
|
+ BIND_ENUM_CONSTANT(FORMAT_RGBA16);
|
|
|
+ BIND_ENUM_CONSTANT(FORMAT_R16I);
|
|
|
+ BIND_ENUM_CONSTANT(FORMAT_RG16I);
|
|
|
+ BIND_ENUM_CONSTANT(FORMAT_RGB16I);
|
|
|
+ BIND_ENUM_CONSTANT(FORMAT_RGBA16I);
|
|
|
BIND_ENUM_CONSTANT(FORMAT_MAX);
|
|
|
|
|
|
BIND_ENUM_CONSTANT(INTERPOLATE_NEAREST);
|
|
|
@@ -4073,6 +4383,22 @@ uint32_t Image::get_format_component_mask(Format p_format) {
|
|
|
return rgba;
|
|
|
case FORMAT_ASTC_8x8_HDR:
|
|
|
return rgba;
|
|
|
+ case FORMAT_R16:
|
|
|
+ return r;
|
|
|
+ case FORMAT_RG16:
|
|
|
+ return rg;
|
|
|
+ case FORMAT_RGB16:
|
|
|
+ return rgb;
|
|
|
+ case FORMAT_RGBA16:
|
|
|
+ return rgba;
|
|
|
+ case FORMAT_R16I:
|
|
|
+ return r;
|
|
|
+ case FORMAT_RG16I:
|
|
|
+ return rg;
|
|
|
+ case FORMAT_RGB16I:
|
|
|
+ return rgb;
|
|
|
+ case FORMAT_RGBA16I:
|
|
|
+ return rgba;
|
|
|
default:
|
|
|
ERR_PRINT("Unhandled format.");
|
|
|
return rgba;
|
|
|
@@ -4216,6 +4542,10 @@ void Image::average_4_rgbe9995(uint32_t &p_out, const uint32_t &p_a, const uint3
|
|
|
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();
|
|
|
}
|
|
|
|
|
|
+void Image::average_4_uint16(uint16_t &p_out, const uint16_t &p_a, const uint16_t &p_b, const uint16_t &p_c, const uint16_t &p_d) {
|
|
|
+ p_out = static_cast<uint16_t>((p_a + p_b + p_c + p_d + 2) >> 2);
|
|
|
+}
|
|
|
+
|
|
|
void Image::renormalize_uint8(uint8_t *p_rgb) {
|
|
|
Vector3 n(p_rgb[0] / 255.0, p_rgb[1] / 255.0, p_rgb[2] / 255.0);
|
|
|
n *= 2.0;
|
|
|
@@ -4249,6 +4579,19 @@ void Image::renormalize_rgbe9995(uint32_t *p_rgb) {
|
|
|
// Never used.
|
|
|
}
|
|
|
|
|
|
+void Image::renormalize_uint16(uint16_t *p_rgb) {
|
|
|
+ Vector3 n(p_rgb[0] / 65535.0, p_rgb[1] / 65535.0, p_rgb[2] / 65535.0);
|
|
|
+ n *= 2.0;
|
|
|
+ n -= Vector3(1, 1, 1);
|
|
|
+ n.normalize();
|
|
|
+ n += Vector3(1, 1, 1);
|
|
|
+ n *= 0.5;
|
|
|
+ n *= 65535;
|
|
|
+ p_rgb[0] = CLAMP(int(n.x), 0, 65535);
|
|
|
+ p_rgb[1] = CLAMP(int(n.y), 0, 65535);
|
|
|
+ p_rgb[2] = CLAMP(int(n.z), 0, 65535);
|
|
|
+}
|
|
|
+
|
|
|
Image::Image(const uint8_t *p_mem_png_jpg, int p_len) {
|
|
|
width = 0;
|
|
|
height = 0;
|