ReactOS 0.4.16-dev-2574-g474348f
tif_webp.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2018, Mapbox
3 * Author: <norman.barker at mapbox.com>
4 *
5 * Permission to use, copy, modify, distribute, and sell this software and
6 * its documentation for any purpose is hereby granted without fee, provided
7 * that (i) the above copyright notices and this permission notice appear in
8 * all copies of the software and related documentation, and (ii) the names of
9 * Sam Leffler and Silicon Graphics may not be used in any advertising or
10 * publicity relating to the software without the specific, prior written
11 * permission of Sam Leffler and Silicon Graphics.
12 *
13 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
14 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
15 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
16 *
17 * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
18 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
19 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
20 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
21 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
22 * OF THIS SOFTWARE.
23 */
24
25#include "tiffiop.h"
26#ifdef WEBP_SUPPORT
27/*
28 * TIFF Library.
29 *
30 * WEBP Compression Support
31 *
32 */
33
34#include "webp/decode.h"
35#include "webp/encode.h"
36
37#include <stdbool.h>
38#include <stdio.h>
39
40#define LSTATE_INIT_DECODE 0x01
41#define LSTATE_INIT_ENCODE 0x02
42/*
43 * State block for each open TIFF
44 * file using WEBP compression/decompression.
45 */
46typedef struct
47{
48 uint16_t nSamples; /* number of samples per pixel */
49
50 int read_error; /* whether a read error has occurred, and which should cause
51 further reads in the same strip/tile to be aborted */
52 int lossless; /* lossy/lossless compression */
53 int lossless_exact; /* lossless exact mode. If TRUE, R,G,B values in areas
54 with alpha = 0 will be preserved */
55 int quality_level; /* compression level */
56 WebPPicture sPicture; /* WebP Picture */
57 WebPConfig sEncoderConfig; /* WebP encoder config */
58 uint8_t *pBuffer; /* buffer to hold raw data on encoding */
59 unsigned int buffer_offset; /* current offset into the buffer */
60 unsigned int buffer_size;
61
62 WebPIDecoder *psDecoder; /* WebPIDecoder */
63 WebPDecBuffer sDecBuffer; /* Decoder buffer */
64 int last_y; /* Last row decoded */
65
66 int state; /* state flags */
67
68 TIFFVGetMethod vgetparent; /* super-class method */
69 TIFFVSetMethod vsetparent; /* super-class method */
70} WebPState;
71
72#define LState(tif) ((WebPState *)(tif)->tif_data)
73#define DecoderState(tif) LState(tif)
74#define EncoderState(tif) LState(tif)
75
76static int TWebPEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s);
77static int TWebPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s);
78
79static int TWebPDatasetWriter(const uint8_t *data, size_t data_size,
80 const WebPPicture *const picture)
81{
82 static const char module[] = "TWebPDatasetWriter";
83 TIFF *tif = (TIFF *)(picture->custom_ptr);
84
85 if ((tif->tif_rawcc + (tmsize_t)data_size) > tif->tif_rawdatasize)
86 {
88 tif, module, "Buffer too small by %" TIFF_SIZE_FORMAT " bytes.",
89 (size_t)(tif->tif_rawcc + data_size - tif->tif_rawdatasize));
90 return 0;
91 }
92 else
93 {
94 _TIFFmemcpy(tif->tif_rawcp, data, data_size);
95 tif->tif_rawcc += data_size;
96 tif->tif_rawcp += data_size;
97 return 1;
98 }
99}
100
101/*
102 * Encode a chunk of pixels.
103 */
104static int TWebPEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s)
105{
106 static const char module[] = "TWebPEncode";
107 WebPState *sp = EncoderState(tif);
108 (void)s;
109
110 assert(sp != NULL);
111 assert(sp->state == LSTATE_INIT_ENCODE);
112
113 if ((uint64_t)sp->buffer_offset + (uint64_t)cc > sp->buffer_size)
114 {
115 TIFFErrorExtR(tif, module, "Too many bytes to be written");
116 return 0;
117 }
118
119 memcpy(sp->pBuffer + sp->buffer_offset, bp, cc);
120 sp->buffer_offset += (unsigned)cc;
121
122 return 1;
123}
124
125static int TWebPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
126{
127 static const char module[] = "WebPDecode";
128 VP8StatusCode status = VP8_STATUS_OK;
129 WebPState *sp = DecoderState(tif);
130 uint32_t segment_width, segment_height;
131 bool decode_whole_strile = false;
132
133 (void)s;
134
135 assert(sp != NULL);
136 assert(sp->state == LSTATE_INIT_DECODE);
137
138 if (sp->read_error)
139 {
140 memset(op, 0, (size_t)occ);
142 "ZIPDecode: Scanline %" PRIu32 " cannot be read due to "
143 "previous error",
144 tif->tif_row);
145 return 0;
146 }
147
148 if (sp->psDecoder == NULL)
149 {
150 TIFFDirectory *td = &tif->tif_dir;
152
153 if (isTiled(tif))
154 {
155 segment_width = td->td_tilewidth;
156 segment_height = td->td_tilelength;
157 }
158 else
159 {
160 segment_width = td->td_imagewidth;
161 segment_height = td->td_imagelength - tif->tif_row;
162 if (segment_height > td->td_rowsperstrip)
163 segment_height = td->td_rowsperstrip;
164 }
165
166 int webp_width, webp_height;
167 if (!WebPGetInfo(tif->tif_rawcp,
169 ? UINT32_MAX
170 : (uint32_t)tif->tif_rawcc,
171 &webp_width, &webp_height))
172 {
173 memset(op, 0, (size_t)occ);
174 sp->read_error = 1;
175 TIFFErrorExtR(tif, module, "WebPGetInfo() failed");
176 return 0;
177 }
178 if ((uint32_t)webp_width != segment_width ||
179 (uint32_t)webp_height != segment_height)
180 {
181 memset(op, 0, (size_t)occ);
182 sp->read_error = 1;
184 tif, module, "WebP blob dimension is %dx%d. Expected %ux%u",
185 webp_width, webp_height, segment_width, segment_height);
186 return 0;
187 }
188
189#if WEBP_DECODER_ABI_VERSION >= 0x0002
190 WebPDecoderConfig config;
191 if (!WebPInitDecoderConfig(&config))
192 {
193 memset(op, 0, (size_t)occ);
194 sp->read_error = 1;
195 TIFFErrorExtR(tif, module, "WebPInitDecoderConfig() failed");
196 return 0;
197 }
198
199 const bool bWebPGetFeaturesOK =
200 WebPGetFeatures(tif->tif_rawcp,
202 ? UINT32_MAX
203 : (uint32_t)tif->tif_rawcc,
204 &config.input) == VP8_STATUS_OK;
205
206 WebPFreeDecBuffer(&config.output);
207
208 if (!bWebPGetFeaturesOK)
209 {
210 memset(op, 0, (size_t)occ);
211 sp->read_error = 1;
212 TIFFErrorExtR(tif, module, "WebPInitDecoderConfig() failed");
213 return 0;
214 }
215
216 const int webp_bands = config.input.has_alpha ? 4 : 3;
217 if (webp_bands != sp->nSamples &&
218 /* We accept the situation where the WebP blob has only 3 bands,
219 * whereas the raster is 4 bands. This can happen when the alpha
220 * channel is fully opaque, and WebP decoding works fine in that
221 * situation.
222 */
223 !(webp_bands == 3 && sp->nSamples == 4))
224 {
225 memset(op, 0, (size_t)occ);
226 sp->read_error = 1;
228 "WebP blob band count is %d. Expected %d", webp_bands,
229 sp->nSamples);
230 return 0;
231 }
232#endif
233
234 buffer_size = segment_width * segment_height * sp->nSamples;
235 if (occ == (tmsize_t)buffer_size)
236 {
237 /* If decoding the whole strip/tile, we can directly use the */
238 /* output buffer */
239 decode_whole_strile = true;
240 }
241 else if (sp->pBuffer == NULL || buffer_size > sp->buffer_size)
242 {
243 if (sp->pBuffer != NULL)
244 {
245 _TIFFfreeExt(tif, sp->pBuffer);
246 sp->pBuffer = NULL;
247 }
248
249 sp->pBuffer = _TIFFmallocExt(tif, buffer_size);
250 if (!sp->pBuffer)
251 {
252 TIFFErrorExtR(tif, module, "Cannot allocate buffer");
253 memset(op, 0, (size_t)occ);
254 sp->read_error = 1;
255 return 0;
256 }
257 sp->buffer_size = buffer_size;
258 }
259
260 sp->last_y = 0;
261
262 WebPInitDecBuffer(&sp->sDecBuffer);
263
264 sp->sDecBuffer.is_external_memory = 1;
265 sp->sDecBuffer.width = segment_width;
266 sp->sDecBuffer.height = segment_height;
267 sp->sDecBuffer.u.RGBA.rgba = decode_whole_strile ? op : sp->pBuffer;
268 sp->sDecBuffer.u.RGBA.stride = segment_width * sp->nSamples;
269 sp->sDecBuffer.u.RGBA.size = buffer_size;
270
271 if (sp->nSamples > 3)
272 {
273 sp->sDecBuffer.colorspace = MODE_RGBA;
274 }
275 else
276 {
277 sp->sDecBuffer.colorspace = MODE_RGB;
278 }
279
280 sp->psDecoder = WebPINewDecoder(&sp->sDecBuffer);
281
282 if (sp->psDecoder == NULL)
283 {
284 memset(op, 0, (size_t)occ);
285 sp->read_error = 1;
286 TIFFErrorExtR(tif, module, "Unable to allocate WebP decoder.");
287 return 0;
288 }
289 }
290
291 if (occ % sp->sDecBuffer.u.RGBA.stride)
292 {
293 // read_error not set here as this is a usage issue that can be
294 // recovered in a following call.
295 memset(op, 0, (size_t)occ);
296 /* Do not set read_error as could potentially be recovered */
297 TIFFErrorExtR(tif, module, "Fractional scanlines cannot be read");
298 return 0;
299 }
300
301 status = WebPIAppend(sp->psDecoder, tif->tif_rawcp, tif->tif_rawcc);
302
303 if (status != VP8_STATUS_OK && status != VP8_STATUS_SUSPENDED)
304 {
305 if (status == VP8_STATUS_INVALID_PARAM)
306 {
307 TIFFErrorExtR(tif, module, "Invalid parameter used.");
308 }
309 else if (status == VP8_STATUS_OUT_OF_MEMORY)
310 {
311 TIFFErrorExtR(tif, module, "Out of memory.");
312 }
313 else
314 {
315 TIFFErrorExtR(tif, module, "Unrecognized error.");
316 }
317 memset(op, 0, (size_t)occ);
318 sp->read_error = 1;
319 return 0;
320 }
321 else
322 {
323 int current_y, stride;
324 uint8_t *buf;
325
326 /* Returns the RGB/A image decoded so far */
327 buf = WebPIDecGetRGB(sp->psDecoder, &current_y, NULL, NULL, &stride);
328
329 if ((buf != NULL) &&
330 (occ <= (tmsize_t)stride * (current_y - sp->last_y)))
331 {
332 const int numberOfExpectedLines =
333 (int)(occ / sp->sDecBuffer.u.RGBA.stride);
334 if (decode_whole_strile)
335 {
336 if (current_y != numberOfExpectedLines)
337 {
338 memset(op, 0, (size_t)occ);
339 sp->read_error = 1;
341 "Unable to decode WebP data: less lines than "
342 "expected.");
343 return 0;
344 }
345 }
346 else
347 {
348 memcpy(op, buf + (sp->last_y * stride), occ);
349 }
350
351 tif->tif_rawcp += tif->tif_rawcc;
352 tif->tif_rawcc = 0;
353 sp->last_y += numberOfExpectedLines;
354
355 if (decode_whole_strile)
356 {
357 /* We can now free the decoder as we're completely done */
358 if (sp->psDecoder != NULL)
359 {
360 WebPIDelete(sp->psDecoder);
361 WebPFreeDecBuffer(&sp->sDecBuffer);
362 sp->psDecoder = NULL;
363 }
364 }
365 return 1;
366 }
367 else
368 {
369 memset(op, 0, (size_t)occ);
370 sp->read_error = 1;
371 TIFFErrorExtR(tif, module, "Unable to decode WebP data.");
372 return 0;
373 }
374 }
375}
376
377static int TWebPFixupTags(TIFF *tif)
378{
379 (void)tif;
381 {
382 static const char module[] = "TWebPFixupTags";
384 "TIFF WEBP requires data to be stored contiguously in "
385 "RGB e.g. RGBRGBRGB "
386#if WEBP_ENCODER_ABI_VERSION >= 0x0100
387 "or RGBARGBARGBA"
388#endif
389 );
390 return 0;
391 }
392 return 1;
393}
394
395static int TWebPSetupDecode(TIFF *tif)
396{
397 static const char module[] = "WebPSetupDecode";
398 uint16_t nBitsPerSample = tif->tif_dir.td_bitspersample;
399 uint16_t sampleFormat = tif->tif_dir.td_sampleformat;
400
401 WebPState *sp = DecoderState(tif);
402 assert(sp != NULL);
403
404 sp->nSamples = tif->tif_dir.td_samplesperpixel;
405
406 /* check band count */
407 if (sp->nSamples != 3
408#if WEBP_ENCODER_ABI_VERSION >= 0x0100
409 && sp->nSamples != 4
410#endif
411 )
412 {
414 "WEBP driver doesn't support %d bands. Must be 3 (RGB) "
415#if WEBP_ENCODER_ABI_VERSION >= 0x0100
416 "or 4 (RGBA) "
417#endif
418 "bands.",
419 sp->nSamples);
420 return 0;
421 }
422
423 /* check bits per sample and data type */
424 if ((nBitsPerSample != 8) && (sampleFormat != 1))
425 {
426 TIFFErrorExtR(tif, module, "WEBP driver requires 8 bit unsigned data");
427 return 0;
428 }
429
430 /* if we were last encoding, terminate this mode */
431 if (sp->state & LSTATE_INIT_ENCODE)
432 {
433 WebPPictureFree(&sp->sPicture);
434 if (sp->pBuffer != NULL)
435 {
436 _TIFFfreeExt(tif, sp->pBuffer);
437 sp->pBuffer = NULL;
438 }
439 sp->buffer_offset = 0;
440 sp->state = 0;
441 }
442
443 sp->state |= LSTATE_INIT_DECODE;
444
445 return 1;
446}
447
448/*
449 * Setup state for decoding a strip.
450 */
451static int TWebPPreDecode(TIFF *tif, uint16_t s)
452{
453 static const char module[] = "TWebPPreDecode";
454 uint32_t segment_width, segment_height;
455 WebPState *sp = DecoderState(tif);
456 TIFFDirectory *td = &tif->tif_dir;
457 (void)s;
458 assert(sp != NULL);
459
460 if (isTiled(tif))
461 {
462 segment_width = td->td_tilewidth;
463 segment_height = td->td_tilelength;
464 }
465 else
466 {
467 segment_width = td->td_imagewidth;
468 segment_height = td->td_imagelength - tif->tif_row;
469 if (segment_height > td->td_rowsperstrip)
470 segment_height = td->td_rowsperstrip;
471 }
472
473 if (segment_width > 16383 || segment_height > 16383)
474 {
476 "WEBP maximum image dimensions are 16383 x 16383.");
477 return 0;
478 }
479
480 if ((sp->state & LSTATE_INIT_DECODE) == 0)
481 tif->tif_setupdecode(tif);
482
483 if (sp->psDecoder != NULL)
484 {
485 WebPIDelete(sp->psDecoder);
486 WebPFreeDecBuffer(&sp->sDecBuffer);
487 sp->psDecoder = NULL;
488 }
489
490 sp->read_error = 0;
491
492 return 1;
493}
494
495static int TWebPSetupEncode(TIFF *tif)
496{
497 static const char module[] = "WebPSetupEncode";
498 uint16_t nBitsPerSample = tif->tif_dir.td_bitspersample;
499 uint16_t sampleFormat = tif->tif_dir.td_sampleformat;
500
501 WebPState *sp = EncoderState(tif);
502 assert(sp != NULL);
503
504 sp->nSamples = tif->tif_dir.td_samplesperpixel;
505
506 /* check band count */
507 if (sp->nSamples != 3
508#if WEBP_ENCODER_ABI_VERSION >= 0x0100
509 && sp->nSamples != 4
510#endif
511 )
512 {
514 "WEBP driver doesn't support %d bands. Must be 3 (RGB) "
515#if WEBP_ENCODER_ABI_VERSION >= 0x0100
516 "or 4 (RGBA) "
517#endif
518 "bands.",
519 sp->nSamples);
520 return 0;
521 }
522
523 /* check bits per sample and data type */
524 if ((nBitsPerSample != 8) || (sampleFormat != SAMPLEFORMAT_UINT))
525 {
526 TIFFErrorExtR(tif, module, "WEBP driver requires 8 bit unsigned data");
527 return 0;
528 }
529
530 if (sp->state & LSTATE_INIT_DECODE)
531 {
532 WebPIDelete(sp->psDecoder);
533 WebPFreeDecBuffer(&sp->sDecBuffer);
534 sp->psDecoder = NULL;
535 sp->last_y = 0;
536 sp->state = 0;
537 }
538
539 sp->state |= LSTATE_INIT_ENCODE;
540
541 if (!WebPPictureInit(&sp->sPicture))
542 {
543 TIFFErrorExtR(tif, module, "Error initializing WebP picture.");
544 return 0;
545 }
546
547 if (!WebPConfigInitInternal(&sp->sEncoderConfig, WEBP_PRESET_DEFAULT,
548 (float)sp->quality_level,
549 WEBP_ENCODER_ABI_VERSION))
550 {
552 "Error creating WebP encoder configuration.");
553 return 0;
554 }
555
556// WebPConfigInitInternal above sets lossless to false
557#if WEBP_ENCODER_ABI_VERSION >= 0x0100
558 sp->sEncoderConfig.lossless = sp->lossless;
559 if (sp->lossless)
560 {
561 sp->sPicture.use_argb = 1;
562#if WEBP_ENCODER_ABI_VERSION >= 0x0209
563 sp->sEncoderConfig.exact = sp->lossless_exact;
564#endif
565 }
566#endif
567
568 if (!WebPValidateConfig(&sp->sEncoderConfig))
569 {
570 TIFFErrorExtR(tif, module, "Error with WebP encoder configuration.");
571 return 0;
572 }
573
574 return 1;
575}
576
577/*
578 * Reset encoding state at the start of a strip.
579 */
580static int TWebPPreEncode(TIFF *tif, uint16_t s)
581{
582 static const char module[] = "TWebPPreEncode";
583 uint32_t segment_width, segment_height;
584 WebPState *sp = EncoderState(tif);
585 TIFFDirectory *td = &tif->tif_dir;
586
587 (void)s;
588
589 assert(sp != NULL);
590 if (sp->state != LSTATE_INIT_ENCODE)
591 tif->tif_setupencode(tif);
592
593 /*
594 * Set encoding parameters for this strip/tile.
595 */
596 if (isTiled(tif))
597 {
598 segment_width = td->td_tilewidth;
599 segment_height = td->td_tilelength;
600 }
601 else
602 {
603 segment_width = td->td_imagewidth;
604 segment_height = td->td_imagelength - tif->tif_row;
605 if (segment_height > td->td_rowsperstrip)
606 segment_height = td->td_rowsperstrip;
607 }
608
609 if (segment_width > 16383 || segment_height > 16383)
610 {
612 "WEBP maximum image dimensions are 16383 x 16383.");
613 return 0;
614 }
615
616 /* set up buffer for raw data */
617 /* given above check and that nSamples <= 4, buffer_size is <= 1 GB */
618 sp->buffer_size = segment_width * segment_height * sp->nSamples;
619
620 if (sp->pBuffer != NULL)
621 {
622 _TIFFfreeExt(tif, sp->pBuffer);
623 sp->pBuffer = NULL;
624 }
625
626 sp->pBuffer = _TIFFmallocExt(tif, sp->buffer_size);
627 if (!sp->pBuffer)
628 {
629 TIFFErrorExtR(tif, module, "Cannot allocate buffer");
630 return 0;
631 }
632 sp->buffer_offset = 0;
633
634 sp->sPicture.width = segment_width;
635 sp->sPicture.height = segment_height;
636 sp->sPicture.writer = TWebPDatasetWriter;
637 sp->sPicture.custom_ptr = tif;
638
639 return 1;
640}
641
642/*
643 * Finish off an encoded strip by flushing it.
644 */
645static int TWebPPostEncode(TIFF *tif)
646{
647 static const char module[] = "WebPPostEncode";
649 WebPState *sp = EncoderState(tif);
650 assert(sp != NULL);
651
652 assert(sp->state == LSTATE_INIT_ENCODE);
653
654 stride = (int64_t)sp->sPicture.width * sp->nSamples;
655
656#if WEBP_ENCODER_ABI_VERSION >= 0x0100
657 if (sp->nSamples == 4)
658 {
659 if (!WebPPictureImportRGBA(&sp->sPicture, sp->pBuffer, (int)stride))
660 {
661 TIFFErrorExtR(tif, module, "WebPPictureImportRGBA() failed");
662 return 0;
663 }
664 }
665 else
666#endif
667 if (!WebPPictureImportRGB(&sp->sPicture, sp->pBuffer, (int)stride))
668 {
669 TIFFErrorExtR(tif, module, "WebPPictureImportRGB() failed");
670 return 0;
671 }
672
673 if (!WebPEncode(&sp->sEncoderConfig, &sp->sPicture))
674 {
675
676#if WEBP_ENCODER_ABI_VERSION >= 0x0100
677 const char *pszErrorMsg = NULL;
678 switch (sp->sPicture.error_code)
679 {
680 case VP8_ENC_ERROR_OUT_OF_MEMORY:
681 pszErrorMsg = "Out of memory";
682 break;
683 case VP8_ENC_ERROR_BITSTREAM_OUT_OF_MEMORY:
684 pszErrorMsg = "Out of memory while flushing bits";
685 break;
686 case VP8_ENC_ERROR_NULL_PARAMETER:
687 pszErrorMsg = "A pointer parameter is NULL";
688 break;
689 case VP8_ENC_ERROR_INVALID_CONFIGURATION:
690 pszErrorMsg = "Configuration is invalid";
691 break;
692 case VP8_ENC_ERROR_BAD_DIMENSION:
693 pszErrorMsg = "Picture has invalid width/height";
694 break;
695 case VP8_ENC_ERROR_PARTITION0_OVERFLOW:
696 pszErrorMsg = "Partition is bigger than 512k. Try using less "
697 "SEGMENTS, or increase PARTITION_LIMIT value";
698 break;
699 case VP8_ENC_ERROR_PARTITION_OVERFLOW:
700 pszErrorMsg = "Partition is bigger than 16M";
701 break;
702 case VP8_ENC_ERROR_BAD_WRITE:
703 pszErrorMsg = "Error while fludshing bytes";
704 break;
705 case VP8_ENC_ERROR_FILE_TOO_BIG:
706 pszErrorMsg = "File is bigger than 4G";
707 break;
708 case VP8_ENC_ERROR_USER_ABORT:
709 pszErrorMsg = "User interrupted";
710 break;
711 default:
713 "WebPEncode returned an unknown error code: %d",
714 sp->sPicture.error_code);
715 pszErrorMsg = "Unknown WebP error type.";
716 break;
717 }
718 TIFFErrorExtR(tif, module, "WebPEncode() failed : %s", pszErrorMsg);
719#else
720 TIFFErrorExtR(tif, module, "Error in WebPEncode()");
721#endif
722 return 0;
723 }
724
725 sp->sPicture.custom_ptr = NULL;
726
727 if (!TIFFFlushData1(tif))
728 {
729 TIFFErrorExtR(tif, module, "Error flushing TIFF WebP encoder.");
730 return 0;
731 }
732
733 return 1;
734}
735
736static void TWebPCleanup(TIFF *tif)
737{
738 WebPState *sp = LState(tif);
739
740 assert(sp != 0);
741
742 tif->tif_tagmethods.vgetfield = sp->vgetparent;
743 tif->tif_tagmethods.vsetfield = sp->vsetparent;
744
745 if (sp->state & LSTATE_INIT_ENCODE)
746 {
747 WebPPictureFree(&sp->sPicture);
748 }
749
750 if (sp->psDecoder != NULL)
751 {
752 WebPIDelete(sp->psDecoder);
753 WebPFreeDecBuffer(&sp->sDecBuffer);
754 sp->psDecoder = NULL;
755 sp->last_y = 0;
756 }
757
758 if (sp->pBuffer != NULL)
759 {
760 _TIFFfreeExt(tif, sp->pBuffer);
761 sp->pBuffer = NULL;
762 }
763
764 _TIFFfreeExt(tif, tif->tif_data);
765 tif->tif_data = NULL;
766
768}
769
770static int TWebPVSetField(TIFF *tif, uint32_t tag, va_list ap)
771{
772 static const char module[] = "WebPVSetField";
773 WebPState *sp = LState(tif);
774
775 switch (tag)
776 {
778 sp->quality_level = (int)va_arg(ap, int);
779 if (sp->quality_level <= 0 || sp->quality_level > 100.0f)
780 {
782 "WEBP_LEVEL should be between 1 and 100");
783 }
784 return 1;
786#if WEBP_ENCODER_ABI_VERSION >= 0x0100
787 sp->lossless = va_arg(ap, int);
788 if (sp->lossless)
789 {
790 sp->quality_level = 100;
791 }
792 return 1;
793#else
795 tif, module,
796 "Need to upgrade WEBP driver, this version doesn't support "
797 "lossless compression.");
798 return 0;
799#endif
801#if WEBP_ENCODER_ABI_VERSION >= 0x0209
802 sp->lossless_exact = va_arg(ap, int);
803 return 1;
804#else
806 tif, module,
807 "Need to upgrade WEBP driver, this version doesn't support "
808 "lossless compression.");
809 return 0;
810#endif
811 default:
812 return (*sp->vsetparent)(tif, tag, ap);
813 }
814 /*NOTREACHED*/
815}
816
817static int TWebPVGetField(TIFF *tif, uint32_t tag, va_list ap)
818{
819 WebPState *sp = LState(tif);
820
821 switch (tag)
822 {
824 *va_arg(ap, int *) = sp->quality_level;
825 break;
827 *va_arg(ap, int *) = sp->lossless;
828 break;
830 *va_arg(ap, int *) = sp->lossless_exact;
831 break;
832 default:
833 return (*sp->vgetparent)(tif, tag, ap);
834 }
835 return 1;
836}
837
838static const TIFFField TWebPFields[] = {
840 FALSE, "WEBP quality", NULL},
842 TRUE, FALSE, "WEBP lossless/lossy", NULL},
844 FIELD_PSEUDO, TRUE, FALSE, "WEBP exact lossless", NULL},
845};
846
847int TIFFInitWebP(TIFF *tif, int scheme)
848{
849 static const char module[] = "TIFFInitWebP";
850 WebPState *sp;
851
852 (void)scheme;
854
855 /*
856 * Merge codec-specific tag information.
857 */
858 if (!_TIFFMergeFields(tif, TWebPFields, TIFFArrayCount(TWebPFields)))
859 {
860 TIFFErrorExtR(tif, module, "Merging WebP codec-specific tags failed");
861 return 0;
862 }
863
864 /*
865 * Allocate state block so tag methods have storage to record values.
866 */
867 tif->tif_data = (uint8_t *)_TIFFmallocExt(tif, sizeof(WebPState));
868 if (tif->tif_data == NULL)
869 goto bad;
870 sp = LState(tif);
871
872 /*
873 * Override parent get/set field methods.
874 */
875 sp->vgetparent = tif->tif_tagmethods.vgetfield;
876 tif->tif_tagmethods.vgetfield = TWebPVGetField; /* hook for codec tags */
877 sp->vsetparent = tif->tif_tagmethods.vsetfield;
878 tif->tif_tagmethods.vsetfield = TWebPVSetField; /* hook for codec tags */
879
880 /* Default values for codec-specific fields */
881 sp->quality_level = 75; /* default comp. level */
882 sp->lossless = 0; /* default to false */
883 sp->lossless_exact = 1; /* exact lossless mode (if lossless enabled) */
884 sp->state = 0;
885 sp->nSamples = 0;
886 sp->psDecoder = NULL;
887 sp->last_y = 0;
888
889 sp->buffer_offset = 0;
890 sp->pBuffer = NULL;
891
892 /*
893 * Install codec methods.
894 * Notes:
895 * encoderow is not supported
896 */
897 tif->tif_fixuptags = TWebPFixupTags;
898 tif->tif_setupdecode = TWebPSetupDecode;
899 tif->tif_predecode = TWebPPreDecode;
900 tif->tif_decoderow = TWebPDecode;
901 tif->tif_decodestrip = TWebPDecode;
902 tif->tif_decodetile = TWebPDecode;
903 tif->tif_setupencode = TWebPSetupEncode;
904 tif->tif_preencode = TWebPPreEncode;
905 tif->tif_postencode = TWebPPostEncode;
906 tif->tif_encoderow = TWebPEncode;
907 tif->tif_encodestrip = TWebPEncode;
908 tif->tif_encodetile = TWebPEncode;
909 tif->tif_cleanup = TWebPCleanup;
910
911 return 1;
912bad:
913 TIFFErrorExtR(tif, module, "No space for WebP state block");
914 return 0;
915}
916
917#endif /* WEBP_SUPPORT */
static int state
Definition: maze.c:121
struct config_s config
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
UINT32 uint32_t
Definition: types.h:75
UINT64 uint64_t
Definition: types.h:77
INT64 int64_t
Definition: types.h:72
UINT op
Definition: effect.c:236
#define assert(_expr)
Definition: assert.h:32
#define PRIu32
Definition: inttypes.h:84
#define va_arg(v, l)
Definition: stdarg.h:27
unsigned short uint16_t
Definition: stdint.h:35
#define UINT32_MAX
Definition: stdint.h:85
unsigned char uint8_t
Definition: stdint.h:33
char * va_list
Definition: vadefs.h:50
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
GLdouble s
Definition: gl.h:2039
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLsizei stride
Definition: glext.h:5848
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
@ picture
Definition: id3.c:95
uint32_t cc
Definition: isohybrid.c:75
if(dx< 0)
Definition: linetemp.h:194
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
static const WCHAR sp[]
Definition: suminfo.c:287
static unsigned(__cdecl *hash_bstr)(bstr_t s)
#define int64_t
Definition: nsiface.idl:57
PVOID pBuffer
DWORD scheme
#define memset(x, y, z)
Definition: compat.h:39
wchar_t const *const size_t const buffer_size
Definition: stat.cpp:95
uint32_t td_rowsperstrip
Definition: tif_dir.h:94
uint32_t td_imagewidth
Definition: tif_dir.h:83
uint32_t td_tilewidth
Definition: tif_dir.h:84
uint16_t td_bitspersample
Definition: tif_dir.h:86
uint16_t td_planarconfig
Definition: tif_dir.h:100
uint16_t td_sampleformat
Definition: tif_dir.h:87
uint16_t td_samplesperpixel
Definition: tif_dir.h:93
uint32_t td_imagelength
Definition: tif_dir.h:83
uint32_t td_tilelength
Definition: tif_dir.h:84
TIFFVGetMethod vgetfield
Definition: tiffio.h:376
TIFFVSetMethod vsetfield
Definition: tiffio.h:375
Definition: ps.c:97
Definition: ecma_167.h:138
Definition: tiffiop.h:113
TIFFCodeMethod tif_encodestrip
Definition: tiffiop.h:208
TIFFCodeMethod tif_encodetile
Definition: tiffiop.h:210
TIFFTagMethods tif_tagmethods
Definition: tiffiop.h:244
TIFFPreMethod tif_preencode
Definition: tiffiop.h:203
TIFFBoolMethod tif_fixuptags
Definition: tiffiop.h:198
tmsize_t tif_rawcc
Definition: tiffiop.h:225
TIFFPreMethod tif_predecode
Definition: tiffiop.h:200
TIFFCodeMethod tif_decodestrip
Definition: tiffiop.h:207
TIFFCodeMethod tif_decoderow
Definition: tiffiop.h:205
TIFFBoolMethod tif_setupencode
Definition: tiffiop.h:201
TIFFDirectory tif_dir
Definition: tiffiop.h:157
TIFFBoolMethod tif_postencode
Definition: tiffiop.h:204
TIFFCodeMethod tif_encoderow
Definition: tiffiop.h:206
TIFFVoidMethod tif_cleanup
Definition: tiffiop.h:213
uint8_t * tif_data
Definition: tiffiop.h:216
uint8_t * tif_rawcp
Definition: tiffiop.h:224
TIFFBoolMethod tif_setupdecode
Definition: tiffiop.h:199
tmsize_t tif_rawdatasize
Definition: tiffiop.h:221
uint32_t tif_row
Definition: tiffiop.h:162
TIFFCodeMethod tif_decodetile
Definition: tiffiop.h:209
#define TIFFInitWebP
Definition: tif_codec.c:80
void _TIFFSetDefaultCompressionState(TIFF *tif)
Definition: tif_compress.c:142
#define TIFF_SIZE_FORMAT
Definition: tif_config.h:168
#define FIELD_PSEUDO
Definition: tif_dir.h:230
@ TIFF_SETGET_INT
Definition: tif_dir.h:258
int _TIFFMergeFields(TIFF *tif, const TIFFField info[], uint32_t n)
Definition: tif_dirinfo.c:573
void TIFFErrorExtR(TIFF *tif, const char *module, const char *fmt,...)
Definition: tif_error.c:107
void _TIFFfreeExt(TIFF *tif, void *p)
Definition: tif_open.c:275
void * _TIFFmallocExt(TIFF *tif, tmsize_t s)
Definition: tif_open.c:173
void _TIFFmemcpy(void *d, const void *s, tmsize_t c)
Definition: tif_unix.c:355
void TIFFWarningExtR(TIFF *tif, const char *module, const char *fmt,...)
Definition: tif_warning.c:80
int TIFFFlushData1(TIFF *tif)
Definition: tif_write.c:931
#define SAMPLEFORMAT_UINT
Definition: tiff.h:334
#define TIFFTAG_WEBP_LEVEL
Definition: tiff.h:763
#define COMPRESSION_WEBP
Definition: tiff.h:217
#define TIFFTAG_WEBP_LOSSLESS_EXACT
Definition: tiff.h:765
#define TIFFTAG_WEBP_LOSSLESS
Definition: tiff.h:764
#define PLANARCONFIG_CONTIG
Definition: tiff.h:265
TIFF_SSIZE_T tmsize_t
Definition: tiffio.h:67
int(* TIFFVSetMethod)(TIFF *, uint32_t, va_list)
Definition: tiffio.h:369
int(* TIFFVGetMethod)(TIFF *, uint32_t, va_list)
Definition: tiffio.h:370
#define TIFF_ANY
Definition: tiffio.h:341
#define isTiled(tif)
Definition: tiffiop.h:274
#define TIFFArrayCount(a)
Definition: tiffiop.h:333
void int int ULONGLONG int va_list * ap
Definition: winesup.h:36