mirror of
https://github.com/godotengine/godot
synced 2024-09-05 06:28:34 +00:00
For in-engine processing allow saving openexr to a buffer.
This commit is contained in:
parent
d1dac8427a
commit
ce42ee790c
|
@ -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>((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 {
|
||||
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));
|
||||
|
||||
|
|
|
@ -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 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 {
|
||||
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<uint8_t> save_png_to_buffer() 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_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;
|
||||
|
|
|
@ -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();
|
||||
|
||||
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<uint8_t>();
|
||||
}
|
||||
|
||||
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);
|
||||
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<uint8_t>());
|
||||
ERR_FAIL_COND_V(p_grayscale && channel_count != 1, Vector<uint8_t>());
|
||||
|
||||
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);
|
||||
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);
|
||||
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 *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;
|
||||
|
||||
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) {
|
||||
print_error(String("Saving EXR failed. Error: {0}").format(varray(err)));
|
||||
Error save_exr(const String &p_path, const Ref<Image> &p_img, bool p_grayscale) {
|
||||
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;
|
||||
} else {
|
||||
Ref<FileAccess> 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;
|
||||
|
|
|
@ -34,5 +34,6 @@
|
|||
#include "core/os/os.h"
|
||||
|
||||
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
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in a new issue