| /* |
| * Copyright (c) 1988-1997 Sam Leffler |
| * Copyright (c) 1991-1997 Silicon Graphics, Inc. |
| * |
| * Permission to use, copy, modify, distribute, and sell this software and |
| * its documentation for any purpose is hereby granted without fee, provided |
| * that (i) the above copyright notices and this permission notice appear in |
| * all copies of the software and related documentation, and (ii) the names of |
| * Sam Leffler and Silicon Graphics may not be used in any advertising or |
| * publicity relating to the software without the specific, prior written |
| * permission of Sam Leffler and Silicon Graphics. |
| * |
| * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, |
| * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY |
| * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. |
| * |
| * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR |
| * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, |
| * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, |
| * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF |
| * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE |
| * OF THIS SOFTWARE. |
| */ |
| |
| /* |
| * TIFF Library |
| * |
| * Compression Scheme Configuration Support. |
| */ |
| #include "tiffiop.h" |
| |
| static int TIFFNoEncode(TIFF *tif, const char *method) |
| { |
| const TIFFCodec *c = TIFFFindCODEC(tif->tif_dir.td_compression); |
| |
| if (c) |
| { |
| TIFFErrorExtR(tif, tif->tif_name, "%s %s encoding is not implemented", |
| c->name, method); |
| } |
| else |
| { |
| TIFFErrorExtR(tif, tif->tif_name, |
| "Compression scheme %" PRIu16 |
| " %s encoding is not implemented", |
| tif->tif_dir.td_compression, method); |
| } |
| return (-1); |
| } |
| |
| int _TIFFNoRowEncode(TIFF *tif, uint8_t *pp, tmsize_t cc, uint16_t s) |
| { |
| (void)pp; |
| (void)cc; |
| (void)s; |
| return (TIFFNoEncode(tif, "scanline")); |
| } |
| |
| int _TIFFNoStripEncode(TIFF *tif, uint8_t *pp, tmsize_t cc, uint16_t s) |
| { |
| (void)pp; |
| (void)cc; |
| (void)s; |
| return (TIFFNoEncode(tif, "strip")); |
| } |
| |
| int _TIFFNoTileEncode(TIFF *tif, uint8_t *pp, tmsize_t cc, uint16_t s) |
| { |
| (void)pp; |
| (void)cc; |
| (void)s; |
| return (TIFFNoEncode(tif, "tile")); |
| } |
| |
| static int TIFFNoDecode(TIFF *tif, const char *method) |
| { |
| const TIFFCodec *c = TIFFFindCODEC(tif->tif_dir.td_compression); |
| |
| if (c) |
| TIFFErrorExtR(tif, tif->tif_name, "%s %s decoding is not implemented", |
| c->name, method); |
| else |
| TIFFErrorExtR(tif, tif->tif_name, |
| "Compression scheme %" PRIu16 |
| " %s decoding is not implemented", |
| tif->tif_dir.td_compression, method); |
| return (0); |
| } |
| |
| static int _TIFFNoFixupTags(TIFF *tif) |
| { |
| (void)tif; |
| return (1); |
| } |
| |
| int _TIFFNoRowDecode(TIFF *tif, uint8_t *pp, tmsize_t cc, uint16_t s) |
| { |
| (void)pp; |
| (void)cc; |
| (void)s; |
| return (TIFFNoDecode(tif, "scanline")); |
| } |
| |
| int _TIFFNoStripDecode(TIFF *tif, uint8_t *pp, tmsize_t cc, uint16_t s) |
| { |
| (void)pp; |
| (void)cc; |
| (void)s; |
| return (TIFFNoDecode(tif, "strip")); |
| } |
| |
| int _TIFFNoTileDecode(TIFF *tif, uint8_t *pp, tmsize_t cc, uint16_t s) |
| { |
| (void)pp; |
| (void)cc; |
| (void)s; |
| return (TIFFNoDecode(tif, "tile")); |
| } |
| |
| int _TIFFNoSeek(TIFF *tif, uint32_t off) |
| { |
| (void)off; |
| TIFFErrorExtR(tif, tif->tif_name, |
| "Compression algorithm does not support random access"); |
| return (0); |
| } |
| |
| int _TIFFNoPreCode(TIFF *tif, uint16_t s) |
| { |
| (void)tif; |
| (void)s; |
| return (1); |
| } |
| |
| static int _TIFFtrue(TIFF *tif) |
| { |
| (void)tif; |
| return (1); |
| } |
| static void _TIFFvoid(TIFF *tif) { (void)tif; } |
| |
| void _TIFFSetDefaultCompressionState(TIFF *tif) |
| { |
| tif->tif_fixuptags = _TIFFNoFixupTags; |
| tif->tif_decodestatus = TRUE; |
| tif->tif_setupdecode = _TIFFtrue; |
| tif->tif_predecode = _TIFFNoPreCode; |
| tif->tif_decoderow = _TIFFNoRowDecode; |
| tif->tif_decodestrip = _TIFFNoStripDecode; |
| tif->tif_decodetile = _TIFFNoTileDecode; |
| tif->tif_encodestatus = TRUE; |
| tif->tif_setupencode = _TIFFtrue; |
| tif->tif_preencode = _TIFFNoPreCode; |
| tif->tif_postencode = _TIFFtrue; |
| tif->tif_encoderow = _TIFFNoRowEncode; |
| tif->tif_encodestrip = _TIFFNoStripEncode; |
| tif->tif_encodetile = _TIFFNoTileEncode; |
| tif->tif_close = _TIFFvoid; |
| tif->tif_seek = _TIFFNoSeek; |
| tif->tif_cleanup = _TIFFvoid; |
| tif->tif_defstripsize = _TIFFDefaultStripSize; |
| tif->tif_deftilesize = _TIFFDefaultTileSize; |
| tif->tif_flags &= ~(TIFF_NOBITREV | TIFF_NOREADRAW); |
| } |
| |
| int TIFFSetCompressionScheme(TIFF *tif, int scheme) |
| { |
| const TIFFCodec *c = TIFFFindCODEC((uint16_t)scheme); |
| |
| _TIFFSetDefaultCompressionState(tif); |
| /* |
| * Don't treat an unknown compression scheme as an error. |
| * This permits applications to open files with data that |
| * the library does not have builtin support for, but which |
| * may still be meaningful. |
| */ |
| return (c ? (*c->init)(tif, scheme) : 1); |
| } |
| |
| /* |
| * Other compression schemes may be registered. Registered |
| * schemes can also override the builtin versions provided |
| * by this library. |
| */ |
| typedef struct _codec |
| { |
| struct _codec *next; |
| TIFFCodec *info; |
| } codec_t; |
| static codec_t *registeredCODECS = NULL; |
| |
| const TIFFCodec *TIFFFindCODEC(uint16_t scheme) |
| { |
| const TIFFCodec *c; |
| codec_t *cd; |
| |
| for (cd = registeredCODECS; cd; cd = cd->next) |
| if (cd->info->scheme == scheme) |
| return ((const TIFFCodec *)cd->info); |
| for (c = _TIFFBuiltinCODECS; c->name; c++) |
| if (c->scheme == scheme) |
| return (c); |
| return ((const TIFFCodec *)0); |
| } |
| |
| TIFFCodec *TIFFRegisterCODEC(uint16_t scheme, const char *name, |
| TIFFInitMethod init) |
| { |
| codec_t *cd = (codec_t *)_TIFFmallocExt( |
| NULL, |
| (tmsize_t)(sizeof(codec_t) + sizeof(TIFFCodec) + strlen(name) + 1)); |
| |
| if (cd != NULL) |
| { |
| cd->info = (TIFFCodec *)((uint8_t *)cd + sizeof(codec_t)); |
| cd->info->name = (char *)((uint8_t *)cd->info + sizeof(TIFFCodec)); |
| strcpy(cd->info->name, name); |
| cd->info->scheme = scheme; |
| cd->info->init = init; |
| cd->next = registeredCODECS; |
| registeredCODECS = cd; |
| } |
| else |
| { |
| TIFFErrorExt(0, "TIFFRegisterCODEC", |
| "No space to register compression scheme %s", name); |
| return NULL; |
| } |
| return (cd->info); |
| } |
| |
| void TIFFUnRegisterCODEC(TIFFCodec *c) |
| { |
| codec_t *cd; |
| codec_t **pcd; |
| |
| for (pcd = ®isteredCODECS; (cd = *pcd) != NULL; pcd = &cd->next) |
| if (cd->info == c) |
| { |
| *pcd = cd->next; |
| _TIFFfreeExt(NULL, cd); |
| return; |
| } |
| TIFFErrorExt(0, "TIFFUnRegisterCODEC", |
| "Cannot remove compression scheme %s; not registered", |
| c->name); |
| } |
| |
| /************************************************************************/ |
| /* TIFFGetConfisuredCODECs() */ |
| /************************************************************************/ |
| |
| /** |
| * Get list of configured codecs, both built-in and registered by user. |
| * Caller is responsible to free this structure. |
| * |
| * @return returns array of TIFFCodec records (the last record should be NULL) |
| * or NULL if function failed. |
| */ |
| |
| TIFFCodec *TIFFGetConfiguredCODECs() |
| { |
| int i = 1; |
| codec_t *cd; |
| const TIFFCodec *c; |
| TIFFCodec *codecs = NULL; |
| TIFFCodec *new_codecs; |
| |
| for (cd = registeredCODECS; cd; cd = cd->next) |
| { |
| new_codecs = |
| (TIFFCodec *)_TIFFreallocExt(NULL, codecs, i * sizeof(TIFFCodec)); |
| if (!new_codecs) |
| { |
| _TIFFfreeExt(NULL, codecs); |
| return NULL; |
| } |
| codecs = new_codecs; |
| _TIFFmemcpy(codecs + i - 1, cd->info, sizeof(TIFFCodec)); |
| i++; |
| } |
| for (c = _TIFFBuiltinCODECS; c->name; c++) |
| { |
| if (TIFFIsCODECConfigured(c->scheme)) |
| { |
| new_codecs = (TIFFCodec *)_TIFFreallocExt(NULL, codecs, |
| i * sizeof(TIFFCodec)); |
| if (!new_codecs) |
| { |
| _TIFFfreeExt(NULL, codecs); |
| return NULL; |
| } |
| codecs = new_codecs; |
| _TIFFmemcpy(codecs + i - 1, (const void *)c, sizeof(TIFFCodec)); |
| i++; |
| } |
| } |
| |
| new_codecs = |
| (TIFFCodec *)_TIFFreallocExt(NULL, codecs, i * sizeof(TIFFCodec)); |
| if (!new_codecs) |
| { |
| _TIFFfreeExt(NULL, codecs); |
| return NULL; |
| } |
| codecs = new_codecs; |
| _TIFFmemset(codecs + i - 1, 0, sizeof(TIFFCodec)); |
| |
| return codecs; |
| } |