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