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