ReactOS  0.4.15-dev-1177-g6cb3b62
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 */
42 typedef struct {
43  TIFFPredictorState predict;
44  ZSTD_DStream* dstream;
45  ZSTD_CStream* cstream;
46  int compression_level; /* compression level */
48  int state; /* state flags */
49 #define LSTATE_INIT_DECODE 0x01
50 #define LSTATE_INIT_ENCODE 0x02
51 
52  TIFFVGetMethod vgetparent; /* super-class method */
53  TIFFVSetMethod vsetparent; /* super-class method */
54 } ZSTDState;
55 
56 #define LState(tif) ((ZSTDState*) (tif)->tif_data)
57 #define DecoderState(tif) LState(tif)
58 #define EncoderState(tif) LState(tif)
59 
60 static int ZSTDEncode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s);
61 static int ZSTDDecode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s);
62 
63 static int
64 ZSTDFixupTags(TIFF* tif)
65 {
66  (void) tif;
67  return 1;
68 }
69 
70 static int
71 ZSTDSetupDecode(TIFF* tif)
72 {
73  ZSTDState* sp = DecoderState(tif);
74 
75  assert(sp != NULL);
76 
77  /* if we were last encoding, terminate this mode */
78  if (sp->state & LSTATE_INIT_ENCODE) {
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 */
91 static int
92 ZSTDPreDecode(TIFF* tif, uint16 s)
93 {
94  static const char module[] = "ZSTDPreDecode";
95  ZSTDState* sp = DecoderState(tif);
96  size_t zstd_ret;
97 
98  (void) s;
99  assert(sp != NULL);
100 
101  if( (sp->state & LSTATE_INIT_DECODE) == 0 )
102  tif->tif_setupdecode(tif);
103 
104  if( sp->dstream )
105  {
106  ZSTD_freeDStream(sp->dstream);
107  sp->dstream = NULL;
108  }
109 
110  sp->dstream = ZSTD_createDStream();
111  if( sp->dstream == NULL ) {
113  "Cannot allocate decompression stream");
114  return 0;
115  }
116  zstd_ret = ZSTD_initDStream(sp->dstream);
117  if( ZSTD_isError(zstd_ret) ) {
119  "Error in ZSTD_initDStream(): %s",
120  ZSTD_getErrorName(zstd_ret));
121  return 0;
122  }
123 
124  return 1;
125 }
126 
127 static int
128 ZSTDDecode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s)
129 {
130  static const char module[] = "ZSTDDecode";
131  ZSTDState* sp = DecoderState(tif);
134  size_t zstd_ret;
135 
136  (void) s;
137  assert(sp != NULL);
138  assert(sp->state == LSTATE_INIT_DECODE);
139 
140  in_buffer.src = tif->tif_rawcp;
141  in_buffer.size = (size_t) tif->tif_rawcc;
142  in_buffer.pos = 0;
143 
144  out_buffer.dst = op;
145  out_buffer.size = (size_t) occ;
146  out_buffer.pos = 0;
147 
148  do {
149  zstd_ret = ZSTD_decompressStream(sp->dstream, &out_buffer,
150  &in_buffer);
151  if( ZSTD_isError(zstd_ret) ) {
153  "Error in ZSTD_decompressStream(): %s",
154  ZSTD_getErrorName(zstd_ret));
155  return 0;
156  }
157  } while( zstd_ret != 0 &&
158  in_buffer.pos < in_buffer.size &&
159  out_buffer.pos < out_buffer.size );
160 
161  if (out_buffer.pos < (size_t)occ) {
163  "Not enough data at scanline %lu (short %lu bytes)",
164  (unsigned long) tif->tif_row,
165  (unsigned long) (size_t)occ - out_buffer.pos);
166  return 0;
167  }
168 
169  tif->tif_rawcp += in_buffer.pos;
170  tif->tif_rawcc -= in_buffer.pos;
171 
172  return 1;
173 }
174 
175 static int
176 ZSTDSetupEncode(TIFF* tif)
177 {
178  ZSTDState* sp = EncoderState(tif);
179 
180  assert(sp != NULL);
181  if (sp->state & LSTATE_INIT_DECODE) {
182  ZSTD_freeDStream(sp->dstream);
183  sp->dstream = NULL;
184  sp->state = 0;
185  }
186 
187  sp->state |= LSTATE_INIT_ENCODE;
188  return 1;
189 }
190 
191 /*
192 * Reset encoding state at the start of a strip.
193 */
194 static int
195 ZSTDPreEncode(TIFF* tif, uint16 s)
196 {
197  static const char module[] = "ZSTDPreEncode";
198  ZSTDState *sp = EncoderState(tif);
199  size_t zstd_ret;
200 
201  (void) s;
202  assert(sp != NULL);
203  if( sp->state != LSTATE_INIT_ENCODE )
204  tif->tif_setupencode(tif);
205 
206  if (sp->cstream) {
207  ZSTD_freeCStream(sp->cstream);
208  sp->cstream = NULL;
209  }
210  sp->cstream = ZSTD_createCStream();
211  if( sp->cstream == NULL ) {
213  "Cannot allocate compression stream");
214  return 0;
215  }
216 
217  zstd_ret = ZSTD_initCStream(sp->cstream, sp->compression_level);
218  if( ZSTD_isError(zstd_ret) ) {
220  "Error in ZSTD_initCStream(): %s",
221  ZSTD_getErrorName(zstd_ret));
222  return 0;
223  }
224 
225  sp->out_buffer.dst = tif->tif_rawdata;
226  sp->out_buffer.size = (size_t)tif->tif_rawdatasize;
227  sp->out_buffer.pos = 0;
228 
229  return 1;
230 }
231 
232 /*
233 * Encode a chunk of pixels.
234 */
235 static int
236 ZSTDEncode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
237 {
238  static const char module[] = "ZSTDEncode";
239  ZSTDState *sp = EncoderState(tif);
241  size_t zstd_ret;
242 
243  assert(sp != NULL);
244  assert(sp->state == LSTATE_INIT_ENCODE);
245 
246  (void) s;
247 
248  in_buffer.src = bp;
249  in_buffer.size = (size_t)cc;
250  in_buffer.pos = 0;
251 
252  do {
253  zstd_ret = ZSTD_compressStream(sp->cstream, &sp->out_buffer,
254  &in_buffer);
255  if( ZSTD_isError(zstd_ret) ) {
257  "Error in ZSTD_compressStream(): %s",
258  ZSTD_getErrorName(zstd_ret));
259  return 0;
260  }
261  if( sp->out_buffer.pos == sp->out_buffer.size ) {
262  tif->tif_rawcc = tif->tif_rawdatasize;
263  TIFFFlushData1(tif);
264  sp->out_buffer.dst = tif->tif_rawcp;
265  sp->out_buffer.pos = 0;
266  }
267  } while( in_buffer.pos < in_buffer.size );
268 
269  return 1;
270 }
271 
272 /*
273 * Finish off an encoded strip by flushing it.
274 */
275 static int
276 ZSTDPostEncode(TIFF* tif)
277 {
278  static const char module[] = "ZSTDPostEncode";
279  ZSTDState *sp = EncoderState(tif);
280  size_t zstd_ret;
281 
282  do {
283  zstd_ret = ZSTD_endStream(sp->cstream, &sp->out_buffer);
284  if( ZSTD_isError(zstd_ret) ) {
286  "Error in ZSTD_endStream(): %s",
287  ZSTD_getErrorName(zstd_ret));
288  return 0;
289  }
290  if( sp->out_buffer.pos > 0 ) {
291  tif->tif_rawcc = sp->out_buffer.pos;
292  TIFFFlushData1(tif);
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 
300 static void
301 ZSTDCleanup(TIFF* tif)
302 {
303  ZSTDState* sp = LState(tif);
304 
305  assert(sp != 0);
306 
308 
309  tif->tif_tagmethods.vgetfield = sp->vgetparent;
310  tif->tif_tagmethods.vsetfield = sp->vsetparent;
311 
312  if (sp->dstream) {
313  ZSTD_freeDStream(sp->dstream);
314  sp->dstream = NULL;
315  }
316  if (sp->cstream) {
317  ZSTD_freeCStream(sp->cstream);
318  sp->cstream = NULL;
319  }
320  _TIFFfree(sp);
321  tif->tif_data = NULL;
322 
324 }
325 
326 static int
327 ZSTDVSetField(TIFF* tif, uint32 tag, va_list ap)
328 {
329  static const char module[] = "ZSTDVSetField";
330  ZSTDState* sp = LState(tif);
331 
332  switch (tag) {
333  case TIFFTAG_ZSTD_LEVEL:
334  sp->compression_level = (int) va_arg(ap, int);
335  if( sp->compression_level <= 0 ||
336  sp->compression_level > ZSTD_maxCLevel() )
337  {
339  "ZSTD_LEVEL should be between 1 and %d",
340  ZSTD_maxCLevel());
341  }
342  return 1;
343  default:
344  return (*sp->vsetparent)(tif, tag, ap);
345  }
346  /*NOTREACHED*/
347 }
348 
349 static int
350 ZSTDVGetField(TIFF* tif, uint32 tag, va_list ap)
351 {
352  ZSTDState* sp = LState(tif);
353 
354  switch (tag) {
355  case TIFFTAG_ZSTD_LEVEL:
356  *va_arg(ap, int*) = sp->compression_level;
357  break;
358  default:
359  return (*sp->vgetparent)(tif, tag, ap);
360  }
361  return 1;
362 }
363 
364 static const TIFFField ZSTDFields[] = {
367  FIELD_PSEUDO, TRUE, FALSE, "ZSTD compression_level", NULL },
368 };
369 
370 int
371 TIFFInitZSTD(TIFF* tif, int scheme)
372 {
373  static const char module[] = "TIFFInitZSTD";
374  ZSTDState* sp;
375 
377 
378  /*
379  * Merge codec-specific tag information.
380  */
381  if (!_TIFFMergeFields(tif, ZSTDFields, TIFFArrayCount(ZSTDFields))) {
383  "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*) _TIFFmalloc(sizeof(ZSTDState));
391  if (tif->tif_data == NULL)
392  goto bad;
393  sp = LState(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  */
431  (void) TIFFPredictorInit(tif);
432  return 1;
433 bad:
435  "No space for ZSTD state block");
436  return 0;
437 }
438 #endif /* ZSTD_SUPPORT */
439 
440 /* vim: set ts=8 sts=8 sw=8 noet: */
TIFFCodeMethod tif_decoderow
Definition: tiffiop.h:180
ZSTDLIB_API const char * ZSTD_getErrorName(size_t code)
Definition: zstd_common.c:39
TIFFTagMethods tif_tagmethods
Definition: tiffiop.h:219
uint8 * tif_rawcp
Definition: tiffiop.h:199
TIFFPreMethod tif_predecode
Definition: tiffiop.h:175
struct png_info_def **typedef void(__cdecl typeof(png_destroy_read_struct))(struct png_struct_def **
Definition: typeof.h:49
void TIFFWarningExt(thandle_t fd, const char *module, const char *fmt,...)
Definition: tif_warning.c:65
#define TIFF_ANY
Definition: tiffio.h:307
#define TRUE
Definition: types.h:120
TIFFCodeMethod tif_encodestrip
Definition: tiffiop.h:183
unsigned int uint32
Definition: types.h:32
int(* TIFFVSetMethod)(TIFF *, uint32, va_list)
Definition: tiffio.h:328
TIFFCodeMethod tif_encoderow
Definition: tiffiop.h:181
ZSTDLIB_API size_t ZSTD_compressStream(ZSTD_CStream *zcs, ZSTD_outBuffer *output, ZSTD_inBuffer *input)
DWORD scheme
#define assert(x)
Definition: debug.h:53
Definition: ecma_167.h:138
uint8 * tif_rawdata
Definition: tiffiop.h:195
thandle_t tif_clientdata
Definition: tiffiop.h:207
tmsize_t tif_rawcc
Definition: tiffiop.h:200
int TIFFPredictorCleanup(TIFF *tif)
Definition: tif_predict.c:857
static HANDLE PIO_APC_ROUTINE PVOID PIO_STATUS_BLOCK ULONG PVOID ULONG PVOID out_buffer
Definition: file.c:100
Definition: tiffiop.h:115
static unsigned char * in_buffer
Definition: iccvid.c:87
#define FALSE
Definition: types.h:117
#define TIFFTAG_ZSTD_LEVEL
Definition: tiff.h:610
TIFF_SSIZE_T tmsize_t
Definition: tiffio.h:65
ZSTDLIB_API size_t ZSTD_freeDStream(ZSTD_DStream *zds)
ZSTDLIB_API size_t ZSTD_decompressStream(ZSTD_DStream *zds, ZSTD_outBuffer *output, ZSTD_inBuffer *input)
int _TIFFMergeFields(TIFF *tif, const TIFFField info[], uint32 n)
Definition: tif_dirinfo.c:369
ZSTDLIB_API ZSTD_DStream * ZSTD_createDStream(void)
smooth NULL
Definition: ftsmooth.c:416
TIFFCodeMethod tif_decodestrip
Definition: tiffiop.h:182
char * va_list
Definition: acmsvcex.h:78
int(* TIFFVGetMethod)(TIFF *, uint32, va_list)
Definition: tiffio.h:329
TIFFCodeMethod tif_encodetile
Definition: tiffiop.h:185
void * _TIFFmalloc(tmsize_t s)
Definition: tif_unix.c:309
TIFFPreMethod tif_preencode
Definition: tiffiop.h:178
__kernel_size_t size_t
Definition: linux.h:237
TIFFBoolMethod tif_postencode
Definition: tiffiop.h:179
ZSTDLIB_API size_t ZSTD_freeCStream(ZSTD_CStream *zcs)
ZSTDLIB_API int ZSTD_maxCLevel(void)
UINT op
Definition: effect.c:224
unsigned char uint8
Definition: types.h:28
void TIFFErrorExt(thandle_t fd, const char *module, const char *fmt,...)
Definition: tif_error.c:65
tmsize_t tif_rawdatasize
Definition: tiffiop.h:196
#define TIFFInitZSTD
Definition: tif_codec.c:75
TIFFCodeMethod tif_decodetile
Definition: tiffiop.h:184
ZSTDLIB_API ZSTD_CStream * ZSTD_createCStream(void)
uint8 * tif_data
Definition: tiffiop.h:191
static int state
Definition: maze.c:121
TIFFVoidMethod tif_cleanup
Definition: tiffiop.h:188
GLdouble s
Definition: gl.h:2039
#define TIFFArrayCount(a)
Definition: tiffiop.h:283
void _TIFFSetDefaultCompressionState(TIFF *tif)
Definition: tif_compress.c:135
uint32_t cc
Definition: isohybrid.c:75
#define ZSTD_isError
#define va_arg(ap, T)
Definition: acmsvcex.h:89
ZSTDLIB_API size_t ZSTD_initCStream(ZSTD_CStream *zcs, int compressionLevel)
int TIFFPredictorInit(TIFF *tif)
Definition: tif_predict.c:816
uint32 tif_row
Definition: tiffiop.h:159
TIFFVGetMethod vgetfield
Definition: tiffio.h:334
unsigned short uint16
Definition: types.h:30
TIFFBoolMethod tif_fixuptags
Definition: tiffiop.h:173
#define COMPRESSION_ZSTD
Definition: tiff.h:193
void int int ULONGLONG int va_list * ap
Definition: winesup.h:32
TIFFVSetMethod vsetfield
Definition: tiffio.h:333
static const WCHAR sp[]
Definition: suminfo.c:288
#define FIELD_PSEUDO
Definition: tif_dir.h:190
void _TIFFfree(void *p)
Definition: tif_unix.c:326
TIFFBoolMethod tif_setupencode
Definition: tiffiop.h:176
int TIFFFlushData1(TIFF *tif)
Definition: tif_write.c:803
ZSTDLIB_API size_t ZSTD_endStream(ZSTD_CStream *zcs, ZSTD_outBuffer *output)
ZSTDLIB_API size_t ZSTD_initDStream(ZSTD_DStream *zds)
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
TIFFBoolMethod tif_setupdecode
Definition: tiffiop.h:174
char * tag
Definition: main.c:59