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