ReactOS  0.4.15-dev-1201-gb2cf5a4
tif_lzma.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2010, Andrey Kiselev <dron@ak4719.spb.edu>
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and
5  * its documentation for any purpose is hereby granted without fee, provided
6  * that (i) the above copyright notices and this permission notice appear in
7  * all copies of the software and related documentation, and (ii) the names of
8  * Sam Leffler and Silicon Graphics may not be used in any advertising or
9  * publicity relating to the software without the specific, prior written
10  * permission of Sam Leffler and Silicon Graphics.
11  *
12  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
13  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
14  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
15  *
16  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
17  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
18  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
19  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
20  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
21  * OF THIS SOFTWARE.
22  */
23 
24 #include <precomp.h>
25 
26 #ifdef LZMA_SUPPORT
27 /*
28  * TIFF Library.
29  *
30  * LZMA2 Compression Support
31  *
32  * You need an LZMA2 SDK to link with. See http://tukaani.org/xz/ for details.
33  *
34  * The codec is derived from ZLIB codec (tif_zip.c).
35  */
36 
37 #include "tif_predict.h"
38 #include "lzma.h"
39 
40 #include <stdio.h>
41 
42 /*
43  * State block for each open TIFF file using LZMA2 compression/decompression.
44  */
45 typedef struct {
46  TIFFPredictorState predict;
47  lzma_stream stream;
48  lzma_filter filters[LZMA_FILTERS_MAX + 1];
49  lzma_options_delta opt_delta; /* delta filter options */
50  lzma_options_lzma opt_lzma; /* LZMA2 filter options */
51  int preset; /* compression level */
52  lzma_check check; /* type of the integrity check */
53  int state; /* state flags */
54 #define LSTATE_INIT_DECODE 0x01
55 #define LSTATE_INIT_ENCODE 0x02
56 
57  TIFFVGetMethod vgetparent; /* super-class method */
58  TIFFVSetMethod vsetparent; /* super-class method */
59 } LZMAState;
60 
61 #define LState(tif) ((LZMAState*) (tif)->tif_data)
62 #define DecoderState(tif) LState(tif)
63 #define EncoderState(tif) LState(tif)
64 
65 static int LZMAEncode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s);
66 static int LZMADecode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s);
67 
68 static const char *
69 LZMAStrerror(lzma_ret ret)
70 {
71  switch (ret) {
72  case LZMA_OK:
73  return "operation completed successfully";
74  case LZMA_STREAM_END:
75  return "end of stream was reached";
76  case LZMA_NO_CHECK:
77  return "input stream has no integrity check";
78  case LZMA_UNSUPPORTED_CHECK:
79  return "cannot calculate the integrity check";
80  case LZMA_GET_CHECK:
81  return "integrity check type is now available";
82  case LZMA_MEM_ERROR:
83  return "cannot allocate memory";
84  case LZMA_MEMLIMIT_ERROR:
85  return "memory usage limit was reached";
86  case LZMA_FORMAT_ERROR:
87  return "file format not recognized";
88  case LZMA_OPTIONS_ERROR:
89  return "invalid or unsupported options";
90  case LZMA_DATA_ERROR:
91  return "data is corrupt";
92  case LZMA_BUF_ERROR:
93  return "no progress is possible (stream is truncated or corrupt)";
94  case LZMA_PROG_ERROR:
95  return "programming error";
96  default:
97  return "unidentified liblzma error";
98  }
99 }
100 
101 static int
102 LZMAFixupTags(TIFF* tif)
103 {
104  (void) tif;
105  return 1;
106 }
107 
108 static int
109 LZMASetupDecode(TIFF* tif)
110 {
111  LZMAState* sp = DecoderState(tif);
112 
113  assert(sp != NULL);
114 
115  /* if we were last encoding, terminate this mode */
116  if (sp->state & LSTATE_INIT_ENCODE) {
117  lzma_end(&sp->stream);
118  sp->state = 0;
119  }
120 
121  sp->state |= LSTATE_INIT_DECODE;
122  return 1;
123 }
124 
125 /*
126  * Setup state for decoding a strip.
127  */
128 static int
129 LZMAPreDecode(TIFF* tif, uint16 s)
130 {
131  static const char module[] = "LZMAPreDecode";
132  LZMAState* sp = DecoderState(tif);
133  lzma_ret ret;
134 
135  (void) s;
136  assert(sp != NULL);
137 
138  if( (sp->state & LSTATE_INIT_DECODE) == 0 )
139  tif->tif_setupdecode(tif);
140 
141  sp->stream.next_in = tif->tif_rawdata;
142  sp->stream.avail_in = (size_t) tif->tif_rawcc;
143  if ((tmsize_t)sp->stream.avail_in != tif->tif_rawcc) {
145  "Liblzma cannot deal with buffers this size");
146  return 0;
147  }
148 
149  /*
150  * Disable memory limit when decoding. UINT64_MAX is a flag to disable
151  * the limit, we are passing (uint64_t)-1 which should be the same.
152  */
153  ret = lzma_stream_decoder(&sp->stream, (uint64_t)-1, 0);
154  if (ret != LZMA_OK) {
156  "Error initializing the stream decoder, %s",
157  LZMAStrerror(ret));
158  return 0;
159  }
160  return 1;
161 }
162 
163 static int
164 LZMADecode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s)
165 {
166  static const char module[] = "LZMADecode";
167  LZMAState* sp = DecoderState(tif);
168 
169  (void) s;
170  assert(sp != NULL);
171  assert(sp->state == LSTATE_INIT_DECODE);
172 
173  sp->stream.next_in = tif->tif_rawcp;
174  sp->stream.avail_in = (size_t) tif->tif_rawcc;
175 
176  sp->stream.next_out = op;
177  sp->stream.avail_out = (size_t) occ;
178  if ((tmsize_t)sp->stream.avail_out != occ) {
180  "Liblzma cannot deal with buffers this size");
181  return 0;
182  }
183 
184  do {
185  /*
186  * Save the current stream state to properly recover from the
187  * decoding errors later.
188  */
189  const uint8_t *next_in = sp->stream.next_in;
190  size_t avail_in = sp->stream.avail_in;
191 
192  lzma_ret ret = lzma_code(&sp->stream, LZMA_RUN);
193  if (ret == LZMA_STREAM_END)
194  break;
195  if (ret == LZMA_MEMLIMIT_ERROR) {
196  lzma_ret r = lzma_stream_decoder(&sp->stream,
197  lzma_memusage(&sp->stream), 0);
198  if (r != LZMA_OK) {
200  "Error initializing the stream decoder, %s",
201  LZMAStrerror(r));
202  break;
203  }
204  sp->stream.next_in = next_in;
205  sp->stream.avail_in = avail_in;
206  continue;
207  }
208  if (ret != LZMA_OK) {
210  "Decoding error at scanline %lu, %s",
211  (unsigned long) tif->tif_row, LZMAStrerror(ret));
212  break;
213  }
214  } while (sp->stream.avail_out > 0);
215  if (sp->stream.avail_out != 0) {
217  "Not enough data at scanline %lu (short %lu bytes)",
218  (unsigned long) tif->tif_row, (unsigned long) sp->stream.avail_out);
219  return 0;
220  }
221 
222  tif->tif_rawcp = (uint8 *)sp->stream.next_in; /* cast away const */
223  tif->tif_rawcc = sp->stream.avail_in;
224 
225  return 1;
226 }
227 
228 static int
229 LZMASetupEncode(TIFF* tif)
230 {
231  LZMAState* sp = EncoderState(tif);
232 
233  assert(sp != NULL);
234  if (sp->state & LSTATE_INIT_DECODE) {
235  lzma_end(&sp->stream);
236  sp->state = 0;
237  }
238 
239  sp->state |= LSTATE_INIT_ENCODE;
240  return 1;
241 }
242 
243 /*
244  * Reset encoding state at the start of a strip.
245  */
246 static int
247 LZMAPreEncode(TIFF* tif, uint16 s)
248 {
249  static const char module[] = "LZMAPreEncode";
250  LZMAState *sp = EncoderState(tif);
251  lzma_ret ret;
252 
253  (void) s;
254  assert(sp != NULL);
255  if( sp->state != LSTATE_INIT_ENCODE )
256  tif->tif_setupencode(tif);
257 
258  sp->stream.next_out = tif->tif_rawdata;
259  sp->stream.avail_out = (size_t)tif->tif_rawdatasize;
260  if ((tmsize_t)sp->stream.avail_out != tif->tif_rawdatasize) {
262  "Liblzma cannot deal with buffers this size");
263  return 0;
264  }
265  ret = lzma_stream_encoder(&sp->stream, sp->filters, sp->check);
266  if (ret != LZMA_OK) {
268  "Error in lzma_stream_encoder(): %s", LZMAStrerror(ret));
269  return 0;
270  }
271  return 1;
272 }
273 
274 /*
275  * Encode a chunk of pixels.
276  */
277 static int
278 LZMAEncode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
279 {
280  static const char module[] = "LZMAEncode";
281  LZMAState *sp = EncoderState(tif);
282 
283  assert(sp != NULL);
284  assert(sp->state == LSTATE_INIT_ENCODE);
285 
286  (void) s;
287  sp->stream.next_in = bp;
288  sp->stream.avail_in = (size_t) cc;
289  if ((tmsize_t)sp->stream.avail_in != cc) {
291  "Liblzma cannot deal with buffers this size");
292  return 0;
293  }
294  do {
295  lzma_ret ret = lzma_code(&sp->stream, LZMA_RUN);
296  if (ret != LZMA_OK) {
298  "Encoding error at scanline %lu, %s",
299  (unsigned long) tif->tif_row, LZMAStrerror(ret));
300  return 0;
301  }
302  if (sp->stream.avail_out == 0) {
303  tif->tif_rawcc = tif->tif_rawdatasize;
304  TIFFFlushData1(tif);
305  sp->stream.next_out = tif->tif_rawdata;
306  sp->stream.avail_out = (size_t)tif->tif_rawdatasize; /* this is a safe typecast, as check is made already in LZMAPreEncode */
307  }
308  } while (sp->stream.avail_in > 0);
309  return 1;
310 }
311 
312 /*
313  * Finish off an encoded strip by flushing the last
314  * string and tacking on an End Of Information code.
315  */
316 static int
317 LZMAPostEncode(TIFF* tif)
318 {
319  static const char module[] = "LZMAPostEncode";
320  LZMAState *sp = EncoderState(tif);
321  lzma_ret ret;
322 
323  sp->stream.avail_in = 0;
324  do {
325  ret = lzma_code(&sp->stream, LZMA_FINISH);
326  switch (ret) {
327  case LZMA_STREAM_END:
328  case LZMA_OK:
329  if ((tmsize_t)sp->stream.avail_out != tif->tif_rawdatasize) {
330  tif->tif_rawcc =
331  tif->tif_rawdatasize - sp->stream.avail_out;
332  TIFFFlushData1(tif);
333  sp->stream.next_out = tif->tif_rawdata;
334  sp->stream.avail_out = (size_t)tif->tif_rawdatasize; /* this is a safe typecast, as check is made already in ZIPPreEncode */
335  }
336  break;
337  default:
338  TIFFErrorExt(tif->tif_clientdata, module, "Liblzma error: %s",
339  LZMAStrerror(ret));
340  return 0;
341  }
342  } while (ret != LZMA_STREAM_END);
343  return 1;
344 }
345 
346 static void
347 LZMACleanup(TIFF* tif)
348 {
349  LZMAState* sp = LState(tif);
350 
351  assert(sp != 0);
352 
354 
355  tif->tif_tagmethods.vgetfield = sp->vgetparent;
356  tif->tif_tagmethods.vsetfield = sp->vsetparent;
357 
358  if (sp->state) {
359  lzma_end(&sp->stream);
360  sp->state = 0;
361  }
362  _TIFFfree(sp);
363  tif->tif_data = NULL;
364 
366 }
367 
368 static int
369 LZMAVSetField(TIFF* tif, uint32 tag, va_list ap)
370 {
371  static const char module[] = "LZMAVSetField";
372  LZMAState* sp = LState(tif);
373 
374  switch (tag) {
375  case TIFFTAG_LZMAPRESET:
376  sp->preset = (int) va_arg(ap, int);
377  lzma_lzma_preset(&sp->opt_lzma, sp->preset);
378  if (sp->state & LSTATE_INIT_ENCODE) {
379  lzma_ret ret = lzma_stream_encoder(&sp->stream,
380  sp->filters,
381  sp->check);
382  if (ret != LZMA_OK) {
384  "Liblzma error: %s",
385  LZMAStrerror(ret));
386  }
387  }
388  return 1;
389  default:
390  return (*sp->vsetparent)(tif, tag, ap);
391  }
392  /*NOTREACHED*/
393 }
394 
395 static int
396 LZMAVGetField(TIFF* tif, uint32 tag, va_list ap)
397 {
398  LZMAState* sp = LState(tif);
399 
400  switch (tag) {
401  case TIFFTAG_LZMAPRESET:
402  *va_arg(ap, int*) = sp->preset;
403  break;
404  default:
405  return (*sp->vgetparent)(tif, tag, ap);
406  }
407  return 1;
408 }
409 
410 static const TIFFField lzmaFields[] = {
412  FIELD_PSEUDO, TRUE, FALSE, "LZMA2 Compression Preset", NULL },
413 };
414 
415 int
416 TIFFInitLZMA(TIFF* tif, int scheme)
417 {
418  static const char module[] = "TIFFInitLZMA";
419  LZMAState* sp;
420  lzma_stream tmp_stream = LZMA_STREAM_INIT;
421 
423 
424  /*
425  * Merge codec-specific tag information.
426  */
427  if (!_TIFFMergeFields(tif, lzmaFields, TIFFArrayCount(lzmaFields))) {
429  "Merging LZMA2 codec-specific tags failed");
430  return 0;
431  }
432 
433  /*
434  * Allocate state block so tag methods have storage to record values.
435  */
436  tif->tif_data = (uint8*) _TIFFmalloc(sizeof(LZMAState));
437  if (tif->tif_data == NULL)
438  goto bad;
439  sp = LState(tif);
440  memcpy(&sp->stream, &tmp_stream, sizeof(lzma_stream));
441 
442  /*
443  * Override parent get/set field methods.
444  */
445  sp->vgetparent = tif->tif_tagmethods.vgetfield;
446  tif->tif_tagmethods.vgetfield = LZMAVGetField; /* hook for codec tags */
447  sp->vsetparent = tif->tif_tagmethods.vsetfield;
448  tif->tif_tagmethods.vsetfield = LZMAVSetField; /* hook for codec tags */
449 
450  /* Default values for codec-specific fields */
451  sp->preset = LZMA_PRESET_DEFAULT; /* default comp. level */
452  sp->check = LZMA_CHECK_NONE;
453  sp->state = 0;
454 
455  /* Data filters. So far we are using delta and LZMA2 filters only. */
456  sp->opt_delta.type = LZMA_DELTA_TYPE_BYTE;
457  /*
458  * The sample size in bytes seems to be reasonable distance for delta
459  * filter.
460  */
461  sp->opt_delta.dist = (tif->tif_dir.td_bitspersample % 8) ?
462  1 : tif->tif_dir.td_bitspersample / 8;
463  sp->filters[0].id = LZMA_FILTER_DELTA;
464  sp->filters[0].options = &sp->opt_delta;
465 
466  lzma_lzma_preset(&sp->opt_lzma, sp->preset);
467  sp->filters[1].id = LZMA_FILTER_LZMA2;
468  sp->filters[1].options = &sp->opt_lzma;
469 
470  sp->filters[2].id = LZMA_VLI_UNKNOWN;
471  sp->filters[2].options = NULL;
472 
473  /*
474  * Install codec methods.
475  */
476  tif->tif_fixuptags = LZMAFixupTags;
477  tif->tif_setupdecode = LZMASetupDecode;
478  tif->tif_predecode = LZMAPreDecode;
479  tif->tif_decoderow = LZMADecode;
480  tif->tif_decodestrip = LZMADecode;
481  tif->tif_decodetile = LZMADecode;
482  tif->tif_setupencode = LZMASetupEncode;
483  tif->tif_preencode = LZMAPreEncode;
484  tif->tif_postencode = LZMAPostEncode;
485  tif->tif_encoderow = LZMAEncode;
486  tif->tif_encodestrip = LZMAEncode;
487  tif->tif_encodetile = LZMAEncode;
488  tif->tif_cleanup = LZMACleanup;
489  /*
490  * Setup predictor setup.
491  */
492  (void) TIFFPredictorInit(tif);
493  return 1;
494 bad:
496  "No space for LZMA2 state block");
497  return 0;
498 }
499 #endif /* LZMA_SUPPORT */
500 
501 /* vim: set ts=8 sts=8 sw=8 noet: */
TIFFCodeMethod tif_decoderow
Definition: tiffiop.h:180
TIFFTagMethods tif_tagmethods
Definition: tiffiop.h:219
uint8 * tif_rawcp
Definition: tiffiop.h:199
uint16 td_bitspersample
Definition: tif_dir.h:75
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
#define TIFF_ANY
Definition: tiffio.h:307
#define TRUE
Definition: types.h:120
TIFFCodeMethod tif_encodestrip
Definition: tiffiop.h:183
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
unsigned int uint32
Definition: types.h:32
int(* TIFFVSetMethod)(TIFF *, uint32, va_list)
Definition: tiffio.h:328
TIFFCodeMethod tif_encoderow
Definition: tiffiop.h:181
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
Definition: tiffiop.h:115
#define FALSE
Definition: types.h:117
TIFF_SSIZE_T tmsize_t
Definition: tiffio.h:65
int _TIFFMergeFields(TIFF *tif, const TIFFField info[], uint32 n)
Definition: tif_dirinfo.c:369
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
#define TIFFInitLZMA
Definition: tif_codec.c:72
TIFFPreMethod tif_preencode
Definition: tiffiop.h:178
__kernel_size_t size_t
Definition: linux.h:237
TIFFBoolMethod tif_postencode
Definition: tiffiop.h:179
if(!(yy_init))
Definition: macro.lex.yy.c:714
UINT op
Definition: effect.c:224
#define COMPRESSION_LZMA
Definition: tiff.h:192
unsigned char uint8
Definition: types.h:28
void TIFFErrorExt(thandle_t fd, const char *module, const char *fmt,...)
Definition: tif_error.c:65
void check(CONTEXT *pContext)
Definition: NtContinue.c:68
tmsize_t tif_rawdatasize
Definition: tiffiop.h:196
int ret
TIFFCodeMethod tif_decodetile
Definition: tiffiop.h:184
uint8 * tif_data
Definition: tiffiop.h:191
GLuint GLuint stream
Definition: glext.h:7522
static int state
Definition: maze.c:121
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
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
BYTE uint8_t
Definition: msvideo1.c:66
uint32_t cc
Definition: isohybrid.c:75
#define va_arg(ap, T)
Definition: acmsvcex.h:89
UINT64 uint64_t
Definition: types.h:77
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
TIFFDirectory tif_dir
Definition: tiffiop.h:151
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
#define TIFFTAG_LZMAPRESET
Definition: tiff.h:606
TIFFBoolMethod tif_setupencode
Definition: tiffiop.h:176
int TIFFFlushData1(TIFF *tif)
Definition: tif_write.c:803
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