diff options
Diffstat (limited to 'src/3rdparty/libtiff/libtiff/tif_webp.c')
-rw-r--r-- | src/3rdparty/libtiff/libtiff/tif_webp.c | 1222 |
1 files changed, 660 insertions, 562 deletions
diff --git a/src/3rdparty/libtiff/libtiff/tif_webp.c b/src/3rdparty/libtiff/libtiff/tif_webp.c index 60ebaca..07db7cc 100644 --- a/src/3rdparty/libtiff/libtiff/tif_webp.c +++ b/src/3rdparty/libtiff/libtiff/tif_webp.c @@ -1,26 +1,26 @@ /* -* Copyright (c) 2018, Mapbox -* Author: <norman.barker at mapbox.com> -* -* Permission to use, copy, modify, distribute, and sell this software and -* its documentation for any purpose is hereby granted without fee, provided -* that (i) the above copyright notices and this permission notice appear in -* all copies of the software and related documentation, and (ii) the names of -* Sam Leffler and Silicon Graphics may not be used in any advertising or -* publicity relating to the software without the specific, prior written -* permission of Sam Leffler and Silicon Graphics. -* -* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, -* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY -* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. -* -* IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR -* ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, -* OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -* WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF -* LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE -* OF THIS SOFTWARE. -*/ + * Copyright (c) 2018, Mapbox + * Author: <norman.barker at mapbox.com> + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ #include "tiffiop.h" #ifdef WEBP_SUPPORT @@ -34,6 +34,7 @@ #include "webp/decode.h" #include "webp/encode.h" +#include <stdbool.h> #include <stdio.h> #define LSTATE_INIT_DECODE 0x01 @@ -42,661 +43,758 @@ * State block for each open TIFF * file using WEBP compression/decompression. */ -typedef struct { - uint16_t nSamples; /* number of samples per pixel */ +typedef struct +{ + uint16_t nSamples; /* number of samples per pixel */ - int lossless; /* lossy/lossless compression */ - 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 */ - unsigned int buffer_size; + int lossless; /* lossy/lossless compression */ + 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 */ + unsigned int buffer_size; - WebPIDecoder* psDecoder; /* WebPIDecoder */ - WebPDecBuffer sDecBuffer; /* Decoder buffer */ - int last_y; /* Last row decoded */ + WebPIDecoder *psDecoder; /* WebPIDecoder */ + WebPDecBuffer sDecBuffer; /* Decoder buffer */ + int last_y; /* Last row decoded */ - int state; /* state flags */ + int state; /* state flags */ - TIFFVGetMethod vgetparent; /* super-class method */ - TIFFVSetMethod vsetparent; /* super-class method */ + TIFFVGetMethod vgetparent; /* super-class method */ + TIFFVSetMethod vsetparent; /* super-class method */ } WebPState; -#define LState(tif) ((WebPState*) (tif)->tif_data) -#define DecoderState(tif) LState(tif) -#define EncoderState(tif) LState(tif) +#define LState(tif) ((WebPState *)(tif)->tif_data) +#define DecoderState(tif) LState(tif) +#define EncoderState(tif) LState(tif) -static int TWebPEncode(TIFF* tif, uint8_t* bp, tmsize_t cc, uint16_t s); -static int TWebPDecode(TIFF* tif, uint8_t* op, tmsize_t occ, uint16_t s); +static int TWebPEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s); +static int TWebPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s); -static -int TWebPDatasetWriter(const uint8_t* data, size_t data_size, - const WebPPicture* const picture) +static int TWebPDatasetWriter(const uint8_t *data, size_t data_size, + const WebPPicture *const picture) { - static const char module[] = "TWebPDatasetWriter"; - TIFF* tif = (TIFF*)(picture->custom_ptr); - - if ( (tif->tif_rawcc + (tmsize_t)data_size) > tif->tif_rawdatasize ) { - TIFFErrorExt(tif->tif_clientdata, module, - "Buffer too small by %"TIFF_SIZE_FORMAT" bytes.", - (size_t) (tif->tif_rawcc + data_size - tif->tif_rawdatasize)); - return 0; - } else { - _TIFFmemcpy(tif->tif_rawcp, data, data_size); - tif->tif_rawcc += data_size; - tif->tif_rawcp += data_size; - return 1; - } + static const char module[] = "TWebPDatasetWriter"; + TIFF *tif = (TIFF *)(picture->custom_ptr); + + if ((tif->tif_rawcc + (tmsize_t)data_size) > tif->tif_rawdatasize) + { + TIFFErrorExtR( + tif, module, "Buffer too small by %" TIFF_SIZE_FORMAT " bytes.", + (size_t)(tif->tif_rawcc + data_size - tif->tif_rawdatasize)); + return 0; + } + else + { + _TIFFmemcpy(tif->tif_rawcp, data, data_size); + tif->tif_rawcc += data_size; + tif->tif_rawcp += data_size; + return 1; + } } /* * Encode a chunk of pixels. */ -static int -TWebPEncode(TIFF* tif, uint8_t* bp, tmsize_t cc, uint16_t s) +static int TWebPEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s) { - static const char module[] = "TWebPEncode"; - WebPState *sp = EncoderState(tif); - (void) s; - - assert(sp != NULL); - assert(sp->state == LSTATE_INIT_ENCODE); + static const char module[] = "TWebPEncode"; + WebPState *sp = EncoderState(tif); + (void)s; - if((uint64_t)sp->buffer_offset + - (uint64_t)cc > sp->buffer_size ) - { - TIFFErrorExt(tif->tif_clientdata, module, - "Too many bytes to be written"); - return 0; - } + assert(sp != NULL); + assert(sp->state == LSTATE_INIT_ENCODE); - memcpy(sp->pBuffer + sp->buffer_offset, - bp, cc); - sp->buffer_offset += (unsigned)cc; + if ((uint64_t)sp->buffer_offset + (uint64_t)cc > sp->buffer_size) + { + TIFFErrorExtR(tif, module, "Too many bytes to be written"); + return 0; + } - return 1; + memcpy(sp->pBuffer + sp->buffer_offset, bp, cc); + sp->buffer_offset += (unsigned)cc; + return 1; } -static int -TWebPDecode(TIFF* tif, uint8_t* op, tmsize_t occ, uint16_t s) +static int TWebPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) { - static const char module[] = "WebPDecode"; - VP8StatusCode status = VP8_STATUS_OK; - WebPState *sp = DecoderState(tif); - (void) s; - - assert(sp != NULL); - assert(sp->state == LSTATE_INIT_DECODE); - - if (occ % sp->sDecBuffer.u.RGBA.stride) - { - TIFFErrorExt(tif->tif_clientdata, module, - "Fractional scanlines cannot be read"); - return 0; - } + static const char module[] = "WebPDecode"; + VP8StatusCode status = VP8_STATUS_OK; + WebPState *sp = DecoderState(tif); + uint32_t segment_width, segment_height; + bool decode_whole_strile = false; + + (void)s; + + assert(sp != NULL); + assert(sp->state == LSTATE_INIT_DECODE); + + if (sp->psDecoder == NULL) + { + TIFFDirectory *td = &tif->tif_dir; + uint32_t buffer_size; + + if (isTiled(tif)) + { + segment_width = td->td_tilewidth; + segment_height = td->td_tilelength; + } + else + { + segment_width = td->td_imagewidth; + segment_height = td->td_imagelength - tif->tif_row; + if (segment_height > td->td_rowsperstrip) + segment_height = td->td_rowsperstrip; + } + + buffer_size = segment_width * segment_height * sp->nSamples; + if (occ == (tmsize_t)buffer_size) + { + /* If decoding the whole strip/tile, we can directly use the */ + /* output buffer */ + decode_whole_strile = true; + } + else if (sp->pBuffer == NULL || buffer_size > sp->buffer_size) + { + if (sp->pBuffer != NULL) + { + _TIFFfreeExt(tif, sp->pBuffer); + sp->pBuffer = NULL; + } + + sp->pBuffer = _TIFFmallocExt(tif, buffer_size); + if (!sp->pBuffer) + { + TIFFErrorExtR(tif, module, "Cannot allocate buffer"); + return 0; + } + sp->buffer_size = buffer_size; + } + + sp->last_y = 0; + + WebPInitDecBuffer(&sp->sDecBuffer); + + sp->sDecBuffer.is_external_memory = 1; + sp->sDecBuffer.width = segment_width; + sp->sDecBuffer.height = segment_height; + sp->sDecBuffer.u.RGBA.rgba = decode_whole_strile ? op : sp->pBuffer; + sp->sDecBuffer.u.RGBA.stride = segment_width * sp->nSamples; + sp->sDecBuffer.u.RGBA.size = buffer_size; + + if (sp->nSamples > 3) + { + sp->sDecBuffer.colorspace = MODE_RGBA; + } + else + { + sp->sDecBuffer.colorspace = MODE_RGB; + } + + sp->psDecoder = WebPINewDecoder(&sp->sDecBuffer); + + if (sp->psDecoder == NULL) + { + TIFFErrorExtR(tif, module, "Unable to allocate WebP decoder."); + return 0; + } + } - status = WebPIAppend(sp->psDecoder, tif->tif_rawcp, tif->tif_rawcc); + if (occ % sp->sDecBuffer.u.RGBA.stride) + { + TIFFErrorExtR(tif, module, "Fractional scanlines cannot be read"); + return 0; + } - if (status != VP8_STATUS_OK && status != VP8_STATUS_SUSPENDED) { - if (status == VP8_STATUS_INVALID_PARAM) { - TIFFErrorExt(tif->tif_clientdata, module, - "Invalid parameter used."); - } else if (status == VP8_STATUS_OUT_OF_MEMORY) { - TIFFErrorExt(tif->tif_clientdata, module, - "Out of memory."); - } else { - TIFFErrorExt(tif->tif_clientdata, module, - "Unrecognized error."); + status = WebPIAppend(sp->psDecoder, tif->tif_rawcp, tif->tif_rawcc); + + if (status != VP8_STATUS_OK && status != VP8_STATUS_SUSPENDED) + { + if (status == VP8_STATUS_INVALID_PARAM) + { + TIFFErrorExtR(tif, module, "Invalid parameter used."); + } + else if (status == VP8_STATUS_OUT_OF_MEMORY) + { + TIFFErrorExtR(tif, module, "Out of memory."); + } + else + { + TIFFErrorExtR(tif, module, "Unrecognized error."); + } + return 0; + } + else + { + int current_y, stride; + uint8_t *buf; + + /* Returns the RGB/A image decoded so far */ + buf = WebPIDecGetRGB(sp->psDecoder, ¤t_y, NULL, NULL, &stride); + + if ((buf != NULL) && + (occ <= (tmsize_t)stride * (current_y - sp->last_y))) + { + const int numberOfExpectedLines = + (int)(occ / sp->sDecBuffer.u.RGBA.stride); + if (decode_whole_strile) + { + if (current_y != numberOfExpectedLines) + { + TIFFErrorExtR(tif, module, + "Unable to decode WebP data: less lines than " + "expected."); + return 0; + } + } + else + { + memcpy(op, buf + (sp->last_y * stride), occ); + } + + tif->tif_rawcp += tif->tif_rawcc; + tif->tif_rawcc = 0; + sp->last_y += numberOfExpectedLines; + + if (decode_whole_strile) + { + /* We can now free the decoder as we're completely done */ + if (sp->psDecoder != NULL) + { + WebPIDelete(sp->psDecoder); + WebPFreeDecBuffer(&sp->sDecBuffer); + sp->psDecoder = NULL; + } + } + return 1; + } + else + { + TIFFErrorExtR(tif, module, "Unable to decode WebP data."); + return 0; + } } - return 0; - } else { - int current_y, stride; - uint8_t* buf; - - /* Returns the RGB/A image decoded so far */ - buf = WebPIDecGetRGB(sp->psDecoder, ¤t_y, NULL, NULL, &stride); - - if ((buf != NULL) && - (occ <= (tmsize_t)stride * (current_y - sp->last_y))) { - memcpy(op, - buf + (sp->last_y * stride), - occ); - - tif->tif_rawcp += tif->tif_rawcc; - tif->tif_rawcc = 0; - sp->last_y += (int)(occ / sp->sDecBuffer.u.RGBA.stride); - return 1; - } else { - TIFFErrorExt(tif->tif_clientdata, module, "Unable to decode WebP data."); - return 0; - } - } } -static int -TWebPFixupTags(TIFF* tif) +static int TWebPFixupTags(TIFF *tif) { - (void) tif; - if (tif->tif_dir.td_planarconfig != PLANARCONFIG_CONTIG) { - static const char module[] = "TWebPFixupTags"; - TIFFErrorExt(tif->tif_clientdata, module, - "TIFF WEBP requires data to be stored contiguously in RGB e.g. RGBRGBRGB " + (void)tif; + if (tif->tif_dir.td_planarconfig != PLANARCONFIG_CONTIG) + { + static const char module[] = "TWebPFixupTags"; + TIFFErrorExtR(tif, module, + "TIFF WEBP requires data to be stored contiguously in " + "RGB e.g. RGBRGBRGB " #if WEBP_ENCODER_ABI_VERSION >= 0x0100 - "or RGBARGBARGBA" + "or RGBARGBARGBA" #endif - ); - return 0; - } - return 1; + ); + return 0; + } + return 1; } -static int -TWebPSetupDecode(TIFF* tif) +static int TWebPSetupDecode(TIFF *tif) { - static const char module[] = "WebPSetupDecode"; - uint16_t nBitsPerSample = tif->tif_dir.td_bitspersample; - uint16_t sampleFormat = tif->tif_dir.td_sampleformat; + static const char module[] = "WebPSetupDecode"; + uint16_t nBitsPerSample = tif->tif_dir.td_bitspersample; + uint16_t sampleFormat = tif->tif_dir.td_sampleformat; - WebPState* sp = DecoderState(tif); - assert(sp != NULL); + WebPState *sp = DecoderState(tif); + assert(sp != NULL); - sp->nSamples = tif->tif_dir.td_samplesperpixel; + sp->nSamples = tif->tif_dir.td_samplesperpixel; - /* check band count */ - if ( sp->nSamples != 3 + /* check band count */ + if (sp->nSamples != 3 #if WEBP_ENCODER_ABI_VERSION >= 0x0100 - && sp->nSamples != 4 + && sp->nSamples != 4 #endif - ) - { - TIFFErrorExt(tif->tif_clientdata, module, - "WEBP driver doesn't support %d bands. Must be 3 (RGB) " - #if WEBP_ENCODER_ABI_VERSION >= 0x0100 - "or 4 (RGBA) " - #endif - "bands.", - sp->nSamples ); - return 0; - } + ) + { + TIFFErrorExtR(tif, module, + "WEBP driver doesn't support %d bands. Must be 3 (RGB) " +#if WEBP_ENCODER_ABI_VERSION >= 0x0100 + "or 4 (RGBA) " +#endif + "bands.", + sp->nSamples); + return 0; + } - /* check bits per sample and data type */ - if ((nBitsPerSample != 8) && (sampleFormat != 1)) { - TIFFErrorExt(tif->tif_clientdata, module, - "WEBP driver requires 8 bit unsigned data"); - return 0; - } + /* check bits per sample and data type */ + if ((nBitsPerSample != 8) && (sampleFormat != 1)) + { + TIFFErrorExtR(tif, module, "WEBP driver requires 8 bit unsigned data"); + return 0; + } - /* if we were last encoding, terminate this mode */ - if (sp->state & LSTATE_INIT_ENCODE) { - WebPPictureFree(&sp->sPicture); - if (sp->pBuffer != NULL) { - _TIFFfree(sp->pBuffer); - sp->pBuffer = NULL; - } - sp->buffer_offset = 0; - sp->state = 0; - } + /* if we were last encoding, terminate this mode */ + if (sp->state & LSTATE_INIT_ENCODE) + { + WebPPictureFree(&sp->sPicture); + if (sp->pBuffer != NULL) + { + _TIFFfreeExt(tif, sp->pBuffer); + sp->pBuffer = NULL; + } + sp->buffer_offset = 0; + sp->state = 0; + } - sp->state |= LSTATE_INIT_DECODE; + sp->state |= LSTATE_INIT_DECODE; - return 1; + return 1; } /* -* Setup state for decoding a strip. -*/ -static int -TWebPPreDecode(TIFF* tif, uint16_t s) + * Setup state for decoding a strip. + */ +static int TWebPPreDecode(TIFF *tif, uint16_t s) { - static const char module[] = "TWebPPreDecode"; - uint32_t segment_width, segment_height; - WebPState* sp = DecoderState(tif); - TIFFDirectory* td = &tif->tif_dir; - (void) s; - assert(sp != NULL); - - if (isTiled(tif)) { - segment_width = td->td_tilewidth; - segment_height = td->td_tilelength; - } else { - segment_width = td->td_imagewidth; - segment_height = td->td_imagelength - tif->tif_row; - if (segment_height > td->td_rowsperstrip) - segment_height = td->td_rowsperstrip; - } - - if( segment_width > 16383 || segment_height > 16383 ) { - TIFFErrorExt(tif->tif_clientdata, module, - "WEBP maximum image dimensions are 16383 x 16383."); - return 0; - } - - if( (sp->state & LSTATE_INIT_DECODE) == 0 ) - tif->tif_setupdecode(tif); - - if (sp->psDecoder != NULL) { - WebPIDelete(sp->psDecoder); - WebPFreeDecBuffer(&sp->sDecBuffer); - sp->psDecoder = NULL; - } - - sp->last_y = 0; - - WebPInitDecBuffer(&sp->sDecBuffer); - - sp->sDecBuffer.is_external_memory = 0; - sp->sDecBuffer.width = segment_width; - sp->sDecBuffer.height = segment_height; - sp->sDecBuffer.u.RGBA.stride = segment_width * sp->nSamples; - sp->sDecBuffer.u.RGBA.size = segment_width * sp->nSamples * segment_height; + static const char module[] = "TWebPPreDecode"; + uint32_t segment_width, segment_height; + WebPState *sp = DecoderState(tif); + TIFFDirectory *td = &tif->tif_dir; + (void)s; + assert(sp != NULL); + + if (isTiled(tif)) + { + segment_width = td->td_tilewidth; + segment_height = td->td_tilelength; + } + else + { + segment_width = td->td_imagewidth; + segment_height = td->td_imagelength - tif->tif_row; + if (segment_height > td->td_rowsperstrip) + segment_height = td->td_rowsperstrip; + } - if (sp->nSamples > 3) { - sp->sDecBuffer.colorspace = MODE_RGBA; - } else { - sp->sDecBuffer.colorspace = MODE_RGB; - } + if (segment_width > 16383 || segment_height > 16383) + { + TIFFErrorExtR(tif, module, + "WEBP maximum image dimensions are 16383 x 16383."); + return 0; + } - sp->psDecoder = WebPINewDecoder(&sp->sDecBuffer); + if ((sp->state & LSTATE_INIT_DECODE) == 0) + tif->tif_setupdecode(tif); - if (sp->psDecoder == NULL) { - TIFFErrorExt(tif->tif_clientdata, module, - "Unable to allocate WebP decoder."); - return 0; - } + if (sp->psDecoder != NULL) + { + WebPIDelete(sp->psDecoder); + WebPFreeDecBuffer(&sp->sDecBuffer); + sp->psDecoder = NULL; + } - return 1; + return 1; } -static int -TWebPSetupEncode(TIFF* tif) +static int TWebPSetupEncode(TIFF *tif) { - static const char module[] = "WebPSetupEncode"; - uint16_t nBitsPerSample = tif->tif_dir.td_bitspersample; - uint16_t sampleFormat = tif->tif_dir.td_sampleformat; + static const char module[] = "WebPSetupEncode"; + uint16_t nBitsPerSample = tif->tif_dir.td_bitspersample; + uint16_t sampleFormat = tif->tif_dir.td_sampleformat; - WebPState* sp = EncoderState(tif); - assert(sp != NULL); + WebPState *sp = EncoderState(tif); + assert(sp != NULL); - sp->nSamples = tif->tif_dir.td_samplesperpixel; + sp->nSamples = tif->tif_dir.td_samplesperpixel; - /* check band count */ - if ( sp->nSamples != 3 + /* check band count */ + if (sp->nSamples != 3 #if WEBP_ENCODER_ABI_VERSION >= 0x0100 - && sp->nSamples != 4 + && sp->nSamples != 4 #endif - ) - { - TIFFErrorExt(tif->tif_clientdata, module, - "WEBP driver doesn't support %d bands. Must be 3 (RGB) " + ) + { + TIFFErrorExtR(tif, module, + "WEBP driver doesn't support %d bands. Must be 3 (RGB) " #if WEBP_ENCODER_ABI_VERSION >= 0x0100 - "or 4 (RGBA) " + "or 4 (RGBA) " #endif - "bands.", - sp->nSamples ); - return 0; - } + "bands.", + sp->nSamples); + return 0; + } - /* check bits per sample and data type */ - if ((nBitsPerSample != 8) || (sampleFormat != SAMPLEFORMAT_UINT)) { - TIFFErrorExt(tif->tif_clientdata, module, - "WEBP driver requires 8 bit unsigned data"); - return 0; - } + /* check bits per sample and data type */ + if ((nBitsPerSample != 8) || (sampleFormat != SAMPLEFORMAT_UINT)) + { + TIFFErrorExtR(tif, module, "WEBP driver requires 8 bit unsigned data"); + return 0; + } - if (sp->state & LSTATE_INIT_DECODE) { - WebPIDelete(sp->psDecoder); - WebPFreeDecBuffer(&sp->sDecBuffer); - sp->psDecoder = NULL; - sp->last_y = 0; - sp->state = 0; - } + if (sp->state & LSTATE_INIT_DECODE) + { + WebPIDelete(sp->psDecoder); + WebPFreeDecBuffer(&sp->sDecBuffer); + sp->psDecoder = NULL; + sp->last_y = 0; + sp->state = 0; + } - sp->state |= LSTATE_INIT_ENCODE; + sp->state |= LSTATE_INIT_ENCODE; - if (!WebPPictureInit(&sp->sPicture)) { - TIFFErrorExt(tif->tif_clientdata, module, - "Error initializing WebP picture."); - return 0; - } + if (!WebPPictureInit(&sp->sPicture)) + { + TIFFErrorExtR(tif, module, "Error initializing WebP picture."); + return 0; + } - if (!WebPConfigInitInternal(&sp->sEncoderConfig, WEBP_PRESET_DEFAULT, - (float)sp->quality_level, - WEBP_ENCODER_ABI_VERSION)) { - TIFFErrorExt(tif->tif_clientdata, module, - "Error creating WebP encoder configuration."); - return 0; - } + if (!WebPConfigInitInternal(&sp->sEncoderConfig, WEBP_PRESET_DEFAULT, + (float)sp->quality_level, + WEBP_ENCODER_ABI_VERSION)) + { + TIFFErrorExtR(tif, module, + "Error creating WebP encoder configuration."); + return 0; + } - // WebPConfigInitInternal above sets lossless to false - #if WEBP_ENCODER_ABI_VERSION >= 0x0100 +// WebPConfigInitInternal above sets lossless to false +#if WEBP_ENCODER_ABI_VERSION >= 0x0100 sp->sEncoderConfig.lossless = sp->lossless; - if (sp->lossless) { - sp->sPicture.use_argb = 1; + if (sp->lossless) + { + sp->sPicture.use_argb = 1; } - #endif +#endif - if (!WebPValidateConfig(&sp->sEncoderConfig)) { - TIFFErrorExt(tif->tif_clientdata, module, - "Error with WebP encoder configuration."); - return 0; - } + if (!WebPValidateConfig(&sp->sEncoderConfig)) + { + TIFFErrorExtR(tif, module, "Error with WebP encoder configuration."); + return 0; + } - return 1; + return 1; } /* -* Reset encoding state at the start of a strip. -*/ -static int -TWebPPreEncode(TIFF* tif, uint16_t s) + * Reset encoding state at the start of a strip. + */ +static int TWebPPreEncode(TIFF *tif, uint16_t s) { - static const char module[] = "TWebPPreEncode"; - uint32_t segment_width, segment_height; - WebPState *sp = EncoderState(tif); - TIFFDirectory* td = &tif->tif_dir; - - (void) s; - - assert(sp != NULL); - if( sp->state != LSTATE_INIT_ENCODE ) - tif->tif_setupencode(tif); - - /* - * Set encoding parameters for this strip/tile. - */ - if (isTiled(tif)) { - segment_width = td->td_tilewidth; - segment_height = td->td_tilelength; - } else { - segment_width = td->td_imagewidth; - segment_height = td->td_imagelength - tif->tif_row; - if (segment_height > td->td_rowsperstrip) - segment_height = td->td_rowsperstrip; - } - - if( segment_width > 16383 || segment_height > 16383 ) { - TIFFErrorExt(tif->tif_clientdata, module, - "WEBP maximum image dimensions are 16383 x 16383."); - return 0; - } - - /* set up buffer for raw data */ - /* given above check and that nSamples <= 4, buffer_size is <= 1 GB */ - sp->buffer_size = segment_width * segment_height * sp->nSamples; - - if (sp->pBuffer != NULL) { - _TIFFfree(sp->pBuffer); - sp->pBuffer = NULL; - } - - sp->pBuffer = _TIFFmalloc(sp->buffer_size); - if( !sp->pBuffer) { - TIFFErrorExt(tif->tif_clientdata, module, "Cannot allocate buffer"); - return 0; - } - sp->buffer_offset = 0; - - sp->sPicture.width = segment_width; - sp->sPicture.height = segment_height; - sp->sPicture.writer = TWebPDatasetWriter; - sp->sPicture.custom_ptr = tif; - - return 1; + static const char module[] = "TWebPPreEncode"; + uint32_t segment_width, segment_height; + WebPState *sp = EncoderState(tif); + TIFFDirectory *td = &tif->tif_dir; + + (void)s; + + assert(sp != NULL); + if (sp->state != LSTATE_INIT_ENCODE) + tif->tif_setupencode(tif); + + /* + * Set encoding parameters for this strip/tile. + */ + if (isTiled(tif)) + { + segment_width = td->td_tilewidth; + segment_height = td->td_tilelength; + } + else + { + segment_width = td->td_imagewidth; + segment_height = td->td_imagelength - tif->tif_row; + if (segment_height > td->td_rowsperstrip) + segment_height = td->td_rowsperstrip; + } + + if (segment_width > 16383 || segment_height > 16383) + { + TIFFErrorExtR(tif, module, + "WEBP maximum image dimensions are 16383 x 16383."); + return 0; + } + + /* set up buffer for raw data */ + /* given above check and that nSamples <= 4, buffer_size is <= 1 GB */ + sp->buffer_size = segment_width * segment_height * sp->nSamples; + + if (sp->pBuffer != NULL) + { + _TIFFfreeExt(tif, sp->pBuffer); + sp->pBuffer = NULL; + } + + sp->pBuffer = _TIFFmallocExt(tif, sp->buffer_size); + if (!sp->pBuffer) + { + TIFFErrorExtR(tif, module, "Cannot allocate buffer"); + return 0; + } + sp->buffer_offset = 0; + + sp->sPicture.width = segment_width; + sp->sPicture.height = segment_height; + sp->sPicture.writer = TWebPDatasetWriter; + sp->sPicture.custom_ptr = tif; + + return 1; } /* -* Finish off an encoded strip by flushing it. -*/ -static int -TWebPPostEncode(TIFF* tif) + * Finish off an encoded strip by flushing it. + */ +static int TWebPPostEncode(TIFF *tif) { - static const char module[] = "WebPPostEncode"; - int64_t stride; - WebPState *sp = EncoderState(tif); - assert(sp != NULL); + static const char module[] = "WebPPostEncode"; + int64_t stride; + WebPState *sp = EncoderState(tif); + assert(sp != NULL); - assert(sp->state == LSTATE_INIT_ENCODE); + assert(sp->state == LSTATE_INIT_ENCODE); - stride = (int64_t)sp->sPicture.width * sp->nSamples; + stride = (int64_t)sp->sPicture.width * sp->nSamples; #if WEBP_ENCODER_ABI_VERSION >= 0x0100 - if (sp->nSamples == 4) { - if (!WebPPictureImportRGBA(&sp->sPicture, sp->pBuffer, (int)stride)) { - TIFFErrorExt(tif->tif_clientdata, module, - "WebPPictureImportRGBA() failed" ); - return 0; - } - } - else + if (sp->nSamples == 4) + { + if (!WebPPictureImportRGBA(&sp->sPicture, sp->pBuffer, (int)stride)) + { + TIFFErrorExtR(tif, module, "WebPPictureImportRGBA() failed"); + return 0; + } + } + else #endif - if (!WebPPictureImportRGB(&sp->sPicture, sp->pBuffer, (int)stride)) { - TIFFErrorExt(tif->tif_clientdata, module, - "WebPPictureImportRGB() failed"); - return 0; - } + if (!WebPPictureImportRGB(&sp->sPicture, sp->pBuffer, (int)stride)) + { + TIFFErrorExtR(tif, module, "WebPPictureImportRGB() failed"); + return 0; + } - if (!WebPEncode(&sp->sEncoderConfig, &sp->sPicture)) { + if (!WebPEncode(&sp->sEncoderConfig, &sp->sPicture)) + { #if WEBP_ENCODER_ABI_VERSION >= 0x0100 - const char* pszErrorMsg = NULL; - switch(sp->sPicture.error_code) { - case VP8_ENC_ERROR_OUT_OF_MEMORY: - pszErrorMsg = "Out of memory"; break; - case VP8_ENC_ERROR_BITSTREAM_OUT_OF_MEMORY: - pszErrorMsg = "Out of memory while flushing bits"; break; - case VP8_ENC_ERROR_NULL_PARAMETER: - pszErrorMsg = "A pointer parameter is NULL"; break; - case VP8_ENC_ERROR_INVALID_CONFIGURATION: - pszErrorMsg = "Configuration is invalid"; break; - case VP8_ENC_ERROR_BAD_DIMENSION: - pszErrorMsg = "Picture has invalid width/height"; break; - case VP8_ENC_ERROR_PARTITION0_OVERFLOW: - pszErrorMsg = "Partition is bigger than 512k. Try using less " - "SEGMENTS, or increase PARTITION_LIMIT value"; - break; - case VP8_ENC_ERROR_PARTITION_OVERFLOW: - pszErrorMsg = "Partition is bigger than 16M"; - break; - case VP8_ENC_ERROR_BAD_WRITE: - pszErrorMsg = "Error while fludshing bytes"; break; - case VP8_ENC_ERROR_FILE_TOO_BIG: - pszErrorMsg = "File is bigger than 4G"; break; - case VP8_ENC_ERROR_USER_ABORT: - pszErrorMsg = "User interrupted"; - break; - default: - TIFFErrorExt(tif->tif_clientdata, module, - "WebPEncode returned an unknown error code: %d", - sp->sPicture.error_code); - pszErrorMsg = "Unknown WebP error type."; - break; - } - TIFFErrorExt(tif->tif_clientdata, module, - "WebPEncode() failed : %s", pszErrorMsg); + const char *pszErrorMsg = NULL; + switch (sp->sPicture.error_code) + { + case VP8_ENC_ERROR_OUT_OF_MEMORY: + pszErrorMsg = "Out of memory"; + break; + case VP8_ENC_ERROR_BITSTREAM_OUT_OF_MEMORY: + pszErrorMsg = "Out of memory while flushing bits"; + break; + case VP8_ENC_ERROR_NULL_PARAMETER: + pszErrorMsg = "A pointer parameter is NULL"; + break; + case VP8_ENC_ERROR_INVALID_CONFIGURATION: + pszErrorMsg = "Configuration is invalid"; + break; + case VP8_ENC_ERROR_BAD_DIMENSION: + pszErrorMsg = "Picture has invalid width/height"; + break; + case VP8_ENC_ERROR_PARTITION0_OVERFLOW: + pszErrorMsg = "Partition is bigger than 512k. Try using less " + "SEGMENTS, or increase PARTITION_LIMIT value"; + break; + case VP8_ENC_ERROR_PARTITION_OVERFLOW: + pszErrorMsg = "Partition is bigger than 16M"; + break; + case VP8_ENC_ERROR_BAD_WRITE: + pszErrorMsg = "Error while fludshing bytes"; + break; + case VP8_ENC_ERROR_FILE_TOO_BIG: + pszErrorMsg = "File is bigger than 4G"; + break; + case VP8_ENC_ERROR_USER_ABORT: + pszErrorMsg = "User interrupted"; + break; + default: + TIFFErrorExtR(tif, module, + "WebPEncode returned an unknown error code: %d", + sp->sPicture.error_code); + pszErrorMsg = "Unknown WebP error type."; + break; + } + TIFFErrorExtR(tif, module, "WebPEncode() failed : %s", pszErrorMsg); #else - TIFFErrorExt(tif->tif_clientdata, module, - "Error in WebPEncode()"); + TIFFErrorExtR(tif, module, "Error in WebPEncode()"); #endif - return 0; - } + return 0; + } - sp->sPicture.custom_ptr = NULL; + sp->sPicture.custom_ptr = NULL; - if (!TIFFFlushData1(tif)) - { - TIFFErrorExt(tif->tif_clientdata, module, - "Error flushing TIFF WebP encoder."); - return 0; - } + if (!TIFFFlushData1(tif)) + { + TIFFErrorExtR(tif, module, "Error flushing TIFF WebP encoder."); + return 0; + } - return 1; + return 1; } -static void -TWebPCleanup(TIFF* tif) +static void TWebPCleanup(TIFF *tif) { - WebPState* sp = LState(tif); + WebPState *sp = LState(tif); - assert(sp != 0); + assert(sp != 0); - tif->tif_tagmethods.vgetfield = sp->vgetparent; - tif->tif_tagmethods.vsetfield = sp->vsetparent; + tif->tif_tagmethods.vgetfield = sp->vgetparent; + tif->tif_tagmethods.vsetfield = sp->vsetparent; - if (sp->state & LSTATE_INIT_ENCODE) { - WebPPictureFree(&sp->sPicture); - } + if (sp->state & LSTATE_INIT_ENCODE) + { + WebPPictureFree(&sp->sPicture); + } - if (sp->psDecoder != NULL) { - WebPIDelete(sp->psDecoder); - WebPFreeDecBuffer(&sp->sDecBuffer); - sp->psDecoder = NULL; - sp->last_y = 0; - } + if (sp->psDecoder != NULL) + { + WebPIDelete(sp->psDecoder); + WebPFreeDecBuffer(&sp->sDecBuffer); + sp->psDecoder = NULL; + sp->last_y = 0; + } - if (sp->pBuffer != NULL) { - _TIFFfree(sp->pBuffer); - sp->pBuffer = NULL; - } + if (sp->pBuffer != NULL) + { + _TIFFfreeExt(tif, sp->pBuffer); + sp->pBuffer = NULL; + } - _TIFFfree(tif->tif_data); - tif->tif_data = NULL; + _TIFFfreeExt(tif, tif->tif_data); + tif->tif_data = NULL; - _TIFFSetDefaultCompressionState(tif); + _TIFFSetDefaultCompressionState(tif); } -static int -TWebPVSetField(TIFF* tif, uint32_t tag, va_list ap) +static int TWebPVSetField(TIFF *tif, uint32_t tag, va_list ap) { - static const char module[] = "WebPVSetField"; - WebPState* sp = LState(tif); - - switch (tag) { - case TIFFTAG_WEBP_LEVEL: - sp->quality_level = (int) va_arg(ap, int); - if( sp->quality_level <= 0 || - sp->quality_level > 100.0f ) { - TIFFWarningExt(tif->tif_clientdata, module, - "WEBP_LEVEL should be between 1 and 100"); - } - return 1; - case TIFFTAG_WEBP_LOSSLESS: - #if WEBP_ENCODER_ABI_VERSION >= 0x0100 - sp->lossless = va_arg(ap, int); - if (sp->lossless){ - sp->quality_level = 100; + static const char module[] = "WebPVSetField"; + WebPState *sp = LState(tif); + + switch (tag) + { + case TIFFTAG_WEBP_LEVEL: + sp->quality_level = (int)va_arg(ap, int); + if (sp->quality_level <= 0 || sp->quality_level > 100.0f) + { + TIFFWarningExtR(tif, module, + "WEBP_LEVEL should be between 1 and 100"); + } + return 1; + case TIFFTAG_WEBP_LOSSLESS: +#if WEBP_ENCODER_ABI_VERSION >= 0x0100 + sp->lossless = va_arg(ap, int); + if (sp->lossless) + { + sp->quality_level = 100; + } + 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); } - return 1; - #else - TIFFErrorExt(tif->tif_clientdata, module, - "Need to upgrade WEBP driver, this version doesn't support " - "lossless compression."); - return 0; - #endif - default: - return (*sp->vsetparent)(tif, tag, ap); - } - /*NOTREACHED*/ + /*NOTREACHED*/ } -static int -TWebPVGetField(TIFF* tif, uint32_t tag, va_list ap) +static int TWebPVGetField(TIFF *tif, uint32_t tag, va_list ap) { - WebPState* sp = LState(tif); - - switch (tag) { - case TIFFTAG_WEBP_LEVEL: - *va_arg(ap, int*) = sp->quality_level; - break; - case TIFFTAG_WEBP_LOSSLESS: - *va_arg(ap, int*) = sp->lossless; - break; - default: - return (*sp->vgetparent)(tif, tag, ap); - } - return 1; + WebPState *sp = LState(tif); + + switch (tag) + { + case TIFFTAG_WEBP_LEVEL: + *va_arg(ap, int *) = sp->quality_level; + break; + case TIFFTAG_WEBP_LOSSLESS: + *va_arg(ap, int *) = sp->lossless; + break; + default: + return (*sp->vgetparent)(tif, tag, ap); + } + return 1; } static const TIFFField TWebPFields[] = { - { TIFFTAG_WEBP_LEVEL, 0, 0, TIFF_ANY, 0, TIFF_SETGET_INT, - TIFF_SETGET_UNDEFINED, - FIELD_PSEUDO, TRUE, FALSE, "WEBP quality", NULL }, - { TIFFTAG_WEBP_LOSSLESS, 0, 0, TIFF_ANY, 0, TIFF_SETGET_INT, - TIFF_SETGET_UNDEFINED, - FIELD_PSEUDO, TRUE, FALSE, "WEBP lossless/lossy", NULL - }, + {TIFFTAG_WEBP_LEVEL, 0, 0, TIFF_ANY, 0, TIFF_SETGET_INT, + TIFF_SETGET_UNDEFINED, FIELD_PSEUDO, TRUE, FALSE, "WEBP quality", NULL}, + {TIFFTAG_WEBP_LOSSLESS, 0, 0, TIFF_ANY, 0, TIFF_SETGET_INT, + TIFF_SETGET_UNDEFINED, FIELD_PSEUDO, TRUE, FALSE, "WEBP lossless/lossy", + NULL}, }; -int -TIFFInitWebP(TIFF* tif, int scheme) +int TIFFInitWebP(TIFF *tif, int scheme) { - static const char module[] = "TIFFInitWebP"; - WebPState* sp; - - (void)scheme; - assert( scheme == COMPRESSION_WEBP ); - - /* - * Merge codec-specific tag information. - */ - if ( !_TIFFMergeFields(tif, TWebPFields, TIFFArrayCount(TWebPFields)) ) { - TIFFErrorExt(tif->tif_clientdata, module, - "Merging WebP codec-specific tags failed"); - return 0; - } - - /* - * Allocate state block so tag methods have storage to record values. - */ - tif->tif_data = (uint8_t*) _TIFFmalloc(sizeof(WebPState)); - if (tif->tif_data == NULL) - goto bad; - sp = LState(tif); - - /* - * Override parent get/set field methods. - */ - sp->vgetparent = tif->tif_tagmethods.vgetfield; - tif->tif_tagmethods.vgetfield = TWebPVGetField; /* hook for codec tags */ - sp->vsetparent = tif->tif_tagmethods.vsetfield; - tif->tif_tagmethods.vsetfield = TWebPVSetField; /* hook for codec tags */ - - /* Default values for codec-specific fields */ - sp->quality_level = 75; /* default comp. level */ - sp->lossless = 0; /* default to false */ - sp->state = 0; - sp->nSamples = 0; - sp->psDecoder = NULL; - sp->last_y = 0; - - sp->buffer_offset = 0; - sp->pBuffer = NULL; - - /* - * Install codec methods. - * Notes: - * encoderow is not supported - */ - tif->tif_fixuptags = TWebPFixupTags; - tif->tif_setupdecode = TWebPSetupDecode; - tif->tif_predecode = TWebPPreDecode; - tif->tif_decoderow = TWebPDecode; - tif->tif_decodestrip = TWebPDecode; - tif->tif_decodetile = TWebPDecode; - tif->tif_setupencode = TWebPSetupEncode; - tif->tif_preencode = TWebPPreEncode; - tif->tif_postencode = TWebPPostEncode; - tif->tif_encoderow = TWebPEncode; - tif->tif_encodestrip = TWebPEncode; - tif->tif_encodetile = TWebPEncode; - tif->tif_cleanup = TWebPCleanup; - - return 1; + static const char module[] = "TIFFInitWebP"; + WebPState *sp; + + (void)scheme; + assert(scheme == COMPRESSION_WEBP); + + /* + * Merge codec-specific tag information. + */ + if (!_TIFFMergeFields(tif, TWebPFields, TIFFArrayCount(TWebPFields))) + { + TIFFErrorExtR(tif, module, "Merging WebP codec-specific tags failed"); + return 0; + } + + /* + * Allocate state block so tag methods have storage to record values. + */ + tif->tif_data = (uint8_t *)_TIFFmallocExt(tif, sizeof(WebPState)); + if (tif->tif_data == NULL) + goto bad; + sp = LState(tif); + + /* + * Override parent get/set field methods. + */ + sp->vgetparent = tif->tif_tagmethods.vgetfield; + tif->tif_tagmethods.vgetfield = TWebPVGetField; /* hook for codec tags */ + sp->vsetparent = tif->tif_tagmethods.vsetfield; + tif->tif_tagmethods.vsetfield = TWebPVSetField; /* hook for codec tags */ + + /* Default values for codec-specific fields */ + sp->quality_level = 75; /* default comp. level */ + sp->lossless = 0; /* default to false */ + sp->state = 0; + sp->nSamples = 0; + sp->psDecoder = NULL; + sp->last_y = 0; + + sp->buffer_offset = 0; + sp->pBuffer = NULL; + + /* + * Install codec methods. + * Notes: + * encoderow is not supported + */ + tif->tif_fixuptags = TWebPFixupTags; + tif->tif_setupdecode = TWebPSetupDecode; + tif->tif_predecode = TWebPPreDecode; + tif->tif_decoderow = TWebPDecode; + tif->tif_decodestrip = TWebPDecode; + tif->tif_decodetile = TWebPDecode; + tif->tif_setupencode = TWebPSetupEncode; + tif->tif_preencode = TWebPPreEncode; + tif->tif_postencode = TWebPPostEncode; + tif->tif_encoderow = TWebPEncode; + tif->tif_encodestrip = TWebPEncode; + tif->tif_encodetile = TWebPEncode; + tif->tif_cleanup = TWebPCleanup; + + return 1; bad: - TIFFErrorExt(tif->tif_clientdata, module, - "No space for WebP state block"); - return 0; + TIFFErrorExtR(tif, module, "No space for WebP state block"); + return 0; } #endif /* WEBP_SUPPORT */ |