diff --git a/core/io/image.cpp b/core/io/image.cpp index a945d3e6cd40..97a46c29db27 100644 --- a/core/io/image.cpp +++ b/core/io/image.cpp @@ -85,6 +85,7 @@ SaveJPGFunc Image::save_jpg_func = nullptr; SaveEXRFunc Image::save_exr_func = nullptr; SavePNGBufferFunc Image::save_png_buffer_func = nullptr; +SaveEXRBufferFunc Image::save_exr_buffer_func = nullptr; SaveJPGBufferFunc Image::save_jpg_buffer_func = nullptr; SaveWebPFunc Image::save_webp_func = nullptr; @@ -2323,6 +2324,13 @@ Error Image::save_exr(const String &p_path, bool p_grayscale) const { return save_exr_func(p_path, Ref((Image *)this), p_grayscale); } +Vector Image::save_exr_to_buffer() const { + if (save_exr_buffer_func == nullptr) { + return Vector(); + } + return save_exr_buffer_func(Ref((Image *)this), false); +} + Error Image::save_webp(const String &p_path, const bool p_lossy, const float p_quality) const { if (save_webp_func == nullptr) { return ERR_UNAVAILABLE; @@ -3180,6 +3188,7 @@ void Image::_bind_methods() { ClassDB::bind_method(D_METHOD("save_jpg", "path", "quality"), &Image::save_jpg, DEFVAL(0.75)); ClassDB::bind_method(D_METHOD("save_jpg_to_buffer", "quality"), &Image::save_jpg_to_buffer, DEFVAL(0.75)); ClassDB::bind_method(D_METHOD("save_exr", "path", "grayscale"), &Image::save_exr, DEFVAL(false)); + ClassDB::bind_method(D_METHOD("save_exr_to_buffer", "grayscale"), &Image::save_exr_to_buffer, DEFVAL(false)); ClassDB::bind_method(D_METHOD("save_webp", "path", "lossy", "quality"), &Image::save_webp, DEFVAL(false), DEFVAL(0.75f)); ClassDB::bind_method(D_METHOD("save_webp_to_buffer", "lossy", "quality"), &Image::save_webp_to_buffer, DEFVAL(false), DEFVAL(0.75f)); diff --git a/core/io/image.h b/core/io/image.h index 229103f79283..10c1156daeb3 100644 --- a/core/io/image.h +++ b/core/io/image.h @@ -52,6 +52,7 @@ typedef Error (*SaveWebPFunc)(const String &p_path, const Ref &p_img, con typedef Vector (*SaveWebPBufferFunc)(const Ref &p_img, const bool p_lossy, const float p_quality); typedef Error (*SaveEXRFunc)(const String &p_path, const Ref &p_img, bool p_grayscale); +typedef Vector (*SaveEXRBufferFunc)(const Ref &p_img, bool p_grayscale); class Image : public Resource { GDCLASS(Image, Resource); @@ -61,6 +62,7 @@ public: static SaveJPGFunc save_jpg_func; static SaveEXRFunc save_exr_func; static SavePNGBufferFunc save_png_buffer_func; + static SaveEXRBufferFunc save_exr_buffer_func; static SaveJPGBufferFunc save_jpg_buffer_func; static SaveWebPFunc save_webp_func; static SaveWebPBufferFunc save_webp_buffer_func; @@ -292,6 +294,7 @@ public: Error save_jpg(const String &p_path, float p_quality = 0.75) const; Vector save_png_to_buffer() const; Vector save_jpg_to_buffer(float p_quality = 0.75) const; + Vector save_exr_to_buffer() const; Error save_exr(const String &p_path, bool p_grayscale) const; Error save_webp(const String &p_path, const bool p_lossy = false, const float p_quality = 0.75f) const; Vector save_webp_to_buffer(const bool p_lossy = false, const float p_quality = 0.75f) const; diff --git a/modules/tinyexr/image_saver_tinyexr.cpp b/modules/tinyexr/image_saver_tinyexr.cpp index 5fa6ace8270a..661fe343afe3 100644 --- a/modules/tinyexr/image_saver_tinyexr.cpp +++ b/modules/tinyexr/image_saver_tinyexr.cpp @@ -141,13 +141,14 @@ static int get_channel_count(Image::Format p_format) { } } -Error save_exr(const String &p_path, const Ref &p_img, bool p_grayscale) { +Vector save_exr_buffer(const Ref &p_img, bool p_grayscale) { Image::Format format = p_img->get_format(); if (!is_supported_format(format)) { // Format not supported print_error("Image format not supported for saving as EXR. Consider saving as PNG."); - return ERR_UNAVAILABLE; + + return Vector(); } EXRHeader header; @@ -175,15 +176,15 @@ Error save_exr(const String &p_path, const Ref &p_img, bool p_grayscale) }; int channel_count = get_channel_count(format); - ERR_FAIL_COND_V(channel_count < 0, ERR_UNAVAILABLE); - ERR_FAIL_COND_V(p_grayscale && channel_count != 1, ERR_INVALID_PARAMETER); + ERR_FAIL_COND_V(channel_count < 0, Vector()); + ERR_FAIL_COND_V(p_grayscale && channel_count != 1, Vector()); int target_pixel_type = get_target_pixel_type(format); - ERR_FAIL_COND_V(target_pixel_type < 0, ERR_UNAVAILABLE); + ERR_FAIL_COND_V(target_pixel_type < 0, Vector()); int target_pixel_type_size = get_pixel_type_size(target_pixel_type); - ERR_FAIL_COND_V(target_pixel_type_size < 0, ERR_UNAVAILABLE); + ERR_FAIL_COND_V(target_pixel_type_size < 0, Vector()); SrcPixelType src_pixel_type = get_source_pixel_type(format); - ERR_FAIL_COND_V(src_pixel_type == SRC_UNSUPPORTED, ERR_UNAVAILABLE); + ERR_FAIL_COND_V(src_pixel_type == SRC_UNSUPPORTED, Vector()); const int pixel_count = p_img->get_width() * p_img->get_height(); const int *channel_mapping = channel_mappings[channel_count - 1]; @@ -270,15 +271,25 @@ Error save_exr(const String &p_path, const Ref &p_img, bool p_grayscale) const char *err = nullptr; size_t bytes = SaveEXRImageToMemory(&image, &header, &mem, &err); + if (err && *err != OK) { + return Vector(); + } + Vector buffer; + buffer.resize(bytes); + memcpy(buffer.ptrw(), mem, bytes); + free(mem); + return buffer; +} - if (bytes == 0) { - print_error(String("Saving EXR failed. Error: {0}").format(varray(err))); +Error save_exr(const String &p_path, const Ref &p_img, bool p_grayscale) { + const Vector buffer = save_exr_buffer(p_img, p_grayscale); + if (buffer.size() == 0) { + print_error(String("Saving EXR failed.")); return ERR_FILE_CANT_WRITE; } else { Ref ref = FileAccess::open(p_path, FileAccess::WRITE); ERR_FAIL_COND_V(ref.is_null(), ERR_FILE_CANT_WRITE); - ref->store_buffer(mem, bytes); - free(mem); + ref->store_buffer(buffer.ptr(), buffer.size()); } return OK; diff --git a/modules/tinyexr/image_saver_tinyexr.h b/modules/tinyexr/image_saver_tinyexr.h index 5bf95b265e20..8f97f55408ee 100644 --- a/modules/tinyexr/image_saver_tinyexr.h +++ b/modules/tinyexr/image_saver_tinyexr.h @@ -34,5 +34,6 @@ #include "core/os/os.h" Error save_exr(const String &p_path, const Ref &p_img, bool p_grayscale); +Vector save_exr_buffer(const Ref &p_img, bool p_grayscale); #endif // IMAGE_SAVER_TINYEXR_H diff --git a/modules/tinyexr/register_types.cpp b/modules/tinyexr/register_types.cpp index d49ac23feadc..c5897f37c389 100644 --- a/modules/tinyexr/register_types.cpp +++ b/modules/tinyexr/register_types.cpp @@ -44,6 +44,7 @@ void initialize_tinyexr_module(ModuleInitializationLevel p_level) { ImageLoader::add_image_format_loader(image_loader_tinyexr); Image::save_exr_func = save_exr; + Image::save_exr_buffer_func = save_exr_buffer; } void uninitialize_tinyexr_module(ModuleInitializationLevel p_level) {