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