]>
Commit | Line | Data |
---|---|---|
1 | ||
2 | /* | |
3 | * Copyright (c) 1988-1997 Sam Leffler | |
4 | * Copyright (c) 1991-1997 Silicon Graphics, Inc. | |
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 | #include <assert.h> | |
28 | #ifdef THUNDER_SUPPORT | |
29 | /* | |
30 | * TIFF Library. | |
31 | * | |
32 | * ThunderScan 4-bit Compression Algorithm Support | |
33 | */ | |
34 | ||
35 | /* | |
36 | * ThunderScan uses an encoding scheme designed for | |
37 | * 4-bit pixel values. Data is encoded in bytes, with | |
38 | * each byte split into a 2-bit code word and a 6-bit | |
39 | * data value. The encoding gives raw data, runs of | |
40 | * pixels, or pixel values encoded as a delta from the | |
41 | * previous pixel value. For the latter, either 2-bit | |
42 | * or 3-bit delta values are used, with the deltas packed | |
43 | * into a single byte. | |
44 | */ | |
45 | #define THUNDER_DATA 0x3f /* mask for 6-bit data */ | |
46 | #define THUNDER_CODE 0xc0 /* mask for 2-bit code word */ | |
47 | /* code values */ | |
48 | #define THUNDER_RUN 0x00 /* run of pixels w/ encoded count */ | |
49 | #define THUNDER_2BITDELTAS 0x40 /* 3 pixels w/ encoded 2-bit deltas */ | |
50 | #define DELTA2_SKIP 2 /* skip code for 2-bit deltas */ | |
51 | #define THUNDER_3BITDELTAS 0x80 /* 2 pixels w/ encoded 3-bit deltas */ | |
52 | #define DELTA3_SKIP 4 /* skip code for 3-bit deltas */ | |
53 | #define THUNDER_RAW 0xc0 /* raw data encoded */ | |
54 | ||
55 | static const int twobitdeltas[4] = { 0, 1, 0, -1 }; | |
56 | static const int threebitdeltas[8] = { 0, 1, 2, 3, 0, -3, -2, -1 }; | |
57 | ||
58 | #define SETPIXEL(op, v) { \ | |
59 | lastpixel = (v) & 0xf; \ | |
60 | if ( npixels < maxpixels ) \ | |
61 | { \ | |
62 | if (npixels++ & 1) \ | |
63 | *op++ |= lastpixel; \ | |
64 | else \ | |
65 | op[0] = (uint8) (lastpixel << 4); \ | |
66 | } \ | |
67 | } | |
68 | ||
69 | static int | |
70 | ThunderSetupDecode(TIFF* tif) | |
71 | { | |
72 | static const char module[] = "ThunderSetupDecode"; | |
73 | ||
74 | if( tif->tif_dir.td_bitspersample != 4 ) | |
75 | { | |
76 | TIFFErrorExt(tif->tif_clientdata, module, | |
77 | "Wrong bitspersample value (%d), Thunder decoder only supports 4bits per sample.", | |
78 | (int) tif->tif_dir.td_bitspersample ); | |
79 | return 0; | |
80 | } | |
81 | ||
82 | ||
83 | return (1); | |
84 | } | |
85 | ||
86 | static int | |
87 | ThunderDecode(TIFF* tif, uint8* op, tmsize_t maxpixels) | |
88 | { | |
89 | static const char module[] = "ThunderDecode"; | |
90 | register unsigned char *bp; | |
91 | register tmsize_t cc; | |
92 | unsigned int lastpixel; | |
93 | tmsize_t npixels; | |
94 | ||
95 | bp = (unsigned char *)tif->tif_rawcp; | |
96 | cc = tif->tif_rawcc; | |
97 | lastpixel = 0; | |
98 | npixels = 0; | |
99 | while (cc > 0 && npixels < maxpixels) { | |
100 | int n, delta; | |
101 | ||
102 | n = *bp++, cc--; | |
103 | switch (n & THUNDER_CODE) { | |
104 | case THUNDER_RUN: /* pixel run */ | |
105 | /* | |
106 | * Replicate the last pixel n times, | |
107 | * where n is the lower-order 6 bits. | |
108 | */ | |
109 | if (npixels & 1) { | |
110 | op[0] |= lastpixel; | |
111 | lastpixel = *op++; npixels++; n--; | |
112 | } else | |
113 | lastpixel |= lastpixel << 4; | |
114 | npixels += n; | |
115 | if (npixels < maxpixels) { | |
116 | for (; n > 0; n -= 2) | |
117 | *op++ = (uint8) lastpixel; | |
118 | } | |
119 | if (n == -1) | |
120 | *--op &= 0xf0; | |
121 | lastpixel &= 0xf; | |
122 | break; | |
123 | case THUNDER_2BITDELTAS: /* 2-bit deltas */ | |
124 | if ((delta = ((n >> 4) & 3)) != DELTA2_SKIP) | |
125 | SETPIXEL(op, lastpixel + twobitdeltas[delta]); | |
126 | if ((delta = ((n >> 2) & 3)) != DELTA2_SKIP) | |
127 | SETPIXEL(op, lastpixel + twobitdeltas[delta]); | |
128 | if ((delta = (n & 3)) != DELTA2_SKIP) | |
129 | SETPIXEL(op, lastpixel + twobitdeltas[delta]); | |
130 | break; | |
131 | case THUNDER_3BITDELTAS: /* 3-bit deltas */ | |
132 | if ((delta = ((n >> 3) & 7)) != DELTA3_SKIP) | |
133 | SETPIXEL(op, lastpixel + threebitdeltas[delta]); | |
134 | if ((delta = (n & 7)) != DELTA3_SKIP) | |
135 | SETPIXEL(op, lastpixel + threebitdeltas[delta]); | |
136 | break; | |
137 | case THUNDER_RAW: /* raw data */ | |
138 | SETPIXEL(op, n); | |
139 | break; | |
140 | } | |
141 | } | |
142 | tif->tif_rawcp = (uint8*) bp; | |
143 | tif->tif_rawcc = cc; | |
144 | if (npixels != maxpixels) { | |
145 | #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) | |
146 | TIFFErrorExt(tif->tif_clientdata, module, | |
147 | "%s data at scanline %lu (%I64u != %I64u)", | |
148 | npixels < maxpixels ? "Not enough" : "Too much", | |
149 | (unsigned long) tif->tif_row, | |
150 | (unsigned __int64) npixels, | |
151 | (unsigned __int64) maxpixels); | |
152 | #else | |
153 | TIFFErrorExt(tif->tif_clientdata, module, | |
154 | "%s data at scanline %lu (%llu != %llu)", | |
155 | npixels < maxpixels ? "Not enough" : "Too much", | |
156 | (unsigned long) tif->tif_row, | |
157 | (unsigned long long) npixels, | |
158 | (unsigned long long) maxpixels); | |
159 | #endif | |
160 | return (0); | |
161 | } | |
162 | ||
163 | return (1); | |
164 | } | |
165 | ||
166 | static int | |
167 | ThunderDecodeRow(TIFF* tif, uint8* buf, tmsize_t occ, uint16 s) | |
168 | { | |
169 | static const char module[] = "ThunderDecodeRow"; | |
170 | uint8* row = buf; | |
171 | ||
172 | (void) s; | |
173 | if (occ % tif->tif_scanlinesize) | |
174 | { | |
175 | TIFFErrorExt(tif->tif_clientdata, module, "Fractional scanlines cannot be read"); | |
176 | return (0); | |
177 | } | |
178 | while (occ > 0) { | |
179 | if (!ThunderDecode(tif, row, tif->tif_dir.td_imagewidth)) | |
180 | return (0); | |
181 | occ -= tif->tif_scanlinesize; | |
182 | row += tif->tif_scanlinesize; | |
183 | } | |
184 | return (1); | |
185 | } | |
186 | ||
187 | int | |
188 | TIFFInitThunderScan(TIFF* tif, int scheme) | |
189 | { | |
190 | (void) scheme; | |
191 | ||
192 | tif->tif_setupdecode = ThunderSetupDecode; | |
193 | tif->tif_decoderow = ThunderDecodeRow; | |
194 | tif->tif_decodestrip = ThunderDecodeRow; | |
195 | return (1); | |
196 | } | |
197 | #endif /* THUNDER_SUPPORT */ | |
198 | ||
199 | /* vim: set ts=8 sts=8 sw=8 noet: */ | |
200 | /* | |
201 | * Local Variables: | |
202 | * mode: c | |
203 | * c-basic-offset: 8 | |
204 | * fill-column: 78 | |
205 | * End: | |
206 | */ |