Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Tetragramm
GitHub Repository: Tetragramm/opencv
Path: blob/master/3rdparty/libtiff/tif_lzma.c
16337 views
1
/* $Id: tif_lzma.c,v 1.6 2016-09-17 09:18:59 erouault Exp $ */
2
3
/*
4
* Copyright (c) 2010, Andrey Kiselev <[email protected]>
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 "unidentified 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_SUPPORT */
494
495
/* vim: set ts=8 sts=8 sw=8 noet: */
496
497