diff --git a/core/image.cpp b/core/image.cpp index b0bed80a6f9..b9386a1b6d2 100644 --- a/core/image.cpp +++ b/core/image.cpp @@ -1898,8 +1898,9 @@ void Image::fill(const Color &c) { unlock(); } -Ref (*Image::_png_mem_loader_func)(const uint8_t *, int) = NULL; -Ref (*Image::_jpg_mem_loader_func)(const uint8_t *, int) = NULL; +ImageMemLoadFunc Image::_png_mem_loader_func = NULL; +ImageMemLoadFunc Image::_jpg_mem_loader_func = NULL; +ImageMemLoadFunc Image::_webp_mem_loader_func = NULL; void (*Image::_image_compress_bc_func)(Image *, Image::CompressSource) = NULL; void (*Image::_image_compress_pvrtc2_func)(Image *) = NULL; @@ -2357,6 +2358,7 @@ void Image::_bind_methods() { ClassDB::bind_method(D_METHOD("load_png_from_buffer", "buffer"), &Image::load_png_from_buffer); ClassDB::bind_method(D_METHOD("load_jpg_from_buffer", "buffer"), &Image::load_jpg_from_buffer); + ClassDB::bind_method(D_METHOD("load_webp_from_buffer", "buffer"), &Image::load_webp_from_buffer); ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "_set_data", "_get_data"); @@ -2649,32 +2651,26 @@ String Image::get_format_name(Format p_format) { } Error Image::load_png_from_buffer(const PoolVector &p_array) { - - int buffer_size = p_array.size(); - - ERR_FAIL_COND_V(buffer_size == 0, ERR_INVALID_PARAMETER); - ERR_FAIL_COND_V(!_png_mem_loader_func, ERR_INVALID_PARAMETER); - - PoolVector::Read r = p_array.read(); - - Ref image = _png_mem_loader_func(r.ptr(), buffer_size); - ERR_FAIL_COND_V(!image.is_valid(), ERR_PARSE_ERROR); - - copy_internals_from(image); - - return OK; + return _load_from_buffer(p_array, _png_mem_loader_func); } Error Image::load_jpg_from_buffer(const PoolVector &p_array) { + return _load_from_buffer(p_array, _jpg_mem_loader_func); +} +Error Image::load_webp_from_buffer(const PoolVector &p_array) { + return _load_from_buffer(p_array, _webp_mem_loader_func); +} + +Error Image::_load_from_buffer(const PoolVector &p_array, ImageMemLoadFunc p_loader) { int buffer_size = p_array.size(); ERR_FAIL_COND_V(buffer_size == 0, ERR_INVALID_PARAMETER); - ERR_FAIL_COND_V(!_jpg_mem_loader_func, ERR_INVALID_PARAMETER); + ERR_FAIL_COND_V(!p_loader, ERR_INVALID_PARAMETER); PoolVector::Read r = p_array.read(); - Ref image = _jpg_mem_loader_func(r.ptr(), buffer_size); + Ref image = p_loader(r.ptr(), buffer_size); ERR_FAIL_COND_V(!image.is_valid(), ERR_PARSE_ERROR); copy_internals_from(image); diff --git a/core/image.h b/core/image.h index 43516e2c0b2..3792103a87a 100644 --- a/core/image.h +++ b/core/image.h @@ -47,6 +47,7 @@ class Image; typedef Error (*SavePNGFunc)(const String &p_path, const Ref &p_img); +typedef Ref (*ImageMemLoadFunc)(const uint8_t *p_png, int p_size); class Image : public Resource { GDCLASS(Image, Resource); @@ -118,8 +119,9 @@ public: //some functions provided by something else - static Ref (*_png_mem_loader_func)(const uint8_t *p_png, int p_size); - static Ref (*_jpg_mem_loader_func)(const uint8_t *p_png, int p_size); + static ImageMemLoadFunc _png_mem_loader_func; + static ImageMemLoadFunc _jpg_mem_loader_func; + static ImageMemLoadFunc _webp_mem_loader_func; static void (*_image_compress_bc_func)(Image *, CompressSource p_source); static void (*_image_compress_pvrtc2_func)(Image *); @@ -175,6 +177,8 @@ private: void _set_data(const Dictionary &p_data); Dictionary _get_data() const; + Error _load_from_buffer(const PoolVector &p_array, ImageMemLoadFunc p_loader); + public: int get_width() const; ///< Get image width int get_height() const; ///< Get image height @@ -302,6 +306,7 @@ public: Error load_png_from_buffer(const PoolVector &p_array); Error load_jpg_from_buffer(const PoolVector &p_array); + Error load_webp_from_buffer(const PoolVector &p_array); Image(const uint8_t *p_mem_png_jpg, int p_len = -1); Image(const char **p_xpm); diff --git a/doc/classes/Image.xml b/doc/classes/Image.xml index 9fc7672a801..e10485a6b2e 100644 --- a/doc/classes/Image.xml +++ b/doc/classes/Image.xml @@ -350,6 +350,15 @@ Loads an image from the binary contents of a PNG file. + + + + + + + Loads an image from the binary contents of a WebP file. + + diff --git a/modules/jpg/image_loader_jpegd.cpp b/modules/jpg/image_loader_jpegd.cpp index 0168be3a26e..437c0d57faf 100644 --- a/modules/jpg/image_loader_jpegd.cpp +++ b/modules/jpg/image_loader_jpegd.cpp @@ -121,9 +121,7 @@ static Ref _jpegd_mem_loader_func(const uint8_t *p_png, int p_size) { Ref img; img.instance(); Error err = jpeg_load_image_from_buffer(img.ptr(), p_png, p_size); - if (err) - ERR_PRINT("Couldn't initialize ImageLoaderJPG with the given resource."); - + ERR_FAIL_COND_V(err, Ref()); return img; } diff --git a/modules/webp/image_loader_webp.cpp b/modules/webp/image_loader_webp.cpp index cdf2d75e969..42b2c77777d 100644 --- a/modules/webp/image_loader_webp.cpp +++ b/modules/webp/image_loader_webp.cpp @@ -116,64 +116,73 @@ static Ref _webp_lossy_unpack(const PoolVector &p_buffer) { return img; } -Error ImageLoaderWEBP::load_image(Ref p_image, FileAccess *f, bool p_force_linear, float p_scale) { +Error webp_load_image_from_buffer(Image *p_image, const uint8_t *p_buffer, int p_buffer_len) { - uint32_t size = f->get_len(); - PoolVector src_image; - src_image.resize(size); + ERR_FAIL_NULL_V(p_image, ERR_INVALID_PARAMETER); WebPBitstreamFeatures features; - - PoolVector::Write src_w = src_image.write(); - f->get_buffer(src_w.ptr(), size); - ERR_FAIL_COND_V(f->eof_reached(), ERR_FILE_EOF); - - if (WebPGetFeatures(src_w.ptr(), size, &features) != VP8_STATUS_OK) { - f->close(); - //ERR_EXPLAIN("Error decoding WEBP image: "+p_file); + if (WebPGetFeatures(p_buffer, p_buffer_len, &features) != VP8_STATUS_OK) { + // ERR_EXPLAIN("Error decoding WEBP image"); ERR_FAIL_V(ERR_FILE_CORRUPT); } - /* - print_line("width: " + itos(features.width)); - print_line("height: " + itos(features.height)); - print_line("alpha: " + itos(features.has_alpha)); - */ - - src_w = PoolVector::Write(); - PoolVector dst_image; int datasize = features.width * features.height * (features.has_alpha ? 4 : 3); dst_image.resize(datasize); - - PoolVector::Read src_r = src_image.read(); PoolVector::Write dst_w = dst_image.write(); bool errdec = false; if (features.has_alpha) { - errdec = WebPDecodeRGBAInto(src_r.ptr(), size, dst_w.ptr(), datasize, 4 * features.width) == NULL; + errdec = WebPDecodeRGBAInto(p_buffer, p_buffer_len, dst_w.ptr(), datasize, 4 * features.width) == NULL; } else { - errdec = WebPDecodeRGBInto(src_r.ptr(), size, dst_w.ptr(), datasize, 3 * features.width) == NULL; + errdec = WebPDecodeRGBInto(p_buffer, p_buffer_len, dst_w.ptr(), datasize, 3 * features.width) == NULL; } - - //ERR_EXPLAIN("Error decoding webp! - "+p_file); - ERR_FAIL_COND_V(errdec, ERR_FILE_CORRUPT); - - src_r = PoolVector::Read(); dst_w = PoolVector::Write(); + //ERR_EXPLAIN("Error decoding webp!"); + ERR_FAIL_COND_V(errdec, ERR_FILE_CORRUPT); + p_image->create(features.width, features.height, 0, features.has_alpha ? Image::FORMAT_RGBA8 : Image::FORMAT_RGB8, dst_image); return OK; } +static Ref _webp_mem_loader_func(const uint8_t *p_png, int p_size) { + + Ref img; + img.instance(); + Error err = webp_load_image_from_buffer(img.ptr(), p_png, p_size); + ERR_FAIL_COND_V(err, Ref()); + return img; +} + +Error ImageLoaderWEBP::load_image(Ref p_image, FileAccess *f, bool p_force_linear, float p_scale) { + + PoolVector src_image; + int src_image_len = f->get_len(); + ERR_FAIL_COND_V(src_image_len == 0, ERR_FILE_CORRUPT); + src_image.resize(src_image_len); + + PoolVector::Write w = src_image.write(); + + f->get_buffer(&w[0], src_image_len); + + f->close(); + + Error err = webp_load_image_from_buffer(p_image.ptr(), w.ptr(), src_image_len); + + w = PoolVector::Write(); + + return err; +} + void ImageLoaderWEBP::get_recognized_extensions(List *p_extensions) const { p_extensions->push_back("webp"); } ImageLoaderWEBP::ImageLoaderWEBP() { - + Image::_webp_mem_loader_func = _webp_mem_loader_func; Image::lossy_packer = _webp_lossy_pack; Image::lossy_unpacker = _webp_lossy_unpack; }