Blender  V3.3
webp.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <webp/decode.h>
10 #include <webp/encode.h>
11 
12 #include "BLI_fileops.h"
13 #include "BLI_utildefines.h"
14 
15 #include "IMB_colormanagement.h"
17 #include "IMB_filetype.h"
18 #include "IMB_imbuf.h"
19 #include "IMB_imbuf_types.h"
20 
21 #include "MEM_guardedalloc.h"
22 
23 bool imb_is_a_webp(const unsigned char *buf, size_t size)
24 {
25  if (WebPGetInfo(buf, size, NULL, NULL)) {
26  return true;
27  }
28  return false;
29 }
30 
31 ImBuf *imb_loadwebp(const unsigned char *mem,
32  size_t size,
33  int flags,
34  char colorspace[IM_MAX_SPACE])
35 {
36  if (!imb_is_a_webp(mem, size)) {
37  return NULL;
38  }
39 
41 
42  WebPBitstreamFeatures features;
43  if (WebPGetFeatures(mem, size, &features) != VP8_STATUS_OK) {
44  fprintf(stderr, "WebP: Failed to parse features\n");
45  return NULL;
46  }
47 
48  const int planes = features.has_alpha ? 32 : 24;
49  ImBuf *ibuf = IMB_allocImBuf(features.width, features.height, planes, 0);
50 
51  if (ibuf == NULL) {
52  fprintf(stderr, "WebP: Failed to allocate image memory\n");
53  return NULL;
54  }
55 
56  if ((flags & IB_test) == 0) {
57  ibuf->ftype = IMB_FTYPE_WEBP;
58  imb_addrectImBuf(ibuf);
59  /* Flip the image during decoding to match Blender. */
60  unsigned char *last_row = (unsigned char *)(ibuf->rect + (ibuf->y - 1) * ibuf->x);
61  if (WebPDecodeRGBAInto(mem, size, last_row, (size_t)(ibuf->x) * ibuf->y * 4, -4 * ibuf->x) ==
62  NULL) {
63  fprintf(stderr, "WebP: Failed to decode image\n");
64  }
65  }
66 
67  return ibuf;
68 }
69 
70 bool imb_savewebp(struct ImBuf *ibuf, const char *name, int UNUSED(flags))
71 {
72  const int bytesperpixel = (ibuf->planes + 7) >> 3;
73  unsigned char *encoded_data, *last_row;
74  size_t encoded_data_size;
75 
76  if (bytesperpixel == 3) {
77  /* We must convert the ImBuf RGBA buffer to RGB as WebP expects a RGB buffer. */
78  const size_t num_pixels = ibuf->x * ibuf->y;
79  const uint8_t *rgba_rect = (uint8_t *)ibuf->rect;
80  uint8_t *rgb_rect = MEM_mallocN(sizeof(uint8_t) * num_pixels * 3, "webp rgb_rect");
81  for (int i = 0; i < num_pixels; i++) {
82  rgb_rect[i * 3 + 0] = rgba_rect[i * 4 + 0];
83  rgb_rect[i * 3 + 1] = rgba_rect[i * 4 + 1];
84  rgb_rect[i * 3 + 2] = rgba_rect[i * 4 + 2];
85  }
86 
87  last_row = (unsigned char *)(rgb_rect + (ibuf->y - 1) * ibuf->x * 3);
88 
89  if (ibuf->foptions.quality == 100.0f) {
90  encoded_data_size = WebPEncodeLosslessRGB(
91  last_row, ibuf->x, ibuf->y, -3 * ibuf->x, &encoded_data);
92  }
93  else {
94  encoded_data_size = WebPEncodeRGB(
95  last_row, ibuf->x, ibuf->y, -3 * ibuf->x, ibuf->foptions.quality, &encoded_data);
96  }
97  MEM_freeN(rgb_rect);
98  }
99  else if (bytesperpixel == 4) {
100  last_row = (unsigned char *)(ibuf->rect + (ibuf->y - 1) * ibuf->x);
101 
102  if (ibuf->foptions.quality == 100.0f) {
103  encoded_data_size = WebPEncodeLosslessRGBA(
104  last_row, ibuf->x, ibuf->y, -4 * ibuf->x, &encoded_data);
105  }
106  else {
107  encoded_data_size = WebPEncodeRGBA(
108  last_row, ibuf->x, ibuf->y, -4 * ibuf->x, ibuf->foptions.quality, &encoded_data);
109  }
110  }
111  else {
112  fprintf(stderr, "WebP: Unsupported bytes per pixel: %d for file: '%s'\n", bytesperpixel, name);
113  return false;
114  }
115 
116  if (encoded_data != NULL) {
117  FILE *fp = BLI_fopen(name, "wb");
118  if (!fp) {
119  free(encoded_data);
120  fprintf(stderr, "WebP: Cannot open file for writing: '%s'\n", name);
121  return false;
122  }
123  fwrite(encoded_data, encoded_data_size, 1, fp);
124  free(encoded_data);
125  fclose(fp);
126  }
127 
128  return true;
129 }
File and directory operations.
FILE * BLI_fopen(const char *filepath, const char *mode) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: fileops.c:906
void BLI_kdtree_nd_() free(KDTree *tree)
Definition: kdtree_impl.h:102
#define UNUSED(x)
@ COLOR_ROLE_DEFAULT_BYTE
struct ImBuf * IMB_allocImBuf(unsigned int x, unsigned int y, unsigned char planes, unsigned int flags)
Definition: allocimbuf.c:500
#define IM_MAX_SPACE
Definition: IMB_imbuf.h:49
bool imb_addrectImBuf(struct ImBuf *ibuf)
Definition: allocimbuf.c:387
Contains defines and structs used throughout the imbuf module.
@ IB_test
Read Guarded memory(de)allocation.
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
void colorspace_set_default_role(char *colorspace, int size, int role)
ccl_gpu_kernel_postfix ccl_global float int num_pixels
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:33
unsigned char uint8_t
Definition: stdint.h:78
ImbFormatOptions foptions
unsigned char planes
enum eImbFileType ftype
unsigned int * rect
ImBuf * imb_loadwebp(const unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE])
Definition: webp.c:31
bool imb_savewebp(struct ImBuf *ibuf, const char *name, int UNUSED(flags))
Definition: webp.c:70
bool imb_is_a_webp(const unsigned char *buf, size_t size)
Definition: webp.c:23