Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHarley Acheson <harley.acheson@gmail.com>2022-09-13 01:41:56 +0300
committerHarley Acheson <harley.acheson@gmail.com>2022-09-13 01:42:51 +0300
commit8851790dd733e49b8be96c978e155a5411007410 (patch)
treebd38d02a8f5770aa15d409a47044444240714894
parentad245f1970343ed41098ed9611a38b167fd757d4 (diff)
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
-rw-r--r--source/blender/imbuf/intern/IMB_filetype.h6
-rw-r--r--source/blender/imbuf/intern/filetype.c2
-rw-r--r--source/blender/imbuf/intern/webp.c86
3 files changed, 93 insertions, 1 deletions
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 <io.h>
+#endif
+
+#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <webp/decode.h>
#include <webp/encode.h>
#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;