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
path: root/source
diff options
context:
space:
mode:
authorAaron Carlisle <carlisle.b3d@gmail.com>2022-03-25 01:24:06 +0300
committerAaron Carlisle <carlisle.b3d@gmail.com>2022-03-25 01:24:06 +0300
commit4fd0a69d7ba86e92390c421a745c6f32f1050c31 (patch)
treee98005f5a099665d09296569fbee1ef5e72b1d1e /source
parent07846b31f34caa88244d192ee7d3aa6c057ac602 (diff)
ImBuf: Add support for WebP image format
Currently only supports single image frames (no animation possible). If quality slider is set to 100 then lossless compression will be used, otherwise lossy compression is used. Gives about 35% reduction of filesize save when re-saving splash screens with lossless compression. Also saves much faster, up to 15x faster than PNG with a better compression ratio as a plus. Note, this is currently left disabled until we have WebP libs (see T95206) For testing precompiled libs can be downloaded from Google: https://storage.googleapis.com/downloads.webmproject.org/releases/webp/index.html Differential Revision: https://developer.blender.org/D1598
Diffstat (limited to 'source')
-rw-r--r--source/blender/blenkernel/CMakeLists.txt4
-rw-r--r--source/blender/blenkernel/intern/image_format.cc36
-rw-r--r--source/blender/editors/space_file/CMakeLists.txt3
-rw-r--r--source/blender/editors/space_image/CMakeLists.txt3
-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
-rw-r--r--source/blender/makesdna/DNA_scene_types.h1
-rw-r--r--source/blender/makesrna/intern/CMakeLists.txt4
-rw-r--r--source/blender/makesrna/intern/rna_scene.c9
-rw-r--r--source/blender/python/intern/CMakeLists.txt4
14 files changed, 243 insertions, 6 deletions
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index 268239ed7b5..bb91b2f63f6 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -607,6 +607,10 @@ if(WITH_IMAGE_HDR)
add_definitions(-DWITH_HDR)
endif()
+if(WITH_IMAGE_WEBP)
+ add_definitions(-DWITH_WEBP)
+endif()
+
if(WITH_CODEC_AVI)
list(APPEND INC
../io/avi
diff --git a/source/blender/blenkernel/intern/image_format.cc b/source/blender/blenkernel/intern/image_format.cc
index 2b5712a1597..3ff0b3da963 100644
--- a/source/blender/blenkernel/intern/image_format.cc
+++ b/source/blender/blenkernel/intern/image_format.cc
@@ -120,6 +120,12 @@ int BKE_imtype_to_ftype(const char imtype, ImbFormatOptions *r_options)
return IMB_FTYPE_JP2;
}
#endif
+#ifdef WITH_WEBP
+ if (imtype == R_IMF_IMTYPE_WEBP) {
+ r_options->quality = 90;
+ return IMB_FTYPE_WEBP;
+ }
+#endif
r_options->quality = 90;
return IMB_FTYPE_JPG;
@@ -177,6 +183,11 @@ char BKE_ftype_to_imtype(const int ftype, const ImbFormatOptions *options)
return R_IMF_IMTYPE_JP2;
}
#endif
+#ifdef WITH_WEBP
+ if (ftype == IMB_FTYPE_WEBP) {
+ return R_IMF_IMTYPE_WEBP;
+ }
+#endif
return R_IMF_IMTYPE_JPEG90;
}
@@ -220,6 +231,7 @@ bool BKE_imtype_supports_quality(const char imtype)
case R_IMF_IMTYPE_JPEG90:
case R_IMF_IMTYPE_JP2:
case R_IMF_IMTYPE_AVIJPEG:
+ case R_IMF_IMTYPE_WEBP:
return true;
}
return false;
@@ -259,6 +271,7 @@ char BKE_imtype_valid_channels(const char imtype, bool write_file)
case R_IMF_IMTYPE_DDS:
case R_IMF_IMTYPE_JP2:
case R_IMF_IMTYPE_DPX:
+ case R_IMF_IMTYPE_WEBP:
chan_flag |= IMA_CHAN_FLAG_ALPHA;
break;
}
@@ -379,6 +392,11 @@ char BKE_imtype_from_arg(const char *imtype_arg)
return R_IMF_IMTYPE_JP2;
}
#endif
+#ifdef WITH_WEBP
+ if (STREQ(imtype_arg, "WEBP")) {
+ return R_IMF_IMTYPE_WEBP;
+ }
+#endif
return R_IMF_IMTYPE_INVALID;
}
@@ -494,6 +512,12 @@ static bool do_add_image_extension(char *string,
}
}
#endif
+#ifdef WITH_WEBP
+ else if (imtype == R_IMF_IMTYPE_WEBP) {
+ if (!BLI_path_extension_check(string, extension_test = ".webp"))
+ extension = extension_test;
+ }
+#endif
else { // R_IMF_IMTYPE_AVIRAW, R_IMF_IMTYPE_AVIJPEG, R_IMF_IMTYPE_JPEG90 etc
if (!(BLI_path_extension_check_n(string, extension_test = ".jpg", ".jpeg", nullptr))) {
extension = extension_test;
@@ -732,6 +756,12 @@ void BKE_image_format_to_imbuf(ImBuf *ibuf, const ImageFormatData *imf)
}
}
#endif
+#ifdef WITH_WEBP
+ else if (imtype == R_IMF_IMTYPE_WEBP) {
+ ibuf->ftype = IMB_FTYPE_WEBP;
+ ibuf->foptions.quality = quality;
+ }
+#endif
else {
/* #R_IMF_IMTYPE_JPEG90, etc. default to JPEG. */
if (quality < 10) {
@@ -864,6 +894,12 @@ void BKE_image_format_from_imbuf(ImageFormatData *im_format, const ImBuf *imbuf)
}
}
#endif
+#ifdef WITH_WEBP
+ else if (ftype == IMB_FTYPE_WEBP) {
+ im_format->imtype = R_IMF_IMTYPE_WEBP;
+ im_format->quality = quality;
+ }
+#endif
else {
im_format->imtype = R_IMF_IMTYPE_JPEG90;
diff --git a/source/blender/editors/space_file/CMakeLists.txt b/source/blender/editors/space_file/CMakeLists.txt
index c4c6fa01025..b8c28e354da 100644
--- a/source/blender/editors/space_file/CMakeLists.txt
+++ b/source/blender/editors/space_file/CMakeLists.txt
@@ -79,6 +79,9 @@ if(WITH_IMAGE_HDR)
add_definitions(-DWITH_HDR)
endif()
+if(WITH_IMAGE_WEBP)
+ add_definitions(-DWITH_WEBP)
+endif()
if(WITH_FREESTYLE)
add_definitions(-DWITH_FREESTYLE)
diff --git a/source/blender/editors/space_image/CMakeLists.txt b/source/blender/editors/space_image/CMakeLists.txt
index f5cc6083b25..c385420b18e 100644
--- a/source/blender/editors/space_image/CMakeLists.txt
+++ b/source/blender/editors/space_image/CMakeLists.txt
@@ -60,6 +60,9 @@ if(WITH_IMAGE_CINEON)
add_definitions(-DWITH_CINEON)
endif()
+if(WITH_IMAGE_WEBP)
+ add_definitions(-DWITH_WEBP)
+endif()
blender_add_lib(bf_editor_space_image "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
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;
+}
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index 24c120ae860..e6b2f2769b8 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -465,6 +465,7 @@ typedef struct ImageFormatData {
#define R_IMF_IMTYPE_XVID 32
#define R_IMF_IMTYPE_THEORA 33
#define R_IMF_IMTYPE_PSD 34
+#define R_IMF_IMTYPE_WEBP 35
#define R_IMF_IMTYPE_INVALID 255
diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt
index 4e3a4aae727..9980545c19d 100644
--- a/source/blender/makesrna/intern/CMakeLists.txt
+++ b/source/blender/makesrna/intern/CMakeLists.txt
@@ -236,6 +236,10 @@ if(WITH_IMAGE_HDR)
add_definitions(-DWITH_HDR)
endif()
+if(WITH_IMAGE_WEBP)
+ add_definitions(-DWITH_WEBP)
+endif()
+
if(WITH_AUDASPACE)
add_definitions(-DWITH_AUDASPACE)
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index 8172a511eb0..6be2c361ba9 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -330,6 +330,13 @@ const EnumPropertyItem rna_enum_curve_fit_method_items[] = {
# define R_IMF_ENUM_TIFF
#endif
+#ifdef WITH_WEBP
+# define R_IMF_ENUM_WEBP \
+ {R_IMF_IMTYPE_WEBP, "WEBP", ICON_FILE_IMAGE, "WebP", "Output image in WebP format"},
+#else
+# define R_IMF_ENUM_WEBP
+#endif
+
#define IMAGE_TYPE_ITEMS_IMAGE_ONLY \
R_IMF_ENUM_BMP \
/* DDS save not supported yet R_IMF_ENUM_DDS */ \
@@ -340,7 +347,7 @@ const EnumPropertyItem rna_enum_curve_fit_method_items[] = {
R_IMF_ENUM_TAGA \
R_IMF_ENUM_TAGA_RAW{0, "", 0, " ", NULL}, \
R_IMF_ENUM_CINEON R_IMF_ENUM_DPX R_IMF_ENUM_EXR_MULTILAYER R_IMF_ENUM_EXR R_IMF_ENUM_HDR \
- R_IMF_ENUM_TIFF
+ R_IMF_ENUM_TIFF R_IMF_ENUM_WEBP
#ifdef RNA_RUNTIME
static const EnumPropertyItem image_only_type_items[] = {
diff --git a/source/blender/python/intern/CMakeLists.txt b/source/blender/python/intern/CMakeLists.txt
index a35f03f9872..f813a006c7e 100644
--- a/source/blender/python/intern/CMakeLists.txt
+++ b/source/blender/python/intern/CMakeLists.txt
@@ -224,6 +224,10 @@ if(WITH_IMAGE_TIFF)
add_definitions(-DWITH_TIFF)
endif()
+if(WITH_WEBP)
+ add_definitions(-DWITH_WEBP)
+endif()
+
if(WITH_INPUT_NDOF)
add_definitions(-DWITH_INPUT_NDOF)
endif()