For in-engine processing allow saving openexr to a buffer.

This commit is contained in:
K. S. Ernest (iFire) Lee 2022-06-19 18:55:47 -07:00
parent d1dac8427a
commit ce42ee790c
5 changed files with 36 additions and 11 deletions

View file

@ -85,6 +85,7 @@ SaveJPGFunc Image::save_jpg_func = nullptr;
SaveEXRFunc Image::save_exr_func = nullptr; SaveEXRFunc Image::save_exr_func = nullptr;
SavePNGBufferFunc Image::save_png_buffer_func = nullptr; SavePNGBufferFunc Image::save_png_buffer_func = nullptr;
SaveEXRBufferFunc Image::save_exr_buffer_func = nullptr;
SaveJPGBufferFunc Image::save_jpg_buffer_func = nullptr; SaveJPGBufferFunc Image::save_jpg_buffer_func = nullptr;
SaveWebPFunc Image::save_webp_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>((Image *)this), p_grayscale); return save_exr_func(p_path, Ref<Image>((Image *)this), p_grayscale);
} }
Vector<uint8_t> Image::save_exr_to_buffer() const {
if (save_exr_buffer_func == nullptr) {
return Vector<uint8_t>();
}
return save_exr_buffer_func(Ref<Image>((Image *)this), false);
}
Error Image::save_webp(const String &p_path, const bool p_lossy, const float p_quality) const { Error Image::save_webp(const String &p_path, const bool p_lossy, const float p_quality) const {
if (save_webp_func == nullptr) { if (save_webp_func == nullptr) {
return ERR_UNAVAILABLE; 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", "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_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", "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", "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)); ClassDB::bind_method(D_METHOD("save_webp_to_buffer", "lossy", "quality"), &Image::save_webp_to_buffer, DEFVAL(false), DEFVAL(0.75f));

View file

@ -52,6 +52,7 @@ typedef Error (*SaveWebPFunc)(const String &p_path, const Ref<Image> &p_img, con
typedef Vector<uint8_t> (*SaveWebPBufferFunc)(const Ref<Image> &p_img, const bool p_lossy, const float p_quality); typedef Vector<uint8_t> (*SaveWebPBufferFunc)(const Ref<Image> &p_img, const bool p_lossy, const float p_quality);
typedef Error (*SaveEXRFunc)(const String &p_path, const Ref<Image> &p_img, bool p_grayscale); typedef Error (*SaveEXRFunc)(const String &p_path, const Ref<Image> &p_img, bool p_grayscale);
typedef Vector<uint8_t> (*SaveEXRBufferFunc)(const Ref<Image> &p_img, bool p_grayscale);
class Image : public Resource { class Image : public Resource {
GDCLASS(Image, Resource); GDCLASS(Image, Resource);
@ -61,6 +62,7 @@ public:
static SaveJPGFunc save_jpg_func; static SaveJPGFunc save_jpg_func;
static SaveEXRFunc save_exr_func; static SaveEXRFunc save_exr_func;
static SavePNGBufferFunc save_png_buffer_func; static SavePNGBufferFunc save_png_buffer_func;
static SaveEXRBufferFunc save_exr_buffer_func;
static SaveJPGBufferFunc save_jpg_buffer_func; static SaveJPGBufferFunc save_jpg_buffer_func;
static SaveWebPFunc save_webp_func; static SaveWebPFunc save_webp_func;
static SaveWebPBufferFunc save_webp_buffer_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; Error save_jpg(const String &p_path, float p_quality = 0.75) const;
Vector<uint8_t> save_png_to_buffer() const; Vector<uint8_t> save_png_to_buffer() const;
Vector<uint8_t> save_jpg_to_buffer(float p_quality = 0.75) const; Vector<uint8_t> save_jpg_to_buffer(float p_quality = 0.75) const;
Vector<uint8_t> save_exr_to_buffer() const;
Error save_exr(const String &p_path, bool p_grayscale) 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; Error save_webp(const String &p_path, const bool p_lossy = false, const float p_quality = 0.75f) const;
Vector<uint8_t> save_webp_to_buffer(const bool p_lossy = false, const float p_quality = 0.75f) const; Vector<uint8_t> save_webp_to_buffer(const bool p_lossy = false, const float p_quality = 0.75f) const;

View file

@ -141,13 +141,14 @@ static int get_channel_count(Image::Format p_format) {
} }
} }
Error save_exr(const String &p_path, const Ref<Image> &p_img, bool p_grayscale) { Vector<uint8_t> save_exr_buffer(const Ref<Image> &p_img, bool p_grayscale) {
Image::Format format = p_img->get_format(); Image::Format format = p_img->get_format();
if (!is_supported_format(format)) { if (!is_supported_format(format)) {
// Format not supported // Format not supported
print_error("Image format not supported for saving as EXR. Consider saving as PNG."); print_error("Image format not supported for saving as EXR. Consider saving as PNG.");
return ERR_UNAVAILABLE;
return Vector<uint8_t>();
} }
EXRHeader header; EXRHeader header;
@ -175,15 +176,15 @@ Error save_exr(const String &p_path, const Ref<Image> &p_img, bool p_grayscale)
}; };
int channel_count = get_channel_count(format); int channel_count = get_channel_count(format);
ERR_FAIL_COND_V(channel_count < 0, ERR_UNAVAILABLE); ERR_FAIL_COND_V(channel_count < 0, Vector<uint8_t>());
ERR_FAIL_COND_V(p_grayscale && channel_count != 1, ERR_INVALID_PARAMETER); ERR_FAIL_COND_V(p_grayscale && channel_count != 1, Vector<uint8_t>());
int target_pixel_type = get_target_pixel_type(format); 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<uint8_t>());
int target_pixel_type_size = get_pixel_type_size(target_pixel_type); 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<uint8_t>());
SrcPixelType src_pixel_type = get_source_pixel_type(format); 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<uint8_t>());
const int pixel_count = p_img->get_width() * p_img->get_height(); const int pixel_count = p_img->get_width() * p_img->get_height();
const int *channel_mapping = channel_mappings[channel_count - 1]; const int *channel_mapping = channel_mappings[channel_count - 1];
@ -270,15 +271,25 @@ Error save_exr(const String &p_path, const Ref<Image> &p_img, bool p_grayscale)
const char *err = nullptr; const char *err = nullptr;
size_t bytes = SaveEXRImageToMemory(&image, &header, &mem, &err); size_t bytes = SaveEXRImageToMemory(&image, &header, &mem, &err);
if (err && *err != OK) {
return Vector<uint8_t>();
}
Vector<uint8_t> buffer;
buffer.resize(bytes);
memcpy(buffer.ptrw(), mem, bytes);
free(mem);
return buffer;
}
if (bytes == 0) { Error save_exr(const String &p_path, const Ref<Image> &p_img, bool p_grayscale) {
print_error(String("Saving EXR failed. Error: {0}").format(varray(err))); const Vector<uint8_t> buffer = save_exr_buffer(p_img, p_grayscale);
if (buffer.size() == 0) {
print_error(String("Saving EXR failed."));
return ERR_FILE_CANT_WRITE; return ERR_FILE_CANT_WRITE;
} else { } else {
Ref<FileAccess> ref = FileAccess::open(p_path, FileAccess::WRITE); Ref<FileAccess> ref = FileAccess::open(p_path, FileAccess::WRITE);
ERR_FAIL_COND_V(ref.is_null(), ERR_FILE_CANT_WRITE); ERR_FAIL_COND_V(ref.is_null(), ERR_FILE_CANT_WRITE);
ref->store_buffer(mem, bytes); ref->store_buffer(buffer.ptr(), buffer.size());
free(mem);
} }
return OK; return OK;

View file

@ -34,5 +34,6 @@
#include "core/os/os.h" #include "core/os/os.h"
Error save_exr(const String &p_path, const Ref<Image> &p_img, bool p_grayscale); Error save_exr(const String &p_path, const Ref<Image> &p_img, bool p_grayscale);
Vector<uint8_t> save_exr_buffer(const Ref<Image> &p_img, bool p_grayscale);
#endif // IMAGE_SAVER_TINYEXR_H #endif // IMAGE_SAVER_TINYEXR_H

View file

@ -44,6 +44,7 @@ void initialize_tinyexr_module(ModuleInitializationLevel p_level) {
ImageLoader::add_image_format_loader(image_loader_tinyexr); ImageLoader::add_image_format_loader(image_loader_tinyexr);
Image::save_exr_func = save_exr; Image::save_exr_func = save_exr;
Image::save_exr_buffer_func = save_exr_buffer;
} }
void uninitialize_tinyexr_module(ModuleInitializationLevel p_level) { void uninitialize_tinyexr_module(ModuleInitializationLevel p_level) {