blob: dedf1d948b5f3086775316339c99f7063fece1c0
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 | 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 |
103 | LZMAFixupTags(TIFF* tif) |
104 | { |
105 | (void) tif; |
106 | return 1; |
107 | } |
108 | |
109 | static int |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |