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:
Diffstat (limited to 'source/blender/imbuf/intern/webp.c')
-rw-r--r--source/blender/imbuf/intern/webp.c107
1 files changed, 98 insertions, 9 deletions
diff --git a/source/blender/imbuf/intern/webp.c b/source/blender/imbuf/intern/webp.c
index 19fe2373ea0..27c26fb19c1 100644
--- a/source/blender/imbuf/intern/webp.c
+++ b/source/blender/imbuf/intern/webp.c
@@ -4,14 +4,23 @@
* \ingroup imbuf
*/
+#ifdef _WIN32
+# include <io.h>
+#else
+# include <unistd.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"
@@ -20,7 +29,7 @@
#include "MEM_guardedalloc.h"
-bool imb_is_a_webp(const unsigned char *buf, size_t size)
+bool imb_is_a_webp(const uchar *buf, size_t size)
{
if (WebPGetInfo(buf, size, NULL, NULL)) {
return true;
@@ -28,10 +37,7 @@ bool imb_is_a_webp(const unsigned char *buf, size_t size)
return false;
}
-ImBuf *imb_loadwebp(const unsigned char *mem,
- size_t size,
- int flags,
- char colorspace[IM_MAX_SPACE])
+ImBuf *imb_loadwebp(const uchar *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE])
{
if (!imb_is_a_webp(mem, size)) {
return NULL;
@@ -57,7 +63,7 @@ ImBuf *imb_loadwebp(const unsigned char *mem,
ibuf->ftype = IMB_FTYPE_WEBP;
imb_addrectImBuf(ibuf);
/* Flip the image during decoding to match Blender. */
- unsigned char *last_row = (unsigned char *)(ibuf->rect + (ibuf->y - 1) * ibuf->x);
+ uchar *last_row = (uchar *)(ibuf->rect + (ibuf->y - 1) * ibuf->x);
if (WebPDecodeRGBAInto(mem, size, last_row, (size_t)(ibuf->x) * ibuf->y * 4, -4 * ibuf->x) ==
NULL) {
fprintf(stderr, "WebP: Failed to decode image\n");
@@ -67,10 +73,93 @@ ImBuf *imb_loadwebp(const unsigned char *mem,
return ibuf;
}
+struct ImBuf *imb_load_filepath_thumbnail_webp(const char *filepath,
+ const int UNUSED(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 uchar *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;
+ }
+
+ /* Return full size of the image. */
+ *r_width = (size_t)config.input.width;
+ *r_height = (size_t)config.input.height;
+
+ 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;
- unsigned char *encoded_data, *last_row;
+ uchar *encoded_data, *last_row;
size_t encoded_data_size;
if (bytesperpixel == 3) {
@@ -84,7 +173,7 @@ bool imb_savewebp(struct ImBuf *ibuf, const char *name, int UNUSED(flags))
rgb_rect[i * 3 + 2] = rgba_rect[i * 4 + 2];
}
- last_row = (unsigned char *)(rgb_rect + (ibuf->y - 1) * ibuf->x * 3);
+ last_row = (uchar *)(rgb_rect + (ibuf->y - 1) * ibuf->x * 3);
if (ibuf->foptions.quality == 100.0f) {
encoded_data_size = WebPEncodeLosslessRGB(
@@ -97,7 +186,7 @@ bool imb_savewebp(struct ImBuf *ibuf, const char *name, int UNUSED(flags))
MEM_freeN(rgb_rect);
}
else if (bytesperpixel == 4) {
- last_row = (unsigned char *)(ibuf->rect + (ibuf->y - 1) * ibuf->x);
+ last_row = (uchar *)(ibuf->rect + (ibuf->y - 1) * ibuf->x);
if (ibuf->foptions.quality == 100.0f) {
encoded_data_size = WebPEncodeLosslessRGBA(