summaryrefslogtreecommitdiffstats
path: root/core/io/image.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'core/io/image.cpp')
-rw-r--r--core/io/image.cpp84
1 files changed, 83 insertions, 1 deletions
diff --git a/core/io/image.cpp b/core/io/image.cpp
index b35d405662..fcbe483e38 100644
--- a/core/io/image.cpp
+++ b/core/io/image.cpp
@@ -30,6 +30,7 @@
#include "image.h"
+#include "core/config/project_settings.h"
#include "core/error/error_list.h"
#include "core/error/error_macros.h"
#include "core/io/image_loader.h"
@@ -2734,6 +2735,27 @@ Error Image::compress(CompressMode p_mode, CompressSource p_source, ASTCFormat p
Error Image::compress_from_channels(CompressMode p_mode, UsedChannels p_channels, ASTCFormat p_astc_format) {
ERR_FAIL_COND_V(data.is_empty(), ERR_INVALID_DATA);
+ // RenderingDevice only.
+ if (GLOBAL_GET("rendering/textures/vram_compression/compress_with_gpu")) {
+ switch (p_mode) {
+ case COMPRESS_BPTC: {
+ // BC7 is unsupported currently.
+ if ((format >= FORMAT_RF && format <= FORMAT_RGBE9995) && _image_compress_bptc_rd_func) {
+ Error result = _image_compress_bptc_rd_func(this, p_channels);
+
+ // If the image was compressed successfully, we return here. If not, we fall back to the default compression scheme.
+ if (result == OK) {
+ return OK;
+ }
+ }
+
+ } break;
+
+ default: {
+ }
+ }
+ }
+
switch (p_mode) {
case COMPRESS_S3TC: {
ERR_FAIL_NULL_V(_image_compress_bc_func, ERR_UNAVAILABLE);
@@ -3115,6 +3137,7 @@ void (*Image::_image_compress_bptc_func)(Image *, Image::UsedChannels) = nullptr
void (*Image::_image_compress_etc1_func)(Image *) = nullptr;
void (*Image::_image_compress_etc2_func)(Image *, Image::UsedChannels) = nullptr;
void (*Image::_image_compress_astc_func)(Image *, Image::ASTCFormat) = nullptr;
+Error (*Image::_image_compress_bptc_rd_func)(Image *, Image::UsedChannels) = nullptr;
void (*Image::_image_decompress_bc)(Image *) = nullptr;
void (*Image::_image_decompress_bptc)(Image *) = nullptr;
void (*Image::_image_decompress_etc1)(Image *) = nullptr;
@@ -3564,6 +3587,7 @@ void Image::_bind_methods() {
ClassDB::bind_method(D_METHOD("fix_alpha_edges"), &Image::fix_alpha_edges);
ClassDB::bind_method(D_METHOD("premultiply_alpha"), &Image::premultiply_alpha);
ClassDB::bind_method(D_METHOD("srgb_to_linear"), &Image::srgb_to_linear);
+ ClassDB::bind_method(D_METHOD("linear_to_srgb"), &Image::linear_to_srgb);
ClassDB::bind_method(D_METHOD("normal_map_to_xy"), &Image::normal_map_to_xy);
ClassDB::bind_method(D_METHOD("rgbe_to_srgb"), &Image::rgbe_to_srgb);
ClassDB::bind_method(D_METHOD("bump_map_to_normal_map", "bump_scale"), &Image::bump_map_to_normal_map, DEFVAL(1.0));
@@ -3800,6 +3824,33 @@ void Image::bump_map_to_normal_map(float bump_scale) {
data = result_image;
}
+bool Image::detect_signed(bool p_include_mips) const {
+ ERR_FAIL_COND_V(is_compressed(), false);
+
+ if (format >= Image::FORMAT_RH && format <= Image::FORMAT_RGBAH) {
+ const uint16_t *img_data = reinterpret_cast<const uint16_t *>(data.ptr());
+ const uint64_t img_size = p_include_mips ? (data.size() / 2) : (width * height * get_format_pixel_size(format) / 2);
+
+ for (uint64_t i = 0; i < img_size; i++) {
+ if ((img_data[i] & 0x8000) != 0 && (img_data[i] & 0x7fff) != 0) {
+ return true;
+ }
+ }
+
+ } else if (format >= Image::FORMAT_RF && format <= Image::FORMAT_RGBAF) {
+ const uint32_t *img_data = reinterpret_cast<const uint32_t *>(data.ptr());
+ const uint64_t img_size = p_include_mips ? (data.size() / 4) : (width * height * get_format_pixel_size(format) / 4);
+
+ for (uint64_t i = 0; i < img_size; i++) {
+ if ((img_data[i] & 0x80000000) != 0 && (img_data[i] & 0x7fffffff) != 0) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
void Image::srgb_to_linear() {
if (data.size() == 0) {
return;
@@ -3831,6 +3882,37 @@ void Image::srgb_to_linear() {
}
}
+void Image::linear_to_srgb() {
+ if (data.size() == 0) {
+ return;
+ }
+
+ static const uint8_t lin2srgb[256] = { 0, 12, 21, 28, 33, 38, 42, 46, 49, 52, 55, 58, 61, 63, 66, 68, 70, 73, 75, 77, 79, 81, 82, 84, 86, 88, 89, 91, 93, 94, 96, 97, 99, 100, 102, 103, 104, 106, 107, 109, 110, 111, 112, 114, 115, 116, 117, 118, 120, 121, 122, 123, 124, 125, 126, 127, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 151, 152, 153, 154, 155, 156, 157, 157, 158, 159, 160, 161, 161, 162, 163, 164, 165, 165, 166, 167, 168, 168, 169, 170, 171, 171, 172, 173, 174, 174, 175, 176, 176, 177, 178, 179, 179, 180, 181, 181, 182, 183, 183, 184, 185, 185, 186, 187, 187, 188, 189, 189, 190, 191, 191, 192, 193, 193, 194, 194, 195, 196, 196, 197, 197, 198, 199, 199, 200, 201, 201, 202, 202, 203, 204, 204, 205, 205, 206, 206, 207, 208, 208, 209, 209, 210, 210, 211, 212, 212, 213, 213, 214, 214, 215, 215, 216, 217, 217, 218, 218, 219, 219, 220, 220, 221, 221, 222, 222, 223, 223, 224, 224, 225, 226, 226, 227, 227, 228, 228, 229, 229, 230, 230, 231, 231, 232, 232, 233, 233, 234, 234, 235, 235, 236, 236, 237, 237, 237, 238, 238, 239, 239, 240, 240, 241, 241, 242, 242, 243, 243, 244, 244, 245, 245, 245, 246, 246, 247, 247, 248, 248, 249, 249, 250, 250, 251, 251, 251, 252, 252, 253, 253, 254, 254, 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] = lin2srgb[data_ptr[(i << 2) + 0]];
+ data_ptr[(i << 2) + 1] = lin2srgb[data_ptr[(i << 2) + 1]];
+ data_ptr[(i << 2) + 2] = lin2srgb[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] = lin2srgb[data_ptr[(i * 3) + 0]];
+ data_ptr[(i * 3) + 1] = lin2srgb[data_ptr[(i * 3) + 1]];
+ data_ptr[(i * 3) + 2] = lin2srgb[data_ptr[(i * 3) + 2]];
+ }
+ }
+}
+
void Image::premultiply_alpha() {
if (data.size() == 0) {
return;
@@ -4143,7 +4225,7 @@ Dictionary Image::compute_image_metrics(const Ref<Image> p_compared_image, bool
result["root_mean_squared"] = INFINITY;
result["peak_snr"] = 0.0f;
- ERR_FAIL_NULL_V(p_compared_image, result);
+ ERR_FAIL_COND_V(p_compared_image.is_null(), result);
Error err = OK;
Ref<Image> compared_image = duplicate(true);
if (compared_image->is_compressed()) {