xref: /reactos/dll/3rdparty/libtiff/tif_zstd.c (revision 743951ec)
1*743951ecSThomas Faber /*
2*743951ecSThomas Faber * Copyright (c) 2017, Planet Labs
3*743951ecSThomas Faber * Author: <even.rouault at spatialys.com>
4*743951ecSThomas Faber *
5*743951ecSThomas Faber * Permission to use, copy, modify, distribute, and sell this software and
6*743951ecSThomas Faber * its documentation for any purpose is hereby granted without fee, provided
7*743951ecSThomas Faber * that (i) the above copyright notices and this permission notice appear in
8*743951ecSThomas Faber * all copies of the software and related documentation, and (ii) the names of
9*743951ecSThomas Faber * Sam Leffler and Silicon Graphics may not be used in any advertising or
10*743951ecSThomas Faber * publicity relating to the software without the specific, prior written
11*743951ecSThomas Faber * permission of Sam Leffler and Silicon Graphics.
12*743951ecSThomas Faber *
13*743951ecSThomas Faber * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
14*743951ecSThomas Faber * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
15*743951ecSThomas Faber * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
16*743951ecSThomas Faber *
17*743951ecSThomas Faber * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
18*743951ecSThomas Faber * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
19*743951ecSThomas Faber * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
20*743951ecSThomas Faber * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
21*743951ecSThomas Faber * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
22*743951ecSThomas Faber * OF THIS SOFTWARE.
23*743951ecSThomas Faber */
24*743951ecSThomas Faber 
25*743951ecSThomas Faber #include "tiffiop.h"
26*743951ecSThomas Faber #ifdef ZSTD_SUPPORT
27*743951ecSThomas Faber /*
28*743951ecSThomas Faber * TIFF Library.
29*743951ecSThomas Faber *
30*743951ecSThomas Faber * ZSTD Compression Support
31*743951ecSThomas Faber *
32*743951ecSThomas Faber */
33*743951ecSThomas Faber 
34*743951ecSThomas Faber #include "tif_predict.h"
35*743951ecSThomas Faber #include "zstd.h"
36*743951ecSThomas Faber 
37*743951ecSThomas Faber #include <stdio.h>
38*743951ecSThomas Faber 
39*743951ecSThomas Faber /*
40*743951ecSThomas Faber * State block for each open TIFF file using ZSTD compression/decompression.
41*743951ecSThomas Faber */
42*743951ecSThomas Faber typedef struct {
43*743951ecSThomas Faber         TIFFPredictorState predict;
44*743951ecSThomas Faber         ZSTD_DStream*   dstream;
45*743951ecSThomas Faber         ZSTD_CStream*   cstream;
46*743951ecSThomas Faber         int             compression_level;      /* compression level */
47*743951ecSThomas Faber         ZSTD_outBuffer  out_buffer;
48*743951ecSThomas Faber         int             state;                  /* state flags */
49*743951ecSThomas Faber #define LSTATE_INIT_DECODE 0x01
50*743951ecSThomas Faber #define LSTATE_INIT_ENCODE 0x02
51*743951ecSThomas Faber 
52*743951ecSThomas Faber         TIFFVGetMethod  vgetparent;            /* super-class method */
53*743951ecSThomas Faber         TIFFVSetMethod  vsetparent;            /* super-class method */
54*743951ecSThomas Faber } ZSTDState;
55*743951ecSThomas Faber 
56*743951ecSThomas Faber #define LState(tif)             ((ZSTDState*) (tif)->tif_data)
57*743951ecSThomas Faber #define DecoderState(tif)       LState(tif)
58*743951ecSThomas Faber #define EncoderState(tif)       LState(tif)
59*743951ecSThomas Faber 
60*743951ecSThomas Faber static int ZSTDEncode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s);
61*743951ecSThomas Faber static int ZSTDDecode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s);
62*743951ecSThomas Faber 
63*743951ecSThomas Faber static int
ZSTDFixupTags(TIFF * tif)64*743951ecSThomas Faber ZSTDFixupTags(TIFF* tif)
65*743951ecSThomas Faber {
66*743951ecSThomas Faber         (void) tif;
67*743951ecSThomas Faber         return 1;
68*743951ecSThomas Faber }
69*743951ecSThomas Faber 
70*743951ecSThomas Faber static int
ZSTDSetupDecode(TIFF * tif)71*743951ecSThomas Faber ZSTDSetupDecode(TIFF* tif)
72*743951ecSThomas Faber {
73*743951ecSThomas Faber         ZSTDState* sp = DecoderState(tif);
74*743951ecSThomas Faber 
75*743951ecSThomas Faber         assert(sp != NULL);
76*743951ecSThomas Faber 
77*743951ecSThomas Faber         /* if we were last encoding, terminate this mode */
78*743951ecSThomas Faber         if (sp->state & LSTATE_INIT_ENCODE) {
79*743951ecSThomas Faber             ZSTD_freeCStream(sp->cstream);
80*743951ecSThomas Faber             sp->cstream = NULL;
81*743951ecSThomas Faber             sp->state = 0;
82*743951ecSThomas Faber         }
83*743951ecSThomas Faber 
84*743951ecSThomas Faber         sp->state |= LSTATE_INIT_DECODE;
85*743951ecSThomas Faber         return 1;
86*743951ecSThomas Faber }
87*743951ecSThomas Faber 
88*743951ecSThomas Faber /*
89*743951ecSThomas Faber * Setup state for decoding a strip.
90*743951ecSThomas Faber */
91*743951ecSThomas Faber static int
ZSTDPreDecode(TIFF * tif,uint16 s)92*743951ecSThomas Faber ZSTDPreDecode(TIFF* tif, uint16 s)
93*743951ecSThomas Faber {
94*743951ecSThomas Faber         static const char module[] = "ZSTDPreDecode";
95*743951ecSThomas Faber         ZSTDState* sp = DecoderState(tif);
96*743951ecSThomas Faber         size_t zstd_ret;
97*743951ecSThomas Faber 
98*743951ecSThomas Faber         (void) s;
99*743951ecSThomas Faber         assert(sp != NULL);
100*743951ecSThomas Faber 
101*743951ecSThomas Faber         if( (sp->state & LSTATE_INIT_DECODE) == 0 )
102*743951ecSThomas Faber             tif->tif_setupdecode(tif);
103*743951ecSThomas Faber 
104*743951ecSThomas Faber         if( sp->dstream )
105*743951ecSThomas Faber         {
106*743951ecSThomas Faber             ZSTD_freeDStream(sp->dstream);
107*743951ecSThomas Faber             sp->dstream = NULL;
108*743951ecSThomas Faber         }
109*743951ecSThomas Faber 
110*743951ecSThomas Faber         sp->dstream = ZSTD_createDStream();
111*743951ecSThomas Faber         if( sp->dstream == NULL ) {
112*743951ecSThomas Faber             TIFFErrorExt(tif->tif_clientdata, module,
113*743951ecSThomas Faber                          "Cannot allocate decompression stream");
114*743951ecSThomas Faber             return 0;
115*743951ecSThomas Faber         }
116*743951ecSThomas Faber         zstd_ret = ZSTD_initDStream(sp->dstream);
117*743951ecSThomas Faber         if( ZSTD_isError(zstd_ret) ) {
118*743951ecSThomas Faber             TIFFErrorExt(tif->tif_clientdata, module,
119*743951ecSThomas Faber                          "Error in ZSTD_initDStream(): %s",
120*743951ecSThomas Faber                          ZSTD_getErrorName(zstd_ret));
121*743951ecSThomas Faber             return 0;
122*743951ecSThomas Faber         }
123*743951ecSThomas Faber 
124*743951ecSThomas Faber         return 1;
125*743951ecSThomas Faber }
126*743951ecSThomas Faber 
127*743951ecSThomas Faber static int
ZSTDDecode(TIFF * tif,uint8 * op,tmsize_t occ,uint16 s)128*743951ecSThomas Faber ZSTDDecode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s)
129*743951ecSThomas Faber {
130*743951ecSThomas Faber         static const char module[] = "ZSTDDecode";
131*743951ecSThomas Faber         ZSTDState* sp = DecoderState(tif);
132*743951ecSThomas Faber         ZSTD_inBuffer   in_buffer;
133*743951ecSThomas Faber         ZSTD_outBuffer  out_buffer;
134*743951ecSThomas Faber         size_t          zstd_ret;
135*743951ecSThomas Faber 
136*743951ecSThomas Faber         (void) s;
137*743951ecSThomas Faber         assert(sp != NULL);
138*743951ecSThomas Faber         assert(sp->state == LSTATE_INIT_DECODE);
139*743951ecSThomas Faber 
140*743951ecSThomas Faber         in_buffer.src = tif->tif_rawcp;
141*743951ecSThomas Faber         in_buffer.size = (size_t) tif->tif_rawcc;
142*743951ecSThomas Faber         in_buffer.pos = 0;
143*743951ecSThomas Faber 
144*743951ecSThomas Faber         out_buffer.dst = op;
145*743951ecSThomas Faber         out_buffer.size = (size_t) occ;
146*743951ecSThomas Faber         out_buffer.pos = 0;
147*743951ecSThomas Faber 
148*743951ecSThomas Faber         do {
149*743951ecSThomas Faber                 zstd_ret = ZSTD_decompressStream(sp->dstream, &out_buffer,
150*743951ecSThomas Faber                                                  &in_buffer);
151*743951ecSThomas Faber                 if( ZSTD_isError(zstd_ret) ) {
152*743951ecSThomas Faber                     TIFFErrorExt(tif->tif_clientdata, module,
153*743951ecSThomas Faber                                 "Error in ZSTD_decompressStream(): %s",
154*743951ecSThomas Faber                                 ZSTD_getErrorName(zstd_ret));
155*743951ecSThomas Faber                     return 0;
156*743951ecSThomas Faber                 }
157*743951ecSThomas Faber         } while( zstd_ret != 0 &&
158*743951ecSThomas Faber                  in_buffer.pos < in_buffer.size &&
159*743951ecSThomas Faber                  out_buffer.pos < out_buffer.size );
160*743951ecSThomas Faber 
161*743951ecSThomas Faber         if (out_buffer.pos < (size_t)occ) {
162*743951ecSThomas Faber                 TIFFErrorExt(tif->tif_clientdata, module,
163*743951ecSThomas Faber                     "Not enough data at scanline %lu (short %lu bytes)",
164*743951ecSThomas Faber                     (unsigned long) tif->tif_row,
165*743951ecSThomas Faber                     (unsigned long) (size_t)occ - out_buffer.pos);
166*743951ecSThomas Faber                 return 0;
167*743951ecSThomas Faber         }
168*743951ecSThomas Faber 
169*743951ecSThomas Faber         tif->tif_rawcp += in_buffer.pos;
170*743951ecSThomas Faber         tif->tif_rawcc -= in_buffer.pos;
171*743951ecSThomas Faber 
172*743951ecSThomas Faber         return 1;
173*743951ecSThomas Faber }
174*743951ecSThomas Faber 
175*743951ecSThomas Faber static int
ZSTDSetupEncode(TIFF * tif)176*743951ecSThomas Faber ZSTDSetupEncode(TIFF* tif)
177*743951ecSThomas Faber {
178*743951ecSThomas Faber         ZSTDState* sp = EncoderState(tif);
179*743951ecSThomas Faber 
180*743951ecSThomas Faber         assert(sp != NULL);
181*743951ecSThomas Faber         if (sp->state & LSTATE_INIT_DECODE) {
182*743951ecSThomas Faber                 ZSTD_freeDStream(sp->dstream);
183*743951ecSThomas Faber                 sp->dstream = NULL;
184*743951ecSThomas Faber                 sp->state = 0;
185*743951ecSThomas Faber         }
186*743951ecSThomas Faber 
187*743951ecSThomas Faber         sp->state |= LSTATE_INIT_ENCODE;
188*743951ecSThomas Faber         return 1;
189*743951ecSThomas Faber }
190*743951ecSThomas Faber 
191*743951ecSThomas Faber /*
192*743951ecSThomas Faber * Reset encoding state at the start of a strip.
193*743951ecSThomas Faber */
194*743951ecSThomas Faber static int
ZSTDPreEncode(TIFF * tif,uint16 s)195*743951ecSThomas Faber ZSTDPreEncode(TIFF* tif, uint16 s)
196*743951ecSThomas Faber {
197*743951ecSThomas Faber         static const char module[] = "ZSTDPreEncode";
198*743951ecSThomas Faber         ZSTDState *sp = EncoderState(tif);
199*743951ecSThomas Faber         size_t zstd_ret;
200*743951ecSThomas Faber 
201*743951ecSThomas Faber         (void) s;
202*743951ecSThomas Faber         assert(sp != NULL);
203*743951ecSThomas Faber         if( sp->state != LSTATE_INIT_ENCODE )
204*743951ecSThomas Faber             tif->tif_setupencode(tif);
205*743951ecSThomas Faber 
206*743951ecSThomas Faber         if (sp->cstream) {
207*743951ecSThomas Faber             ZSTD_freeCStream(sp->cstream);
208*743951ecSThomas Faber             sp->cstream = NULL;
209*743951ecSThomas Faber         }
210*743951ecSThomas Faber         sp->cstream = ZSTD_createCStream();
211*743951ecSThomas Faber         if( sp->cstream == NULL ) {
212*743951ecSThomas Faber             TIFFErrorExt(tif->tif_clientdata, module,
213*743951ecSThomas Faber                          "Cannot allocate compression stream");
214*743951ecSThomas Faber             return 0;
215*743951ecSThomas Faber         }
216*743951ecSThomas Faber 
217*743951ecSThomas Faber         zstd_ret = ZSTD_initCStream(sp->cstream, sp->compression_level);
218*743951ecSThomas Faber         if( ZSTD_isError(zstd_ret) ) {
219*743951ecSThomas Faber             TIFFErrorExt(tif->tif_clientdata, module,
220*743951ecSThomas Faber                          "Error in ZSTD_initCStream(): %s",
221*743951ecSThomas Faber                          ZSTD_getErrorName(zstd_ret));
222*743951ecSThomas Faber             return 0;
223*743951ecSThomas Faber         }
224*743951ecSThomas Faber 
225*743951ecSThomas Faber         sp->out_buffer.dst = tif->tif_rawdata;
226*743951ecSThomas Faber         sp->out_buffer.size = (size_t)tif->tif_rawdatasize;
227*743951ecSThomas Faber         sp->out_buffer.pos = 0;
228*743951ecSThomas Faber 
229*743951ecSThomas Faber         return 1;
230*743951ecSThomas Faber }
231*743951ecSThomas Faber 
232*743951ecSThomas Faber /*
233*743951ecSThomas Faber * Encode a chunk of pixels.
234*743951ecSThomas Faber */
235*743951ecSThomas Faber static int
ZSTDEncode(TIFF * tif,uint8 * bp,tmsize_t cc,uint16 s)236*743951ecSThomas Faber ZSTDEncode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
237*743951ecSThomas Faber {
238*743951ecSThomas Faber         static const char module[] = "ZSTDEncode";
239*743951ecSThomas Faber         ZSTDState *sp = EncoderState(tif);
240*743951ecSThomas Faber         ZSTD_inBuffer   in_buffer;
241*743951ecSThomas Faber         size_t          zstd_ret;
242*743951ecSThomas Faber 
243*743951ecSThomas Faber         assert(sp != NULL);
244*743951ecSThomas Faber         assert(sp->state == LSTATE_INIT_ENCODE);
245*743951ecSThomas Faber 
246*743951ecSThomas Faber         (void) s;
247*743951ecSThomas Faber 
248*743951ecSThomas Faber         in_buffer.src = bp;
249*743951ecSThomas Faber         in_buffer.size = (size_t)cc;
250*743951ecSThomas Faber         in_buffer.pos = 0;
251*743951ecSThomas Faber 
252*743951ecSThomas Faber         do {
253*743951ecSThomas Faber                 zstd_ret = ZSTD_compressStream(sp->cstream, &sp->out_buffer,
254*743951ecSThomas Faber                                                &in_buffer);
255*743951ecSThomas Faber                 if( ZSTD_isError(zstd_ret) ) {
256*743951ecSThomas Faber                     TIFFErrorExt(tif->tif_clientdata, module,
257*743951ecSThomas Faber                                 "Error in ZSTD_compressStream(): %s",
258*743951ecSThomas Faber                                 ZSTD_getErrorName(zstd_ret));
259*743951ecSThomas Faber                     return 0;
260*743951ecSThomas Faber                 }
261*743951ecSThomas Faber                 if( sp->out_buffer.pos == sp->out_buffer.size ) {
262*743951ecSThomas Faber                         tif->tif_rawcc = tif->tif_rawdatasize;
263*743951ecSThomas Faber                         TIFFFlushData1(tif);
264*743951ecSThomas Faber                         sp->out_buffer.dst = tif->tif_rawcp;
265*743951ecSThomas Faber                         sp->out_buffer.pos = 0;
266*743951ecSThomas Faber                 }
267*743951ecSThomas Faber         } while( in_buffer.pos < in_buffer.size );
268*743951ecSThomas Faber 
269*743951ecSThomas Faber         return 1;
270*743951ecSThomas Faber }
271*743951ecSThomas Faber 
272*743951ecSThomas Faber /*
273*743951ecSThomas Faber * Finish off an encoded strip by flushing it.
274*743951ecSThomas Faber */
275*743951ecSThomas Faber static int
ZSTDPostEncode(TIFF * tif)276*743951ecSThomas Faber ZSTDPostEncode(TIFF* tif)
277*743951ecSThomas Faber {
278*743951ecSThomas Faber         static const char module[] = "ZSTDPostEncode";
279*743951ecSThomas Faber         ZSTDState *sp = EncoderState(tif);
280*743951ecSThomas Faber         size_t          zstd_ret;
281*743951ecSThomas Faber 
282*743951ecSThomas Faber         do {
283*743951ecSThomas Faber                 zstd_ret = ZSTD_endStream(sp->cstream, &sp->out_buffer);
284*743951ecSThomas Faber                 if( ZSTD_isError(zstd_ret) ) {
285*743951ecSThomas Faber                     TIFFErrorExt(tif->tif_clientdata, module,
286*743951ecSThomas Faber                                 "Error in ZSTD_endStream(): %s",
287*743951ecSThomas Faber                                 ZSTD_getErrorName(zstd_ret));
288*743951ecSThomas Faber                     return 0;
289*743951ecSThomas Faber                 }
290*743951ecSThomas Faber                 if( sp->out_buffer.pos > 0 ) {
291*743951ecSThomas Faber                         tif->tif_rawcc = sp->out_buffer.pos;
292*743951ecSThomas Faber                         TIFFFlushData1(tif);
293*743951ecSThomas Faber                         sp->out_buffer.dst = tif->tif_rawcp;
294*743951ecSThomas Faber                         sp->out_buffer.pos = 0;
295*743951ecSThomas Faber                 }
296*743951ecSThomas Faber         } while (zstd_ret != 0);
297*743951ecSThomas Faber         return 1;
298*743951ecSThomas Faber }
299*743951ecSThomas Faber 
300*743951ecSThomas Faber static void
ZSTDCleanup(TIFF * tif)301*743951ecSThomas Faber ZSTDCleanup(TIFF* tif)
302*743951ecSThomas Faber {
303*743951ecSThomas Faber         ZSTDState* sp = LState(tif);
304*743951ecSThomas Faber 
305*743951ecSThomas Faber         assert(sp != 0);
306*743951ecSThomas Faber 
307*743951ecSThomas Faber         (void)TIFFPredictorCleanup(tif);
308*743951ecSThomas Faber 
309*743951ecSThomas Faber         tif->tif_tagmethods.vgetfield = sp->vgetparent;
310*743951ecSThomas Faber         tif->tif_tagmethods.vsetfield = sp->vsetparent;
311*743951ecSThomas Faber 
312*743951ecSThomas Faber         if (sp->dstream) {
313*743951ecSThomas Faber             ZSTD_freeDStream(sp->dstream);
314*743951ecSThomas Faber             sp->dstream = NULL;
315*743951ecSThomas Faber         }
316*743951ecSThomas Faber         if (sp->cstream) {
317*743951ecSThomas Faber             ZSTD_freeCStream(sp->cstream);
318*743951ecSThomas Faber             sp->cstream = NULL;
319*743951ecSThomas Faber         }
320*743951ecSThomas Faber         _TIFFfree(sp);
321*743951ecSThomas Faber         tif->tif_data = NULL;
322*743951ecSThomas Faber 
323*743951ecSThomas Faber         _TIFFSetDefaultCompressionState(tif);
324*743951ecSThomas Faber }
325*743951ecSThomas Faber 
326*743951ecSThomas Faber static int
ZSTDVSetField(TIFF * tif,uint32 tag,va_list ap)327*743951ecSThomas Faber ZSTDVSetField(TIFF* tif, uint32 tag, va_list ap)
328*743951ecSThomas Faber {
329*743951ecSThomas Faber 	static const char module[] = "ZSTDVSetField";
330*743951ecSThomas Faber         ZSTDState* sp = LState(tif);
331*743951ecSThomas Faber 
332*743951ecSThomas Faber         switch (tag) {
333*743951ecSThomas Faber         case TIFFTAG_ZSTD_LEVEL:
334*743951ecSThomas Faber                 sp->compression_level = (int) va_arg(ap, int);
335*743951ecSThomas Faber                 if( sp->compression_level <= 0 ||
336*743951ecSThomas Faber                     sp->compression_level > ZSTD_maxCLevel() )
337*743951ecSThomas Faber                 {
338*743951ecSThomas Faber                     TIFFWarningExt(tif->tif_clientdata, module,
339*743951ecSThomas Faber                                    "ZSTD_LEVEL should be between 1 and %d",
340*743951ecSThomas Faber                                    ZSTD_maxCLevel());
341*743951ecSThomas Faber                 }
342*743951ecSThomas Faber                 return 1;
343*743951ecSThomas Faber         default:
344*743951ecSThomas Faber                 return (*sp->vsetparent)(tif, tag, ap);
345*743951ecSThomas Faber         }
346*743951ecSThomas Faber         /*NOTREACHED*/
347*743951ecSThomas Faber }
348*743951ecSThomas Faber 
349*743951ecSThomas Faber static int
ZSTDVGetField(TIFF * tif,uint32 tag,va_list ap)350*743951ecSThomas Faber ZSTDVGetField(TIFF* tif, uint32 tag, va_list ap)
351*743951ecSThomas Faber {
352*743951ecSThomas Faber         ZSTDState* sp = LState(tif);
353*743951ecSThomas Faber 
354*743951ecSThomas Faber         switch (tag) {
355*743951ecSThomas Faber         case TIFFTAG_ZSTD_LEVEL:
356*743951ecSThomas Faber                 *va_arg(ap, int*) = sp->compression_level;
357*743951ecSThomas Faber                 break;
358*743951ecSThomas Faber         default:
359*743951ecSThomas Faber                 return (*sp->vgetparent)(tif, tag, ap);
360*743951ecSThomas Faber         }
361*743951ecSThomas Faber         return 1;
362*743951ecSThomas Faber }
363*743951ecSThomas Faber 
364*743951ecSThomas Faber static const TIFFField ZSTDFields[] = {
365*743951ecSThomas Faber         { TIFFTAG_ZSTD_LEVEL, 0, 0, TIFF_ANY, 0, TIFF_SETGET_INT,
366*743951ecSThomas Faber           TIFF_SETGET_UNDEFINED,
367*743951ecSThomas Faber           FIELD_PSEUDO, TRUE, FALSE, "ZSTD compression_level", NULL },
368*743951ecSThomas Faber };
369*743951ecSThomas Faber 
370*743951ecSThomas Faber int
TIFFInitZSTD(TIFF * tif,int scheme)371*743951ecSThomas Faber TIFFInitZSTD(TIFF* tif, int scheme)
372*743951ecSThomas Faber {
373*743951ecSThomas Faber         static const char module[] = "TIFFInitZSTD";
374*743951ecSThomas Faber         ZSTDState* sp;
375*743951ecSThomas Faber 
376*743951ecSThomas Faber         assert( scheme == COMPRESSION_ZSTD );
377*743951ecSThomas Faber 
378*743951ecSThomas Faber         /*
379*743951ecSThomas Faber         * Merge codec-specific tag information.
380*743951ecSThomas Faber         */
381*743951ecSThomas Faber         if (!_TIFFMergeFields(tif, ZSTDFields, TIFFArrayCount(ZSTDFields))) {
382*743951ecSThomas Faber                 TIFFErrorExt(tif->tif_clientdata, module,
383*743951ecSThomas Faber                             "Merging ZSTD codec-specific tags failed");
384*743951ecSThomas Faber                 return 0;
385*743951ecSThomas Faber         }
386*743951ecSThomas Faber 
387*743951ecSThomas Faber         /*
388*743951ecSThomas Faber         * Allocate state block so tag methods have storage to record values.
389*743951ecSThomas Faber         */
390*743951ecSThomas Faber         tif->tif_data = (uint8*) _TIFFmalloc(sizeof(ZSTDState));
391*743951ecSThomas Faber         if (tif->tif_data == NULL)
392*743951ecSThomas Faber                 goto bad;
393*743951ecSThomas Faber         sp = LState(tif);
394*743951ecSThomas Faber 
395*743951ecSThomas Faber         /*
396*743951ecSThomas Faber         * Override parent get/set field methods.
397*743951ecSThomas Faber         */
398*743951ecSThomas Faber         sp->vgetparent = tif->tif_tagmethods.vgetfield;
399*743951ecSThomas Faber         tif->tif_tagmethods.vgetfield = ZSTDVGetField;	/* hook for codec tags */
400*743951ecSThomas Faber         sp->vsetparent = tif->tif_tagmethods.vsetfield;
401*743951ecSThomas Faber         tif->tif_tagmethods.vsetfield = ZSTDVSetField;	/* hook for codec tags */
402*743951ecSThomas Faber 
403*743951ecSThomas Faber         /* Default values for codec-specific fields */
404*743951ecSThomas Faber         sp->compression_level = 9;		/* default comp. level */
405*743951ecSThomas Faber         sp->state = 0;
406*743951ecSThomas Faber         sp->dstream = 0;
407*743951ecSThomas Faber         sp->cstream = 0;
408*743951ecSThomas Faber         sp->out_buffer.dst = NULL;
409*743951ecSThomas Faber         sp->out_buffer.size = 0;
410*743951ecSThomas Faber         sp->out_buffer.pos = 0;
411*743951ecSThomas Faber 
412*743951ecSThomas Faber         /*
413*743951ecSThomas Faber         * Install codec methods.
414*743951ecSThomas Faber         */
415*743951ecSThomas Faber         tif->tif_fixuptags = ZSTDFixupTags;
416*743951ecSThomas Faber         tif->tif_setupdecode = ZSTDSetupDecode;
417*743951ecSThomas Faber         tif->tif_predecode = ZSTDPreDecode;
418*743951ecSThomas Faber         tif->tif_decoderow = ZSTDDecode;
419*743951ecSThomas Faber         tif->tif_decodestrip = ZSTDDecode;
420*743951ecSThomas Faber         tif->tif_decodetile = ZSTDDecode;
421*743951ecSThomas Faber         tif->tif_setupencode = ZSTDSetupEncode;
422*743951ecSThomas Faber         tif->tif_preencode = ZSTDPreEncode;
423*743951ecSThomas Faber         tif->tif_postencode = ZSTDPostEncode;
424*743951ecSThomas Faber         tif->tif_encoderow = ZSTDEncode;
425*743951ecSThomas Faber         tif->tif_encodestrip = ZSTDEncode;
426*743951ecSThomas Faber         tif->tif_encodetile = ZSTDEncode;
427*743951ecSThomas Faber         tif->tif_cleanup = ZSTDCleanup;
428*743951ecSThomas Faber         /*
429*743951ecSThomas Faber         * Setup predictor setup.
430*743951ecSThomas Faber         */
431*743951ecSThomas Faber         (void) TIFFPredictorInit(tif);
432*743951ecSThomas Faber         return 1;
433*743951ecSThomas Faber bad:
434*743951ecSThomas Faber         TIFFErrorExt(tif->tif_clientdata, module,
435*743951ecSThomas Faber                     "No space for ZSTD state block");
436*743951ecSThomas Faber         return 0;
437*743951ecSThomas Faber }
438*743951ecSThomas Faber #endif /* ZSTD_SUPPORT */
439*743951ecSThomas Faber 
440*743951ecSThomas Faber /* vim: set ts=8 sts=8 sw=8 noet: */
441