ReactOS 0.4.16-dev-2574-g474348f
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 "tiffiop.h"
25#ifdef LZMA_SUPPORT
26/*
27 * TIFF Library.
28 *
29 * LZMA2 Compression Support
30 *
31 * You need an LZMA2 SDK to link with. See http://tukaani.org/xz/ for details.
32 *
33 * The codec is derived from ZLIB codec (tif_zip.c).
34 */
35
36#include "lzma.h"
37#include "tif_predict.h"
38
39#include <stdio.h>
40
41/*
42 * State block for each open TIFF file using LZMA2 compression/decompression.
43 */
44typedef struct
45{
46 TIFFPredictorState predict;
47 int read_error; /* whether a read error has occurred, and which should cause
48 further reads in the same strip/tile to be aborted */
49 lzma_stream stream;
50 lzma_filter filters[LZMA_FILTERS_MAX + 1];
51 lzma_options_delta opt_delta; /* delta filter options */
52 lzma_options_lzma opt_lzma; /* LZMA2 filter options */
53 int preset; /* compression level */
54 lzma_check check; /* type of the integrity check */
55 int state; /* state flags */
56#define LSTATE_INIT_DECODE 0x01
57#define LSTATE_INIT_ENCODE 0x02
58
59 TIFFVGetMethod vgetparent; /* super-class method */
60 TIFFVSetMethod vsetparent; /* super-class method */
61} LZMAState;
62
63#define GetLZMAState(tif) ((LZMAState *)(tif)->tif_data)
64#define LZMADecoderState(tif) GetLZMAState(tif)
65#define LZMAEncoderState(tif) GetLZMAState(tif)
66
67static int LZMAEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s);
68static int LZMADecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s);
69
70static const char *LZMAStrerror(lzma_ret ret)
71{
72 switch (ret)
73 {
74 case LZMA_OK:
75 return "operation completed successfully";
76 case LZMA_STREAM_END:
77 return "end of stream was reached";
78 case LZMA_NO_CHECK:
79 return "input stream has no integrity check";
80 case LZMA_UNSUPPORTED_CHECK:
81 return "cannot calculate the integrity check";
82 case LZMA_GET_CHECK:
83 return "integrity check type is now available";
84 case LZMA_MEM_ERROR:
85 return "cannot allocate memory";
86 case LZMA_MEMLIMIT_ERROR:
87 return "memory usage limit was reached";
88 case LZMA_FORMAT_ERROR:
89 return "file format not recognized";
90 case LZMA_OPTIONS_ERROR:
91 return "invalid or unsupported options";
92 case LZMA_DATA_ERROR:
93 return "data is corrupt";
94 case LZMA_BUF_ERROR:
95 return "no progress is possible (stream is truncated or corrupt)";
96 case LZMA_PROG_ERROR:
97 return "programming error";
98 default:
99 return "unidentified liblzma error";
100 }
101}
102
103static int LZMAFixupTags(TIFF *tif)
104{
105 (void)tif;
106 return 1;
107}
108
109static int LZMASetupDecode(TIFF *tif)
110{
111 LZMAState *sp = LZMADecoderState(tif);
112
113 assert(sp != NULL);
114
115 /* if we were last encoding, terminate this mode */
116 if (sp->state & LSTATE_INIT_ENCODE)
117 {
118 lzma_end(&sp->stream);
119 sp->state = 0;
120 }
121
122 sp->state |= LSTATE_INIT_DECODE;
123 return 1;
124}
125
126/*
127 * Setup state for decoding a strip.
128 */
129static int LZMAPreDecode(TIFF *tif, uint16_t s)
130{
131 static const char module[] = "LZMAPreDecode";
132 LZMAState *sp = LZMADecoderState(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)
144 {
146 "Liblzma cannot deal with buffers this size");
147 return 0;
148 }
149
150 /*
151 * Disable memory limit when decoding. UINT64_MAX is a flag to disable
152 * the limit, we are passing (uint64_t)-1 which should be the same.
153 */
154 ret = lzma_stream_decoder(&sp->stream, (uint64_t)-1, 0);
155 if (ret != LZMA_OK)
156 {
157 TIFFErrorExtR(tif, module, "Error initializing the stream decoder, %s",
158 LZMAStrerror(ret));
159 return 0;
160 }
161
162 sp->read_error = 0;
163
164 return 1;
165}
166
167static int LZMADecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
168{
169 static const char module[] = "LZMADecode";
170 LZMAState *sp = LZMADecoderState(tif);
171
172 (void)s;
173 assert(sp != NULL);
174 assert(sp->state == LSTATE_INIT_DECODE);
175
176 if (sp->read_error)
177 {
178 memset(op, 0, (size_t)occ);
180 "LZMADecode: Scanline %" PRIu32 " cannot be read due to "
181 "previous error",
182 tif->tif_row);
183 return 0;
184 }
185
186 sp->stream.next_in = tif->tif_rawcp;
187 sp->stream.avail_in = (size_t)tif->tif_rawcc;
188
189 sp->stream.next_out = op;
190 sp->stream.avail_out = (size_t)occ;
191 if ((tmsize_t)sp->stream.avail_out != occ)
192 {
193 // read_error not set here as this is a usage issue that can be
194 // recovered in a following call.
195 memset(op, 0, (size_t)occ);
197 "Liblzma cannot deal with buffers this size");
198 return 0;
199 }
200
201 do
202 {
203 /*
204 * Save the current stream state to properly recover from the
205 * decoding errors later.
206 */
207 const uint8_t *next_in = sp->stream.next_in;
208 size_t avail_in = sp->stream.avail_in;
209
210 lzma_ret ret = lzma_code(&sp->stream, LZMA_RUN);
211 if (ret == LZMA_STREAM_END)
212 break;
213 if (ret == LZMA_MEMLIMIT_ERROR)
214 {
215 lzma_ret r =
216 lzma_stream_decoder(&sp->stream, lzma_memusage(&sp->stream), 0);
217 if (r != LZMA_OK)
218 {
219 sp->read_error = 1;
220 memset(op, 0, (size_t)occ);
222 "Error initializing the stream decoder, %s",
223 LZMAStrerror(r));
224 break;
225 }
226 sp->stream.next_in = next_in;
227 sp->stream.avail_in = avail_in;
228 continue;
229 }
230 if (ret != LZMA_OK)
231 {
233 "Decoding error at scanline %" PRIu32 ", %s",
234 tif->tif_row, LZMAStrerror(ret));
235 break;
236 }
237 } while (sp->stream.avail_out > 0);
238 if (sp->stream.avail_out != 0)
239 {
240 sp->read_error = 1;
241 memset(sp->stream.next_out, 0, sp->stream.avail_out);
243 "Not enough data at scanline %" PRIu32
244 " (short %" TIFF_SIZE_FORMAT " bytes)",
245 tif->tif_row, sp->stream.avail_out);
246 return 0;
247 }
248
249 tif->tif_rawcp = (uint8_t *)sp->stream.next_in; /* cast away const */
250 tif->tif_rawcc = sp->stream.avail_in;
251
252 return 1;
253}
254
255static int LZMASetupEncode(TIFF *tif)
256{
257 LZMAState *sp = LZMAEncoderState(tif);
258
259 assert(sp != NULL);
260 if (sp->state & LSTATE_INIT_DECODE)
261 {
262 lzma_end(&sp->stream);
263 sp->state = 0;
264 }
265
266 sp->state |= LSTATE_INIT_ENCODE;
267 return 1;
268}
269
270/*
271 * Reset encoding state at the start of a strip.
272 */
273static int LZMAPreEncode(TIFF *tif, uint16_t s)
274{
275 static const char module[] = "LZMAPreEncode";
276 LZMAState *sp = LZMAEncoderState(tif);
277 lzma_ret ret;
278
279 (void)s;
280 assert(sp != NULL);
281 if (sp->state != LSTATE_INIT_ENCODE)
282 tif->tif_setupencode(tif);
283
284 sp->stream.next_out = tif->tif_rawdata;
285 sp->stream.avail_out = (size_t)tif->tif_rawdatasize;
286 if ((tmsize_t)sp->stream.avail_out != tif->tif_rawdatasize)
287 {
289 "Liblzma cannot deal with buffers this size");
290 return 0;
291 }
292 ret = lzma_stream_encoder(&sp->stream, sp->filters, sp->check);
293 if (ret != LZMA_OK)
294 {
295 TIFFErrorExtR(tif, module, "Error in lzma_stream_encoder(): %s",
296 LZMAStrerror(ret));
297 return 0;
298 }
299 return 1;
300}
301
302/*
303 * Encode a chunk of pixels.
304 */
305static int LZMAEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s)
306{
307 static const char module[] = "LZMAEncode";
308 LZMAState *sp = LZMAEncoderState(tif);
309
310 assert(sp != NULL);
311 assert(sp->state == LSTATE_INIT_ENCODE);
312
313 (void)s;
314 sp->stream.next_in = bp;
315 sp->stream.avail_in = (size_t)cc;
316 if ((tmsize_t)sp->stream.avail_in != cc)
317 {
319 "Liblzma cannot deal with buffers this size");
320 return 0;
321 }
322 do
323 {
324 lzma_ret ret = lzma_code(&sp->stream, LZMA_RUN);
325 if (ret != LZMA_OK)
326 {
328 "Encoding error at scanline %" PRIu32 ", %s",
329 tif->tif_row, LZMAStrerror(ret));
330 return 0;
331 }
332 if (sp->stream.avail_out == 0)
333 {
334 tif->tif_rawcc = tif->tif_rawdatasize;
335 if (!TIFFFlushData1(tif))
336 return 0;
337 sp->stream.next_out = tif->tif_rawdata;
338 sp->stream.avail_out =
339 (size_t)
340 tif->tif_rawdatasize; /* this is a safe typecast, as check
341 is made already in LZMAPreEncode */
342 }
343 } while (sp->stream.avail_in > 0);
344 return 1;
345}
346
347/*
348 * Finish off an encoded strip by flushing the last
349 * string and tacking on an End Of Information code.
350 */
351static int LZMAPostEncode(TIFF *tif)
352{
353 static const char module[] = "LZMAPostEncode";
354 LZMAState *sp = LZMAEncoderState(tif);
355 lzma_ret ret;
356
357 sp->stream.avail_in = 0;
358 do
359 {
360 ret = lzma_code(&sp->stream, LZMA_FINISH);
361 switch (ret)
362 {
363 case LZMA_STREAM_END:
364 case LZMA_OK:
365 if ((tmsize_t)sp->stream.avail_out != tif->tif_rawdatasize)
366 {
367 tif->tif_rawcc =
368 tif->tif_rawdatasize - sp->stream.avail_out;
369 if (!TIFFFlushData1(tif))
370 return 0;
371 sp->stream.next_out = tif->tif_rawdata;
372 sp->stream.avail_out =
373 (size_t)
374 tif->tif_rawdatasize; /* this is a safe typecast, as
375 check is made already in
376 ZIPPreEncode */
377 }
378 break;
379 default:
380 TIFFErrorExtR(tif, module, "Liblzma error: %s",
381 LZMAStrerror(ret));
382 return 0;
383 }
384 } while (ret != LZMA_STREAM_END);
385 return 1;
386}
387
388static void LZMACleanup(TIFF *tif)
389{
390 LZMAState *sp = GetLZMAState(tif);
391
392 assert(sp != 0);
393
395
396 tif->tif_tagmethods.vgetfield = sp->vgetparent;
397 tif->tif_tagmethods.vsetfield = sp->vsetparent;
398
399 if (sp->state)
400 {
401 lzma_end(&sp->stream);
402 sp->state = 0;
403 }
404 _TIFFfreeExt(tif, sp);
405 tif->tif_data = NULL;
406
408}
409
410static int LZMAVSetField(TIFF *tif, uint32_t tag, va_list ap)
411{
412 static const char module[] = "LZMAVSetField";
413 LZMAState *sp = GetLZMAState(tif);
414
415 switch (tag)
416 {
418 sp->preset = (int)va_arg(ap, int);
419 lzma_lzma_preset(&sp->opt_lzma, sp->preset);
420 if (sp->state & LSTATE_INIT_ENCODE)
421 {
422 lzma_ret ret =
423 lzma_stream_encoder(&sp->stream, sp->filters, sp->check);
424 if (ret != LZMA_OK)
425 {
426 TIFFErrorExtR(tif, module, "Liblzma error: %s",
427 LZMAStrerror(ret));
428 }
429 }
430 return 1;
431 default:
432 return (*sp->vsetparent)(tif, tag, ap);
433 }
434 /*NOTREACHED*/
435}
436
437static int LZMAVGetField(TIFF *tif, uint32_t tag, va_list ap)
438{
439 LZMAState *sp = GetLZMAState(tif);
440
441 switch (tag)
442 {
444 *va_arg(ap, int *) = sp->preset;
445 break;
446 default:
447 return (*sp->vgetparent)(tif, tag, ap);
448 }
449 return 1;
450}
451
452static const TIFFField lzmaFields[] = {
454 FALSE, "LZMA2 Compression Preset", NULL},
455};
456
457int TIFFInitLZMA(TIFF *tif, int scheme)
458{
459 static const char module[] = "TIFFInitLZMA";
460 LZMAState *sp;
461 lzma_stream tmp_stream = LZMA_STREAM_INIT;
462
463 (void)scheme;
465
466 /*
467 * Merge codec-specific tag information.
468 */
469 if (!_TIFFMergeFields(tif, lzmaFields, TIFFArrayCount(lzmaFields)))
470 {
471 TIFFErrorExtR(tif, module, "Merging LZMA2 codec-specific tags failed");
472 return 0;
473 }
474
475 /*
476 * Allocate state block so tag methods have storage to record values.
477 */
478 tif->tif_data = (uint8_t *)_TIFFmallocExt(tif, sizeof(LZMAState));
479 if (tif->tif_data == NULL)
480 goto bad;
481 sp = GetLZMAState(tif);
482 memcpy(&sp->stream, &tmp_stream, sizeof(lzma_stream));
483
484 /*
485 * Override parent get/set field methods.
486 */
487 sp->vgetparent = tif->tif_tagmethods.vgetfield;
488 tif->tif_tagmethods.vgetfield = LZMAVGetField; /* hook for codec tags */
489 sp->vsetparent = tif->tif_tagmethods.vsetfield;
490 tif->tif_tagmethods.vsetfield = LZMAVSetField; /* hook for codec tags */
491
492 /* Default values for codec-specific fields */
493 sp->preset = LZMA_PRESET_DEFAULT; /* default comp. level */
494 sp->check = LZMA_CHECK_NONE;
495 sp->state = 0;
496
497 /* Data filters. So far we are using delta and LZMA2 filters only. */
498 sp->opt_delta.type = LZMA_DELTA_TYPE_BYTE;
499 /*
500 * The sample size in bytes seems to be reasonable distance for delta
501 * filter.
502 */
503 sp->opt_delta.dist = (tif->tif_dir.td_bitspersample % 8)
504 ? 1
505 : tif->tif_dir.td_bitspersample / 8;
506 sp->filters[0].id = LZMA_FILTER_DELTA;
507 sp->filters[0].options = &sp->opt_delta;
508
509 lzma_lzma_preset(&sp->opt_lzma, sp->preset);
510 sp->filters[1].id = LZMA_FILTER_LZMA2;
511 sp->filters[1].options = &sp->opt_lzma;
512
513 sp->filters[2].id = LZMA_VLI_UNKNOWN;
514 sp->filters[2].options = NULL;
515
516 /*
517 * Install codec methods.
518 */
519 tif->tif_fixuptags = LZMAFixupTags;
520 tif->tif_setupdecode = LZMASetupDecode;
521 tif->tif_predecode = LZMAPreDecode;
522 tif->tif_decoderow = LZMADecode;
523 tif->tif_decodestrip = LZMADecode;
524 tif->tif_decodetile = LZMADecode;
525 tif->tif_setupencode = LZMASetupEncode;
526 tif->tif_preencode = LZMAPreEncode;
527 tif->tif_postencode = LZMAPostEncode;
528 tif->tif_encoderow = LZMAEncode;
529 tif->tif_encodestrip = LZMAEncode;
530 tif->tif_encodetile = LZMAEncode;
531 tif->tif_cleanup = LZMACleanup;
532 /*
533 * Setup predictor setup.
534 */
536 return 1;
537bad:
538 TIFFErrorExtR(tif, module, "No space for LZMA2 state block");
539 return 0;
540}
541#endif /* LZMA_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
UINT64 uint64_t
Definition: types.h:77
UINT op
Definition: effect.c:236
#define assert(_expr)
Definition: assert.h:32
unsigned int size_t
Definition: corecrt.h:203
#define PRIu32
Definition: inttypes.h:84
#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
#define check(expected, result)
Definition: dplayx.c:32
return ret
Definition: mutex.c:146
GLdouble s
Definition: gl.h:2039
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
uint32_t cc
Definition: isohybrid.c:75
if(dx< 0)
Definition: linetemp.h:194
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
static const WCHAR sp[]
Definition: suminfo.c:287
DWORD scheme
#define memset(x, y, z)
Definition: compat.h:39
uint16_t td_bitspersample
Definition: tif_dir.h:86
TIFFVGetMethod vgetfield
Definition: tiffio.h:376
TIFFVSetMethod vsetfield
Definition: tiffio.h:375
Definition: parse.h:23
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
TIFFDirectory tif_dir
Definition: tiffiop.h:157
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 TIFFInitLZMA
Definition: tif_codec.c:74
void _TIFFSetDefaultCompressionState(TIFF *tif)
Definition: tif_compress.c:142
#define TIFF_SIZE_FORMAT
Definition: tif_config.h:168
#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
int TIFFFlushData1(TIFF *tif)
Definition: tif_write.c:931
#define COMPRESSION_LZMA
Definition: tiff.h:215
#define TIFFTAG_LZMAPRESET
Definition: tiff.h:751
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