Home | History | Annotate | Download | only in libtiff
      1 /* $Id: tif_compress.c,v 1.25 2016-10-25 20:04:22 erouault 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 (0);
     86 }
     87 
     88 static 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) != NULL; 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