diff options
author | Juan Linietsky <reduzio@gmail.com> | 2018-07-20 12:00:21 -0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-07-20 12:00:21 -0300 |
commit | 6c09cdd1361881ab44c971bae57f3a273f8b5110 (patch) | |
tree | 2973692d9995482e4eae9b20b01cf9359bcd9d32 | |
parent | 814fdd398507bf697f249d58b8b349f253bb0289 (diff) | |
parent | c5efe5d625529af5df908808791599f8dceaf50c (diff) |
Merge pull request #20157 from GodotExplorer/image-load-webp
Add webp buffer loader for Image
-rw-r--r-- | core/image.cpp | 32 | ||||
-rw-r--r-- | core/image.h | 9 | ||||
-rw-r--r-- | doc/classes/Image.xml | 9 | ||||
-rw-r--r-- | modules/jpg/image_loader_jpegd.cpp | 4 | ||||
-rw-r--r-- | modules/webp/image_loader_webp.cpp | 67 |
5 files changed, 69 insertions, 52 deletions
diff --git a/core/image.cpp b/core/image.cpp index b0bed80a6f..b9386a1b6d 100644 --- a/core/image.cpp +++ b/core/image.cpp @@ -1898,8 +1898,9 @@ void Image::fill(const Color &c) { unlock(); } -Ref<Image> (*Image::_png_mem_loader_func)(const uint8_t *, int) = NULL; -Ref<Image> (*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<uint8_t> &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<uint8_t>::Read r = p_array.read(); - - Ref<Image> 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<uint8_t> &p_array) { + return _load_from_buffer(p_array, _jpg_mem_loader_func); +} + +Error Image::load_webp_from_buffer(const PoolVector<uint8_t> &p_array) { + return _load_from_buffer(p_array, _webp_mem_loader_func); +} +Error Image::_load_from_buffer(const PoolVector<uint8_t> &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<uint8_t>::Read r = p_array.read(); - Ref<Image> image = _jpg_mem_loader_func(r.ptr(), buffer_size); + Ref<Image> 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 43516e2c0b..3792103a87 100644 --- a/core/image.h +++ b/core/image.h @@ -47,6 +47,7 @@ class Image; typedef Error (*SavePNGFunc)(const String &p_path, const Ref<Image> &p_img); +typedef Ref<Image> (*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<Image> (*_png_mem_loader_func)(const uint8_t *p_png, int p_size); - static Ref<Image> (*_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<uint8_t> &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<uint8_t> &p_array); Error load_jpg_from_buffer(const PoolVector<uint8_t> &p_array); + Error load_webp_from_buffer(const PoolVector<uint8_t> &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 9fc7672a80..e10485a6b2 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. </description> </method> + <method name="load_webp_from_buffer"> + <return type="int" enum="Error"> + </return> + <argument index="0" name="buffer" type="PoolByteArray"> + </argument> + <description> + Loads an image from the binary contents of a WebP file. + </description> + </method> <method name="lock"> <return type="void"> </return> diff --git a/modules/jpg/image_loader_jpegd.cpp b/modules/jpg/image_loader_jpegd.cpp index 0168be3a26..437c0d57fa 100644 --- a/modules/jpg/image_loader_jpegd.cpp +++ b/modules/jpg/image_loader_jpegd.cpp @@ -121,9 +121,7 @@ static Ref<Image> _jpegd_mem_loader_func(const uint8_t *p_png, int p_size) { Ref<Image> 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<Image>()); return img; } diff --git a/modules/webp/image_loader_webp.cpp b/modules/webp/image_loader_webp.cpp index cdf2d75e96..42b2c77777 100644 --- a/modules/webp/image_loader_webp.cpp +++ b/modules/webp/image_loader_webp.cpp @@ -116,64 +116,73 @@ static Ref<Image> _webp_lossy_unpack(const PoolVector<uint8_t> &p_buffer) { return img; } -Error ImageLoaderWEBP::load_image(Ref<Image> 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<uint8_t> src_image; - src_image.resize(size); + ERR_FAIL_NULL_V(p_image, ERR_INVALID_PARAMETER); WebPBitstreamFeatures features; - - PoolVector<uint8_t>::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<uint8_t>::Write(); - PoolVector<uint8_t> dst_image; int datasize = features.width * features.height * (features.has_alpha ? 4 : 3); dst_image.resize(datasize); - - PoolVector<uint8_t>::Read src_r = src_image.read(); PoolVector<uint8_t>::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; } + dst_w = PoolVector<uint8_t>::Write(); - //ERR_EXPLAIN("Error decoding webp! - "+p_file); + //ERR_EXPLAIN("Error decoding webp!"); ERR_FAIL_COND_V(errdec, ERR_FILE_CORRUPT); - src_r = PoolVector<uint8_t>::Read(); - dst_w = PoolVector<uint8_t>::Write(); - p_image->create(features.width, features.height, 0, features.has_alpha ? Image::FORMAT_RGBA8 : Image::FORMAT_RGB8, dst_image); return OK; } +static Ref<Image> _webp_mem_loader_func(const uint8_t *p_png, int p_size) { + + Ref<Image> img; + img.instance(); + Error err = webp_load_image_from_buffer(img.ptr(), p_png, p_size); + ERR_FAIL_COND_V(err, Ref<Image>()); + return img; +} + +Error ImageLoaderWEBP::load_image(Ref<Image> p_image, FileAccess *f, bool p_force_linear, float p_scale) { + + PoolVector<uint8_t> 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<uint8_t>::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<uint8_t>::Write(); + + return err; +} + void ImageLoaderWEBP::get_recognized_extensions(List<String> *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; } |