From 8851790dd733e49b8be96c978e155a5411007410 Mon Sep 17 00:00:00 2001 From: Harley Acheson Date: Mon, 12 Sep 2022 15:41:56 -0700 Subject: IMBUF: Improved Thumbnailing of WebP Images Thumbnail WebP images quicker while using much less RAM. See D15908 for more details. Differential Revision: https://developer.blender.org/D15908 Reviewed by Brecht Van Lommel --- source/blender/imbuf/intern/IMB_filetype.h | 6 +++ source/blender/imbuf/intern/filetype.c | 2 +- source/blender/imbuf/intern/webp.c | 86 ++++++++++++++++++++++++++++++ 3 files changed, 93 insertions(+), 1 deletion(-) (limited to 'source') diff --git a/source/blender/imbuf/intern/IMB_filetype.h b/source/blender/imbuf/intern/IMB_filetype.h index 9a0a6998fab..bd17316d173 100644 --- a/source/blender/imbuf/intern/IMB_filetype.h +++ b/source/blender/imbuf/intern/IMB_filetype.h @@ -264,6 +264,12 @@ struct ImBuf *imb_loadwebp(const unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]); +struct ImBuf *imb_load_filepath_thumbnail_webp(const char *filepath, + const int flags, + const size_t max_thumb_size, + char colorspace[], + size_t *r_width, + size_t *r_height); bool imb_savewebp(struct ImBuf *ibuf, const char *name, int flags); /** \} */ diff --git a/source/blender/imbuf/intern/filetype.c b/source/blender/imbuf/intern/filetype.c index 92fa980cd7f..e1d2bea4ae9 100644 --- a/source/blender/imbuf/intern/filetype.c +++ b/source/blender/imbuf/intern/filetype.c @@ -217,7 +217,7 @@ const ImFileType IMB_FILE_TYPES[] = { .is_a = imb_is_a_webp, .load = imb_loadwebp, .load_filepath = NULL, - .load_filepath_thumbnail = NULL, + .load_filepath_thumbnail = imb_load_filepath_thumbnail_webp, .save = imb_savewebp, .load_tile = NULL, .flag = 0, diff --git a/source/blender/imbuf/intern/webp.c b/source/blender/imbuf/intern/webp.c index 19fe2373ea0..40be072177e 100644 --- a/source/blender/imbuf/intern/webp.c +++ b/source/blender/imbuf/intern/webp.c @@ -4,14 +4,21 @@ * \ingroup imbuf */ +#ifdef _WIN32 +# include +#endif + +#include #include #include #include #include #include "BLI_fileops.h" +#include "BLI_mmap.h" #include "BLI_utildefines.h" +#include "IMB_allocimbuf.h" #include "IMB_colormanagement.h" #include "IMB_colormanagement_intern.h" #include "IMB_filetype.h" @@ -67,6 +74,85 @@ ImBuf *imb_loadwebp(const unsigned char *mem, return ibuf; } +struct ImBuf *imb_load_filepath_thumbnail_webp(const char *filepath, + const int flags, + const size_t max_thumb_size, + char colorspace[], + size_t *r_width, + size_t *r_height) +{ + const int file = BLI_open(filepath, O_BINARY | O_RDONLY, 0); + if (file == -1) { + return NULL; + } + + const size_t data_size = BLI_file_descriptor_size(file); + + imb_mmap_lock(); + BLI_mmap_file *mmap_file = BLI_mmap_open(file); + imb_mmap_unlock(); + close(file); + if (mmap_file == NULL) { + return NULL; + } + + const unsigned char *data = BLI_mmap_get_pointer(mmap_file); + + WebPDecoderConfig config; + if (!data || !WebPInitDecoderConfig(&config) || + WebPGetFeatures(data, data_size, &config.input) != VP8_STATUS_OK) { + fprintf(stderr, "WebP: Invalid file\n"); + imb_mmap_lock(); + BLI_mmap_free(mmap_file); + imb_mmap_unlock(); + return NULL; + } + + const float scale = (float)max_thumb_size / MAX2(config.input.width, config.input.height); + const int dest_w = (int)(config.input.width * scale); + const int dest_h = (int)(config.input.height * scale); + + colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE); + struct ImBuf *ibuf = IMB_allocImBuf(dest_w, dest_h, 32, IB_rect); + if (ibuf == NULL) { + fprintf(stderr, "WebP: Failed to allocate image memory\n"); + imb_mmap_lock(); + BLI_mmap_free(mmap_file); + imb_mmap_unlock(); + return NULL; + } + + config.options.no_fancy_upsampling = 1; + config.options.use_scaling = 1; + config.options.scaled_width = dest_w; + config.options.scaled_height = dest_h; + config.options.bypass_filtering = 1; + config.options.use_threads = 0; + config.options.flip = 1; + config.output.is_external_memory = 1; + config.output.colorspace = MODE_RGBA; + config.output.u.RGBA.rgba = (uint8_t *)ibuf->rect; + config.output.u.RGBA.stride = 4 * ibuf->x; + config.output.u.RGBA.size = (size_t)(config.output.u.RGBA.stride * ibuf->y); + + if (WebPDecode(data, data_size, &config) != VP8_STATUS_OK) { + fprintf(stderr, "WebP: Failed to decode image\n"); + imb_mmap_lock(); + BLI_mmap_free(mmap_file); + imb_mmap_unlock(); + return NULL; + } + + /* Free the output buffer. */ + WebPFreeDecBuffer(&config.output); + + imb_mmap_lock(); + BLI_mmap_free(mmap_file); + imb_mmap_unlock(); + + return ibuf; +} + bool imb_savewebp(struct ImBuf *ibuf, const char *name, int UNUSED(flags)) { const int bytesperpixel = (ibuf->planes + 7) >> 3; -- cgit v1.2.3