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