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