12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541 |
- /*
- * Copyright (c) 2018, Even Rouault
- * 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 LERC_SUPPORT
- /*
- * TIFF Library.
- *
- * LERC Compression Support
- *
- */
- #error #include "Lerc_c_api.h"
- #include "zlib.h"
- #ifdef ZSTD_SUPPORT
- #include "zstd.h"
- #endif
- #if LIBDEFLATE_SUPPORT
- #error #include "libdeflate.h"
- #endif
- #define LIBDEFLATE_MAX_COMPRESSION_LEVEL 12
- #include <assert.h>
- #define LSTATE_INIT_DECODE 0x01
- #define LSTATE_INIT_ENCODE 0x02
- #ifndef LERC_AT_LEAST_VERSION
- #define LERC_AT_LEAST_VERSION(maj, min, patch) 0
- #endif
- /*
- * State block for each open TIFF file using LERC compression/decompression.
- */
- typedef struct
- {
- double maxzerror; /* max z error */
- int lerc_version;
- int additional_compression;
- int zstd_compress_level; /* zstd */
- int zipquality; /* deflate */
- int state; /* state flags */
- uint32_t segment_width;
- uint32_t segment_height;
- unsigned int uncompressed_size;
- unsigned int uncompressed_alloc;
- uint8_t *uncompressed_buffer;
- unsigned int uncompressed_offset;
- uint8_t *uncompressed_buffer_multiband;
- unsigned int uncompressed_buffer_multiband_alloc;
- unsigned int mask_size;
- uint8_t *mask_buffer;
- unsigned int compressed_size;
- void *compressed_buffer;
- #if LIBDEFLATE_SUPPORT
- struct libdeflate_decompressor *libdeflate_dec;
- struct libdeflate_compressor *libdeflate_enc;
- #endif
- TIFFVGetMethod vgetparent; /* super-class method */
- TIFFVSetMethod vsetparent; /* super-class method */
- } LERCState;
- #define GetLERCState(tif) ((LERCState *)(tif)->tif_data)
- #define LERCDecoderState(tif) GetLERCState(tif)
- #define LERCEncoderState(tif) GetLERCState(tif)
- static int LERCEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s);
- static int LERCDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s);
- static int LERCFixupTags(TIFF *tif)
- {
- (void)tif;
- return 1;
- }
- static int LERCSetupDecode(TIFF *tif)
- {
- LERCState *sp = LERCDecoderState(tif);
- assert(sp != NULL);
- /* if we were last encoding, terminate this mode */
- if (sp->state & LSTATE_INIT_ENCODE)
- {
- sp->state = 0;
- }
- sp->state |= LSTATE_INIT_DECODE;
- return 1;
- }
- static int GetLercDataType(TIFF *tif)
- {
- TIFFDirectory *td = &tif->tif_dir;
- static const char module[] = "GetLercDataType";
- if (td->td_sampleformat == SAMPLEFORMAT_INT && td->td_bitspersample == 8)
- {
- return 0;
- }
- if (td->td_sampleformat == SAMPLEFORMAT_UINT && td->td_bitspersample == 8)
- {
- return 1;
- }
- if (td->td_sampleformat == SAMPLEFORMAT_INT && td->td_bitspersample == 16)
- {
- return 2;
- }
- if (td->td_sampleformat == SAMPLEFORMAT_UINT && td->td_bitspersample == 16)
- {
- return 3;
- }
- if (td->td_sampleformat == SAMPLEFORMAT_INT && td->td_bitspersample == 32)
- {
- return 4;
- }
- if (td->td_sampleformat == SAMPLEFORMAT_UINT && td->td_bitspersample == 32)
- {
- return 5;
- }
- if (td->td_sampleformat == SAMPLEFORMAT_IEEEFP &&
- td->td_bitspersample == 32)
- {
- return 6;
- }
- if (td->td_sampleformat == SAMPLEFORMAT_IEEEFP &&
- td->td_bitspersample == 64)
- {
- return 7;
- }
- TIFFErrorExtR(
- tif, module,
- "Unsupported combination of SampleFormat and td_bitspersample");
- return -1;
- }
- static int SetupBuffers(TIFF *tif, LERCState *sp, const char *module)
- {
- TIFFDirectory *td = &tif->tif_dir;
- uint64_t new_size_64;
- uint64_t new_alloc_64;
- unsigned int new_size;
- unsigned int new_alloc;
- sp->uncompressed_offset = 0;
- if (isTiled(tif))
- {
- sp->segment_width = td->td_tilewidth;
- sp->segment_height = td->td_tilelength;
- }
- else
- {
- sp->segment_width = td->td_imagewidth;
- sp->segment_height = td->td_imagelength - tif->tif_row;
- if (sp->segment_height > td->td_rowsperstrip)
- sp->segment_height = td->td_rowsperstrip;
- }
- new_size_64 = (uint64_t)sp->segment_width * sp->segment_height *
- (td->td_bitspersample / 8);
- if (td->td_planarconfig == PLANARCONFIG_CONTIG)
- {
- new_size_64 *= td->td_samplesperpixel;
- }
- new_size = (unsigned int)new_size_64;
- sp->uncompressed_size = new_size;
- /* add some margin as we are going to use it also to store deflate/zstd
- * compressed data. We also need extra margin when writing very small
- * rasters with one mask per band. */
- new_alloc_64 = 256 + new_size_64 + new_size_64 / 3;
- #ifdef ZSTD_SUPPORT
- {
- size_t zstd_max = ZSTD_compressBound((size_t)new_size_64);
- if (new_alloc_64 < zstd_max)
- {
- new_alloc_64 = zstd_max;
- }
- }
- #endif
- new_alloc = (unsigned int)new_alloc_64;
- if (new_alloc != new_alloc_64)
- {
- TIFFErrorExtR(tif, module, "Too large uncompressed strip/tile");
- _TIFFfreeExt(tif, sp->uncompressed_buffer);
- sp->uncompressed_buffer = 0;
- sp->uncompressed_alloc = 0;
- return 0;
- }
- if (sp->uncompressed_alloc < new_alloc)
- {
- _TIFFfreeExt(tif, sp->uncompressed_buffer);
- sp->uncompressed_buffer = _TIFFmallocExt(tif, new_alloc);
- if (!sp->uncompressed_buffer)
- {
- TIFFErrorExtR(tif, module, "Cannot allocate buffer");
- _TIFFfreeExt(tif, sp->uncompressed_buffer);
- sp->uncompressed_buffer = 0;
- sp->uncompressed_alloc = 0;
- return 0;
- }
- sp->uncompressed_alloc = new_alloc;
- }
- if ((td->td_planarconfig == PLANARCONFIG_CONTIG &&
- td->td_extrasamples > 0 &&
- td->td_sampleinfo[td->td_extrasamples - 1] == EXTRASAMPLE_UNASSALPHA &&
- GetLercDataType(tif) == 1) ||
- (td->td_sampleformat == SAMPLEFORMAT_IEEEFP &&
- (td->td_bitspersample == 32 || td->td_bitspersample == 64)))
- {
- unsigned int mask_size = sp->segment_width * sp->segment_height;
- #if LERC_AT_LEAST_VERSION(3, 0, 0)
- if (td->td_sampleformat == SAMPLEFORMAT_IEEEFP &&
- td->td_planarconfig == PLANARCONFIG_CONTIG)
- {
- /* We may need one mask per band */
- mask_size *= td->td_samplesperpixel;
- }
- #endif
- if (sp->mask_size < mask_size)
- {
- void *mask_buffer =
- _TIFFreallocExt(tif, sp->mask_buffer, mask_size);
- if (mask_buffer == NULL)
- {
- TIFFErrorExtR(tif, module, "Cannot allocate buffer");
- sp->mask_size = 0;
- _TIFFfreeExt(tif, sp->uncompressed_buffer);
- sp->uncompressed_buffer = 0;
- sp->uncompressed_alloc = 0;
- return 0;
- }
- sp->mask_buffer = (uint8_t *)mask_buffer;
- sp->mask_size = mask_size;
- }
- }
- return 1;
- }
- /*
- * Setup state for decoding a strip.
- */
- static int LERCPreDecode(TIFF *tif, uint16_t s)
- {
- static const char module[] = "LERCPreDecode";
- lerc_status lerc_ret;
- TIFFDirectory *td = &tif->tif_dir;
- LERCState *sp = LERCDecoderState(tif);
- int lerc_data_type;
- unsigned int infoArray[9];
- unsigned nomask_bands = td->td_samplesperpixel;
- int ndims;
- int use_mask = 0;
- uint8_t *lerc_data = tif->tif_rawcp;
- unsigned int lerc_data_size = (unsigned int)tif->tif_rawcc;
- (void)s;
- assert(sp != NULL);
- if (sp->state != LSTATE_INIT_DECODE)
- tif->tif_setupdecode(tif);
- lerc_data_type = GetLercDataType(tif);
- if (lerc_data_type < 0)
- return 0;
- if (!SetupBuffers(tif, sp, module))
- return 0;
- if (sp->additional_compression != LERC_ADD_COMPRESSION_NONE)
- {
- if (sp->compressed_size < sp->uncompressed_alloc)
- {
- _TIFFfreeExt(tif, sp->compressed_buffer);
- sp->compressed_buffer = _TIFFmallocExt(tif, sp->uncompressed_alloc);
- if (!sp->compressed_buffer)
- {
- sp->compressed_size = 0;
- return 0;
- }
- sp->compressed_size = sp->uncompressed_alloc;
- }
- }
- if (sp->additional_compression == LERC_ADD_COMPRESSION_DEFLATE)
- {
- #if LIBDEFLATE_SUPPORT
- enum libdeflate_result res;
- size_t lerc_data_sizet = 0;
- if (sp->libdeflate_dec == NULL)
- {
- sp->libdeflate_dec = libdeflate_alloc_decompressor();
- if (sp->libdeflate_dec == NULL)
- {
- TIFFErrorExtR(tif, module, "Cannot allocate decompressor");
- return 0;
- }
- }
- res = libdeflate_zlib_decompress(
- sp->libdeflate_dec, tif->tif_rawcp, (size_t)tif->tif_rawcc,
- sp->compressed_buffer, sp->compressed_size, &lerc_data_sizet);
- if (res != LIBDEFLATE_SUCCESS)
- {
- TIFFErrorExtR(tif, module, "Decoding error at scanline %lu",
- (unsigned long)tif->tif_row);
- return 0;
- }
- assert(lerc_data_sizet == (unsigned int)lerc_data_sizet);
- lerc_data = sp->compressed_buffer;
- lerc_data_size = (unsigned int)lerc_data_sizet;
- #else
- z_stream strm;
- int zlib_ret;
- memset(&strm, 0, sizeof(strm));
- strm.zalloc = NULL;
- strm.zfree = NULL;
- strm.opaque = NULL;
- zlib_ret = inflateInit(&strm);
- if (zlib_ret != Z_OK)
- {
- TIFFErrorExtR(tif, module, "inflateInit() failed");
- inflateEnd(&strm);
- return 0;
- }
- strm.avail_in = (uInt)tif->tif_rawcc;
- strm.next_in = tif->tif_rawcp;
- strm.avail_out = sp->compressed_size;
- strm.next_out = sp->compressed_buffer;
- zlib_ret = inflate(&strm, Z_FINISH);
- if (zlib_ret != Z_STREAM_END && zlib_ret != Z_OK)
- {
- TIFFErrorExtR(tif, module, "inflate() failed");
- inflateEnd(&strm);
- return 0;
- }
- lerc_data = sp->compressed_buffer;
- lerc_data_size = sp->compressed_size - strm.avail_out;
- inflateEnd(&strm);
- #endif
- }
- else if (sp->additional_compression == LERC_ADD_COMPRESSION_ZSTD)
- {
- #ifdef ZSTD_SUPPORT
- size_t zstd_ret;
- zstd_ret = ZSTD_decompress(sp->compressed_buffer, sp->compressed_size,
- tif->tif_rawcp, tif->tif_rawcc);
- if (ZSTD_isError(zstd_ret))
- {
- TIFFErrorExtR(tif, module, "Error in ZSTD_decompress(): %s",
- ZSTD_getErrorName(zstd_ret));
- return 0;
- }
- lerc_data = sp->compressed_buffer;
- lerc_data_size = (unsigned int)zstd_ret;
- #else
- TIFFErrorExtR(tif, module, "ZSTD support missing");
- return 0;
- #endif
- }
- else if (sp->additional_compression != LERC_ADD_COMPRESSION_NONE)
- {
- TIFFErrorExtR(tif, module, "Unhandled additional compression");
- return 0;
- }
- lerc_ret =
- lerc_getBlobInfo(lerc_data, lerc_data_size, infoArray, NULL, 9, 0);
- if (lerc_ret != 0)
- {
- TIFFErrorExtR(tif, module, "lerc_getBlobInfo() failed");
- return 0;
- }
- /* If the configuration is compatible of a LERC mask, and that the */
- /* LERC info has dim == samplesperpixel - 1, then there is a LERC */
- /* mask. */
- if (td->td_planarconfig == PLANARCONFIG_CONTIG && td->td_extrasamples > 0 &&
- td->td_sampleinfo[td->td_extrasamples - 1] == EXTRASAMPLE_UNASSALPHA &&
- GetLercDataType(tif) == 1 &&
- infoArray[2] == td->td_samplesperpixel - 1U)
- {
- use_mask = 1;
- nomask_bands--;
- }
- else if (td->td_sampleformat == SAMPLEFORMAT_IEEEFP)
- {
- use_mask = 1;
- }
- ndims = td->td_planarconfig == PLANARCONFIG_CONTIG ? nomask_bands : 1;
- /* Info returned in infoArray is { version, dataType, nDim/nDepth, nCols,
- nRows, nBands, nValidPixels, blobSize,
- and starting with liblerc 3.0 nRequestedMasks } */
- if (infoArray[0] != (unsigned)sp->lerc_version)
- {
- TIFFWarningExtR(tif, module,
- "Unexpected version number: %d. Expected: %d",
- infoArray[0], sp->lerc_version);
- }
- if (infoArray[1] != (unsigned)lerc_data_type)
- {
- TIFFErrorExtR(tif, module, "Unexpected dataType: %d. Expected: %d",
- infoArray[1], lerc_data_type);
- return 0;
- }
- const unsigned nFoundDims = infoArray[2];
- #if LERC_AT_LEAST_VERSION(3, 0, 0)
- if (td->td_sampleformat == SAMPLEFORMAT_IEEEFP &&
- td->td_planarconfig == PLANARCONFIG_CONTIG &&
- td->td_samplesperpixel > 1)
- {
- if (nFoundDims != 1 && nFoundDims != (unsigned)ndims)
- {
- TIFFErrorExtR(tif, module, "Unexpected nDim: %d. Expected: 1 or %d",
- nFoundDims, ndims);
- return 0;
- }
- }
- else
- #endif
- if (nFoundDims != (unsigned)ndims)
- {
- TIFFErrorExtR(tif, module, "Unexpected nDim: %d. Expected: %d",
- nFoundDims, ndims);
- return 0;
- }
- if (infoArray[3] != sp->segment_width)
- {
- TIFFErrorExtR(tif, module, "Unexpected nCols: %d. Expected: %du",
- infoArray[3], sp->segment_width);
- return 0;
- }
- if (infoArray[4] != sp->segment_height)
- {
- TIFFErrorExtR(tif, module, "Unexpected nRows: %d. Expected: %u",
- infoArray[4], sp->segment_height);
- return 0;
- }
- const unsigned nFoundBands = infoArray[5];
- if (td->td_sampleformat == SAMPLEFORMAT_IEEEFP &&
- td->td_planarconfig == PLANARCONFIG_CONTIG &&
- td->td_samplesperpixel > 1 && nFoundDims == 1)
- {
- #if !LERC_AT_LEAST_VERSION(3, 0, 0)
- if (nFoundBands == td->td_samplesperpixel)
- {
- TIFFErrorExtR(
- tif, module,
- "Unexpected nBands: %d. This file may have been generated with "
- "a liblerc version >= 3.0, with one mask per band, and is not "
- "supported by this older version of liblerc",
- nFoundBands);
- return 0;
- }
- #endif
- if (nFoundBands != td->td_samplesperpixel)
- {
- TIFFErrorExtR(tif, module, "Unexpected nBands: %d. Expected: %d",
- nFoundBands, td->td_samplesperpixel);
- return 0;
- }
- }
- else if (nFoundBands != 1)
- {
- TIFFErrorExtR(tif, module, "Unexpected nBands: %d. Expected: %d",
- nFoundBands, 1);
- return 0;
- }
- if (infoArray[7] != lerc_data_size)
- {
- TIFFErrorExtR(tif, module, "Unexpected blobSize: %d. Expected: %u",
- infoArray[7], lerc_data_size);
- return 0;
- }
- int nRequestedMasks = use_mask ? 1 : 0;
- #if LERC_AT_LEAST_VERSION(3, 0, 0)
- const int nFoundMasks = infoArray[8];
- if (td->td_sampleformat == SAMPLEFORMAT_IEEEFP &&
- td->td_planarconfig == PLANARCONFIG_CONTIG &&
- td->td_samplesperpixel > 1 && nFoundDims == 1)
- {
- if (nFoundMasks != 0 && nFoundMasks != td->td_samplesperpixel)
- {
- TIFFErrorExtR(tif, module,
- "Unexpected nFoundMasks: %d. Expected: 0 or %d",
- nFoundMasks, td->td_samplesperpixel);
- return 0;
- }
- nRequestedMasks = nFoundMasks;
- }
- else
- {
- if (nFoundMasks != 0 && nFoundMasks != 1)
- {
- TIFFErrorExtR(tif, module,
- "Unexpected nFoundMasks: %d. Expected: 0 or 1",
- nFoundMasks);
- return 0;
- }
- }
- if (td->td_sampleformat == SAMPLEFORMAT_IEEEFP && nFoundMasks == 0)
- {
- nRequestedMasks = 0;
- use_mask = 0;
- }
- #endif
- const unsigned nb_pixels = sp->segment_width * sp->segment_height;
- #if LERC_AT_LEAST_VERSION(3, 0, 0)
- if (nRequestedMasks > 1)
- {
- unsigned int num_bytes_needed =
- nb_pixels * td->td_samplesperpixel * (td->td_bitspersample / 8);
- if (sp->uncompressed_buffer_multiband_alloc < num_bytes_needed)
- {
- _TIFFfreeExt(tif, sp->uncompressed_buffer_multiband);
- sp->uncompressed_buffer_multiband =
- _TIFFmallocExt(tif, num_bytes_needed);
- if (!sp->uncompressed_buffer_multiband)
- {
- sp->uncompressed_buffer_multiband_alloc = 0;
- return 0;
- }
- sp->uncompressed_buffer_multiband_alloc = num_bytes_needed;
- }
- lerc_ret = lerc_decode(lerc_data, lerc_data_size, nRequestedMasks,
- sp->mask_buffer, nFoundDims, sp->segment_width,
- sp->segment_height, nFoundBands, lerc_data_type,
- sp->uncompressed_buffer_multiband);
- }
- else
- #endif
- {
- lerc_ret =
- lerc_decode(lerc_data, lerc_data_size,
- #if LERC_AT_LEAST_VERSION(3, 0, 0)
- nRequestedMasks,
- #endif
- use_mask ? sp->mask_buffer : NULL, nFoundDims,
- sp->segment_width, sp->segment_height, nFoundBands,
- lerc_data_type, sp->uncompressed_buffer);
- }
- if (lerc_ret != 0)
- {
- TIFFErrorExtR(tif, module, "lerc_decode() failed");
- return 0;
- }
- /* Interleave alpha mask with other samples. */
- if (use_mask && GetLercDataType(tif) == 1)
- {
- unsigned src_stride =
- (td->td_samplesperpixel - 1) * (td->td_bitspersample / 8);
- unsigned dst_stride =
- td->td_samplesperpixel * (td->td_bitspersample / 8);
- unsigned i = sp->segment_width * sp->segment_height;
- /* Operate from end to begin to be able to move in place */
- while (i > 0 && i > nomask_bands)
- {
- i--;
- sp->uncompressed_buffer[i * dst_stride + td->td_samplesperpixel -
- 1] = 255 * sp->mask_buffer[i];
- memcpy(sp->uncompressed_buffer + i * dst_stride,
- sp->uncompressed_buffer + i * src_stride, src_stride);
- }
- /* First pixels must use memmove due to overlapping areas */
- while (i > 0)
- {
- i--;
- sp->uncompressed_buffer[i * dst_stride + td->td_samplesperpixel -
- 1] = 255 * sp->mask_buffer[i];
- memmove(sp->uncompressed_buffer + i * dst_stride,
- sp->uncompressed_buffer + i * src_stride, src_stride);
- }
- }
- else if (use_mask && td->td_sampleformat == SAMPLEFORMAT_IEEEFP)
- {
- unsigned i;
- #if WORDS_BIGENDIAN
- const unsigned char nan_bytes[] = {0x7f, 0xc0, 0, 0};
- #else
- const unsigned char nan_bytes[] = {0, 0, 0xc0, 0x7f};
- #endif
- float nan_float32;
- memcpy(&nan_float32, nan_bytes, 4);
- if (td->td_planarconfig == PLANARCONFIG_SEPARATE ||
- td->td_samplesperpixel == 1)
- {
- if (td->td_bitspersample == 32)
- {
- for (i = 0; i < nb_pixels; i++)
- {
- if (sp->mask_buffer[i] == 0)
- ((float *)sp->uncompressed_buffer)[i] = nan_float32;
- }
- }
- else
- {
- const double nan_float64 = nan_float32;
- for (i = 0; i < nb_pixels; i++)
- {
- if (sp->mask_buffer[i] == 0)
- ((double *)sp->uncompressed_buffer)[i] = nan_float64;
- }
- }
- }
- else if (nRequestedMasks == 1)
- {
- assert(nFoundDims == td->td_samplesperpixel);
- assert(nFoundBands == 1);
- unsigned k = 0;
- if (td->td_bitspersample == 32)
- {
- for (i = 0; i < nb_pixels; i++)
- {
- for (int j = 0; j < td->td_samplesperpixel; j++)
- {
- if (sp->mask_buffer[i] == 0)
- ((float *)sp->uncompressed_buffer)[k] = nan_float32;
- ++k;
- }
- }
- }
- else
- {
- const double nan_float64 = nan_float32;
- for (i = 0; i < nb_pixels; i++)
- {
- for (int j = 0; j < td->td_samplesperpixel; j++)
- {
- if (sp->mask_buffer[i] == 0)
- ((double *)sp->uncompressed_buffer)[k] =
- nan_float64;
- ++k;
- }
- }
- }
- }
- #if LERC_AT_LEAST_VERSION(3, 0, 0)
- else
- {
- assert(nRequestedMasks == td->td_samplesperpixel);
- assert(nFoundDims == 1);
- assert(nFoundBands == td->td_samplesperpixel);
- unsigned k = 0;
- if (td->td_bitspersample == 32)
- {
- for (i = 0; i < nb_pixels; i++)
- {
- for (int j = 0; j < td->td_samplesperpixel; j++)
- {
- if (sp->mask_buffer[i + j * nb_pixels] == 0)
- ((float *)sp->uncompressed_buffer)[k] = nan_float32;
- else
- ((float *)sp->uncompressed_buffer)[k] =
- ((float *)sp->uncompressed_buffer_multiband)
- [i + j * nb_pixels];
- ++k;
- }
- }
- }
- else
- {
- const double nan_float64 = nan_float32;
- for (i = 0; i < nb_pixels; i++)
- {
- for (int j = 0; j < td->td_samplesperpixel; j++)
- {
- if (sp->mask_buffer[i + j * nb_pixels] == 0)
- ((double *)sp->uncompressed_buffer)[k] =
- nan_float64;
- else
- ((double *)sp->uncompressed_buffer)[k] =
- ((double *)sp->uncompressed_buffer_multiband)
- [i + j * nb_pixels];
- ++k;
- }
- }
- }
- }
- #endif
- }
- return 1;
- }
- /*
- * Decode a strip, tile or scanline.
- */
- static int LERCDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
- {
- static const char module[] = "LERCDecode";
- LERCState *sp = LERCDecoderState(tif);
- (void)s;
- assert(sp != NULL);
- assert(sp->state == LSTATE_INIT_DECODE);
- if (sp->uncompressed_buffer == 0)
- {
- memset(op, 0, (size_t)occ);
- TIFFErrorExtR(tif, module, "Uncompressed buffer not allocated");
- return 0;
- }
- if ((uint64_t)sp->uncompressed_offset + (uint64_t)occ >
- sp->uncompressed_size)
- {
- memset(op, 0, (size_t)occ);
- TIFFErrorExtR(tif, module, "Too many bytes read");
- return 0;
- }
- memcpy(op, sp->uncompressed_buffer + sp->uncompressed_offset, occ);
- sp->uncompressed_offset += (unsigned)occ;
- return 1;
- }
- static int LERCSetupEncode(TIFF *tif)
- {
- LERCState *sp = LERCEncoderState(tif);
- assert(sp != NULL);
- if (sp->state & LSTATE_INIT_DECODE)
- {
- sp->state = 0;
- }
- sp->state |= LSTATE_INIT_ENCODE;
- return 1;
- }
- /*
- * Reset encoding state at the start of a strip.
- */
- static int LERCPreEncode(TIFF *tif, uint16_t s)
- {
- static const char module[] = "LERCPreEncode";
- LERCState *sp = LERCEncoderState(tif);
- int lerc_data_type;
- (void)s;
- assert(sp != NULL);
- if (sp->state != LSTATE_INIT_ENCODE)
- tif->tif_setupencode(tif);
- lerc_data_type = GetLercDataType(tif);
- if (lerc_data_type < 0)
- return 0;
- if (!SetupBuffers(tif, sp, module))
- return 0;
- return 1;
- }
- /*
- * Encode a chunk of pixels.
- */
- static int LERCEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s)
- {
- static const char module[] = "LERCEncode";
- LERCState *sp = LERCEncoderState(tif);
- (void)s;
- assert(sp != NULL);
- assert(sp->state == LSTATE_INIT_ENCODE);
- if ((uint64_t)sp->uncompressed_offset + (uint64_t)cc >
- sp->uncompressed_size)
- {
- TIFFErrorExtR(tif, module, "Too many bytes written");
- return 0;
- }
- memcpy(sp->uncompressed_buffer + sp->uncompressed_offset, bp, cc);
- sp->uncompressed_offset += (unsigned)cc;
- return 1;
- }
- /*
- * Finish off an encoded strip by flushing it.
- */
- static int LERCPostEncode(TIFF *tif)
- {
- lerc_status lerc_ret;
- static const char module[] = "LERCPostEncode";
- LERCState *sp = LERCEncoderState(tif);
- unsigned int numBytesWritten = 0;
- TIFFDirectory *td = &tif->tif_dir;
- int use_mask = 0;
- unsigned dst_nbands = td->td_samplesperpixel;
- if (sp->uncompressed_offset != sp->uncompressed_size)
- {
- TIFFErrorExtR(tif, module, "Unexpected number of bytes in the buffer");
- return 0;
- }
- int mask_count = 1;
- const unsigned nb_pixels = sp->segment_width * sp->segment_height;
- /* Extract alpha mask (if containing only 0 and 255 values, */
- /* and compact array of regular bands */
- if (td->td_planarconfig == PLANARCONFIG_CONTIG && td->td_extrasamples > 0 &&
- td->td_sampleinfo[td->td_extrasamples - 1] == EXTRASAMPLE_UNASSALPHA &&
- GetLercDataType(tif) == 1)
- {
- const unsigned dst_stride =
- (td->td_samplesperpixel - 1) * (td->td_bitspersample / 8);
- const unsigned src_stride =
- td->td_samplesperpixel * (td->td_bitspersample / 8);
- unsigned i = 0;
- use_mask = 1;
- for (i = 0; i < nb_pixels; i++)
- {
- int v = sp->uncompressed_buffer[i * src_stride +
- td->td_samplesperpixel - 1];
- if (v != 0 && v != 255)
- {
- use_mask = 0;
- break;
- }
- }
- if (use_mask)
- {
- dst_nbands--;
- /* First pixels must use memmove due to overlapping areas */
- for (i = 0; i < dst_nbands && i < nb_pixels; i++)
- {
- memmove(sp->uncompressed_buffer + i * dst_stride,
- sp->uncompressed_buffer + i * src_stride, dst_stride);
- sp->mask_buffer[i] =
- sp->uncompressed_buffer[i * src_stride +
- td->td_samplesperpixel - 1];
- }
- for (; i < nb_pixels; i++)
- {
- memcpy(sp->uncompressed_buffer + i * dst_stride,
- sp->uncompressed_buffer + i * src_stride, dst_stride);
- sp->mask_buffer[i] =
- sp->uncompressed_buffer[i * src_stride +
- td->td_samplesperpixel - 1];
- }
- }
- }
- else if (td->td_sampleformat == SAMPLEFORMAT_IEEEFP &&
- (td->td_bitspersample == 32 || td->td_bitspersample == 64))
- {
- /* Check for NaN values */
- unsigned i;
- if (td->td_bitspersample == 32)
- {
- if (td->td_planarconfig == PLANARCONFIG_CONTIG && dst_nbands > 1)
- {
- unsigned k = 0;
- for (i = 0; i < nb_pixels; i++)
- {
- int count_nan = 0;
- for (int j = 0; j < td->td_samplesperpixel; ++j)
- {
- const float val = ((float *)sp->uncompressed_buffer)[k];
- ++k;
- if (val != val)
- {
- ++count_nan;
- }
- }
- if (count_nan > 0)
- {
- use_mask = 1;
- if (count_nan < td->td_samplesperpixel)
- {
- mask_count = td->td_samplesperpixel;
- break;
- }
- }
- }
- }
- else
- {
- for (i = 0; i < nb_pixels; i++)
- {
- const float val = ((float *)sp->uncompressed_buffer)[i];
- if (val != val)
- {
- use_mask = 1;
- break;
- }
- }
- }
- }
- else
- {
- if (td->td_planarconfig == PLANARCONFIG_CONTIG && dst_nbands > 1)
- {
- unsigned k = 0;
- for (i = 0; i < nb_pixels; i++)
- {
- int count_nan = 0;
- for (int j = 0; j < td->td_samplesperpixel; ++j)
- {
- const double val =
- ((double *)sp->uncompressed_buffer)[k];
- ++k;
- if (val != val)
- {
- ++count_nan;
- }
- }
- if (count_nan > 0)
- {
- use_mask = 1;
- if (count_nan < td->td_samplesperpixel)
- {
- mask_count = td->td_samplesperpixel;
- break;
- }
- }
- }
- }
- else
- {
- for (i = 0; i < nb_pixels; i++)
- {
- const double val = ((double *)sp->uncompressed_buffer)[i];
- if (val != val)
- {
- use_mask = 1;
- break;
- }
- }
- }
- }
- if (use_mask)
- {
- if (mask_count > 1)
- {
- #if LERC_AT_LEAST_VERSION(3, 0, 0)
- unsigned int num_bytes_needed =
- nb_pixels * dst_nbands * (td->td_bitspersample / 8);
- if (sp->uncompressed_buffer_multiband_alloc < num_bytes_needed)
- {
- _TIFFfreeExt(tif, sp->uncompressed_buffer_multiband);
- sp->uncompressed_buffer_multiband =
- _TIFFmallocExt(tif, num_bytes_needed);
- if (!sp->uncompressed_buffer_multiband)
- {
- sp->uncompressed_buffer_multiband_alloc = 0;
- return 0;
- }
- sp->uncompressed_buffer_multiband_alloc = num_bytes_needed;
- }
- unsigned k = 0;
- if (td->td_bitspersample == 32)
- {
- for (i = 0; i < nb_pixels; i++)
- {
- for (int j = 0; j < td->td_samplesperpixel; ++j)
- {
- const float val =
- ((float *)sp->uncompressed_buffer)[k];
- ((float *)sp->uncompressed_buffer_multiband)
- [i + j * nb_pixels] = val;
- ++k;
- sp->mask_buffer[i + j * nb_pixels] =
- (val == val) ? 255 : 0;
- }
- }
- }
- else
- {
- for (i = 0; i < nb_pixels; i++)
- {
- for (int j = 0; j < td->td_samplesperpixel; ++j)
- {
- const double val =
- ((double *)sp->uncompressed_buffer)[k];
- ((double *)sp->uncompressed_buffer_multiband)
- [i + j * nb_pixels] = val;
- ++k;
- sp->mask_buffer[i + j * nb_pixels] =
- (val == val) ? 255 : 0;
- }
- }
- }
- #else
- TIFFErrorExtR(tif, module,
- "lerc_encode() would need to create one mask per "
- "sample, but this requires liblerc >= 3.0");
- return 0;
- #endif
- }
- else if (td->td_planarconfig == PLANARCONFIG_CONTIG &&
- dst_nbands > 1)
- {
- if (td->td_bitspersample == 32)
- {
- for (i = 0; i < nb_pixels; i++)
- {
- const float val =
- ((float *)sp->uncompressed_buffer)[i * dst_nbands];
- sp->mask_buffer[i] = (val == val) ? 255 : 0;
- }
- }
- else
- {
- for (i = 0; i < nb_pixels; i++)
- {
- const double val =
- ((double *)sp->uncompressed_buffer)[i * dst_nbands];
- sp->mask_buffer[i] = (val == val) ? 255 : 0;
- }
- }
- }
- else
- {
- if (td->td_bitspersample == 32)
- {
- for (i = 0; i < nb_pixels; i++)
- {
- const float val = ((float *)sp->uncompressed_buffer)[i];
- sp->mask_buffer[i] = (val == val) ? 255 : 0;
- }
- }
- else
- {
- for (i = 0; i < nb_pixels; i++)
- {
- const double val =
- ((double *)sp->uncompressed_buffer)[i];
- sp->mask_buffer[i] = (val == val) ? 255 : 0;
- }
- }
- }
- }
- }
- unsigned int estimated_compressed_size = sp->uncompressed_alloc;
- #if LERC_AT_LEAST_VERSION(3, 0, 0)
- if (mask_count > 1)
- {
- estimated_compressed_size += nb_pixels * mask_count / 8;
- }
- #endif
- if (sp->compressed_size < estimated_compressed_size)
- {
- _TIFFfreeExt(tif, sp->compressed_buffer);
- sp->compressed_buffer = _TIFFmallocExt(tif, estimated_compressed_size);
- if (!sp->compressed_buffer)
- {
- sp->compressed_size = 0;
- return 0;
- }
- sp->compressed_size = estimated_compressed_size;
- }
- #if LERC_AT_LEAST_VERSION(3, 0, 0)
- if (mask_count > 1)
- {
- lerc_ret = lerc_encodeForVersion(
- sp->uncompressed_buffer_multiband, sp->lerc_version,
- GetLercDataType(tif), 1, sp->segment_width, sp->segment_height,
- dst_nbands, dst_nbands, sp->mask_buffer, sp->maxzerror,
- sp->compressed_buffer, sp->compressed_size, &numBytesWritten);
- }
- else
- #endif
- {
- lerc_ret = lerc_encodeForVersion(
- sp->uncompressed_buffer, sp->lerc_version, GetLercDataType(tif),
- td->td_planarconfig == PLANARCONFIG_CONTIG ? dst_nbands : 1,
- sp->segment_width, sp->segment_height, 1,
- #if LERC_AT_LEAST_VERSION(3, 0, 0)
- use_mask ? 1 : 0,
- #endif
- use_mask ? sp->mask_buffer : NULL, sp->maxzerror,
- sp->compressed_buffer, sp->compressed_size, &numBytesWritten);
- }
- if (lerc_ret != 0)
- {
- TIFFErrorExtR(tif, module, "lerc_encode() failed");
- return 0;
- }
- assert(numBytesWritten < estimated_compressed_size);
- if (sp->additional_compression == LERC_ADD_COMPRESSION_DEFLATE)
- {
- #if LIBDEFLATE_SUPPORT
- if (sp->libdeflate_enc == NULL)
- {
- /* To get results as good as zlib, we ask for an extra */
- /* level of compression */
- sp->libdeflate_enc = libdeflate_alloc_compressor(
- sp->zipquality == Z_DEFAULT_COMPRESSION ? 7
- : sp->zipquality >= 6 && sp->zipquality <= 9
- ? sp->zipquality + 1
- : sp->zipquality);
- if (sp->libdeflate_enc == NULL)
- {
- TIFFErrorExtR(tif, module, "Cannot allocate compressor");
- return 0;
- }
- }
- /* Should not happen normally */
- if (libdeflate_zlib_compress_bound(
- sp->libdeflate_enc, numBytesWritten) > sp->uncompressed_alloc)
- {
- TIFFErrorExtR(tif, module,
- "Output buffer for libdeflate too small");
- return 0;
- }
- tif->tif_rawcc = libdeflate_zlib_compress(
- sp->libdeflate_enc, sp->compressed_buffer, numBytesWritten,
- sp->uncompressed_buffer, sp->uncompressed_alloc);
- if (tif->tif_rawcc == 0)
- {
- TIFFErrorExtR(tif, module, "Encoder error at scanline %lu",
- (unsigned long)tif->tif_row);
- return 0;
- }
- #else
- z_stream strm;
- int zlib_ret;
- int cappedQuality = sp->zipquality;
- if (cappedQuality > Z_BEST_COMPRESSION)
- cappedQuality = Z_BEST_COMPRESSION;
- memset(&strm, 0, sizeof(strm));
- strm.zalloc = NULL;
- strm.zfree = NULL;
- strm.opaque = NULL;
- zlib_ret = deflateInit(&strm, cappedQuality);
- if (zlib_ret != Z_OK)
- {
- TIFFErrorExtR(tif, module, "deflateInit() failed");
- return 0;
- }
- strm.avail_in = numBytesWritten;
- strm.next_in = sp->compressed_buffer;
- strm.avail_out = sp->uncompressed_alloc;
- strm.next_out = sp->uncompressed_buffer;
- zlib_ret = deflate(&strm, Z_FINISH);
- if (zlib_ret == Z_STREAM_END)
- {
- tif->tif_rawcc = sp->uncompressed_alloc - strm.avail_out;
- }
- deflateEnd(&strm);
- if (zlib_ret != Z_STREAM_END)
- {
- TIFFErrorExtR(tif, module, "deflate() failed");
- return 0;
- }
- #endif
- {
- int ret;
- uint8_t *tif_rawdata_backup = tif->tif_rawdata;
- tif->tif_rawdata = sp->uncompressed_buffer;
- ret = TIFFFlushData1(tif);
- tif->tif_rawdata = tif_rawdata_backup;
- if (!ret)
- {
- return 0;
- }
- }
- }
- else if (sp->additional_compression == LERC_ADD_COMPRESSION_ZSTD)
- {
- #ifdef ZSTD_SUPPORT
- size_t zstd_ret = ZSTD_compress(
- sp->uncompressed_buffer, sp->uncompressed_alloc,
- sp->compressed_buffer, numBytesWritten, sp->zstd_compress_level);
- if (ZSTD_isError(zstd_ret))
- {
- TIFFErrorExtR(tif, module, "Error in ZSTD_compress(): %s",
- ZSTD_getErrorName(zstd_ret));
- return 0;
- }
- {
- int ret;
- uint8_t *tif_rawdata_backup = tif->tif_rawdata;
- tif->tif_rawdata = sp->uncompressed_buffer;
- tif->tif_rawcc = zstd_ret;
- ret = TIFFFlushData1(tif);
- tif->tif_rawdata = tif_rawdata_backup;
- if (!ret)
- {
- return 0;
- }
- }
- #else
- TIFFErrorExtR(tif, module, "ZSTD support missing");
- return 0;
- #endif
- }
- else if (sp->additional_compression != LERC_ADD_COMPRESSION_NONE)
- {
- TIFFErrorExtR(tif, module, "Unhandled additional compression");
- return 0;
- }
- else
- {
- int ret;
- uint8_t *tif_rawdata_backup = tif->tif_rawdata;
- tif->tif_rawdata = sp->compressed_buffer;
- tif->tif_rawcc = numBytesWritten;
- ret = TIFFFlushData1(tif);
- tif->tif_rawdata = tif_rawdata_backup;
- if (!ret)
- return 0;
- }
- return 1;
- }
- static void LERCCleanup(TIFF *tif)
- {
- LERCState *sp = GetLERCState(tif);
- assert(sp != 0);
- tif->tif_tagmethods.vgetfield = sp->vgetparent;
- tif->tif_tagmethods.vsetfield = sp->vsetparent;
- _TIFFfreeExt(tif, sp->uncompressed_buffer);
- _TIFFfreeExt(tif, sp->uncompressed_buffer_multiband);
- _TIFFfreeExt(tif, sp->compressed_buffer);
- _TIFFfreeExt(tif, sp->mask_buffer);
- #if LIBDEFLATE_SUPPORT
- if (sp->libdeflate_dec)
- libdeflate_free_decompressor(sp->libdeflate_dec);
- if (sp->libdeflate_enc)
- libdeflate_free_compressor(sp->libdeflate_enc);
- #endif
- _TIFFfreeExt(tif, sp);
- tif->tif_data = NULL;
- _TIFFSetDefaultCompressionState(tif);
- }
- static const TIFFField LERCFields[] = {
- {TIFFTAG_LERC_PARAMETERS, TIFF_VARIABLE2, TIFF_VARIABLE2, TIFF_LONG, 0,
- TIFF_SETGET_C32_UINT32, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, FALSE, TRUE,
- "LercParameters", NULL},
- {TIFFTAG_LERC_MAXZERROR, 0, 0, TIFF_ANY, 0, TIFF_SETGET_DOUBLE,
- TIFF_SETGET_UNDEFINED, FIELD_PSEUDO, TRUE, FALSE, "LercMaximumError",
- NULL},
- {TIFFTAG_LERC_VERSION, 0, 0, TIFF_ANY, 0, TIFF_SETGET_UINT32,
- TIFF_SETGET_UNDEFINED, FIELD_PSEUDO, FALSE, FALSE, "LercVersion", NULL},
- {TIFFTAG_LERC_ADD_COMPRESSION, 0, 0, TIFF_ANY, 0, TIFF_SETGET_UINT32,
- TIFF_SETGET_UNDEFINED, FIELD_PSEUDO, FALSE, FALSE,
- "LercAdditionalCompression", NULL},
- {TIFFTAG_ZSTD_LEVEL, 0, 0, TIFF_ANY, 0, TIFF_SETGET_INT,
- TIFF_SETGET_UNDEFINED, FIELD_PSEUDO, TRUE, FALSE,
- "ZSTD zstd_compress_level", NULL},
- {TIFFTAG_ZIPQUALITY, 0, 0, TIFF_ANY, 0, TIFF_SETGET_INT,
- TIFF_SETGET_UNDEFINED, FIELD_PSEUDO, TRUE, FALSE, "", NULL},
- };
- static int LERCVSetFieldBase(TIFF *tif, uint32_t tag, ...)
- {
- LERCState *sp = GetLERCState(tif);
- int ret;
- va_list ap;
- va_start(ap, tag);
- ret = (*sp->vsetparent)(tif, tag, ap);
- va_end(ap);
- return ret;
- }
- static int LERCVSetField(TIFF *tif, uint32_t tag, va_list ap)
- {
- static const char module[] = "LERCVSetField";
- LERCState *sp = GetLERCState(tif);
- switch (tag)
- {
- case TIFFTAG_LERC_PARAMETERS:
- {
- uint32_t count = va_arg(ap, int);
- int *params = va_arg(ap, int *);
- if (count < 2)
- {
- TIFFErrorExtR(tif, module,
- "Invalid count for LercParameters: %u", count);
- return 0;
- }
- sp->lerc_version = params[0];
- sp->additional_compression = params[1];
- return LERCVSetFieldBase(tif, TIFFTAG_LERC_PARAMETERS, count,
- params);
- }
- case TIFFTAG_LERC_MAXZERROR:
- sp->maxzerror = va_arg(ap, double);
- return 1;
- case TIFFTAG_LERC_VERSION:
- {
- int params[2] = {0, 0};
- int version = va_arg(ap, int);
- if (version != LERC_VERSION_2_4)
- {
- TIFFErrorExtR(tif, module, "Invalid value for LercVersion: %d",
- version);
- return 0;
- }
- sp->lerc_version = version;
- params[0] = sp->lerc_version;
- params[1] = sp->additional_compression;
- return LERCVSetFieldBase(tif, TIFFTAG_LERC_PARAMETERS, 2, params);
- }
- case TIFFTAG_LERC_ADD_COMPRESSION:
- {
- int params[2] = {0, 0};
- int additional_compression = va_arg(ap, int);
- #ifndef ZSTD_SUPPORT
- if (additional_compression == LERC_ADD_COMPRESSION_ZSTD)
- {
- TIFFErrorExtR(tif, module,
- "LERC_ZSTD requested, but ZSTD not available");
- return 0;
- }
- #endif
- if (additional_compression != LERC_ADD_COMPRESSION_NONE &&
- additional_compression != LERC_ADD_COMPRESSION_DEFLATE &&
- additional_compression != LERC_ADD_COMPRESSION_ZSTD)
- {
- TIFFErrorExtR(tif, module,
- "Invalid value for LercAdditionalCompression: %d",
- additional_compression);
- return 0;
- }
- sp->additional_compression = additional_compression;
- params[0] = sp->lerc_version;
- params[1] = sp->additional_compression;
- return LERCVSetFieldBase(tif, TIFFTAG_LERC_PARAMETERS, 2, params);
- }
- #ifdef ZSTD_SUPPORT
- case TIFFTAG_ZSTD_LEVEL:
- {
- sp->zstd_compress_level = (int)va_arg(ap, int);
- if (sp->zstd_compress_level <= 0 ||
- sp->zstd_compress_level > ZSTD_maxCLevel())
- {
- TIFFWarningExtR(tif, module,
- "ZSTD_LEVEL should be between 1 and %d",
- ZSTD_maxCLevel());
- }
- return 1;
- }
- #endif
- case TIFFTAG_ZIPQUALITY:
- {
- sp->zipquality = (int)va_arg(ap, int);
- if (sp->zipquality < Z_DEFAULT_COMPRESSION ||
- sp->zipquality > LIBDEFLATE_MAX_COMPRESSION_LEVEL)
- {
- TIFFErrorExtR(
- tif, module,
- "Invalid ZipQuality value. Should be in [-1,%d] range",
- LIBDEFLATE_MAX_COMPRESSION_LEVEL);
- return 0;
- }
- #if LIBDEFLATE_SUPPORT
- if (sp->libdeflate_enc)
- {
- libdeflate_free_compressor(sp->libdeflate_enc);
- sp->libdeflate_enc = NULL;
- }
- #endif
- return (1);
- }
- default:
- return (*sp->vsetparent)(tif, tag, ap);
- }
- /*NOTREACHED*/
- }
- static int LERCVGetField(TIFF *tif, uint32_t tag, va_list ap)
- {
- LERCState *sp = GetLERCState(tif);
- switch (tag)
- {
- case TIFFTAG_LERC_MAXZERROR:
- *va_arg(ap, double *) = sp->maxzerror;
- break;
- case TIFFTAG_LERC_VERSION:
- *va_arg(ap, int *) = sp->lerc_version;
- break;
- case TIFFTAG_LERC_ADD_COMPRESSION:
- *va_arg(ap, int *) = sp->additional_compression;
- break;
- case TIFFTAG_ZSTD_LEVEL:
- *va_arg(ap, int *) = sp->zstd_compress_level;
- break;
- case TIFFTAG_ZIPQUALITY:
- *va_arg(ap, int *) = sp->zipquality;
- break;
- default:
- return (*sp->vgetparent)(tif, tag, ap);
- }
- return 1;
- }
- int TIFFInitLERC(TIFF *tif, int scheme)
- {
- static const char module[] = "TIFFInitLERC";
- LERCState *sp;
- (void)scheme;
- assert(scheme == COMPRESSION_LERC);
- /*
- * Merge codec-specific tag information.
- */
- if (!_TIFFMergeFields(tif, LERCFields, TIFFArrayCount(LERCFields)))
- {
- TIFFErrorExtR(tif, module, "Merging LERC codec-specific tags failed");
- return 0;
- }
- /*
- * Allocate state block so tag methods have storage to record values.
- */
- tif->tif_data = (uint8_t *)_TIFFcallocExt(tif, 1, sizeof(LERCState));
- if (tif->tif_data == NULL)
- goto bad;
- sp = GetLERCState(tif);
- /*
- * Override parent get/set field methods.
- */
- sp->vgetparent = tif->tif_tagmethods.vgetfield;
- tif->tif_tagmethods.vgetfield = LERCVGetField; /* hook for codec tags */
- sp->vsetparent = tif->tif_tagmethods.vsetfield;
- tif->tif_tagmethods.vsetfield = LERCVSetField; /* hook for codec tags */
- /*
- * Install codec methods.
- */
- tif->tif_fixuptags = LERCFixupTags;
- tif->tif_setupdecode = LERCSetupDecode;
- tif->tif_predecode = LERCPreDecode;
- tif->tif_decoderow = LERCDecode;
- tif->tif_decodestrip = LERCDecode;
- tif->tif_decodetile = LERCDecode;
- tif->tif_setupencode = LERCSetupEncode;
- tif->tif_preencode = LERCPreEncode;
- tif->tif_postencode = LERCPostEncode;
- tif->tif_encoderow = LERCEncode;
- tif->tif_encodestrip = LERCEncode;
- tif->tif_encodetile = LERCEncode;
- tif->tif_cleanup = LERCCleanup;
- /* Default values for codec-specific fields */
- TIFFSetField(tif, TIFFTAG_LERC_VERSION, LERC_VERSION_2_4);
- TIFFSetField(tif, TIFFTAG_LERC_ADD_COMPRESSION, LERC_ADD_COMPRESSION_NONE);
- sp->maxzerror = 0.0;
- sp->zstd_compress_level = 9; /* default comp. level */
- sp->zipquality = Z_DEFAULT_COMPRESSION; /* default comp. level */
- sp->state = 0;
- return 1;
- bad:
- TIFFErrorExtR(tif, module, "No space for LERC state block");
- return 0;
- }
- #endif /* LERC_SUPPORT */
|