34#include "webp/decode.h"
35#include "webp/encode.h"
40#define LSTATE_INIT_DECODE 0x01
41#define LSTATE_INIT_ENCODE 0x02
57 WebPConfig sEncoderConfig;
59 unsigned int buffer_offset;
62 WebPIDecoder *psDecoder;
63 WebPDecBuffer sDecBuffer;
72#define LState(tif) ((WebPState *)(tif)->tif_data)
73#define DecoderState(tif) LState(tif)
74#define EncoderState(tif) LState(tif)
79static int TWebPDatasetWriter(
const uint8_t *
data,
size_t data_size,
80 const WebPPicture *
const picture)
82 static const char module[] =
"TWebPDatasetWriter";
106 static const char module[] =
"TWebPEncode";
107 WebPState *
sp = EncoderState(tif);
111 assert(
sp->state == LSTATE_INIT_ENCODE);
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;
136 assert(
sp->state == LSTATE_INIT_DECODE);
142 "ZIPDecode: Scanline %" PRIu32 " cannot be read due to "
148 if (
sp->psDecoder ==
NULL)
166 int webp_width, webp_height;
171 &webp_width, &webp_height))
178 if ((
uint32_t)webp_width != segment_width ||
179 (
uint32_t)webp_height != segment_height)
184 tif,
module,
"WebP blob dimension is %dx%d. Expected %ux%u",
185 webp_width, webp_height, segment_width, segment_height);
189#if WEBP_DECODER_ABI_VERSION >= 0x0002
191 if (!WebPInitDecoderConfig(&
config))
199 const bool bWebPGetFeaturesOK =
204 &
config.input) == VP8_STATUS_OK;
206 WebPFreeDecBuffer(&
config.output);
208 if (!bWebPGetFeaturesOK)
216 const int webp_bands =
config.input.has_alpha ? 4 : 3;
217 if (webp_bands !=
sp->nSamples &&
223 !(webp_bands == 3 &&
sp->nSamples == 4))
228 "WebP blob band count is %d. Expected %d", webp_bands,
239 decode_whole_strile =
true;
262 WebPInitDecBuffer(&
sp->sDecBuffer);
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;
271 if (
sp->nSamples > 3)
273 sp->sDecBuffer.colorspace = MODE_RGBA;
277 sp->sDecBuffer.colorspace = MODE_RGB;
280 sp->psDecoder = WebPINewDecoder(&
sp->sDecBuffer);
282 if (
sp->psDecoder ==
NULL)
291 if (occ %
sp->sDecBuffer.u.RGBA.stride)
303 if (
status != VP8_STATUS_OK &&
status != VP8_STATUS_SUSPENDED)
305 if (
status == VP8_STATUS_INVALID_PARAM)
309 else if (
status == VP8_STATUS_OUT_OF_MEMORY)
332 const int numberOfExpectedLines =
333 (
int)(occ /
sp->sDecBuffer.u.RGBA.stride);
334 if (decode_whole_strile)
336 if (current_y != numberOfExpectedLines)
341 "Unable to decode WebP data: less lines than "
353 sp->last_y += numberOfExpectedLines;
355 if (decode_whole_strile)
358 if (
sp->psDecoder !=
NULL)
360 WebPIDelete(
sp->psDecoder);
361 WebPFreeDecBuffer(&
sp->sDecBuffer);
377static int TWebPFixupTags(
TIFF *tif)
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
395static int TWebPSetupDecode(
TIFF *tif)
397 static const char module[] =
"WebPSetupDecode";
401 WebPState *
sp = DecoderState(tif);
407 if (
sp->nSamples != 3
408#
if WEBP_ENCODER_ABI_VERSION >= 0x0100
414 "WEBP driver doesn't support %d bands. Must be 3 (RGB) "
415#
if WEBP_ENCODER_ABI_VERSION >= 0x0100
424 if ((nBitsPerSample != 8) && (sampleFormat != 1))
431 if (
sp->state & LSTATE_INIT_ENCODE)
433 WebPPictureFree(&
sp->sPicture);
439 sp->buffer_offset = 0;
443 sp->state |= LSTATE_INIT_DECODE;
453 static const char module[] =
"TWebPPreDecode";
454 uint32_t segment_width, segment_height;
455 WebPState *
sp = DecoderState(tif);
473 if (segment_width > 16383 || segment_height > 16383)
476 "WEBP maximum image dimensions are 16383 x 16383.");
480 if ((
sp->state & LSTATE_INIT_DECODE) == 0)
483 if (
sp->psDecoder !=
NULL)
485 WebPIDelete(
sp->psDecoder);
486 WebPFreeDecBuffer(&
sp->sDecBuffer);
495static int TWebPSetupEncode(
TIFF *tif)
497 static const char module[] =
"WebPSetupEncode";
501 WebPState *
sp = EncoderState(tif);
507 if (
sp->nSamples != 3
508#
if WEBP_ENCODER_ABI_VERSION >= 0x0100
514 "WEBP driver doesn't support %d bands. Must be 3 (RGB) "
515#
if WEBP_ENCODER_ABI_VERSION >= 0x0100
530 if (
sp->state & LSTATE_INIT_DECODE)
532 WebPIDelete(
sp->psDecoder);
533 WebPFreeDecBuffer(&
sp->sDecBuffer);
539 sp->state |= LSTATE_INIT_ENCODE;
541 if (!WebPPictureInit(&
sp->sPicture))
547 if (!WebPConfigInitInternal(&
sp->sEncoderConfig, WEBP_PRESET_DEFAULT,
548 (
float)
sp->quality_level,
549 WEBP_ENCODER_ABI_VERSION))
552 "Error creating WebP encoder configuration.");
557#if WEBP_ENCODER_ABI_VERSION >= 0x0100
558 sp->sEncoderConfig.lossless =
sp->lossless;
561 sp->sPicture.use_argb = 1;
562#if WEBP_ENCODER_ABI_VERSION >= 0x0209
563 sp->sEncoderConfig.exact =
sp->lossless_exact;
568 if (!WebPValidateConfig(&
sp->sEncoderConfig))
582 static const char module[] =
"TWebPPreEncode";
583 uint32_t segment_width, segment_height;
584 WebPState *
sp = EncoderState(tif);
590 if (
sp->state != LSTATE_INIT_ENCODE)
609 if (segment_width > 16383 || segment_height > 16383)
612 "WEBP maximum image dimensions are 16383 x 16383.");
618 sp->buffer_size = segment_width * segment_height *
sp->nSamples;
632 sp->buffer_offset = 0;
634 sp->sPicture.width = segment_width;
635 sp->sPicture.height = segment_height;
636 sp->sPicture.writer = TWebPDatasetWriter;
637 sp->sPicture.custom_ptr = tif;
645static int TWebPPostEncode(
TIFF *tif)
647 static const char module[] =
"WebPPostEncode";
649 WebPState *
sp = EncoderState(tif);
652 assert(
sp->state == LSTATE_INIT_ENCODE);
656#
if WEBP_ENCODER_ABI_VERSION >= 0x0100
657 if (
sp->nSamples == 4)
659 if (!WebPPictureImportRGBA(&
sp->sPicture,
sp->pBuffer, (
int)
stride))
667 if (!WebPPictureImportRGB(&
sp->sPicture,
sp->pBuffer, (
int)
stride))
673 if (!WebPEncode(&
sp->sEncoderConfig, &
sp->sPicture))
676#if WEBP_ENCODER_ABI_VERSION >= 0x0100
677 const char *pszErrorMsg =
NULL;
678 switch (
sp->sPicture.error_code)
680 case VP8_ENC_ERROR_OUT_OF_MEMORY:
681 pszErrorMsg =
"Out of memory";
683 case VP8_ENC_ERROR_BITSTREAM_OUT_OF_MEMORY:
684 pszErrorMsg =
"Out of memory while flushing bits";
686 case VP8_ENC_ERROR_NULL_PARAMETER:
687 pszErrorMsg =
"A pointer parameter is NULL";
689 case VP8_ENC_ERROR_INVALID_CONFIGURATION:
690 pszErrorMsg =
"Configuration is invalid";
692 case VP8_ENC_ERROR_BAD_DIMENSION:
693 pszErrorMsg =
"Picture has invalid width/height";
695 case VP8_ENC_ERROR_PARTITION0_OVERFLOW:
696 pszErrorMsg =
"Partition is bigger than 512k. Try using less "
697 "SEGMENTS, or increase PARTITION_LIMIT value";
699 case VP8_ENC_ERROR_PARTITION_OVERFLOW:
700 pszErrorMsg =
"Partition is bigger than 16M";
702 case VP8_ENC_ERROR_BAD_WRITE:
703 pszErrorMsg =
"Error while fludshing bytes";
705 case VP8_ENC_ERROR_FILE_TOO_BIG:
706 pszErrorMsg =
"File is bigger than 4G";
708 case VP8_ENC_ERROR_USER_ABORT:
709 pszErrorMsg =
"User interrupted";
713 "WebPEncode returned an unknown error code: %d",
714 sp->sPicture.error_code);
715 pszErrorMsg =
"Unknown WebP error type.";
725 sp->sPicture.custom_ptr =
NULL;
736static void TWebPCleanup(
TIFF *tif)
738 WebPState *
sp = LState(tif);
745 if (
sp->state & LSTATE_INIT_ENCODE)
747 WebPPictureFree(&
sp->sPicture);
750 if (
sp->psDecoder !=
NULL)
752 WebPIDelete(
sp->psDecoder);
753 WebPFreeDecBuffer(&
sp->sDecBuffer);
772 static const char module[] =
"WebPVSetField";
773 WebPState *
sp = LState(tif);
779 if (
sp->quality_level <= 0 ||
sp->quality_level > 100.0f)
782 "WEBP_LEVEL should be between 1 and 100");
786#if WEBP_ENCODER_ABI_VERSION >= 0x0100
790 sp->quality_level = 100;
796 "Need to upgrade WEBP driver, this version doesn't support "
797 "lossless compression.");
801#if WEBP_ENCODER_ABI_VERSION >= 0x0209
807 "Need to upgrade WEBP driver, this version doesn't support "
808 "lossless compression.");
812 return (*
sp->vsetparent)(tif,
tag,
ap);
819 WebPState *
sp = LState(tif);
833 return (*
sp->vgetparent)(tif,
tag,
ap);
849 static const char module[] =
"TIFFInitWebP";
881 sp->quality_level = 75;
883 sp->lossless_exact = 1;
889 sp->buffer_offset = 0;
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
GLenum GLuint GLenum GLsizei const GLchar * buf
#define memcpy(s1, s2, n)
static unsigned(__cdecl *hash_bstr)(bstr_t s)
wchar_t const *const size_t const buffer_size
uint16_t td_bitspersample
uint16_t td_samplesperpixel
TIFFCodeMethod tif_encodestrip
TIFFCodeMethod tif_encodetile
TIFFTagMethods tif_tagmethods
TIFFPreMethod tif_preencode
TIFFBoolMethod tif_fixuptags
TIFFPreMethod tif_predecode
TIFFCodeMethod tif_decodestrip
TIFFCodeMethod tif_decoderow
TIFFBoolMethod tif_setupencode
TIFFBoolMethod tif_postencode
TIFFCodeMethod tif_encoderow
TIFFVoidMethod tif_cleanup
TIFFBoolMethod tif_setupdecode
TIFFCodeMethod tif_decodetile
void _TIFFSetDefaultCompressionState(TIFF *tif)
int _TIFFMergeFields(TIFF *tif, const TIFFField info[], uint32_t n)
void TIFFErrorExtR(TIFF *tif, const char *module, const char *fmt,...)
void _TIFFfreeExt(TIFF *tif, void *p)
void * _TIFFmallocExt(TIFF *tif, tmsize_t s)
void _TIFFmemcpy(void *d, const void *s, tmsize_t c)
void TIFFWarningExtR(TIFF *tif, const char *module, const char *fmt,...)
int TIFFFlushData1(TIFF *tif)
#define SAMPLEFORMAT_UINT
#define TIFFTAG_WEBP_LEVEL
#define TIFFTAG_WEBP_LOSSLESS_EXACT
#define TIFFTAG_WEBP_LOSSLESS
#define PLANARCONFIG_CONTIG
int(* TIFFVSetMethod)(TIFF *, uint32_t, va_list)
int(* TIFFVGetMethod)(TIFF *, uint32_t, va_list)
#define TIFFArrayCount(a)
void int int ULONGLONG int va_list * ap