34
#include "webp/decode.h"
35
#include "webp/encode.h"
40
#define LSTATE_INIT_DECODE 0x01
41
#define LSTATE_INIT_ENCODE 0x02
55
WebPConfig sEncoderConfig;
57
unsigned int buffer_offset;
58
unsigned int buffer_size;
60
WebPIDecoder *psDecoder;
61
WebPDecBuffer sDecBuffer;
66
TIFFVGetMethod vgetparent;
67
TIFFVSetMethod vsetparent;
70
#define LState(tif) ((WebPState *)(tif)->tif_data)
71
#define DecoderState(tif) LState(tif)
72
#define EncoderState(tif) LState(tif)
74
static int TWebPEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s);
75
static int TWebPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s);
77
static int TWebPDatasetWriter(const uint8_t *data, size_t data_size,
78
const WebPPicture *const picture)
80
static const char module[] = "TWebPDatasetWriter";
81
TIFF *tif = (TIFF *)(picture->custom_ptr);
83
if ((tif->tif_rawcc + (tmsize_t)data_size) > tif->tif_rawdatasize)
86
tif, module, "Buffer too small by %" TIFF_SIZE_FORMAT " bytes.",
87
(size_t)(tif->tif_rawcc + data_size - tif->tif_rawdatasize));
92
_TIFFmemcpy(tif->tif_rawcp, data, data_size);
93
tif->tif_rawcc += data_size;
94
tif->tif_rawcp += data_size;
102
static int TWebPEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s)
104
static const char module[] = "TWebPEncode";
105
WebPState *sp = EncoderState(tif);
109
assert(sp->state == LSTATE_INIT_ENCODE);
111
if ((uint64_t)sp->buffer_offset + (uint64_t)cc > sp->buffer_size)
113
TIFFErrorExtR(tif, module, "Too many bytes to be written");
117
memcpy(sp->pBuffer + sp->buffer_offset, bp, cc);
118
sp->buffer_offset += (unsigned)cc;
123
static int TWebPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
125
static const char module[] = "WebPDecode";
126
VP8StatusCode status = VP8_STATUS_OK;
127
WebPState *sp = DecoderState(tif);
128
uint32_t segment_width, segment_height;
129
bool decode_whole_strile = false;
134
assert(sp->state == LSTATE_INIT_DECODE);
136
if (sp->psDecoder == NULL)
138
TIFFDirectory *td = &tif->tif_dir;
139
uint32_t buffer_size;
143
segment_width = td->td_tilewidth;
144
segment_height = td->td_tilelength;
148
segment_width = td->td_imagewidth;
149
segment_height = td->td_imagelength - tif->tif_row;
150
if (segment_height > td->td_rowsperstrip)
151
segment_height = td->td_rowsperstrip;
154
int webp_width, webp_height;
155
if (!WebPGetInfo(tif->tif_rawcp,
156
(uint64_t)tif->tif_rawcc > UINT32_MAX
158
: (uint32_t)tif->tif_rawcc,
159
&webp_width, &webp_height))
161
TIFFErrorExtR(tif, module, "WebPGetInfo() failed");
164
if ((uint32_t)webp_width != segment_width ||
165
(uint32_t)webp_height != segment_height)
168
tif, module, "WebP blob dimension is %dx%d. Expected %ux%u",
169
webp_width, webp_height, segment_width, segment_height);
173
#if WEBP_DECODER_ABI_VERSION >= 0x0002
174
WebPDecoderConfig config;
175
if (!WebPInitDecoderConfig(&config))
177
TIFFErrorExtR(tif, module, "WebPInitDecoderConfig() failed");
181
const bool bWebPGetFeaturesOK =
182
WebPGetFeatures(tif->tif_rawcp,
183
(uint64_t)tif->tif_rawcc > UINT32_MAX
185
: (uint32_t)tif->tif_rawcc,
186
&config.input) == VP8_STATUS_OK;
188
WebPFreeDecBuffer(&config.output);
190
if (!bWebPGetFeaturesOK)
192
TIFFErrorExtR(tif, module, "WebPInitDecoderConfig() failed");
196
const int webp_bands = config.input.has_alpha ? 4 : 3;
197
if (webp_bands != sp->nSamples &&
203
!(webp_bands == 3 && sp->nSamples == 4))
205
TIFFErrorExtR(tif, module,
206
"WebP blob band count is %d. Expected %d", webp_bands,
212
buffer_size = segment_width * segment_height * sp->nSamples;
213
if (occ == (tmsize_t)buffer_size)
217
decode_whole_strile = true;
219
else if (sp->pBuffer == NULL || buffer_size > sp->buffer_size)
221
if (sp->pBuffer != NULL)
223
_TIFFfreeExt(tif, sp->pBuffer);
227
sp->pBuffer = _TIFFmallocExt(tif, buffer_size);
230
TIFFErrorExtR(tif, module, "Cannot allocate buffer");
233
sp->buffer_size = buffer_size;
238
WebPInitDecBuffer(&sp->sDecBuffer);
240
sp->sDecBuffer.is_external_memory = 1;
241
sp->sDecBuffer.width = segment_width;
242
sp->sDecBuffer.height = segment_height;
243
sp->sDecBuffer.u.RGBA.rgba = decode_whole_strile ? op : sp->pBuffer;
244
sp->sDecBuffer.u.RGBA.stride = segment_width * sp->nSamples;
245
sp->sDecBuffer.u.RGBA.size = buffer_size;
247
if (sp->nSamples > 3)
249
sp->sDecBuffer.colorspace = MODE_RGBA;
253
sp->sDecBuffer.colorspace = MODE_RGB;
256
sp->psDecoder = WebPINewDecoder(&sp->sDecBuffer);
258
if (sp->psDecoder == NULL)
260
TIFFErrorExtR(tif, module, "Unable to allocate WebP decoder.");
265
if (occ % sp->sDecBuffer.u.RGBA.stride)
267
TIFFErrorExtR(tif, module, "Fractional scanlines cannot be read");
271
status = WebPIAppend(sp->psDecoder, tif->tif_rawcp, tif->tif_rawcc);
273
if (status != VP8_STATUS_OK && status != VP8_STATUS_SUSPENDED)
275
if (status == VP8_STATUS_INVALID_PARAM)
277
TIFFErrorExtR(tif, module, "Invalid parameter used.");
279
else if (status == VP8_STATUS_OUT_OF_MEMORY)
281
TIFFErrorExtR(tif, module, "Out of memory.");
285
TIFFErrorExtR(tif, module, "Unrecognized error.");
291
int current_y, stride;
295
buf = WebPIDecGetRGB(sp->psDecoder, ¤t_y, NULL, NULL, &stride);
298
(occ <= (tmsize_t)stride * (current_y - sp->last_y)))
300
const int numberOfExpectedLines =
301
(int)(occ / sp->sDecBuffer.u.RGBA.stride);
302
if (decode_whole_strile)
304
if (current_y != numberOfExpectedLines)
306
TIFFErrorExtR(tif, module,
307
"Unable to decode WebP data: less lines than "
314
memcpy(op, buf + (sp->last_y * stride), occ);
317
tif->tif_rawcp += tif->tif_rawcc;
319
sp->last_y += numberOfExpectedLines;
321
if (decode_whole_strile)
324
if (sp->psDecoder != NULL)
326
WebPIDelete(sp->psDecoder);
327
WebPFreeDecBuffer(&sp->sDecBuffer);
328
sp->psDecoder = NULL;
335
TIFFErrorExtR(tif, module, "Unable to decode WebP data.");
341
static int TWebPFixupTags(TIFF *tif)
344
if (tif->tif_dir.td_planarconfig != PLANARCONFIG_CONTIG)
346
static const char module[] = "TWebPFixupTags";
347
TIFFErrorExtR(tif, module,
348
"TIFF WEBP requires data to be stored contiguously in "
349
"RGB e.g. RGBRGBRGB "
350
#if WEBP_ENCODER_ABI_VERSION >= 0x0100
359
static int TWebPSetupDecode(TIFF *tif)
361
static const char module[] = "WebPSetupDecode";
362
uint16_t nBitsPerSample = tif->tif_dir.td_bitspersample;
363
uint16_t sampleFormat = tif->tif_dir.td_sampleformat;
365
WebPState *sp = DecoderState(tif);
368
sp->nSamples = tif->tif_dir.td_samplesperpixel;
371
if (sp->nSamples != 3
372
#if WEBP_ENCODER_ABI_VERSION >= 0x0100
377
TIFFErrorExtR(tif, module,
378
"WEBP driver doesn't support %d bands. Must be 3 (RGB) "
379
#if WEBP_ENCODER_ABI_VERSION >= 0x0100
388
if ((nBitsPerSample != 8) && (sampleFormat != 1))
390
TIFFErrorExtR(tif, module, "WEBP driver requires 8 bit unsigned data");
395
if (sp->state & LSTATE_INIT_ENCODE)
397
WebPPictureFree(&sp->sPicture);
398
if (sp->pBuffer != NULL)
400
_TIFFfreeExt(tif, sp->pBuffer);
403
sp->buffer_offset = 0;
407
sp->state |= LSTATE_INIT_DECODE;
415
static int TWebPPreDecode(TIFF *tif, uint16_t s)
417
static const char module[] = "TWebPPreDecode";
418
uint32_t segment_width, segment_height;
419
WebPState *sp = DecoderState(tif);
420
TIFFDirectory *td = &tif->tif_dir;
426
segment_width = td->td_tilewidth;
427
segment_height = td->td_tilelength;
431
segment_width = td->td_imagewidth;
432
segment_height = td->td_imagelength - tif->tif_row;
433
if (segment_height > td->td_rowsperstrip)
434
segment_height = td->td_rowsperstrip;
437
if (segment_width > 16383 || segment_height > 16383)
439
TIFFErrorExtR(tif, module,
440
"WEBP maximum image dimensions are 16383 x 16383.");
444
if ((sp->state & LSTATE_INIT_DECODE) == 0)
445
tif->tif_setupdecode(tif);
447
if (sp->psDecoder != NULL)
449
WebPIDelete(sp->psDecoder);
450
WebPFreeDecBuffer(&sp->sDecBuffer);
451
sp->psDecoder = NULL;
457
static int TWebPSetupEncode(TIFF *tif)
459
static const char module[] = "WebPSetupEncode";
460
uint16_t nBitsPerSample = tif->tif_dir.td_bitspersample;
461
uint16_t sampleFormat = tif->tif_dir.td_sampleformat;
463
WebPState *sp = EncoderState(tif);
466
sp->nSamples = tif->tif_dir.td_samplesperpixel;
469
if (sp->nSamples != 3
470
#if WEBP_ENCODER_ABI_VERSION >= 0x0100
475
TIFFErrorExtR(tif, module,
476
"WEBP driver doesn't support %d bands. Must be 3 (RGB) "
477
#if WEBP_ENCODER_ABI_VERSION >= 0x0100
486
if ((nBitsPerSample != 8) || (sampleFormat != SAMPLEFORMAT_UINT))
488
TIFFErrorExtR(tif, module, "WEBP driver requires 8 bit unsigned data");
492
if (sp->state & LSTATE_INIT_DECODE)
494
WebPIDelete(sp->psDecoder);
495
WebPFreeDecBuffer(&sp->sDecBuffer);
496
sp->psDecoder = NULL;
501
sp->state |= LSTATE_INIT_ENCODE;
503
if (!WebPPictureInit(&sp->sPicture))
505
TIFFErrorExtR(tif, module, "Error initializing WebP picture.");
509
if (!WebPConfigInitInternal(&sp->sEncoderConfig, WEBP_PRESET_DEFAULT,
510
(float)sp->quality_level,
511
WEBP_ENCODER_ABI_VERSION))
513
TIFFErrorExtR(tif, module,
514
"Error creating WebP encoder configuration.");
519
#if WEBP_ENCODER_ABI_VERSION >= 0x0100
520
sp->sEncoderConfig.lossless = sp->lossless;
523
sp->sPicture.use_argb = 1;
524
#if WEBP_ENCODER_ABI_VERSION >= 0x0209
525
sp->sEncoderConfig.exact = sp->lossless_exact;
530
if (!WebPValidateConfig(&sp->sEncoderConfig))
532
TIFFErrorExtR(tif, module, "Error with WebP encoder configuration.");
542
static int TWebPPreEncode(TIFF *tif, uint16_t s)
544
static const char module[] = "TWebPPreEncode";
545
uint32_t segment_width, segment_height;
546
WebPState *sp = EncoderState(tif);
547
TIFFDirectory *td = &tif->tif_dir;
552
if (sp->state != LSTATE_INIT_ENCODE)
553
tif->tif_setupencode(tif);
560
segment_width = td->td_tilewidth;
561
segment_height = td->td_tilelength;
565
segment_width = td->td_imagewidth;
566
segment_height = td->td_imagelength - tif->tif_row;
567
if (segment_height > td->td_rowsperstrip)
568
segment_height = td->td_rowsperstrip;
571
if (segment_width > 16383 || segment_height > 16383)
573
TIFFErrorExtR(tif, module,
574
"WEBP maximum image dimensions are 16383 x 16383.");
580
sp->buffer_size = segment_width * segment_height * sp->nSamples;
582
if (sp->pBuffer != NULL)
584
_TIFFfreeExt(tif, sp->pBuffer);
588
sp->pBuffer = _TIFFmallocExt(tif, sp->buffer_size);
591
TIFFErrorExtR(tif, module, "Cannot allocate buffer");
594
sp->buffer_offset = 0;
596
sp->sPicture.width = segment_width;
597
sp->sPicture.height = segment_height;
598
sp->sPicture.writer = TWebPDatasetWriter;
599
sp->sPicture.custom_ptr = tif;
607
static int TWebPPostEncode(TIFF *tif)
609
static const char module[] = "WebPPostEncode";
611
WebPState *sp = EncoderState(tif);
614
assert(sp->state == LSTATE_INIT_ENCODE);
616
stride = (int64_t)sp->sPicture.width * sp->nSamples;
618
#if WEBP_ENCODER_ABI_VERSION >= 0x0100
619
if (sp->nSamples == 4)
621
if (!WebPPictureImportRGBA(&sp->sPicture, sp->pBuffer, (int)stride))
623
TIFFErrorExtR(tif, module, "WebPPictureImportRGBA() failed");
629
if (!WebPPictureImportRGB(&sp->sPicture, sp->pBuffer, (int)stride))
631
TIFFErrorExtR(tif, module, "WebPPictureImportRGB() failed");
635
if (!WebPEncode(&sp->sEncoderConfig, &sp->sPicture))
638
#if WEBP_ENCODER_ABI_VERSION >= 0x0100
639
const char *pszErrorMsg = NULL;
640
switch (sp->sPicture.error_code)
642
case VP8_ENC_ERROR_OUT_OF_MEMORY:
643
pszErrorMsg = "Out of memory";
645
case VP8_ENC_ERROR_BITSTREAM_OUT_OF_MEMORY:
646
pszErrorMsg = "Out of memory while flushing bits";
648
case VP8_ENC_ERROR_NULL_PARAMETER:
649
pszErrorMsg = "A pointer parameter is NULL";
651
case VP8_ENC_ERROR_INVALID_CONFIGURATION:
652
pszErrorMsg = "Configuration is invalid";
654
case VP8_ENC_ERROR_BAD_DIMENSION:
655
pszErrorMsg = "Picture has invalid width/height";
657
case VP8_ENC_ERROR_PARTITION0_OVERFLOW:
658
pszErrorMsg = "Partition is bigger than 512k. Try using less "
659
"SEGMENTS, or increase PARTITION_LIMIT value";
661
case VP8_ENC_ERROR_PARTITION_OVERFLOW:
662
pszErrorMsg = "Partition is bigger than 16M";
664
case VP8_ENC_ERROR_BAD_WRITE:
665
pszErrorMsg = "Error while fludshing bytes";
667
case VP8_ENC_ERROR_FILE_TOO_BIG:
668
pszErrorMsg = "File is bigger than 4G";
670
case VP8_ENC_ERROR_USER_ABORT:
671
pszErrorMsg = "User interrupted";
674
TIFFErrorExtR(tif, module,
675
"WebPEncode returned an unknown error code: %d",
676
sp->sPicture.error_code);
677
pszErrorMsg = "Unknown WebP error type.";
680
TIFFErrorExtR(tif, module, "WebPEncode() failed : %s", pszErrorMsg);
682
TIFFErrorExtR(tif, module, "Error in WebPEncode()");
687
sp->sPicture.custom_ptr = NULL;
689
if (!TIFFFlushData1(tif))
691
TIFFErrorExtR(tif, module, "Error flushing TIFF WebP encoder.");
698
static void TWebPCleanup(TIFF *tif)
700
WebPState *sp = LState(tif);
704
tif->tif_tagmethods.vgetfield = sp->vgetparent;
705
tif->tif_tagmethods.vsetfield = sp->vsetparent;
707
if (sp->state & LSTATE_INIT_ENCODE)
709
WebPPictureFree(&sp->sPicture);
712
if (sp->psDecoder != NULL)
714
WebPIDelete(sp->psDecoder);
715
WebPFreeDecBuffer(&sp->sDecBuffer);
716
sp->psDecoder = NULL;
720
if (sp->pBuffer != NULL)
722
_TIFFfreeExt(tif, sp->pBuffer);
726
_TIFFfreeExt(tif, tif->tif_data);
727
tif->tif_data = NULL;
729
_TIFFSetDefaultCompressionState(tif);
732
static int TWebPVSetField(TIFF *tif, uint32_t tag, va_list ap)
734
static const char module[] = "WebPVSetField";
735
WebPState *sp = LState(tif);
739
case TIFFTAG_WEBP_LEVEL:
740
sp->quality_level = (int)va_arg(ap, int);
741
if (sp->quality_level <= 0 || sp->quality_level > 100.0f)
743
TIFFWarningExtR(tif, module,
744
"WEBP_LEVEL should be between 1 and 100");
747
case TIFFTAG_WEBP_LOSSLESS:
748
#if WEBP_ENCODER_ABI_VERSION >= 0x0100
749
sp->lossless = va_arg(ap, int);
752
sp->quality_level = 100;
758
"Need to upgrade WEBP driver, this version doesn't support "
759
"lossless compression.");
762
case TIFFTAG_WEBP_LOSSLESS_EXACT:
763
#if WEBP_ENCODER_ABI_VERSION >= 0x0209
764
sp->lossless_exact = va_arg(ap, int);
769
"Need to upgrade WEBP driver, this version doesn't support "
770
"lossless compression.");
774
return (*sp->vsetparent)(tif, tag, ap);
779
static int TWebPVGetField(TIFF *tif, uint32_t tag, va_list ap)
781
WebPState *sp = LState(tif);
785
case TIFFTAG_WEBP_LEVEL:
786
*va_arg(ap, int *) = sp->quality_level;
788
case TIFFTAG_WEBP_LOSSLESS:
789
*va_arg(ap, int *) = sp->lossless;
791
case TIFFTAG_WEBP_LOSSLESS_EXACT:
792
*va_arg(ap, int *) = sp->lossless_exact;
795
return (*sp->vgetparent)(tif, tag, ap);
800
static const TIFFField TWebPFields[] = {
801
{TIFFTAG_WEBP_LEVEL, 0, 0, TIFF_ANY, 0, TIFF_SETGET_INT,
802
TIFF_SETGET_UNDEFINED, FIELD_PSEUDO, TRUE, FALSE, "WEBP quality", NULL},
803
{TIFFTAG_WEBP_LOSSLESS, 0, 0, TIFF_ANY, 0, TIFF_SETGET_INT,
804
TIFF_SETGET_UNDEFINED, FIELD_PSEUDO, TRUE, FALSE, "WEBP lossless/lossy",
806
{TIFFTAG_WEBP_LOSSLESS_EXACT, 0, 0, TIFF_ANY, 0, TIFF_SETGET_INT,
807
TIFF_SETGET_UNDEFINED, FIELD_PSEUDO, TRUE, FALSE, "WEBP exact lossless",
811
int TIFFInitWebP(TIFF *tif, int scheme)
813
static const char module[] = "TIFFInitWebP";
817
assert(scheme == COMPRESSION_WEBP);
822
if (!_TIFFMergeFields(tif, TWebPFields, TIFFArrayCount(TWebPFields)))
824
TIFFErrorExtR(tif, module, "Merging WebP codec-specific tags failed");
831
tif->tif_data = (uint8_t *)_TIFFmallocExt(tif, sizeof(WebPState));
832
if (tif->tif_data == NULL)
839
sp->vgetparent = tif->tif_tagmethods.vgetfield;
840
tif->tif_tagmethods.vgetfield = TWebPVGetField;
841
sp->vsetparent = tif->tif_tagmethods.vsetfield;
842
tif->tif_tagmethods.vsetfield = TWebPVSetField;
845
sp->quality_level = 75;
847
sp->lossless_exact = 1;
850
sp->psDecoder = NULL;
853
sp->buffer_offset = 0;
861
tif->tif_fixuptags = TWebPFixupTags;
862
tif->tif_setupdecode = TWebPSetupDecode;
863
tif->tif_predecode = TWebPPreDecode;
864
tif->tif_decoderow = TWebPDecode;
865
tif->tif_decodestrip = TWebPDecode;
866
tif->tif_decodetile = TWebPDecode;
867
tif->tif_setupencode = TWebPSetupEncode;
868
tif->tif_preencode = TWebPPreEncode;
869
tif->tif_postencode = TWebPPostEncode;
870
tif->tif_encoderow = TWebPEncode;
871
tif->tif_encodestrip = TWebPEncode;
872
tif->tif_encodetile = TWebPEncode;
873
tif->tif_cleanup = TWebPCleanup;
877
TIFFErrorExtR(tif, module, "No space for WebP state block");