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