|  | /* | 
|  | * 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. | 
|  | */ | 
|  |  | 
|  | #include "tiffiop.h" | 
|  | #include <assert.h> | 
|  | #ifdef THUNDER_SUPPORT | 
|  | /* | 
|  | * TIFF Library. | 
|  | * | 
|  | * ThunderScan 4-bit Compression Algorithm Support | 
|  | */ | 
|  |  | 
|  | /* | 
|  | * ThunderScan uses an encoding scheme designed for | 
|  | * 4-bit pixel values.  Data is encoded in bytes, with | 
|  | * each byte split into a 2-bit code word and a 6-bit | 
|  | * data value.  The encoding gives raw data, runs of | 
|  | * pixels, or pixel values encoded as a delta from the | 
|  | * previous pixel value.  For the latter, either 2-bit | 
|  | * or 3-bit delta values are used, with the deltas packed | 
|  | * into a single byte. | 
|  | */ | 
|  | #define	THUNDER_DATA		0x3f	/* mask for 6-bit data */ | 
|  | #define	THUNDER_CODE		0xc0	/* mask for 2-bit code word */ | 
|  | /* code values */ | 
|  | #define	THUNDER_RUN		0x00	/* run of pixels w/ encoded count */ | 
|  | #define	THUNDER_2BITDELTAS	0x40	/* 3 pixels w/ encoded 2-bit deltas */ | 
|  | #define	    DELTA2_SKIP		2	/* skip code for 2-bit deltas */ | 
|  | #define	THUNDER_3BITDELTAS	0x80	/* 2 pixels w/ encoded 3-bit deltas */ | 
|  | #define	    DELTA3_SKIP		4	/* skip code for 3-bit deltas */ | 
|  | #define	THUNDER_RAW		0xc0	/* raw data encoded */ | 
|  |  | 
|  | static const int twobitdeltas[4] = { 0, 1, 0, -1 }; | 
|  | static const int threebitdeltas[8] = { 0, 1, 2, 3, 0, -3, -2, -1 }; | 
|  |  | 
|  | #define	SETPIXEL(op, v) {                     \ | 
|  | lastpixel = (v) & 0xf;                \ | 
|  | if ( npixels < maxpixels )         \ | 
|  | {                                     \ | 
|  | if (npixels++ & 1)                  \ | 
|  | *op++ |= lastpixel;               \ | 
|  | else                                \ | 
|  | op[0] = (uint8) (lastpixel << 4); \ | 
|  | }                                     \ | 
|  | } | 
|  |  | 
|  | static int | 
|  | ThunderSetupDecode(TIFF* tif) | 
|  | { | 
|  | static const char module[] = "ThunderSetupDecode"; | 
|  |  | 
|  | if( tif->tif_dir.td_bitspersample != 4 ) | 
|  | { | 
|  | TIFFErrorExt(tif->tif_clientdata, module, | 
|  | "Wrong bitspersample value (%d), Thunder decoder only supports 4bits per sample.", | 
|  | (int) tif->tif_dir.td_bitspersample ); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  |  | 
|  | return (1); | 
|  | } | 
|  |  | 
|  | static int | 
|  | ThunderDecode(TIFF* tif, uint8* op, tmsize_t maxpixels) | 
|  | { | 
|  | static const char module[] = "ThunderDecode"; | 
|  | register unsigned char *bp; | 
|  | register tmsize_t cc; | 
|  | unsigned int lastpixel; | 
|  | tmsize_t npixels; | 
|  |  | 
|  | bp = (unsigned char *)tif->tif_rawcp; | 
|  | cc = tif->tif_rawcc; | 
|  | lastpixel = 0; | 
|  | npixels = 0; | 
|  | while (cc > 0 && npixels < maxpixels) { | 
|  | int n, delta; | 
|  |  | 
|  | n = *bp++; | 
|  | cc--; | 
|  | switch (n & THUNDER_CODE) { | 
|  | case THUNDER_RUN:		/* pixel run */ | 
|  | /* | 
|  | * Replicate the last pixel n times, | 
|  | * where n is the lower-order 6 bits. | 
|  | */ | 
|  | if (npixels & 1) { | 
|  | op[0] |= lastpixel; | 
|  | lastpixel = *op++; npixels++; n--; | 
|  | } else | 
|  | lastpixel |= lastpixel << 4; | 
|  | npixels += n; | 
|  | if (npixels < maxpixels) { | 
|  | for (; n > 0; n -= 2) | 
|  | *op++ = (uint8) lastpixel; | 
|  | } | 
|  | if (n == -1) | 
|  | *--op &= 0xf0; | 
|  | lastpixel &= 0xf; | 
|  | break; | 
|  | case THUNDER_2BITDELTAS:	/* 2-bit deltas */ | 
|  | if ((delta = ((n >> 4) & 3)) != DELTA2_SKIP) | 
|  | SETPIXEL(op, (unsigned)((int)lastpixel + twobitdeltas[delta])); | 
|  | if ((delta = ((n >> 2) & 3)) != DELTA2_SKIP) | 
|  | SETPIXEL(op, (unsigned)((int)lastpixel + twobitdeltas[delta])); | 
|  | if ((delta = (n & 3)) != DELTA2_SKIP) | 
|  | SETPIXEL(op, (unsigned)((int)lastpixel + twobitdeltas[delta])); | 
|  | break; | 
|  | case THUNDER_3BITDELTAS:	/* 3-bit deltas */ | 
|  | if ((delta = ((n >> 3) & 7)) != DELTA3_SKIP) | 
|  | SETPIXEL(op, (unsigned)((int)lastpixel + threebitdeltas[delta])); | 
|  | if ((delta = (n & 7)) != DELTA3_SKIP) | 
|  | SETPIXEL(op, (unsigned)((int)lastpixel + threebitdeltas[delta])); | 
|  | break; | 
|  | case THUNDER_RAW:		/* raw data */ | 
|  | SETPIXEL(op, n); | 
|  | break; | 
|  | } | 
|  | } | 
|  | tif->tif_rawcp = (uint8*) bp; | 
|  | tif->tif_rawcc = cc; | 
|  | if (npixels != maxpixels) { | 
|  | #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) | 
|  | TIFFErrorExt(tif->tif_clientdata, module, | 
|  | "%s data at scanline %lu (%I64u != %I64u)", | 
|  | npixels < maxpixels ? "Not enough" : "Too much", | 
|  | (unsigned long) tif->tif_row, | 
|  | (unsigned __int64) npixels, | 
|  | (unsigned __int64) maxpixels); | 
|  | #else | 
|  | TIFFErrorExt(tif->tif_clientdata, module, | 
|  | "%s data at scanline %lu (%llu != %llu)", | 
|  | npixels < maxpixels ? "Not enough" : "Too much", | 
|  | (unsigned long) tif->tif_row, | 
|  | (unsigned long long) npixels, | 
|  | (unsigned long long) maxpixels); | 
|  | #endif | 
|  | return (0); | 
|  | } | 
|  |  | 
|  | return (1); | 
|  | } | 
|  |  | 
|  | static int | 
|  | ThunderDecodeRow(TIFF* tif, uint8* buf, tmsize_t occ, uint16 s) | 
|  | { | 
|  | static const char module[] = "ThunderDecodeRow"; | 
|  | uint8* row = buf; | 
|  |  | 
|  | (void) s; | 
|  | if (occ % tif->tif_scanlinesize) | 
|  | { | 
|  | TIFFErrorExt(tif->tif_clientdata, module, "Fractional scanlines cannot be read"); | 
|  | return (0); | 
|  | } | 
|  | while (occ > 0) { | 
|  | if (!ThunderDecode(tif, row, tif->tif_dir.td_imagewidth)) | 
|  | return (0); | 
|  | occ -= tif->tif_scanlinesize; | 
|  | row += tif->tif_scanlinesize; | 
|  | } | 
|  | return (1); | 
|  | } | 
|  |  | 
|  | int | 
|  | TIFFInitThunderScan(TIFF* tif, int scheme) | 
|  | { | 
|  | (void) scheme; | 
|  |  | 
|  | tif->tif_setupdecode = ThunderSetupDecode; | 
|  | tif->tif_decoderow = ThunderDecodeRow; | 
|  | tif->tif_decodestrip = ThunderDecodeRow; | 
|  | return (1); | 
|  | } | 
|  | #endif /* THUNDER_SUPPORT */ | 
|  |  | 
|  | /* vim: set ts=8 sts=8 sw=8 noet: */ | 
|  | /* | 
|  | * Local Variables: | 
|  | * mode: c | 
|  | * c-basic-offset: 8 | 
|  | * fill-column: 78 | 
|  | * End: | 
|  | */ |