"Fossies" - the Fresh Open Source Software Archive 
Member "libgd-2.3.3/src/gd_webp.c" (11 Sep 2021, 9348 Bytes) of package /linux/www/libgd-2.3.3.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
1 /**
2 * File: WebP IO
3 *
4 * Read and write WebP images.
5 */
6
7 #ifdef HAVE_CONFIG_H
8 #include "config.h"
9 #endif /* HAVE_CONFIG_H */
10
11
12 #include <stdio.h>
13 #include <math.h>
14 #include <string.h>
15 #include <stdlib.h>
16 #include "gd.h"
17 #include "gd_errors.h"
18 #include "gdhelpers.h"
19
20 #ifdef HAVE_LIBWEBP
21 #include "webp/decode.h"
22 #include "webp/encode.h"
23
24 #define GD_WEBP_ALLOC_STEP (4*1024)
25
26 /*
27 Function: gdImageCreateFromWebp
28
29 <gdImageCreateFromWebp> is called to load truecolor images from
30 WebP format files. Invoke <gdImageCreateFromWebp> with an
31 already opened pointer to a file containing the desired
32 image. <gdImageCreateFromWebp> returns a <gdImagePtr> to the new
33 truecolor image, or NULL if unable to load the image (most often
34 because the file is corrupt or does not contain a WebP
35 image). <gdImageCreateFromWebp> does not close the file.
36
37 You can inspect the sx and sy members of the image to determine
38 its size. The image must eventually be destroyed using
39 <gdImageDestroy>.
40
41 *The returned image is always a truecolor image.*
42
43 Variants:
44
45 <gdImageCreateFromWebpPtr> creates an image from WebP data
46 already in memory.
47
48 <gdImageCreateFromWebpCtx> reads its data via the function
49 pointers in a <gdIOCtx> structure.
50
51 Parameters:
52
53 infile - The input FILE pointer.
54
55 Returns:
56
57 A pointer to the new *truecolor* image. This will need to be
58 destroyed with <gdImageDestroy> once it is no longer needed.
59
60 On error, returns NULL.
61 */
62 BGD_DECLARE(gdImagePtr) gdImageCreateFromWebp (FILE * inFile)
63 {
64 gdImagePtr im;
65 gdIOCtx *in = gdNewFileCtx(inFile);
66 if (!in) {
67 return 0;
68 }
69 im = gdImageCreateFromWebpCtx(in);
70 in->gd_free(in);
71
72 return im;
73 }
74
75
76 /*
77 Function: gdImageCreateFromWebpPtr
78
79 See <gdImageCreateFromWebp>.
80
81 Parameters:
82
83 size - size of WebP data in bytes.
84 data - pointer to WebP data.
85 */
86 BGD_DECLARE(gdImagePtr) gdImageCreateFromWebpPtr (int size, void *data)
87 {
88 gdImagePtr im;
89 gdIOCtx *in = gdNewDynamicCtxEx(size, data, 0);
90 if (!in)
91 return 0;
92 im = gdImageCreateFromWebpCtx(in);
93 in->gd_free(in);
94 return im;
95 }
96
97 /*
98 Function: gdImageCreateFromWebpCtx
99
100 See <gdImageCreateFromWebp>.
101 */
102 BGD_DECLARE(gdImagePtr) gdImageCreateFromWebpCtx (gdIOCtx * infile)
103 {
104 int width, height;
105 uint8_t *filedata = NULL;
106 uint8_t *argb = NULL;
107 unsigned char *read, *temp;
108 ssize_t size = 0, n;
109 gdImagePtr im;
110 int x, y;
111 uint8_t *p;
112
113 do {
114 temp = gdRealloc(filedata, size+GD_WEBP_ALLOC_STEP);
115 if (temp) {
116 filedata = temp;
117 read = temp + size;
118 } else {
119 if (filedata) {
120 gdFree(filedata);
121 }
122 gd_error("WebP decode: realloc failed");
123 return NULL;
124 }
125
126 n = gdGetBuf(read, GD_WEBP_ALLOC_STEP, infile);
127 if (n>0 && n!=EOF) {
128 size += n;
129 }
130 } while (n>0 && n!=EOF);
131
132 if (WebPGetInfo(filedata,size, &width, &height) == 0) {
133 gd_error("gd-webp cannot get webp info");
134 gdFree(temp);
135 return NULL;
136 }
137
138 im = gdImageCreateTrueColor(width, height);
139 if (!im) {
140 gdFree(temp);
141 return NULL;
142 }
143 argb = WebPDecodeARGB(filedata, size, &width, &height);
144 if (!argb) {
145 gd_error("gd-webp cannot allocate temporary buffer");
146 gdFree(temp);
147 gdImageDestroy(im);
148 return NULL;
149 }
150 for (y = 0, p = argb; y < height; y++) {
151 for (x = 0; x < width; x++) {
152 register uint8_t a = gdAlphaMax - (*(p++) >> 1);
153 register uint8_t r = *(p++);
154 register uint8_t g = *(p++);
155 register uint8_t b = *(p++);
156 im->tpixels[y][x] = gdTrueColorAlpha(r, g, b, a);
157 }
158 }
159 /* do not use gdFree here, in case gdFree/alloc is mapped to something else than libc */
160 free(argb);
161 gdFree(temp);
162 im->saveAlphaFlag = 1;
163 return im;
164 }
165
166
167 /* returns 0 on success, 1 on failure */
168 static int _gdImageWebpCtx (gdImagePtr im, gdIOCtx * outfile, int quality)
169 {
170 uint8_t *argb;
171 int x, y;
172 uint8_t *p;
173 uint8_t *out;
174 size_t out_size;
175 int ret = 0;
176
177 if (im == NULL) {
178 return 1;
179 }
180
181 if (!gdImageTrueColor(im)) {
182 gd_error("Palette image not supported by webp");
183 return 1;
184 }
185
186 if (quality == -1) {
187 quality = 80;
188 }
189
190 if (overflow2(gdImageSX(im), 4)) {
191 return 1;
192 }
193
194 if (overflow2(gdImageSX(im) * 4, gdImageSY(im))) {
195 return 1;
196 }
197
198 argb = (uint8_t *)gdMalloc(gdImageSX(im) * 4 * gdImageSY(im));
199 if (!argb) {
200 return 1;
201 }
202 p = argb;
203 for (y = 0; y < gdImageSY(im); y++) {
204 for (x = 0; x < gdImageSX(im); x++) {
205 register int c;
206 register char a;
207 c = im->tpixels[y][x];
208 a = gdTrueColorGetAlpha(c);
209 if (a == 127) {
210 a = 0;
211 } else {
212 a = 255 - ((a << 1) + (a >> 6));
213 }
214 *(p++) = gdTrueColorGetRed(c);
215 *(p++) = gdTrueColorGetGreen(c);
216 *(p++) = gdTrueColorGetBlue(c);
217 *(p++) = a;
218 }
219 }
220 if (quality >= gdWebpLossless) {
221 out_size = WebPEncodeLosslessRGBA(argb, gdImageSX(im), gdImageSY(im), gdImageSX(im) * 4, &out);
222 } else {
223 out_size = WebPEncodeRGBA(argb, gdImageSX(im), gdImageSY(im), gdImageSX(im) * 4, quality, &out);
224 }
225 if (out_size == 0) {
226 gd_error("gd-webp encoding failed");
227 ret = 1;
228 goto freeargb;
229 }
230
231 int res = gdPutBuf(out, out_size, outfile);
232 free(out);
233 if (res != out_size) {
234 gd_error("gd-webp write error\n");
235 ret = 1;
236 }
237
238 freeargb:
239 gdFree(argb);
240
241 return ret;
242 }
243
244
245 /*
246 Function: gdImageWebpCtx
247
248 Write the image as WebP data via a <gdIOCtx>. See <gdImageWebpEx>
249 for more details.
250
251 Parameters:
252
253 im - The image to write.
254 outfile - The output sink.
255 quality - Image quality.
256
257 Returns:
258
259 Nothing.
260 */
261 BGD_DECLARE(void) gdImageWebpCtx (gdImagePtr im, gdIOCtx * outfile, int quality)
262 {
263 _gdImageWebpCtx(im, outfile, quality);
264 }
265
266 /*
267 Function: gdImageWebpEx
268
269 <gdImageWebpEx> outputs the specified image to the specified file in
270 WebP format. The file must be open for writing. Under MSDOS and
271 all versions of Windows, it is important to use "wb" as opposed to
272 simply "w" as the mode when opening the file, and under Unix there
273 is no penalty for doing so. <gdImageWebpEx> does not close the file;
274 your code must do so.
275
276 If _quality_ is -1, a reasonable quality value (which should yield a
277 good general quality / size tradeoff for most situations) is used. Otherwise
278 _quality_ should be a value in the range 0-100, higher quality values
279 usually implying both higher quality and larger image sizes.
280
281 If _quality_ is greater than or equal to <gdWebpLossless> then the image
282 will be written in the lossless WebP format.
283
284 Variants:
285
286 <gdImageWebpCtx> stores the image using a <gdIOCtx> struct.
287
288 <gdImageWebpPtrEx> stores the image to RAM.
289
290 Parameters:
291
292 im - The image to save.
293 outFile - The FILE pointer to write to.
294 quality - Compression quality (0-100).
295
296 Returns:
297
298 Nothing.
299 */
300 BGD_DECLARE(void) gdImageWebpEx (gdImagePtr im, FILE * outFile, int quality)
301 {
302 gdIOCtx *out = gdNewFileCtx(outFile);
303 if (out == NULL) {
304 return;
305 }
306 _gdImageWebpCtx(im, out, quality);
307 out->gd_free(out);
308 }
309
310 /*
311 Function: gdImageWebp
312
313 Variant of <gdImageWebpEx> which uses the default quality (-1).
314
315 Parameters:
316
317 im - The image to save
318 outFile - The FILE pointer to write to.
319
320 Returns:
321
322 Nothing.
323 */
324 BGD_DECLARE(void) gdImageWebp (gdImagePtr im, FILE * outFile)
325 {
326 gdIOCtx *out = gdNewFileCtx(outFile);
327 if (out == NULL) {
328 return;
329 }
330 _gdImageWebpCtx(im, out, -1);
331 out->gd_free(out);
332 }
333
334 /*
335 Function: gdImageWebpPtr
336
337 See <gdImageWebpEx>.
338 */
339 BGD_DECLARE(void *) gdImageWebpPtr (gdImagePtr im, int *size)
340 {
341 void *rv;
342 gdIOCtx *out = gdNewDynamicCtx(2048, NULL);
343 if (out == NULL) {
344 return NULL;
345 }
346 if (_gdImageWebpCtx(im, out, -1)) {
347 rv = NULL;
348 } else {
349 rv = gdDPExtractData(out, size);
350 }
351 out->gd_free(out);
352
353 return rv;
354 }
355
356 /*
357 Function: gdImageWebpPtrEx
358
359 See <gdImageWebpEx>.
360 */
361 BGD_DECLARE(void *) gdImageWebpPtrEx (gdImagePtr im, int *size, int quality)
362 {
363 void *rv;
364
365 gdIOCtx *out = gdNewDynamicCtx(2048, NULL);
366 if (out == NULL) {
367 return NULL;
368 }
369 if (_gdImageWebpCtx(im, out, quality)) {
370 rv = NULL;
371 } else {
372 rv = gdDPExtractData(out, size);
373 }
374 out->gd_free(out);
375 return rv;
376 }
377
378 #else /* !HAVE_LIBWEBP */
379
380 static void _noWebpError(void)
381 {
382 gd_error("WEBP image support has been disabled\n");
383 }
384
385 BGD_DECLARE(gdImagePtr) gdImageCreateFromWebp (FILE * inFile)
386 {
387 ARG_NOT_USED(inFile);
388 _noWebpError();
389 return NULL;
390 }
391
392 BGD_DECLARE(gdImagePtr) gdImageCreateFromWebpPtr (int size, void *data)
393 {
394 ARG_NOT_USED(size);
395 ARG_NOT_USED(data);
396 _noWebpError();
397 return NULL;
398 }
399
400 BGD_DECLARE(gdImagePtr) gdImageCreateFromWebpCtx (gdIOCtx * infile)
401 {
402 ARG_NOT_USED(infile);
403 _noWebpError();
404 return NULL;
405 }
406
407 BGD_DECLARE(void) gdImageWebpCtx (gdImagePtr im, gdIOCtx * outfile, int quality)
408 {
409 ARG_NOT_USED(im);
410 ARG_NOT_USED(outfile);
411 ARG_NOT_USED(quality);
412 _noWebpError();
413 }
414
415 BGD_DECLARE(void) gdImageWebpEx (gdImagePtr im, FILE * outFile, int quality)
416 {
417 ARG_NOT_USED(im);
418 ARG_NOT_USED(outFile);
419 ARG_NOT_USED(quality);
420 _noWebpError();
421 }
422
423 BGD_DECLARE(void) gdImageWebp (gdImagePtr im, FILE * outFile)
424 {
425 ARG_NOT_USED(im);
426 ARG_NOT_USED(outFile);
427 _noWebpError();
428 }
429
430 BGD_DECLARE(void *) gdImageWebpPtr (gdImagePtr im, int *size)
431 {
432 ARG_NOT_USED(im);
433 ARG_NOT_USED(size);
434 _noWebpError();
435 return NULL;
436 }
437
438 BGD_DECLARE(void *) gdImageWebpPtrEx (gdImagePtr im, int *size, int quality)
439 {
440 ARG_NOT_USED(im);
441 ARG_NOT_USED(size);
442 ARG_NOT_USED(quality);
443 _noWebpError();
444 return NULL;
445 }
446
447 #endif /* HAVE_LIBWEBP */