summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/libtiff/libtiff/tif_webp.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/libtiff/libtiff/tif_webp.c')
-rw-r--r--src/3rdparty/libtiff/libtiff/tif_webp.c87
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;