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')
-rw-r--r--source/blender/imbuf/CMakeLists.txt13
-rw-r--r--source/blender/imbuf/IMB_imbuf_types.h3
-rw-r--r--source/blender/imbuf/intern/IMB_filetype.h13
-rw-r--r--source/blender/imbuf/intern/filetype.c14
-rw-r--r--source/blender/imbuf/intern/util.c13
-rw-r--r--source/blender/imbuf/intern/webp.c129
6 files changed, 180 insertions, 5 deletions
diff --git a/source/blender/imbuf/CMakeLists.txt b/source/blender/imbuf/CMakeLists.txt
index 25961e6e1d5..e46326467cc 100644
--- a/source/blender/imbuf/CMakeLists.txt
+++ b/source/blender/imbuf/CMakeLists.txt
@@ -174,6 +174,19 @@ if(WITH_IMAGE_HDR)
add_definitions(-DWITH_HDR)
endif()
+if(WITH_IMAGE_WEBP)
+ list(APPEND SRC
+ intern/webp.c
+ )
+ list(APPEND INC_SYS
+ ${WEBP_INCLUDE_DIRS}
+ )
+ list(APPEND LIB
+ ${WEBP_LIBRARIES}
+ )
+ add_definitions(-DWITH_WEBP)
+endif()
+
list(APPEND INC
../../../intern/opencolorio
)
diff --git a/source/blender/imbuf/IMB_imbuf_types.h b/source/blender/imbuf/IMB_imbuf_types.h
index 98b7cc6e87f..934163846e4 100644
--- a/source/blender/imbuf/IMB_imbuf_types.h
+++ b/source/blender/imbuf/IMB_imbuf_types.h
@@ -80,6 +80,9 @@ enum eImbFileType {
#ifdef WITH_DDS
IMB_FTYPE_DDS = 13,
#endif
+#ifdef WITH_WEBP
+ IMB_FTYPE_WEBP = 14,
+#endif
};
/* Only for readability. */
diff --git a/source/blender/imbuf/intern/IMB_filetype.h b/source/blender/imbuf/intern/IMB_filetype.h
index 035c5b10c60..31f8b3a9505 100644
--- a/source/blender/imbuf/intern/IMB_filetype.h
+++ b/source/blender/imbuf/intern/IMB_filetype.h
@@ -238,3 +238,16 @@ void imb_loadtiletiff(
bool imb_savetiff(struct ImBuf *ibuf, const char *filepath, int flags);
/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Format: TIFF (#IMB_FTYPE_WEBP)
+ * \{ */
+
+bool imb_is_a_webp(const unsigned char *buf, size_t size);
+struct ImBuf *imb_loadwebp(const unsigned char *mem,
+ size_t size,
+ int flags,
+ char colorspace[IM_MAX_SPACE]);
+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 60442f97885..548bc9e120c 100644
--- a/source/blender/imbuf/intern/filetype.c
+++ b/source/blender/imbuf/intern/filetype.c
@@ -197,6 +197,20 @@ const ImFileType IMB_FILE_TYPES[] = {
.default_save_role = COLOR_ROLE_DEFAULT_FLOAT,
},
#endif
+#ifdef WITH_WEBP
+ {
+ .init = NULL,
+ .exit = NULL,
+ .is_a = imb_is_a_webp,
+ .load = imb_loadwebp,
+ .load_filepath = NULL,
+ .save = imb_savewebp,
+ .load_tile = NULL,
+ .flag = 0,
+ .filetype = IMB_FTYPE_WEBP,
+ .default_save_role = COLOR_ROLE_DEFAULT_BYTE,
+ },
+#endif
{NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0},
};
diff --git a/source/blender/imbuf/intern/util.c b/source/blender/imbuf/intern/util.c
index 241f1a736f4..45b50c866fe 100644
--- a/source/blender/imbuf/intern/util.c
+++ b/source/blender/imbuf/intern/util.c
@@ -41,12 +41,12 @@
#define UTIL_DEBUG 0
const char *imb_ext_image[] = {
- ".png", ".tga", ".bmp", ".jpg", ".jpeg", ".sgi", ".rgb", ".rgba",
+ ".png", ".tga", ".bmp", ".jpg", ".jpeg", ".sgi", ".rgb", ".rgba",
#ifdef WITH_TIFF
- ".tif", ".tiff", ".tx",
+ ".tif", ".tiff", ".tx",
#endif
#ifdef WITH_OPENJPEG
- ".jp2", ".j2c",
+ ".jp2", ".j2c",
#endif
#ifdef WITH_HDR
".hdr",
@@ -55,13 +55,16 @@ const char *imb_ext_image[] = {
".dds",
#endif
#ifdef WITH_CINEON
- ".dpx", ".cin",
+ ".dpx", ".cin",
#endif
#ifdef WITH_OPENEXR
".exr",
#endif
#ifdef WITH_OPENIMAGEIO
- ".psd", ".pdd", ".psb",
+ ".psd", ".pdd", ".psb",
+#endif
+#ifdef WITH_WEBP
+ ".webp",
#endif
NULL,
};
diff --git a/source/blender/imbuf/intern/webp.c b/source/blender/imbuf/intern/webp.c
new file mode 100644
index 00000000000..1070920e458
--- /dev/null
+++ b/source/blender/imbuf/intern/webp.c
@@ -0,0 +1,129 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+/** \file blender/imbuf/intern/webp.c
+ * \ingroup imbuf
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <webp/decode.h>
+#include <webp/encode.h>
+
+#include "BLI_fileops.h"
+#include "BLI_utildefines.h"
+
+#include "IMB_colormanagement.h"
+#include "IMB_colormanagement_intern.h"
+#include "IMB_filetype.h"
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
+
+#include "MEM_guardedalloc.h"
+
+bool imb_is_a_webp(const unsigned char *buf, size_t size)
+{
+ if (WebPGetInfo(buf, size, NULL, NULL)) {
+ return true;
+ }
+ return false;
+}
+
+ImBuf *imb_loadwebp(const unsigned char *mem,
+ size_t size,
+ int flags,
+ char colorspace[IM_MAX_SPACE])
+{
+ if (!imb_is_a_webp(mem, size)) {
+ return NULL;
+ }
+
+ colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE);
+
+ WebPBitstreamFeatures features;
+ if (WebPGetFeatures(mem, size, &features) != VP8_STATUS_OK) {
+ fprintf(stderr, "WebP: Failed to parse features\n");
+ return NULL;
+ }
+
+ const int planes = features.has_alpha ? 32 : 24;
+ ImBuf *ibuf = IMB_allocImBuf(features.width, features.height, planes, 0);
+
+ if (ibuf == NULL) {
+ fprintf(stderr, "WebP: Failed to allocate image memory\n");
+ return NULL;
+ }
+
+ if ((flags & IB_test) == 0) {
+ 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);
+ 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");
+ }
+ }
+
+ 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;
+ size_t encoded_data_size;
+
+ if (bytesperpixel == 3) {
+ /* We must convert the ImBuf RGBA buffer to RGB as WebP expects a RGB buffer. */
+ const size_t num_pixels = ibuf->x * ibuf->y;
+ const uint8_t *rgba_rect = (uint8_t *)ibuf->rect;
+ uint8_t *rgb_rect = MEM_mallocN(sizeof(uint8_t) * num_pixels * 3, "webp rgb_rect");
+ for (int i = 0; i < num_pixels; i++) {
+ rgb_rect[i * 3 + 0] = rgba_rect[i * 4 + 0];
+ rgb_rect[i * 3 + 1] = rgba_rect[i * 4 + 1];
+ rgb_rect[i * 3 + 2] = rgba_rect[i * 4 + 2];
+ }
+
+ last_row = (unsigned char *)(rgb_rect + (ibuf->y - 1) * ibuf->x * 3);
+ MEM_freeN(rgb_rect);
+
+ if (ibuf->foptions.quality == 100.0f) {
+ encoded_data_size = WebPEncodeLosslessRGB(
+ last_row, ibuf->x, ibuf->y, -3 * ibuf->x, &encoded_data);
+ }
+ else {
+ encoded_data_size = WebPEncodeRGB(
+ last_row, ibuf->x, ibuf->y, -3 * ibuf->x, ibuf->foptions.quality, &encoded_data);
+ }
+ }
+ else if (bytesperpixel == 4) {
+ last_row = (unsigned char *)(ibuf->rect + (ibuf->y - 1) * ibuf->x);
+
+ if (ibuf->foptions.quality == 100.0f) {
+ encoded_data_size = WebPEncodeLosslessRGBA(
+ last_row, ibuf->x, ibuf->y, -4 * ibuf->x, &encoded_data);
+ }
+ else {
+ encoded_data_size = WebPEncodeRGBA(
+ last_row, ibuf->x, ibuf->y, -4 * ibuf->x, ibuf->foptions.quality, &encoded_data);
+ }
+ }
+ else {
+ fprintf(stderr, "WebP: Unsupported bytes per pixel: %d for file: '%s'\n", bytesperpixel, name);
+ return false;
+ }
+
+ if (encoded_data != NULL) {
+ FILE *fp = BLI_fopen(name, "wb");
+ if (!fp) {
+ free(encoded_data);
+ fprintf(stderr, "WebP: Cannot open file for writing: '%s'\n", name);
+ return false;
+ }
+ fwrite(encoded_data, encoded_data_size, 1, fp);
+ free(encoded_data);
+ fclose(fp);
+ }
+
+ return true;
+}