diff options
Diffstat (limited to 'src/3rdparty/libtiff/libtiff/tif_webp.c')
-rw-r--r-- | src/3rdparty/libtiff/libtiff/tif_webp.c | 87 |
1 files changed, 84 insertions, 3 deletions
diff --git a/src/3rdparty/libtiff/libtiff/tif_webp.c b/src/3rdparty/libtiff/libtiff/tif_webp.c index 07db7cc..bf9d77e 100644 --- a/src/3rdparty/libtiff/libtiff/tif_webp.c +++ b/src/3rdparty/libtiff/libtiff/tif_webp.c @@ -47,9 +47,11 @@ typedef struct { uint16_t nSamples; /* number of samples per pixel */ - int lossless; /* lossy/lossless compression */ - int quality_level; /* compression level */ - WebPPicture sPicture; /* WebP Picture */ + int lossless; /* lossy/lossless compression */ + int lossless_exact; /* lossless exact mode. If TRUE, R,G,B values in areas + with alpha = 0 will be preserved */ + int quality_level; /* compression level */ + WebPPicture sPicture; /* WebP Picture */ WebPConfig sEncoderConfig; /* WebP encoder config */ uint8_t *pBuffer; /* buffer to hold raw data on encoding */ unsigned int buffer_offset; /* current offset into the buffer */ @@ -149,6 +151,64 @@ static int TWebPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) segment_height = td->td_rowsperstrip; } + int webp_width, webp_height; + if (!WebPGetInfo(tif->tif_rawcp, + (uint64_t)tif->tif_rawcc > UINT32_MAX + ? UINT32_MAX + : (uint32_t)tif->tif_rawcc, + &webp_width, &webp_height)) + { + TIFFErrorExtR(tif, module, "WebPGetInfo() failed"); + return 0; + } + if ((uint32_t)webp_width != segment_width || + (uint32_t)webp_height != segment_height) + { + TIFFErrorExtR( + tif, module, "WebP blob dimension is %dx%d. Expected %ux%u", + webp_width, webp_height, segment_width, segment_height); + return 0; + } + +#if WEBP_DECODER_ABI_VERSION >= 0x0002 + WebPDecoderConfig config; + if (!WebPInitDecoderConfig(&config)) + { + TIFFErrorExtR(tif, module, "WebPInitDecoderConfig() failed"); + return 0; + } + + const bool bWebPGetFeaturesOK = + WebPGetFeatures(tif->tif_rawcp, + (uint64_t)tif->tif_rawcc > UINT32_MAX + ? UINT32_MAX + : (uint32_t)tif->tif_rawcc, + &config.input) == VP8_STATUS_OK; + + WebPFreeDecBuffer(&config.output); + + if (!bWebPGetFeaturesOK) + { + TIFFErrorExtR(tif, module, "WebPInitDecoderConfig() failed"); + return 0; + } + + const int webp_bands = config.input.has_alpha ? 4 : 3; + if (webp_bands != sp->nSamples && + /* We accept the situation where the WebP blob has only 3 bands, + * whereas the raster is 4 bands. This can happen when the alpha + * channel is fully opaque, and WebP decoding works fine in that + * situation. + */ + !(webp_bands == 3 && sp->nSamples == 4)) + { + TIFFErrorExtR(tif, module, + "WebP blob band count is %d. Expected %d", webp_bands, + sp->nSamples); + return 0; + } +#endif + buffer_size = segment_width * segment_height * sp->nSamples; if (occ == (tmsize_t)buffer_size) { @@ -461,6 +521,9 @@ static int TWebPSetupEncode(TIFF *tif) if (sp->lossless) { sp->sPicture.use_argb = 1; +#if WEBP_ENCODER_ABI_VERSION >= 0x0209 + sp->sEncoderConfig.exact = sp->lossless_exact; +#endif } #endif @@ -696,6 +759,17 @@ static int TWebPVSetField(TIFF *tif, uint32_t tag, va_list ap) "lossless compression."); return 0; #endif + case TIFFTAG_WEBP_LOSSLESS_EXACT: +#if WEBP_ENCODER_ABI_VERSION >= 0x0209 + sp->lossless_exact = va_arg(ap, int); + return 1; +#else + TIFFErrorExtR( + tif, module, + "Need to upgrade WEBP driver, this version doesn't support " + "lossless compression."); + return 0; +#endif default: return (*sp->vsetparent)(tif, tag, ap); } @@ -714,6 +788,9 @@ static int TWebPVGetField(TIFF *tif, uint32_t tag, va_list ap) case TIFFTAG_WEBP_LOSSLESS: *va_arg(ap, int *) = sp->lossless; break; + case TIFFTAG_WEBP_LOSSLESS_EXACT: + *va_arg(ap, int *) = sp->lossless_exact; + break; default: return (*sp->vgetparent)(tif, tag, ap); } @@ -726,6 +803,9 @@ static const TIFFField TWebPFields[] = { {TIFFTAG_WEBP_LOSSLESS, 0, 0, TIFF_ANY, 0, TIFF_SETGET_INT, TIFF_SETGET_UNDEFINED, FIELD_PSEUDO, TRUE, FALSE, "WEBP lossless/lossy", NULL}, + {TIFFTAG_WEBP_LOSSLESS_EXACT, 0, 0, TIFF_ANY, 0, TIFF_SETGET_INT, + TIFF_SETGET_UNDEFINED, FIELD_PSEUDO, TRUE, FALSE, "WEBP exact lossless", + NULL}, }; int TIFFInitWebP(TIFF *tif, int scheme) @@ -764,6 +844,7 @@ int TIFFInitWebP(TIFF *tif, int scheme) /* Default values for codec-specific fields */ sp->quality_level = 75; /* default comp. level */ sp->lossless = 0; /* default to false */ + sp->lossless_exact = 1; /* exact lossless mode (if lossless enabled) */ sp->state = 0; sp->nSamples = 0; sp->psDecoder = NULL; |