• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 *
LZMAStrerror(lzma_ret ret)70 LZMAStrerror(lzma_ret ret)
71 {
72     switch (ret) {
73         case LZMA_OK:
74             return "operation completed successfully";
75         case LZMA_STREAM_END:
76             return "end of stream was reached";
77         case LZMA_NO_CHECK:
78             return "input stream has no integrity check";
79         case LZMA_UNSUPPORTED_CHECK:
80             return "cannot calculate the integrity check";
81         case LZMA_GET_CHECK:
82             return "integrity check type is now available";
83         case LZMA_MEM_ERROR:
84             return "cannot allocate memory";
85         case LZMA_MEMLIMIT_ERROR:
86             return "memory usage limit was reached";
87         case LZMA_FORMAT_ERROR:
88             return "file format not recognized";
89         case LZMA_OPTIONS_ERROR:
90             return "invalid or unsupported options";
91         case LZMA_DATA_ERROR:
92             return "data is corrupt";
93         case LZMA_BUF_ERROR:
94             return "no progress is possible (stream is truncated or corrupt)";
95         case LZMA_PROG_ERROR:
96             return "programming error";
97         default:
98             return "unindentified liblzma error";
99     }
100 }
101 
102 static int
LZMAFixupTags(TIFF * tif)103 LZMAFixupTags(TIFF* tif)
104 {
105     (void) tif;
106     return 1;
107 }
108 
109 static int
LZMASetupDecode(TIFF * tif)110 LZMASetupDecode(TIFF* tif)
111 {
112     LZMAState* sp = DecoderState(tif);
113 
114     assert(sp != NULL);
115 
116         /* if we were last encoding, terminate this mode */
117     if (sp->state & LSTATE_INIT_ENCODE) {
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  */
129 static int
LZMAPreDecode(TIFF * tif,uint16 s)130 LZMAPreDecode(TIFF* tif, uint16 s)
131 {
132     static const char module[] = "LZMAPreDecode";
133     LZMAState* sp = DecoderState(tif);
134     lzma_ret ret;
135 
136     (void) s;
137     assert(sp != NULL);
138 
139     if( (sp->state & LSTATE_INIT_DECODE) == 0 )
140             tif->tif_setupdecode(tif);
141 
142     sp->stream.next_in = tif->tif_rawdata;
143     sp->stream.avail_in = (size_t) tif->tif_rawcc;
144     if ((tmsize_t)sp->stream.avail_in != tif->tif_rawcc) {
145         TIFFErrorExt(tif->tif_clientdata, module,
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         TIFFErrorExt(tif->tif_clientdata, module,
157                  "Error initializing the stream decoder, %s",
158                  LZMAStrerror(ret));
159         return 0;
160     }
161     return 1;
162 }
163 
164 static int
LZMADecode(TIFF * tif,uint8 * op,tmsize_t occ,uint16 s)165 LZMADecode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s)
166 {
167     static const char module[] = "LZMADecode";
168     LZMAState* sp = DecoderState(tif);
169 
170     (void) s;
171     assert(sp != NULL);
172     assert(sp->state == LSTATE_INIT_DECODE);
173 
174         sp->stream.next_in = tif->tif_rawcp;
175         sp->stream.avail_in = (size_t) tif->tif_rawcc;
176 
177     sp->stream.next_out = op;
178     sp->stream.avail_out = (size_t) occ;
179     if ((tmsize_t)sp->stream.avail_out != occ) {
180         TIFFErrorExt(tif->tif_clientdata, module,
181                  "Liblzma cannot deal with buffers this size");
182         return 0;
183     }
184 
185     do {
186         /*
187          * Save the current stream state to properly recover from the
188          * decoding errors later.
189          */
190         const uint8_t *next_in = sp->stream.next_in;
191         size_t avail_in = sp->stream.avail_in;
192 
193         lzma_ret ret = lzma_code(&sp->stream, LZMA_RUN);
194         if (ret == LZMA_STREAM_END)
195             break;
196         if (ret == LZMA_MEMLIMIT_ERROR) {
197             lzma_ret r = lzma_stream_decoder(&sp->stream,
198                              lzma_memusage(&sp->stream), 0);
199             if (r != LZMA_OK) {
200                 TIFFErrorExt(tif->tif_clientdata, module,
201                          "Error initializing the stream decoder, %s",
202                          LZMAStrerror(r));
203                 break;
204             }
205             sp->stream.next_in = next_in;
206             sp->stream.avail_in = avail_in;
207             continue;
208         }
209         if (ret != LZMA_OK) {
210             TIFFErrorExt(tif->tif_clientdata, module,
211                 "Decoding error at scanline %lu, %s",
212                 (unsigned long) tif->tif_row, LZMAStrerror(ret));
213             break;
214         }
215     } while (sp->stream.avail_out > 0);
216     if (sp->stream.avail_out != 0) {
217         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         return 0;
221     }
222 
223         tif->tif_rawcp = (uint8 *)sp->stream.next_in; /* cast away const */
224         tif->tif_rawcc = sp->stream.avail_in;
225 
226     return 1;
227 }
228 
229 static int
LZMASetupEncode(TIFF * tif)230 LZMASetupEncode(TIFF* tif)
231 {
232     LZMAState* sp = EncoderState(tif);
233 
234     assert(sp != NULL);
235     if (sp->state & LSTATE_INIT_DECODE) {
236         lzma_end(&sp->stream);
237         sp->state = 0;
238     }
239 
240     sp->state |= LSTATE_INIT_ENCODE;
241     return 1;
242 }
243 
244 /*
245  * Reset encoding state at the start of a strip.
246  */
247 static int
LZMAPreEncode(TIFF * tif,uint16 s)248 LZMAPreEncode(TIFF* tif, uint16 s)
249 {
250     static const char module[] = "LZMAPreEncode";
251     LZMAState *sp = EncoderState(tif);
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) {
261         TIFFErrorExt(tif->tif_clientdata, module,
262                  "Liblzma cannot deal with buffers this size");
263         return 0;
264     }
265     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
LZMAEncode(TIFF * tif,uint8 * bp,tmsize_t cc,uint16 s)272 LZMAEncode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
273 {
274     static const char module[] = "LZMAEncode";
275     LZMAState *sp = EncoderState(tif);
276 
277     assert(sp != NULL);
278     assert(sp->state == LSTATE_INIT_ENCODE);
279 
280     (void) s;
281     sp->stream.next_in = bp;
282     sp->stream.avail_in = (size_t) cc;
283     if ((tmsize_t)sp->stream.avail_in != cc) {
284         TIFFErrorExt(tif->tif_clientdata, module,
285                  "Liblzma cannot deal with buffers this size");
286         return 0;
287     }
288     do {
289         lzma_ret ret = lzma_code(&sp->stream, LZMA_RUN);
290         if (ret != LZMA_OK) {
291             TIFFErrorExt(tif->tif_clientdata, module,
292                 "Encoding error at scanline %lu, %s",
293                 (unsigned long) tif->tif_row, LZMAStrerror(ret));
294             return 0;
295         }
296         if (sp->stream.avail_out == 0) {
297             tif->tif_rawcc = tif->tif_rawdatasize;
298             TIFFFlushData1(tif);
299             sp->stream.next_out = tif->tif_rawdata;
300             sp->stream.avail_out = (size_t)tif->tif_rawdatasize;  /* this is a safe typecast, as check is made already in LZMAPreEncode */
301         }
302     } while (sp->stream.avail_in > 0);
303     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
LZMAPostEncode(TIFF * tif)311 LZMAPostEncode(TIFF* tif)
312 {
313     static const char module[] = "LZMAPostEncode";
314     LZMAState *sp = EncoderState(tif);
315     lzma_ret ret;
316 
317     sp->stream.avail_in = 0;
318     do {
319         ret = lzma_code(&sp->stream, LZMA_FINISH);
320         switch (ret) {
321         case LZMA_STREAM_END:
322         case LZMA_OK:
323             if ((tmsize_t)sp->stream.avail_out != tif->tif_rawdatasize) {
324                 tif->tif_rawcc =
325                     tif->tif_rawdatasize - sp->stream.avail_out;
326                 TIFFFlushData1(tif);
327                 sp->stream.next_out = tif->tif_rawdata;
328                 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             TIFFErrorExt(tif->tif_clientdata, module, "Liblzma error: %s",
333                      LZMAStrerror(ret));
334             return 0;
335         }
336     } while (ret != LZMA_STREAM_END);
337     return 1;
338 }
339 
340 static void
LZMACleanup(TIFF * tif)341 LZMACleanup(TIFF* tif)
342 {
343     LZMAState* sp = LState(tif);
344 
345     assert(sp != 0);
346 
347     (void)TIFFPredictorCleanup(tif);
348 
349     tif->tif_tagmethods.vgetfield = sp->vgetparent;
350     tif->tif_tagmethods.vsetfield = sp->vsetparent;
351 
352     if (sp->state) {
353         lzma_end(&sp->stream);
354         sp->state = 0;
355     }
356     _TIFFfree(sp);
357     tif->tif_data = NULL;
358 
359     _TIFFSetDefaultCompressionState(tif);
360 }
361 
362 static int
LZMAVSetField(TIFF * tif,uint32 tag,va_list ap)363 LZMAVSetField(TIFF* tif, uint32 tag, va_list ap)
364 {
365     static const char module[] = "LZMAVSetField";
366     LZMAState* sp = LState(tif);
367 
368     switch (tag) {
369     case TIFFTAG_LZMAPRESET:
370         sp->preset = (int) va_arg(ap, int);
371         lzma_lzma_preset(&sp->opt_lzma, sp->preset);
372         if (sp->state & LSTATE_INIT_ENCODE) {
373             lzma_ret ret = lzma_stream_encoder(&sp->stream,
374                                sp->filters,
375                                sp->check);
376             if (ret != LZMA_OK) {
377                 TIFFErrorExt(tif->tif_clientdata, module,
378                          "Liblzma error: %s",
379                          LZMAStrerror(ret));
380             }
381         }
382         return 1;
383     default:
384         return (*sp->vsetparent)(tif, tag, ap);
385     }
386     /*NOTREACHED*/
387 }
388 
389 static int
LZMAVGetField(TIFF * tif,uint32 tag,va_list ap)390 LZMAVGetField(TIFF* tif, uint32 tag, va_list ap)
391 {
392     LZMAState* sp = LState(tif);
393 
394     switch (tag) {
395     case TIFFTAG_LZMAPRESET:
396         *va_arg(ap, int*) = sp->preset;
397         break;
398     default:
399         return (*sp->vgetparent)(tif, tag, ap);
400     }
401     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
TIFFInitLZMA(TIFF * tif,int scheme)410 TIFFInitLZMA(TIFF* tif, int scheme)
411 {
412     static const char module[] = "TIFFInitLZMA";
413     LZMAState* sp;
414     lzma_stream tmp_stream = LZMA_STREAM_INIT;
415 
416     assert( scheme == COMPRESSION_LZMA );
417 
418     /*
419      * Merge codec-specific tag information.
420      */
421     if (!_TIFFMergeFields(tif, lzmaFields, TIFFArrayCount(lzmaFields))) {
422         TIFFErrorExt(tif->tif_clientdata, module,
423                  "Merging LZMA2 codec-specific tags failed");
424         return 0;
425     }
426 
427     /*
428      * Allocate state block so tag methods have storage to record values.
429      */
430     tif->tif_data = (uint8*) _TIFFmalloc(sizeof(LZMAState));
431     if (tif->tif_data == NULL)
432         goto bad;
433     sp = LState(tif);
434     memcpy(&sp->stream, &tmp_stream, sizeof(lzma_stream));
435 
436     /*
437      * Override parent get/set field methods.
438      */
439     sp->vgetparent = tif->tif_tagmethods.vgetfield;
440     tif->tif_tagmethods.vgetfield = LZMAVGetField;	/* hook for codec tags */
441     sp->vsetparent = tif->tif_tagmethods.vsetfield;
442     tif->tif_tagmethods.vsetfield = LZMAVSetField;	/* hook for codec tags */
443 
444     /* Default values for codec-specific fields */
445     sp->preset = LZMA_PRESET_DEFAULT;		/* default comp. level */
446     sp->check = LZMA_CHECK_NONE;
447     sp->state = 0;
448 
449     /* Data filters. So far we are using delta and LZMA2 filters only. */
450     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     sp->opt_delta.dist = (tif->tif_dir.td_bitspersample % 8) ?
456         1 : tif->tif_dir.td_bitspersample / 8;
457     sp->filters[0].id = LZMA_FILTER_DELTA;
458     sp->filters[0].options = &sp->opt_delta;
459 
460     lzma_lzma_preset(&sp->opt_lzma, sp->preset);
461     sp->filters[1].id = LZMA_FILTER_LZMA2;
462     sp->filters[1].options = &sp->opt_lzma;
463 
464     sp->filters[2].id = LZMA_VLI_UNKNOWN;
465     sp->filters[2].options = NULL;
466 
467     /*
468      * Install codec methods.
469      */
470     tif->tif_fixuptags = LZMAFixupTags;
471     tif->tif_setupdecode = LZMASetupDecode;
472     tif->tif_predecode = LZMAPreDecode;
473     tif->tif_decoderow = LZMADecode;
474     tif->tif_decodestrip = LZMADecode;
475     tif->tif_decodetile = LZMADecode;
476     tif->tif_setupencode = LZMASetupEncode;
477     tif->tif_preencode = LZMAPreEncode;
478     tif->tif_postencode = LZMAPostEncode;
479     tif->tif_encoderow = LZMAEncode;
480     tif->tif_encodestrip = LZMAEncode;
481     tif->tif_encodetile = LZMAEncode;
482     tif->tif_cleanup = LZMACleanup;
483     /*
484      * Setup predictor setup.
485      */
486     (void) TIFFPredictorInit(tif);
487     return 1;
488 bad:
489     TIFFErrorExt(tif->tif_clientdata, module,
490              "No space for LZMA2 state block");
491     return 0;
492 }
493 #endif /* LZMA_SUPORT */
494 
495 /* vim: set ts=8 sts=8 sw=8 noet: */
496