Home | History | Annotate | Download | only in libtiff
      1 /* $Id: tif_compress.c,v 1.22 2010-03-10 18:56:48 bfriesen Exp $ */
      2 
      3 /*
      4  * Copyright (c) 1988-1997 Sam Leffler
      5  * Copyright (c) 1991-1997 Silicon Graphics, Inc.
      6  *
      7  * Permission to use, copy, modify, distribute, and sell this software and
      8  * its documentation for any purpose is hereby granted without fee, provided
      9  * that (i) the above copyright notices and this permission notice appear in
     10  * all copies of the software and related documentation, and (ii) the names of
     11  * Sam Leffler and Silicon Graphics may not be used in any advertising or
     12  * publicity relating to the software without the specific, prior written
     13  * permission of Sam Leffler and Silicon Graphics.
     14  *
     15  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
     16  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
     17  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
     18  *
     19  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
     20  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
     21  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
     22  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
     23  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
     24  * OF THIS SOFTWARE.
     25  */
     26 
     27 /*
     28  * TIFF Library
     29  *
     30  * Compression Scheme Configuration Support.
     31  */
     32 #include "tiffiop.h"
     33 
     34 static int
     35 TIFFNoEncode(TIFF* tif, const char* method)
     36 {
     37     const TIFFCodec* c = TIFFFindCODEC(tif->tif_dir.td_compression);
     38 
     39     if (c) {
     40         TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
     41                  "%s %s encoding is not implemented",
     42                  c->name, method);
     43     } else {
     44         TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
     45             "Compression scheme %u %s encoding is not implemented",
     46                  tif->tif_dir.td_compression, method);
     47     }
     48     return (-1);
     49 }
     50 
     51 int
     52 _TIFFNoRowEncode(TIFF* tif, uint8* pp, tmsize_t cc, uint16 s)
     53 {
     54     (void) pp; (void) cc; (void) s;
     55     return (TIFFNoEncode(tif, "scanline"));
     56 }
     57 
     58 int
     59 _TIFFNoStripEncode(TIFF* tif, uint8* pp, tmsize_t cc, uint16 s)
     60 {
     61     (void) pp; (void) cc; (void) s;
     62     return (TIFFNoEncode(tif, "strip"));
     63 }
     64 
     65 int
     66 _TIFFNoTileEncode(TIFF* tif, uint8* pp, tmsize_t cc, uint16 s)
     67 {
     68     (void) pp; (void) cc; (void) s;
     69     return (TIFFNoEncode(tif, "tile"));
     70 }
     71 
     72 static int
     73 TIFFNoDecode(TIFF* tif, const char* method)
     74 {
     75     const TIFFCodec* c = TIFFFindCODEC(tif->tif_dir.td_compression);
     76 
     77     if (c)
     78         TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
     79                  "%s %s decoding is not implemented",
     80                  c->name, method);
     81     else
     82         TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
     83                  "Compression scheme %u %s decoding is not implemented",
     84                  tif->tif_dir.td_compression, method);
     85     return (-1);
     86 }
     87 
     88 int
     89 _TIFFNoFixupTags(TIFF* tif)
     90 {
     91     (void) tif;
     92     return (1);
     93 }
     94 
     95 int
     96 _TIFFNoRowDecode(TIFF* tif, uint8* pp, tmsize_t cc, uint16 s)
     97 {
     98     (void) pp; (void) cc; (void) s;
     99     return (TIFFNoDecode(tif, "scanline"));
    100 }
    101 
    102 int
    103 _TIFFNoStripDecode(TIFF* tif, uint8* pp, tmsize_t cc, uint16 s)
    104 {
    105     (void) pp; (void) cc; (void) s;
    106     return (TIFFNoDecode(tif, "strip"));
    107 }
    108 
    109 int
    110 _TIFFNoTileDecode(TIFF* tif, uint8* pp, tmsize_t cc, uint16 s)
    111 {
    112     (void) pp; (void) cc; (void) s;
    113     return (TIFFNoDecode(tif, "tile"));
    114 }
    115 
    116 int
    117 _TIFFNoSeek(TIFF* tif, uint32 off)
    118 {
    119     (void) off;
    120     TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
    121              "Compression algorithm does not support random access");
    122     return (0);
    123 }
    124 
    125 int
    126 _TIFFNoPreCode(TIFF* tif, uint16 s)
    127 {
    128     (void) tif; (void) s;
    129     return (1);
    130 }
    131 
    132 static int _TIFFtrue(TIFF* tif) { (void) tif; return (1); }
    133 static void _TIFFvoid(TIFF* tif) { (void) tif; }
    134 
    135 void
    136 _TIFFSetDefaultCompressionState(TIFF* tif)
    137 {
    138     tif->tif_fixuptags = _TIFFNoFixupTags;
    139     tif->tif_decodestatus = TRUE;
    140     tif->tif_setupdecode = _TIFFtrue;
    141     tif->tif_predecode = _TIFFNoPreCode;
    142     tif->tif_decoderow = _TIFFNoRowDecode;
    143     tif->tif_decodestrip = _TIFFNoStripDecode;
    144     tif->tif_decodetile = _TIFFNoTileDecode;
    145     tif->tif_encodestatus = TRUE;
    146     tif->tif_setupencode = _TIFFtrue;
    147     tif->tif_preencode = _TIFFNoPreCode;
    148     tif->tif_postencode = _TIFFtrue;
    149     tif->tif_encoderow = _TIFFNoRowEncode;
    150     tif->tif_encodestrip = _TIFFNoStripEncode;
    151     tif->tif_encodetile = _TIFFNoTileEncode;
    152     tif->tif_close = _TIFFvoid;
    153     tif->tif_seek = _TIFFNoSeek;
    154     tif->tif_cleanup = _TIFFvoid;
    155     tif->tif_defstripsize = _TIFFDefaultStripSize;
    156     tif->tif_deftilesize = _TIFFDefaultTileSize;
    157     tif->tif_flags &= ~(TIFF_NOBITREV|TIFF_NOREADRAW);
    158 }
    159 
    160 int
    161 TIFFSetCompressionScheme(TIFF* tif, int scheme)
    162 {
    163     const TIFFCodec *c = TIFFFindCODEC((uint16) scheme);
    164 
    165     _TIFFSetDefaultCompressionState(tif);
    166     /*
    167      * Don't treat an unknown compression scheme as an error.
    168      * This permits applications to open files with data that
    169      * the library does not have builtin support for, but which
    170      * may still be meaningful.
    171      */
    172     return (c ? (*c->init)(tif, scheme) : 1);
    173 }
    174 
    175 /*
    176  * Other compression schemes may be registered.  Registered
    177  * schemes can also override the builtin versions provided
    178  * by this library.
    179  */
    180 typedef struct _codec {
    181     struct _codec* next;
    182     TIFFCodec* info;
    183 } codec_t;
    184 static codec_t* registeredCODECS = NULL;
    185 
    186 const TIFFCodec*
    187 TIFFFindCODEC(uint16 scheme)
    188 {
    189     const TIFFCodec* c;
    190     codec_t* cd;
    191 
    192     for (cd = registeredCODECS; cd; cd = cd->next)
    193         if (cd->info->scheme == scheme)
    194             return ((const TIFFCodec*) cd->info);
    195     for (c = _TIFFBuiltinCODECS; c->name; c++)
    196         if (c->scheme == scheme)
    197             return (c);
    198     return ((const TIFFCodec*) 0);
    199 }
    200 
    201 TIFFCodec*
    202 TIFFRegisterCODEC(uint16 scheme, const char* name, TIFFInitMethod init)
    203 {
    204     codec_t* cd = (codec_t*)
    205         _TIFFmalloc((tmsize_t)(sizeof (codec_t) + sizeof (TIFFCodec) + strlen(name)+1));
    206 
    207     if (cd != NULL) {
    208         cd->info = (TIFFCodec*) ((uint8*) cd + sizeof (codec_t));
    209         cd->info->name = (char*)
    210             ((uint8*) cd->info + sizeof (TIFFCodec));
    211         strcpy(cd->info->name, name);
    212         cd->info->scheme = scheme;
    213         cd->info->init = init;
    214         cd->next = registeredCODECS;
    215         registeredCODECS = cd;
    216     } else {
    217         TIFFErrorExt(0, "TIFFRegisterCODEC",
    218             "No space to register compression scheme %s", name);
    219         return NULL;
    220     }
    221     return (cd->info);
    222 }
    223 
    224 void
    225 TIFFUnRegisterCODEC(TIFFCodec* c)
    226 {
    227     codec_t* cd;
    228     codec_t** pcd;
    229 
    230     for (pcd = &registeredCODECS; (cd = *pcd); pcd = &cd->next)
    231         if (cd->info == c) {
    232             *pcd = cd->next;
    233             _TIFFfree(cd);
    234             return;
    235         }
    236     TIFFErrorExt(0, "TIFFUnRegisterCODEC",
    237         "Cannot remove compression scheme %s; not registered", c->name);
    238 }
    239 
    240 /************************************************************************/
    241 /*                       TIFFGetConfisuredCODECs()                      */
    242 /************************************************************************/
    243 
    244 /**
    245  * Get list of configured codecs, both built-in and registered by user.
    246  * Caller is responsible to free this structure.
    247  *
    248  * @return returns array of TIFFCodec records (the last record should be NULL)
    249  * or NULL if function failed.
    250  */
    251 
    252 TIFFCodec*
    253 TIFFGetConfiguredCODECs()
    254 {
    255     int i = 1;
    256     codec_t *cd;
    257     const TIFFCodec* c;
    258     TIFFCodec* codecs = NULL;
    259     TIFFCodec* new_codecs;
    260 
    261     for (cd = registeredCODECS; cd; cd = cd->next) {
    262         new_codecs = (TIFFCodec *)
    263             _TIFFrealloc(codecs, i * sizeof(TIFFCodec));
    264         if (!new_codecs) {
    265             _TIFFfree (codecs);
    266             return NULL;
    267         }
    268         codecs = new_codecs;
    269         _TIFFmemcpy(codecs + i - 1, cd, sizeof(TIFFCodec));
    270         i++;
    271     }
    272     for (c = _TIFFBuiltinCODECS; c->name; c++) {
    273         if (TIFFIsCODECConfigured(c->scheme)) {
    274             new_codecs = (TIFFCodec *)
    275                 _TIFFrealloc(codecs, i * sizeof(TIFFCodec));
    276             if (!new_codecs) {
    277                 _TIFFfree (codecs);
    278                 return NULL;
    279             }
    280             codecs = new_codecs;
    281             _TIFFmemcpy(codecs + i - 1, (const void*)c, sizeof(TIFFCodec));
    282             i++;
    283         }
    284     }
    285 
    286     new_codecs = (TIFFCodec *) _TIFFrealloc(codecs, i * sizeof(TIFFCodec));
    287     if (!new_codecs) {
    288         _TIFFfree (codecs);
    289         return NULL;
    290     }
    291     codecs = new_codecs;
    292     _TIFFmemset(codecs + i - 1, 0, sizeof(TIFFCodec));
    293 
    294     return codecs;
    295 }
    296 
    297 /* vim: set ts=8 sts=8 sw=8 noet: */
    298 /*
    299  * Local Variables:
    300  * mode: c
    301  * c-basic-offset: 8
    302  * fill-column: 78
    303  * End:
    304  */
    305