ReactOS 0.4.15-dev-7842-g558ab78
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 */
45typedef 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
65static int LZMAEncode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s);
66static int LZMADecode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s);
67
68static const char *
69LZMAStrerror(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
101static int
102LZMAFixupTags(TIFF* tif)
103{
104 (void) tif;
105 return 1;
106}
107
108static int
109LZMASetupDecode(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 */
128static int
129LZMAPreDecode(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
163static int
164LZMADecode(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
228static int
229LZMASetupEncode(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 */
246static int
247LZMAPreEncode(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 */
277static int
278LZMAEncode(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 */
316static int
317LZMAPostEncode(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
346static void
347LZMACleanup(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
368static int
369LZMAVSetField(TIFF* tif, uint32 tag, va_list ap)
370{
371 static const char module[] = "LZMAVSetField";
372 LZMAState* sp = LState(tif);
373
374 switch (tag) {
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
395static int
396LZMAVGetField(TIFF* tif, uint32 tag, va_list ap)
397{
398 LZMAState* sp = LState(tif);
399
400 switch (tag) {
402 *va_arg(ap, int*) = sp->preset;
403 break;
404 default:
405 return (*sp->vgetparent)(tif, tag, ap);
406 }
407 return 1;
408}
409
410static const TIFFField lzmaFields[] = {
412 FIELD_PSEUDO, TRUE, FALSE, "LZMA2 Compression Preset", NULL },
413};
414
415int
416TIFFInitLZMA(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;
494bad:
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: */
char * va_list
Definition: acmsvcex.h:78
#define va_arg(ap, T)
Definition: acmsvcex.h:89
static int state
Definition: maze.c:121
unsigned short uint16
Definition: types.h:30
unsigned int uint32
Definition: types.h:32
unsigned char uint8
Definition: types.h:28
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
UINT64 uint64_t
Definition: types.h:77
UINT op
Definition: effect.c:236
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
#define assert(x)
Definition: debug.h:53
#define check(expected, result)
Definition: dplayx.c:32
__kernel_size_t size_t
Definition: linux.h:237
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
BYTE uint8_t
Definition: msvideo1.c:66
DWORD scheme
uint16 td_bitspersample
Definition: tif_dir.h:75
TIFFVGetMethod vgetfield
Definition: tiffio.h:334
TIFFVSetMethod vsetfield
Definition: tiffio.h:333
Definition: parse.h:23
Definition: ecma_167.h:138
Definition: tiffiop.h:115
TIFFCodeMethod tif_encodestrip
Definition: tiffiop.h:183
TIFFCodeMethod tif_encodetile
Definition: tiffiop.h:185
TIFFTagMethods tif_tagmethods
Definition: tiffiop.h:219
TIFFPreMethod tif_preencode
Definition: tiffiop.h:178
TIFFBoolMethod tif_fixuptags
Definition: tiffiop.h:173
tmsize_t tif_rawcc
Definition: tiffiop.h:200
TIFFPreMethod tif_predecode
Definition: tiffiop.h:175
TIFFCodeMethod tif_decodestrip
Definition: tiffiop.h:182
thandle_t tif_clientdata
Definition: tiffiop.h:207
TIFFCodeMethod tif_decoderow
Definition: tiffiop.h:180
TIFFBoolMethod tif_setupencode
Definition: tiffiop.h:176
TIFFDirectory tif_dir
Definition: tiffiop.h:151
TIFFBoolMethod tif_postencode
Definition: tiffiop.h:179
uint8 * tif_data
Definition: tiffiop.h:191
TIFFCodeMethod tif_encoderow
Definition: tiffiop.h:181
TIFFVoidMethod tif_cleanup
Definition: tiffiop.h:188
uint32 tif_row
Definition: tiffiop.h:159
TIFFBoolMethod tif_setupdecode
Definition: tiffiop.h:174
tmsize_t tif_rawdatasize
Definition: tiffiop.h:196
uint8 * tif_rawcp
Definition: tiffiop.h:199
TIFFCodeMethod tif_decodetile
Definition: tiffiop.h:184
uint8 * tif_rawdata
Definition: tiffiop.h:195
#define TIFFInitLZMA
Definition: tif_codec.c:72
void _TIFFSetDefaultCompressionState(TIFF *tif)
Definition: tif_compress.c:135
#define FIELD_PSEUDO
Definition: tif_dir.h:190
@ TIFF_SETGET_UNDEFINED
Definition: tif_dir.h:204
@ TIFF_SETGET_INT
Definition: tif_dir.h:217
int _TIFFMergeFields(TIFF *tif, const TIFFField info[], uint32 n)
Definition: tif_dirinfo.c:369
void TIFFErrorExt(thandle_t fd, const char *module, const char *fmt,...)
Definition: tif_error.c:65
int TIFFPredictorCleanup(TIFF *tif)
Definition: tif_predict.c:857
int TIFFPredictorInit(TIFF *tif)
Definition: tif_predict.c:816
void _TIFFfree(void *p)
Definition: tif_unix.c:326
void * _TIFFmalloc(tmsize_t s)
Definition: tif_unix.c:309
int TIFFFlushData1(TIFF *tif)
Definition: tif_write.c:803
#define COMPRESSION_LZMA
Definition: tiff.h:191
#define TIFFTAG_LZMAPRESET
Definition: tiff.h:565
TIFF_SSIZE_T tmsize_t
Definition: tiffio.h:65
int(* TIFFVGetMethod)(TIFF *, uint32, va_list)
Definition: tiffio.h:329
#define TIFF_ANY
Definition: tiffio.h:307
int(* TIFFVSetMethod)(TIFF *, uint32, va_list)
Definition: tiffio.h:328
#define TIFFArrayCount(a)
Definition: tiffiop.h:283
int ret
void int int ULONGLONG int va_list * ap
Definition: winesup.h:36