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