LCOV - code coverage report
Current view: directory - frmts/gtiff/libtiff - tif_lzma.c (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 204 0 0.0 %
Date: 2012-12-26 Functions: 13 0 0.0 %

       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@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               0 : LZMAStrerror(lzma_ret ret)
      71                 : {
      72               0 :   switch (ret) {
      73                 :     case LZMA_OK:
      74               0 :         return "operation completed successfully";
      75                 :     case LZMA_STREAM_END:
      76               0 :         return "end of stream was reached";
      77                 :     case LZMA_NO_CHECK:
      78               0 :         return "input stream has no integrity check";
      79                 :     case LZMA_UNSUPPORTED_CHECK:
      80               0 :         return "cannot calculate the integrity check";
      81                 :     case LZMA_GET_CHECK:
      82               0 :         return "integrity check type is now available";
      83                 :     case LZMA_MEM_ERROR:
      84               0 :         return "cannot allocate memory";
      85                 :     case LZMA_MEMLIMIT_ERROR:
      86               0 :         return "memory usage limit was reached";
      87                 :     case LZMA_FORMAT_ERROR:
      88               0 :         return "file format not recognized";
      89                 :     case LZMA_OPTIONS_ERROR:
      90               0 :         return "invalid or unsupported options";
      91                 :     case LZMA_DATA_ERROR:
      92               0 :         return "data is corrupt";
      93                 :     case LZMA_BUF_ERROR:
      94               0 :         return "no progress is possible (stream is truncated or corrupt)";
      95                 :     case LZMA_PROG_ERROR:
      96               0 :         return "programming error";
      97                 :     default:
      98               0 :         return "unindentified liblzma error";
      99                 :   }
     100                 : }
     101                 : 
     102                 : static int
     103               0 : LZMAFixupTags(TIFF* tif)
     104                 : {
     105                 :   (void) tif;
     106               0 :   return 1;
     107                 : }
     108                 : 
     109                 : static int
     110               0 : LZMASetupDecode(TIFF* tif)
     111                 : {
     112               0 :   LZMAState* sp = DecoderState(tif);
     113                 : 
     114               0 :   assert(sp != NULL);
     115                 :         
     116                 :         /* if we were last encoding, terminate this mode */
     117               0 :   if (sp->state & LSTATE_INIT_ENCODE) {
     118               0 :       lzma_end(&sp->stream);
     119               0 :       sp->state = 0;
     120                 :   }
     121                 : 
     122               0 :   sp->state |= LSTATE_INIT_DECODE;
     123               0 :   return 1;
     124                 : }
     125                 : 
     126                 : /*
     127                 :  * Setup state for decoding a strip.
     128                 :  */
     129                 : static int
     130               0 : LZMAPreDecode(TIFF* tif, uint16 s)
     131                 : {
     132                 :   static const char module[] = "LZMAPreDecode";
     133               0 :   LZMAState* sp = DecoderState(tif);
     134                 :   lzma_ret ret;
     135                 : 
     136                 :   (void) s;
     137               0 :   assert(sp != NULL);
     138                 : 
     139               0 :   if( (sp->state & LSTATE_INIT_DECODE) == 0 )
     140               0 :             tif->tif_setupdecode(tif);
     141                 : 
     142               0 :   sp->stream.next_in = tif->tif_rawdata;
     143               0 :   sp->stream.avail_in = (size_t) tif->tif_rawcc;
     144               0 :   if ((tmsize_t)sp->stream.avail_in != tif->tif_rawcc) {
     145               0 :     TIFFErrorExt(tif->tif_clientdata, module,
     146                 :            "Liblzma cannot deal with buffers this size");
     147               0 :     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               0 :   ret = lzma_stream_decoder(&sp->stream, (uint64_t)-1, 0);
     155               0 :   if (ret != LZMA_OK) {
     156               0 :     TIFFErrorExt(tif->tif_clientdata, module,
     157                 :            "Error initializing the stream decoder, %s",
     158                 :            LZMAStrerror(ret));
     159               0 :     return 0;
     160                 :   }
     161               0 :   return 1;
     162                 : }
     163                 : 
     164                 : static int
     165               0 : LZMADecode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s)
     166                 : {
     167                 :   static const char module[] = "LZMADecode";
     168               0 :   LZMAState* sp = DecoderState(tif);
     169                 : 
     170                 :   (void) s;
     171               0 :   assert(sp != NULL);
     172               0 :   assert(sp->state == LSTATE_INIT_DECODE);
     173                 : 
     174               0 :         sp->stream.next_in = tif->tif_rawcp;
     175               0 :         sp->stream.avail_in = (size_t) tif->tif_rawcc;
     176                 : 
     177               0 :   sp->stream.next_out = op;
     178               0 :   sp->stream.avail_out = (size_t) occ;
     179               0 :   if ((tmsize_t)sp->stream.avail_out != occ) {
     180               0 :     TIFFErrorExt(tif->tif_clientdata, module,
     181                 :            "Liblzma cannot deal with buffers this size");
     182               0 :     return 0;
     183                 :   }
     184                 : 
     185                 :   do {
     186                 :     /*
     187                 :      * Save the current stream state to properly recover from the
     188                 :      * decoding errors later.
     189                 :      */
     190               0 :     const uint8_t *next_in = sp->stream.next_in;
     191               0 :     size_t avail_in = sp->stream.avail_in;
     192                 : 
     193               0 :     lzma_ret ret = lzma_code(&sp->stream, LZMA_RUN);
     194               0 :     if (ret == LZMA_STREAM_END)
     195               0 :       break;
     196               0 :     if (ret == LZMA_MEMLIMIT_ERROR) {
     197               0 :       lzma_ret r = lzma_stream_decoder(&sp->stream,
     198               0 :                lzma_memusage(&sp->stream), 0);
     199               0 :       if (r != LZMA_OK) {
     200               0 :         TIFFErrorExt(tif->tif_clientdata, module,
     201                 :                "Error initializing the stream decoder, %s",
     202                 :                LZMAStrerror(r));
     203               0 :         break;
     204                 :       }
     205               0 :       sp->stream.next_in = next_in;
     206               0 :       sp->stream.avail_in = avail_in;
     207               0 :       continue;
     208                 :     }
     209               0 :     if (ret != LZMA_OK) {
     210               0 :       TIFFErrorExt(tif->tif_clientdata, module,
     211                 :           "Decoding error at scanline %lu, %s",
     212                 :           (unsigned long) tif->tif_row, LZMAStrerror(ret));
     213               0 :       break;
     214                 :     }
     215               0 :   } while (sp->stream.avail_out > 0);
     216               0 :   if (sp->stream.avail_out != 0) {
     217               0 :     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               0 :     return 0;
     221                 :   }
     222                 : 
     223               0 :         tif->tif_rawcp = (uint8 *)sp->stream.next_in; /* cast away const */
     224               0 :         tif->tif_rawcc = sp->stream.avail_in;
     225                 :         
     226               0 :   return 1;
     227                 : }
     228                 : 
     229                 : static int
     230               0 : LZMASetupEncode(TIFF* tif)
     231                 : {
     232               0 :   LZMAState* sp = EncoderState(tif);
     233                 : 
     234               0 :   assert(sp != NULL);
     235               0 :   if (sp->state & LSTATE_INIT_DECODE) {
     236               0 :     lzma_end(&sp->stream);
     237               0 :     sp->state = 0;
     238                 :   }
     239                 : 
     240               0 :   sp->state |= LSTATE_INIT_ENCODE;
     241               0 :   return 1;
     242                 : }
     243                 : 
     244                 : /*
     245                 :  * Reset encoding state at the start of a strip.
     246                 :  */
     247                 : static int
     248               0 : LZMAPreEncode(TIFF* tif, uint16 s)
     249                 : {
     250                 :   static const char module[] = "LZMAPreEncode";
     251               0 :   LZMAState *sp = EncoderState(tif);
     252                 : 
     253                 :   (void) s;
     254               0 :   assert(sp != NULL);
     255               0 :   if( sp->state != LSTATE_INIT_ENCODE )
     256               0 :             tif->tif_setupencode(tif);
     257                 : 
     258               0 :   sp->stream.next_out = tif->tif_rawdata;
     259               0 :   sp->stream.avail_out = (size_t)tif->tif_rawdatasize;
     260               0 :   if ((tmsize_t)sp->stream.avail_out != tif->tif_rawdatasize) {
     261               0 :     TIFFErrorExt(tif->tif_clientdata, module,
     262                 :            "Liblzma cannot deal with buffers this size");
     263               0 :     return 0;
     264                 :   }
     265               0 :   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               0 : LZMAEncode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
     273                 : {
     274                 :   static const char module[] = "LZMAEncode";
     275               0 :   LZMAState *sp = EncoderState(tif);
     276                 : 
     277               0 :   assert(sp != NULL);
     278               0 :   assert(sp->state == LSTATE_INIT_ENCODE);
     279                 : 
     280                 :   (void) s;
     281               0 :   sp->stream.next_in = bp;
     282               0 :   sp->stream.avail_in = (size_t) cc;
     283               0 :   if ((tmsize_t)sp->stream.avail_in != cc) {
     284               0 :     TIFFErrorExt(tif->tif_clientdata, module,
     285                 :            "Liblzma cannot deal with buffers this size");
     286               0 :     return 0;
     287                 :   }
     288                 :   do {
     289               0 :     lzma_ret ret = lzma_code(&sp->stream, LZMA_RUN);
     290               0 :     if (ret != LZMA_OK) {
     291               0 :       TIFFErrorExt(tif->tif_clientdata, module,
     292                 :         "Encoding error at scanline %lu, %s",
     293                 :         (unsigned long) tif->tif_row, LZMAStrerror(ret));
     294               0 :       return 0;
     295                 :     }
     296               0 :     if (sp->stream.avail_out == 0) {
     297               0 :       tif->tif_rawcc = tif->tif_rawdatasize;
     298               0 :       TIFFFlushData1(tif);
     299               0 :       sp->stream.next_out = tif->tif_rawdata;
     300               0 :       sp->stream.avail_out = (size_t)tif->tif_rawdatasize;  /* this is a safe typecast, as check is made already in LZMAPreEncode */
     301                 :     }
     302               0 :   } while (sp->stream.avail_in > 0);
     303               0 :   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               0 : LZMAPostEncode(TIFF* tif)
     312                 : {
     313                 :   static const char module[] = "LZMAPostEncode";
     314               0 :   LZMAState *sp = EncoderState(tif);
     315                 :   lzma_ret ret;
     316                 : 
     317               0 :   sp->stream.avail_in = 0;
     318                 :   do {
     319               0 :     ret = lzma_code(&sp->stream, LZMA_FINISH);
     320               0 :     switch (ret) {
     321                 :     case LZMA_STREAM_END:
     322                 :     case LZMA_OK:
     323               0 :       if ((tmsize_t)sp->stream.avail_out != tif->tif_rawdatasize) {
     324               0 :         tif->tif_rawcc =
     325               0 :           tif->tif_rawdatasize - sp->stream.avail_out;
     326               0 :         TIFFFlushData1(tif);
     327               0 :         sp->stream.next_out = tif->tif_rawdata;
     328               0 :         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               0 :       TIFFErrorExt(tif->tif_clientdata, module, "Liblzma error: %s",
     333                 :              LZMAStrerror(ret));
     334               0 :       return 0;
     335                 :     }
     336               0 :   } while (ret != LZMA_STREAM_END);
     337               0 :   return 1;
     338                 : }
     339                 : 
     340                 : static void
     341               0 : LZMACleanup(TIFF* tif)
     342                 : {
     343               0 :   LZMAState* sp = LState(tif);
     344                 : 
     345               0 :   assert(sp != 0);
     346                 : 
     347               0 :   (void)TIFFPredictorCleanup(tif);
     348                 : 
     349               0 :   tif->tif_tagmethods.vgetfield = sp->vgetparent;
     350               0 :   tif->tif_tagmethods.vsetfield = sp->vsetparent;
     351                 : 
     352               0 :   if (sp->state) {
     353               0 :     lzma_end(&sp->stream);
     354               0 :     sp->state = 0;
     355                 :   }
     356               0 :   _TIFFfree(sp);
     357               0 :   tif->tif_data = NULL;
     358                 : 
     359               0 :   _TIFFSetDefaultCompressionState(tif);
     360               0 : }
     361                 : 
     362                 : static int
     363               0 : LZMAVSetField(TIFF* tif, uint32 tag, va_list ap)
     364                 : {
     365                 :   static const char module[] = "LZMAVSetField";
     366               0 :   LZMAState* sp = LState(tif);
     367                 : 
     368               0 :   switch (tag) {
     369                 :   case TIFFTAG_LZMAPRESET:
     370               0 :     sp->preset = (int) va_arg(ap, int);
     371               0 :     lzma_lzma_preset(&sp->opt_lzma, sp->preset);
     372               0 :     if (sp->state & LSTATE_INIT_ENCODE) {
     373               0 :       lzma_ret ret = lzma_stream_encoder(&sp->stream,
     374                 :                  sp->filters,
     375               0 :                  sp->check);
     376               0 :       if (ret != LZMA_OK) {
     377               0 :         TIFFErrorExt(tif->tif_clientdata, module,
     378                 :                "Liblzma error: %s",
     379                 :                LZMAStrerror(ret));
     380                 :       }
     381                 :     }
     382               0 :     return 1;
     383                 :   default:
     384               0 :     return (*sp->vsetparent)(tif, tag, ap);
     385                 :   }
     386                 :   /*NOTREACHED*/
     387                 : }
     388                 : 
     389                 : static int
     390               0 : LZMAVGetField(TIFF* tif, uint32 tag, va_list ap)
     391                 : {
     392               0 :   LZMAState* sp = LState(tif);
     393                 : 
     394               0 :   switch (tag) {
     395                 :   case TIFFTAG_LZMAPRESET:
     396               0 :     *va_arg(ap, int*) = sp->preset;
     397                 :     break;
     398                 :   default:
     399               0 :     return (*sp->vgetparent)(tif, tag, ap);
     400                 :   }
     401               0 :   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               0 : TIFFInitLZMA(TIFF* tif, int scheme)
     411                 : {
     412                 :   static const char module[] = "TIFFInitLZMA";
     413                 :   LZMAState* sp;
     414               0 :   lzma_stream tmp_stream = LZMA_STREAM_INIT;
     415                 : 
     416               0 :   assert( scheme == COMPRESSION_LZMA );
     417                 : 
     418                 :   /*
     419                 :    * Merge codec-specific tag information.
     420                 :    */
     421               0 :   if (!_TIFFMergeFields(tif, lzmaFields, TIFFArrayCount(lzmaFields))) {
     422               0 :     TIFFErrorExt(tif->tif_clientdata, module,
     423                 :            "Merging LZMA2 codec-specific tags failed");
     424               0 :     return 0;
     425                 :   }
     426                 : 
     427                 :   /*
     428                 :    * Allocate state block so tag methods have storage to record values.
     429                 :    */
     430               0 :   tif->tif_data = (uint8*) _TIFFmalloc(sizeof(LZMAState));
     431               0 :   if (tif->tif_data == NULL)
     432               0 :     goto bad;
     433               0 :   sp = LState(tif);
     434               0 :   memcpy(&sp->stream, &tmp_stream, sizeof(lzma_stream));
     435                 : 
     436                 :   /*
     437                 :    * Override parent get/set field methods.
     438                 :    */
     439               0 :   sp->vgetparent = tif->tif_tagmethods.vgetfield;
     440               0 :   tif->tif_tagmethods.vgetfield = LZMAVGetField; /* hook for codec tags */
     441               0 :   sp->vsetparent = tif->tif_tagmethods.vsetfield;
     442               0 :   tif->tif_tagmethods.vsetfield = LZMAVSetField; /* hook for codec tags */
     443                 : 
     444                 :   /* Default values for codec-specific fields */
     445               0 :   sp->preset = LZMA_PRESET_DEFAULT;    /* default comp. level */
     446               0 :   sp->check = LZMA_CHECK_NONE;
     447               0 :   sp->state = 0;
     448                 : 
     449                 :   /* Data filters. So far we are using delta and LZMA2 filters only. */
     450               0 :   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               0 :   sp->opt_delta.dist = (tif->tif_dir.td_bitspersample % 8) ?
     456                 :     1 : tif->tif_dir.td_bitspersample / 8;
     457               0 :   sp->filters[0].id = LZMA_FILTER_DELTA;
     458               0 :   sp->filters[0].options = &sp->opt_delta;
     459                 : 
     460               0 :   lzma_lzma_preset(&sp->opt_lzma, sp->preset);
     461               0 :   sp->filters[1].id = LZMA_FILTER_LZMA2;
     462               0 :   sp->filters[1].options = &sp->opt_lzma;
     463                 : 
     464               0 :   sp->filters[2].id = LZMA_VLI_UNKNOWN;
     465               0 :   sp->filters[2].options = NULL;
     466                 : 
     467                 :   /*
     468                 :    * Install codec methods.
     469                 :    */
     470               0 :   tif->tif_fixuptags = LZMAFixupTags;
     471               0 :   tif->tif_setupdecode = LZMASetupDecode;
     472               0 :   tif->tif_predecode = LZMAPreDecode;
     473               0 :   tif->tif_decoderow = LZMADecode;
     474               0 :   tif->tif_decodestrip = LZMADecode;
     475               0 :   tif->tif_decodetile = LZMADecode;
     476               0 :   tif->tif_setupencode = LZMASetupEncode;
     477               0 :   tif->tif_preencode = LZMAPreEncode;
     478               0 :   tif->tif_postencode = LZMAPostEncode;
     479               0 :   tif->tif_encoderow = LZMAEncode;
     480               0 :   tif->tif_encodestrip = LZMAEncode;
     481               0 :   tif->tif_encodetile = LZMAEncode;
     482               0 :   tif->tif_cleanup = LZMACleanup;
     483                 :   /*
     484                 :    * Setup predictor setup.
     485                 :    */
     486               0 :   (void) TIFFPredictorInit(tif);
     487               0 :   return 1;
     488                 : bad:
     489               0 :   TIFFErrorExt(tif->tif_clientdata, module,
     490                 :          "No space for LZMA2 state block");
     491               0 :   return 0;
     492                 : }
     493                 : #endif /* LZMA_SUPORT */
     494                 : 
     495                 : /* vim: set ts=8 sts=8 sw=8 noet: */

Generated by: LCOV version 1.7