Home | History | Annotate | Download | only in libtiff
      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 (at) 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