mirror of https://github.com/opencv/opencv.git
parent
5f57842575
commit
ff1ec6ccc6
56 changed files with 5168 additions and 927 deletions
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,67 @@ |
||||
/*
|
||||
* Copyright (c) 2009 Frank Warmerdam |
||||
* |
||||
* 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. |
||||
*/ |
||||
|
||||
#ifndef _LIBPORT_ |
||||
#define _LIBPORT_ |
||||
|
||||
int getopt(int argc, char * const argv[], const char *optstring); |
||||
extern char *optarg; |
||||
extern int opterr; |
||||
extern int optind; |
||||
extern int optopt; |
||||
|
||||
int strcasecmp(const char *s1, const char *s2); |
||||
|
||||
#ifndef HAVE_GETOPT |
||||
# define HAVE_GETOPT 1 |
||||
#endif |
||||
|
||||
#if HAVE_STRTOL |
||||
long strtol(const char *nptr, char **endptr, int base); |
||||
#endif |
||||
#if HAVE_STRTOLL |
||||
long long strtoll(const char *nptr, char **endptr, int base); |
||||
#endif |
||||
#if HAVE_STRTOUL |
||||
unsigned long strtoul(const char *nptr, char **endptr, int base); |
||||
#endif |
||||
#if HAVE_STRTOULL |
||||
unsigned long long strtoull(const char *nptr, char **endptr, int base); |
||||
#endif |
||||
|
||||
#if 0 |
||||
void * |
||||
lfind(const void *key, const void *base, size_t *nmemb, size_t size, |
||||
int(*compar)(const void *, const void *)); |
||||
#endif |
||||
|
||||
#if !defined(HAVE_SNPRINTF) |
||||
#undef vsnprintf |
||||
#define vsnprintf _TIFF_vsnprintf_f |
||||
|
||||
#undef snprintf |
||||
#define snprintf _TIFF_snprintf_f |
||||
int snprintf(char* str, size_t size, const char* format, ...); |
||||
#endif |
||||
|
||||
#endif /* ndef _LIBPORT_ */ |
@ -0,0 +1,684 @@ |
||||
/*
|
||||
* 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 |
||||
/*
|
||||
* TIFF Library. |
||||
* |
||||
* WEBP Compression Support |
||||
* |
||||
*/ |
||||
|
||||
#include "webp/decode.h" |
||||
#include "webp/encode.h" |
||||
|
||||
#include <stdio.h> |
||||
|
||||
#define LSTATE_INIT_DECODE 0x01 |
||||
#define LSTATE_INIT_ENCODE 0x02 |
||||
/*
|
||||
* State block for each open TIFF |
||||
* file using WEBP compression/decompression. |
||||
*/ |
||||
typedef struct { |
||||
uint16 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* 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 */ |
||||
|
||||
int state; /* state flags */ |
||||
|
||||
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) |
||||
|
||||
static int TWebPEncode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s); |
||||
static int TWebPDecode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s); |
||||
|
||||
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;
|
||||
} |
||||
} |
||||
|
||||
/*
|
||||
* Encode a chunk of pixels. |
||||
*/ |
||||
static int |
||||
TWebPEncode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s) |
||||
{ |
||||
static const char module[] = "TWebPEncode"; |
||||
WebPState *sp = EncoderState(tif); |
||||
(void) s; |
||||
|
||||
assert(sp != NULL); |
||||
assert(sp->state == LSTATE_INIT_ENCODE); |
||||
|
||||
if( (uint64)sp->buffer_offset + |
||||
(uint64)cc > sp->buffer_size ) |
||||
{ |
||||
TIFFErrorExt(tif->tif_clientdata, module, |
||||
"Too many bytes to be written"); |
||||
return 0; |
||||
} |
||||
|
||||
memcpy(sp->pBuffer + sp->buffer_offset, |
||||
bp, cc); |
||||
sp->buffer_offset += (unsigned)cc; |
||||
|
||||
return 1; |
||||
|
||||
} |
||||
|
||||
static int |
||||
TWebPDecode(TIFF* tif, uint8* op, tmsize_t occ, uint16 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; |
||||
} |
||||
|
||||
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) { |
||||
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.");
|
||||
} |
||||
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 <= 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 += 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) |
||||
{ |
||||
(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 " |
||||
#if WEBP_ENCODER_ABI_VERSION >= 0x0100 |
||||
"or RGBARGBARGBA" |
||||
#endif |
||||
); |
||||
return 0; |
||||
} |
||||
return 1; |
||||
} |
||||
|
||||
static int |
||||
TWebPSetupDecode(TIFF* tif) |
||||
{ |
||||
static const char module[] = "WebPSetupDecode"; |
||||
uint16 nBitsPerSample = tif->tif_dir.td_bitspersample; |
||||
uint16 sampleFormat = tif->tif_dir.td_sampleformat; |
||||
|
||||
WebPState* sp = DecoderState(tif); |
||||
assert(sp != NULL); |
||||
|
||||
sp->nSamples = tif->tif_dir.td_samplesperpixel; |
||||
|
||||
/* check band count */ |
||||
if ( sp->nSamples != 3 |
||||
#if WEBP_ENCODER_ABI_VERSION >= 0x0100 |
||||
&& 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; |
||||
} |
||||
|
||||
/* 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; |
||||
} |
||||
|
||||
/* 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; |
||||
} |
||||
|
||||
sp->state |= LSTATE_INIT_DECODE; |
||||
|
||||
return 1; |
||||
} |
||||
|
||||
/*
|
||||
* Setup state for decoding a strip. |
||||
*/ |
||||
static int |
||||
TWebPPreDecode(TIFF* tif, uint16 s) |
||||
{ |
||||
static const char module[] = "TWebPPreDecode"; |
||||
uint32 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->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; |
||||
|
||||
if (sp->nSamples > 3) { |
||||
sp->sDecBuffer.colorspace = MODE_RGBA; |
||||
} else { |
||||
sp->sDecBuffer.colorspace = MODE_RGB; |
||||
} |
||||
|
||||
sp->psDecoder = WebPINewDecoder(&sp->sDecBuffer); |
||||
|
||||
if (sp->psDecoder == NULL) { |
||||
TIFFErrorExt(tif->tif_clientdata, module, |
||||
"Unable to allocate WebP decoder."); |
||||
return 0; |
||||
} |
||||
|
||||
return 1; |
||||
} |
||||
|
||||
static int |
||||
TWebPSetupEncode(TIFF* tif) |
||||
{ |
||||
static const char module[] = "WebPSetupEncode"; |
||||
uint16 nBitsPerSample = tif->tif_dir.td_bitspersample; |
||||
uint16 sampleFormat = tif->tif_dir.td_sampleformat; |
||||
|
||||
WebPState* sp = EncoderState(tif); |
||||
assert(sp != NULL); |
||||
|
||||
sp->nSamples = tif->tif_dir.td_samplesperpixel; |
||||
|
||||
/* check band count */ |
||||
if ( sp->nSamples != 3 |
||||
#if WEBP_ENCODER_ABI_VERSION >= 0x0100 |
||||
&& 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; |
||||
} |
||||
|
||||
/* 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; |
||||
} |
||||
|
||||
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; |
||||
|
||||
if (!WebPConfigInitInternal(&sp->sEncoderConfig, WEBP_PRESET_DEFAULT, |
||||
sp->quality_level, |
||||
WEBP_ENCODER_ABI_VERSION)) { |
||||
TIFFErrorExt(tif->tif_clientdata, module, |
||||
"Error creating WebP encoder configuration."); |
||||
return 0; |
||||
} |
||||
|
||||
#if WEBP_ENCODER_ABI_VERSION >= 0x0100 |
||||
sp->sEncoderConfig.lossless = sp->lossless; |
||||
#endif |
||||
|
||||
if (!WebPValidateConfig(&sp->sEncoderConfig)) { |
||||
TIFFErrorExt(tif->tif_clientdata, module, |
||||
"Error with WebP encoder configuration."); |
||||
return 0; |
||||
} |
||||
|
||||
if (!WebPPictureInit(&sp->sPicture)) { |
||||
TIFFErrorExt(tif->tif_clientdata, module, |
||||
"Error initializing WebP picture."); |
||||
return 0; |
||||
} |
||||
|
||||
return 1; |
||||
} |
||||
|
||||
/*
|
||||
* Reset encoding state at the start of a strip. |
||||
*/ |
||||
static int |
||||
TWebPPreEncode(TIFF* tif, uint16 s) |
||||
{ |
||||
static const char module[] = "TWebPPreEncode"; |
||||
uint32 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; |
||||
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; |
||||
} |
||||
|
||||
/*
|
||||
* 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); |
||||
|
||||
assert(sp->state == LSTATE_INIT_ENCODE); |
||||
|
||||
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 |
||||
#endif |
||||
if (!WebPPictureImportRGB(&sp->sPicture, sp->pBuffer, (int)stride)) { |
||||
TIFFErrorExt(tif->tif_clientdata, module, |
||||
"WebPPictureImportRGB() failed"); |
||||
return 0; |
||||
} |
||||
|
||||
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); |
||||
#else |
||||
TIFFErrorExt(tif->tif_clientdata, module, |
||||
"Error in WebPEncode()"); |
||||
#endif |
||||
return 0; |
||||
} |
||||
|
||||
sp->sPicture.custom_ptr = NULL; |
||||
|
||||
if (!TIFFFlushData1(tif)) |
||||
{ |
||||
TIFFErrorExt(tif->tif_clientdata, module, |
||||
"Error flushing TIFF WebP encoder."); |
||||
return 0; |
||||
} |
||||
|
||||
return 1; |
||||
} |
||||
|
||||
static void |
||||
TWebPCleanup(TIFF* tif) |
||||
{ |
||||
WebPState* sp = LState(tif); |
||||
|
||||
assert(sp != 0); |
||||
|
||||
tif->tif_tagmethods.vgetfield = sp->vgetparent; |
||||
tif->tif_tagmethods.vsetfield = sp->vsetparent; |
||||
|
||||
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->pBuffer != NULL) { |
||||
_TIFFfree(sp->pBuffer); |
||||
sp->pBuffer = NULL; |
||||
} |
||||
|
||||
if (tif->tif_data) { |
||||
_TIFFfree(tif->tif_data); |
||||
tif->tif_data = NULL; |
||||
} |
||||
|
||||
_TIFFSetDefaultCompressionState(tif); |
||||
} |
||||
|
||||
static int |
||||
TWebPVSetField(TIFF* tif, uint32 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); |
||||
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*/ |
||||
} |
||||
|
||||
static int |
||||
TWebPVGetField(TIFF* tif, uint32 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; |
||||
} |
||||
|
||||
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 |
||||
}, |
||||
}; |
||||
|
||||
int |
||||
TIFFInitWebP(TIFF* tif, int scheme) |
||||
{ |
||||
static const char module[] = "TIFFInitWebP"; |
||||
WebPState* sp; |
||||
|
||||
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*) _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.0f; /* 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; |
||||
} |
||||
|
||||
#endif /* WEBP_SUPPORT */ |
@ -0,0 +1,440 @@ |
||||
/*
|
||||
* Copyright (c) 2017, Planet Labs |
||||
* Author: <even.rouault at spatialys.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 ZSTD_SUPPORT |
||||
/*
|
||||
* TIFF Library. |
||||
* |
||||
* ZSTD Compression Support |
||||
* |
||||
*/ |
||||
|
||||
#include "tif_predict.h" |
||||
#include "zstd.h" |
||||
|
||||
#include <stdio.h> |
||||
|
||||
/*
|
||||
* State block for each open TIFF file using ZSTD compression/decompression. |
||||
*/ |
||||
typedef struct { |
||||
TIFFPredictorState predict; |
||||
ZSTD_DStream* dstream; |
||||
ZSTD_CStream* cstream; |
||||
int compression_level; /* compression level */ |
||||
ZSTD_outBuffer out_buffer; |
||||
int state; /* state flags */ |
||||
#define LSTATE_INIT_DECODE 0x01 |
||||
#define LSTATE_INIT_ENCODE 0x02 |
||||
|
||||
TIFFVGetMethod vgetparent; /* super-class method */ |
||||
TIFFVSetMethod vsetparent; /* super-class method */ |
||||
} ZSTDState; |
||||
|
||||
#define LState(tif) ((ZSTDState*) (tif)->tif_data) |
||||
#define DecoderState(tif) LState(tif) |
||||
#define EncoderState(tif) LState(tif) |
||||
|
||||
static int ZSTDEncode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s); |
||||
static int ZSTDDecode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s); |
||||
|
||||
static int |
||||
ZSTDFixupTags(TIFF* tif) |
||||
{ |
||||
(void) tif; |
||||
return 1; |
||||
} |
||||
|
||||
static int |
||||
ZSTDSetupDecode(TIFF* tif) |
||||
{ |
||||
ZSTDState* sp = DecoderState(tif); |
||||
|
||||
assert(sp != NULL); |
||||
|
||||
/* if we were last encoding, terminate this mode */ |
||||
if (sp->state & LSTATE_INIT_ENCODE) { |
||||
ZSTD_freeCStream(sp->cstream); |
||||
sp->cstream = NULL; |
||||
sp->state = 0; |
||||
} |
||||
|
||||
sp->state |= LSTATE_INIT_DECODE; |
||||
return 1; |
||||
} |
||||
|
||||
/*
|
||||
* Setup state for decoding a strip. |
||||
*/ |
||||
static int |
||||
ZSTDPreDecode(TIFF* tif, uint16 s) |
||||
{ |
||||
static const char module[] = "ZSTDPreDecode"; |
||||
ZSTDState* sp = DecoderState(tif); |
||||
size_t zstd_ret; |
||||
|
||||
(void) s; |
||||
assert(sp != NULL); |
||||
|
||||
if( (sp->state & LSTATE_INIT_DECODE) == 0 ) |
||||
tif->tif_setupdecode(tif); |
||||
|
||||
if( sp->dstream ) |
||||
{ |
||||
ZSTD_freeDStream(sp->dstream); |
||||
sp->dstream = NULL; |
||||
} |
||||
|
||||
sp->dstream = ZSTD_createDStream(); |
||||
if( sp->dstream == NULL ) { |
||||
TIFFErrorExt(tif->tif_clientdata, module, |
||||
"Cannot allocate decompression stream"); |
||||
return 0; |
||||
} |
||||
zstd_ret = ZSTD_initDStream(sp->dstream); |
||||
if( ZSTD_isError(zstd_ret) ) { |
||||
TIFFErrorExt(tif->tif_clientdata, module, |
||||
"Error in ZSTD_initDStream(): %s", |
||||
ZSTD_getErrorName(zstd_ret)); |
||||
return 0; |
||||
} |
||||
|
||||
return 1; |
||||
} |
||||
|
||||
static int |
||||
ZSTDDecode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s) |
||||
{ |
||||
static const char module[] = "ZSTDDecode"; |
||||
ZSTDState* sp = DecoderState(tif); |
||||
ZSTD_inBuffer in_buffer; |
||||
ZSTD_outBuffer out_buffer; |
||||
size_t zstd_ret; |
||||
|
||||
(void) s; |
||||
assert(sp != NULL); |
||||
assert(sp->state == LSTATE_INIT_DECODE); |
||||
|
||||
in_buffer.src = tif->tif_rawcp; |
||||
in_buffer.size = (size_t) tif->tif_rawcc; |
||||
in_buffer.pos = 0; |
||||
|
||||
out_buffer.dst = op; |
||||
out_buffer.size = (size_t) occ; |
||||
out_buffer.pos = 0; |
||||
|
||||
do { |
||||
zstd_ret = ZSTD_decompressStream(sp->dstream, &out_buffer, |
||||
&in_buffer); |
||||
if( ZSTD_isError(zstd_ret) ) { |
||||
TIFFErrorExt(tif->tif_clientdata, module, |
||||
"Error in ZSTD_decompressStream(): %s", |
||||
ZSTD_getErrorName(zstd_ret)); |
||||
return 0; |
||||
} |
||||
} while( zstd_ret != 0 && |
||||
in_buffer.pos < in_buffer.size && |
||||
out_buffer.pos < out_buffer.size ); |
||||
|
||||
if (out_buffer.pos < (size_t)occ) { |
||||
TIFFErrorExt(tif->tif_clientdata, module, |
||||
"Not enough data at scanline %lu (short %lu bytes)", |
||||
(unsigned long) tif->tif_row, |
||||
(unsigned long) (size_t)occ - out_buffer.pos); |
||||
return 0; |
||||
} |
||||
|
||||
tif->tif_rawcp += in_buffer.pos; |
||||
tif->tif_rawcc -= in_buffer.pos; |
||||
|
||||
return 1; |
||||
} |
||||
|
||||
static int |
||||
ZSTDSetupEncode(TIFF* tif) |
||||
{ |
||||
ZSTDState* sp = EncoderState(tif); |
||||
|
||||
assert(sp != NULL); |
||||
if (sp->state & LSTATE_INIT_DECODE) { |
||||
ZSTD_freeDStream(sp->dstream); |
||||
sp->dstream = NULL; |
||||
sp->state = 0; |
||||
} |
||||
|
||||
sp->state |= LSTATE_INIT_ENCODE; |
||||
return 1; |
||||
} |
||||
|
||||
/*
|
||||
* Reset encoding state at the start of a strip. |
||||
*/ |
||||
static int |
||||
ZSTDPreEncode(TIFF* tif, uint16 s) |
||||
{ |
||||
static const char module[] = "ZSTDPreEncode"; |
||||
ZSTDState *sp = EncoderState(tif); |
||||
size_t zstd_ret; |
||||
|
||||
(void) s; |
||||
assert(sp != NULL); |
||||
if( sp->state != LSTATE_INIT_ENCODE ) |
||||
tif->tif_setupencode(tif); |
||||
|
||||
if (sp->cstream) { |
||||
ZSTD_freeCStream(sp->cstream); |
||||
sp->cstream = NULL; |
||||
} |
||||
sp->cstream = ZSTD_createCStream(); |
||||
if( sp->cstream == NULL ) { |
||||
TIFFErrorExt(tif->tif_clientdata, module, |
||||
"Cannot allocate compression stream"); |
||||
return 0; |
||||
} |
||||
|
||||
zstd_ret = ZSTD_initCStream(sp->cstream, sp->compression_level); |
||||
if( ZSTD_isError(zstd_ret) ) { |
||||
TIFFErrorExt(tif->tif_clientdata, module, |
||||
"Error in ZSTD_initCStream(): %s", |
||||
ZSTD_getErrorName(zstd_ret)); |
||||
return 0; |
||||
} |
||||
|
||||
sp->out_buffer.dst = tif->tif_rawdata; |
||||
sp->out_buffer.size = (size_t)tif->tif_rawdatasize; |
||||
sp->out_buffer.pos = 0; |
||||
|
||||
return 1; |
||||
} |
||||
|
||||
/*
|
||||
* Encode a chunk of pixels. |
||||
*/ |
||||
static int |
||||
ZSTDEncode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s) |
||||
{ |
||||
static const char module[] = "ZSTDEncode"; |
||||
ZSTDState *sp = EncoderState(tif); |
||||
ZSTD_inBuffer in_buffer; |
||||
size_t zstd_ret; |
||||
|
||||
assert(sp != NULL); |
||||
assert(sp->state == LSTATE_INIT_ENCODE); |
||||
|
||||
(void) s; |
||||
|
||||
in_buffer.src = bp; |
||||
in_buffer.size = (size_t)cc; |
||||
in_buffer.pos = 0; |
||||
|
||||
do { |
||||
zstd_ret = ZSTD_compressStream(sp->cstream, &sp->out_buffer, |
||||
&in_buffer); |
||||
if( ZSTD_isError(zstd_ret) ) { |
||||
TIFFErrorExt(tif->tif_clientdata, module, |
||||
"Error in ZSTD_compressStream(): %s", |
||||
ZSTD_getErrorName(zstd_ret)); |
||||
return 0; |
||||
} |
||||
if( sp->out_buffer.pos == sp->out_buffer.size ) { |
||||
tif->tif_rawcc = tif->tif_rawdatasize; |
||||
TIFFFlushData1(tif); |
||||
sp->out_buffer.dst = tif->tif_rawcp; |
||||
sp->out_buffer.pos = 0; |
||||
} |
||||
} while( in_buffer.pos < in_buffer.size ); |
||||
|
||||
return 1; |
||||
} |
||||
|
||||
/*
|
||||
* Finish off an encoded strip by flushing it. |
||||
*/ |
||||
static int |
||||
ZSTDPostEncode(TIFF* tif) |
||||
{ |
||||
static const char module[] = "ZSTDPostEncode"; |
||||
ZSTDState *sp = EncoderState(tif); |
||||
size_t zstd_ret; |
||||
|
||||
do { |
||||
zstd_ret = ZSTD_endStream(sp->cstream, &sp->out_buffer); |
||||
if( ZSTD_isError(zstd_ret) ) { |
||||
TIFFErrorExt(tif->tif_clientdata, module, |
||||
"Error in ZSTD_endStream(): %s", |
||||
ZSTD_getErrorName(zstd_ret)); |
||||
return 0; |
||||
} |
||||
if( sp->out_buffer.pos > 0 ) { |
||||
tif->tif_rawcc = sp->out_buffer.pos; |
||||
TIFFFlushData1(tif); |
||||
sp->out_buffer.dst = tif->tif_rawcp; |
||||
sp->out_buffer.pos = 0; |
||||
} |
||||
} while (zstd_ret != 0); |
||||
return 1; |
||||
} |
||||
|
||||
static void |
||||
ZSTDCleanup(TIFF* tif) |
||||
{ |
||||
ZSTDState* sp = LState(tif); |
||||
|
||||
assert(sp != 0); |
||||
|
||||
(void)TIFFPredictorCleanup(tif); |
||||
|
||||
tif->tif_tagmethods.vgetfield = sp->vgetparent; |
||||
tif->tif_tagmethods.vsetfield = sp->vsetparent; |
||||
|
||||
if (sp->dstream) { |
||||
ZSTD_freeDStream(sp->dstream); |
||||
sp->dstream = NULL; |
||||
} |
||||
if (sp->cstream) { |
||||
ZSTD_freeCStream(sp->cstream); |
||||
sp->cstream = NULL; |
||||
} |
||||
_TIFFfree(sp); |
||||
tif->tif_data = NULL; |
||||
|
||||
_TIFFSetDefaultCompressionState(tif); |
||||
} |
||||
|
||||
static int |
||||
ZSTDVSetField(TIFF* tif, uint32 tag, va_list ap) |
||||
{ |
||||
static const char module[] = "ZSTDVSetField"; |
||||
ZSTDState* sp = LState(tif); |
||||
|
||||
switch (tag) { |
||||
case TIFFTAG_ZSTD_LEVEL: |
||||
sp->compression_level = (int) va_arg(ap, int); |
||||
if( sp->compression_level <= 0 || |
||||
sp->compression_level > ZSTD_maxCLevel() ) |
||||
{ |
||||
TIFFWarningExt(tif->tif_clientdata, module, |
||||
"ZSTD_LEVEL should be between 1 and %d", |
||||
ZSTD_maxCLevel()); |
||||
} |
||||
return 1; |
||||
default: |
||||
return (*sp->vsetparent)(tif, tag, ap); |
||||
} |
||||
/*NOTREACHED*/ |
||||
} |
||||
|
||||
static int |
||||
ZSTDVGetField(TIFF* tif, uint32 tag, va_list ap) |
||||
{ |
||||
ZSTDState* sp = LState(tif); |
||||
|
||||
switch (tag) { |
||||
case TIFFTAG_ZSTD_LEVEL: |
||||
*va_arg(ap, int*) = sp->compression_level; |
||||
break; |
||||
default: |
||||
return (*sp->vgetparent)(tif, tag, ap); |
||||
} |
||||
return 1; |
||||
} |
||||
|
||||
static const TIFFField ZSTDFields[] = { |
||||
{ TIFFTAG_ZSTD_LEVEL, 0, 0, TIFF_ANY, 0, TIFF_SETGET_INT, |
||||
TIFF_SETGET_UNDEFINED, |
||||
FIELD_PSEUDO, TRUE, FALSE, "ZSTD compression_level", NULL }, |
||||
}; |
||||
|
||||
int |
||||
TIFFInitZSTD(TIFF* tif, int scheme) |
||||
{ |
||||
static const char module[] = "TIFFInitZSTD"; |
||||
ZSTDState* sp; |
||||
|
||||
assert( scheme == COMPRESSION_ZSTD ); |
||||
|
||||
/*
|
||||
* Merge codec-specific tag information. |
||||
*/ |
||||
if (!_TIFFMergeFields(tif, ZSTDFields, TIFFArrayCount(ZSTDFields))) { |
||||
TIFFErrorExt(tif->tif_clientdata, module, |
||||
"Merging ZSTD codec-specific tags failed"); |
||||
return 0; |
||||
} |
||||
|
||||
/*
|
||||
* Allocate state block so tag methods have storage to record values. |
||||
*/ |
||||
tif->tif_data = (uint8*) _TIFFmalloc(sizeof(ZSTDState)); |
||||
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 = ZSTDVGetField; /* hook for codec tags */ |
||||
sp->vsetparent = tif->tif_tagmethods.vsetfield; |
||||
tif->tif_tagmethods.vsetfield = ZSTDVSetField; /* hook for codec tags */ |
||||
|
||||
/* Default values for codec-specific fields */ |
||||
sp->compression_level = 9; /* default comp. level */ |
||||
sp->state = 0; |
||||
sp->dstream = 0; |
||||
sp->cstream = 0; |
||||
sp->out_buffer.dst = NULL; |
||||
sp->out_buffer.size = 0; |
||||
sp->out_buffer.pos = 0; |
||||
|
||||
/*
|
||||
* Install codec methods. |
||||
*/ |
||||
tif->tif_fixuptags = ZSTDFixupTags; |
||||
tif->tif_setupdecode = ZSTDSetupDecode; |
||||
tif->tif_predecode = ZSTDPreDecode; |
||||
tif->tif_decoderow = ZSTDDecode; |
||||
tif->tif_decodestrip = ZSTDDecode; |
||||
tif->tif_decodetile = ZSTDDecode; |
||||
tif->tif_setupencode = ZSTDSetupEncode; |
||||
tif->tif_preencode = ZSTDPreEncode; |
||||
tif->tif_postencode = ZSTDPostEncode; |
||||
tif->tif_encoderow = ZSTDEncode; |
||||
tif->tif_encodestrip = ZSTDEncode; |
||||
tif->tif_encodetile = ZSTDEncode; |
||||
tif->tif_cleanup = ZSTDCleanup; |
||||
/*
|
||||
* Setup predictor setup. |
||||
*/ |
||||
(void) TIFFPredictorInit(tif); |
||||
return 1; |
||||
bad: |
||||
TIFFErrorExt(tif->tif_clientdata, module, |
||||
"No space for ZSTD state block"); |
||||
return 0; |
||||
} |
||||
#endif /* ZSTD_SUPPORT */ |
||||
|
||||
/* vim: set ts=8 sts=8 sw=8 noet: */ |
Loading…
Reference in new issue