diff options
Diffstat (limited to 'modules/webp/image_loader_webp.cpp')
| -rw-r--r-- | modules/webp/image_loader_webp.cpp | 81 | 
1 files changed, 74 insertions, 7 deletions
| diff --git a/modules/webp/image_loader_webp.cpp b/modules/webp/image_loader_webp.cpp index b304c4824f..5bebad2b53 100644 --- a/modules/webp/image_loader_webp.cpp +++ b/modules/webp/image_loader_webp.cpp @@ -30,6 +30,7 @@  #include "image_loader_webp.h" +#include "core/config/project_settings.h"  #include "core/io/marshalls.h"  #include "core/os/os.h"  #include "core/string/print_string.h" @@ -68,13 +69,78 @@ static Vector<uint8_t> _webp_lossy_pack(const Ref<Image> &p_image, float p_quali  	w[1] = 'E';  	w[2] = 'B';  	w[3] = 'P'; -	copymem(&w[4], dst_buff, dst_size); -	free(dst_buff); +	memcpy(&w[4], dst_buff, dst_size); +	WebPFree(dst_buff);  	return dst;  } -static Ref<Image> _webp_lossy_unpack(const Vector<uint8_t> &p_buffer) { +static Vector<uint8_t> _webp_lossless_pack(const Ref<Image> &p_image) { +	ERR_FAIL_COND_V(p_image.is_null() || p_image->is_empty(), Vector<uint8_t>()); + +	int compression_level = ProjectSettings::get_singleton()->get("rendering/textures/lossless_compression/webp_compression_level"); +	compression_level = CLAMP(compression_level, 0, 9); + +	Ref<Image> img = p_image->duplicate(); +	if (img->detect_alpha()) { +		img->convert(Image::FORMAT_RGBA8); +	} else { +		img->convert(Image::FORMAT_RGB8); +	} + +	Size2 s(img->get_width(), img->get_height()); +	Vector<uint8_t> data = img->get_data(); +	const uint8_t *r = data.ptr(); + +	// we need to use the more complex API in order to access the 'exact' flag... + +	WebPConfig config; +	WebPPicture pic; +	if (!WebPConfigInit(&config) || !WebPConfigLosslessPreset(&config, compression_level) || !WebPPictureInit(&pic)) { +		ERR_FAIL_V(Vector<uint8_t>()); +	} + +	WebPMemoryWriter wrt; +	config.exact = 1; +	pic.use_argb = 1; +	pic.width = s.width; +	pic.height = s.height; +	pic.writer = WebPMemoryWrite; +	pic.custom_ptr = &wrt; +	WebPMemoryWriterInit(&wrt); + +	bool success_import = false; +	if (img->get_format() == Image::FORMAT_RGB8) { +		success_import = WebPPictureImportRGB(&pic, r, 3 * s.width); +	} else { +		success_import = WebPPictureImportRGBA(&pic, r, 4 * s.width); +	} +	bool success_encode = false; +	if (success_import) { +		success_encode = WebPEncode(&config, &pic); +	} +	WebPPictureFree(&pic); + +	if (!success_encode) { +		WebPMemoryWriterClear(&wrt); +		ERR_FAIL_V_MSG(Vector<uint8_t>(), "WebP packing failed."); +	} + +	// copy from wrt +	Vector<uint8_t> dst; +	dst.resize(4 + wrt.size); +	uint8_t *w = dst.ptrw(); +	w[0] = 'W'; +	w[1] = 'E'; +	w[2] = 'B'; +	w[3] = 'P'; +	memcpy(&w[4], wrt.mem, wrt.size); +	WebPMemoryWriterClear(&wrt); + +	return dst; +} + +static Ref<Image> _webp_unpack(const Vector<uint8_t> &p_buffer) {  	int size = p_buffer.size() - 4;  	ERR_FAIL_COND_V(size <= 0, Ref<Image>());  	const uint8_t *r = p_buffer.ptr(); @@ -139,7 +205,7 @@ Error webp_load_image_from_buffer(Image *p_image, const uint8_t *p_buffer, int p  static Ref<Image> _webp_mem_loader_func(const uint8_t *p_png, int p_size) {  	Ref<Image> img; -	img.instance(); +	img.instantiate();  	Error err = webp_load_image_from_buffer(img.ptr(), p_png, p_size);  	ERR_FAIL_COND_V(err, Ref<Image>());  	return img; @@ -147,7 +213,7 @@ static Ref<Image> _webp_mem_loader_func(const uint8_t *p_png, int p_size) {  Error ImageLoaderWEBP::load_image(Ref<Image> p_image, FileAccess *f, bool p_force_linear, float p_scale) {  	Vector<uint8_t> src_image; -	int src_image_len = f->get_len(); +	uint64_t src_image_len = f->get_length();  	ERR_FAIL_COND_V(src_image_len == 0, ERR_FILE_CORRUPT);  	src_image.resize(src_image_len); @@ -168,6 +234,7 @@ void ImageLoaderWEBP::get_recognized_extensions(List<String> *p_extensions) cons  ImageLoaderWEBP::ImageLoaderWEBP() {  	Image::_webp_mem_loader_func = _webp_mem_loader_func; -	Image::lossy_packer = _webp_lossy_pack; -	Image::lossy_unpacker = _webp_lossy_unpack; +	Image::webp_lossy_packer = _webp_lossy_pack; +	Image::webp_lossless_packer = _webp_lossless_pack; +	Image::webp_unpacker = _webp_unpack;  } |