]>
Commit | Line | Data |
---|---|---|
b47c832e RR |
1 | /* $Header$ */ |
2 | ||
3 | /* | |
4 | * Copyright (c) 1988-1997 Sam Leffler | |
5 | * Copyright (c) 1991-1997 Silicon Graphics, Inc. | |
6 | * | |
00cb87b4 | 7 | * Permission to use, copy, modify, distribute, and sell this software and |
b47c832e RR |
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. | |
00cb87b4 VZ |
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 | * | |
b47c832e RR |
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, | |
00cb87b4 VZ |
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 | |
b47c832e RR |
24 | * OF THIS SOFTWARE. |
25 | */ | |
26 | ||
27 | #include "tiffiop.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++ & 1) \ | |
61 | *op++ |= lastpixel; \ | |
62 | else \ | |
00cb87b4 | 63 | op[0] = (tidataval_t) (lastpixel << 4); \ |
b47c832e RR |
64 | } |
65 | ||
66 | static int | |
67 | ThunderDecode(TIFF* tif, tidata_t op, tsize_t maxpixels) | |
68 | { | |
69 | register u_char *bp; | |
70 | register tsize_t cc; | |
71 | u_int lastpixel; | |
72 | tsize_t npixels; | |
73 | ||
74 | bp = (u_char *)tif->tif_rawcp; | |
75 | cc = tif->tif_rawcc; | |
76 | lastpixel = 0; | |
77 | npixels = 0; | |
78 | while (cc > 0 && npixels < maxpixels) { | |
79 | int n, delta; | |
80 | ||
81 | n = *bp++, cc--; | |
82 | switch (n & THUNDER_CODE) { | |
83 | case THUNDER_RUN: /* pixel run */ | |
84 | /* | |
85 | * Replicate the last pixel n times, | |
86 | * where n is the lower-order 6 bits. | |
87 | */ | |
88 | if (npixels & 1) { | |
89 | op[0] |= lastpixel; | |
90 | lastpixel = *op++; npixels++; n--; | |
91 | } else | |
92 | lastpixel |= lastpixel << 4; | |
93 | npixels += n; | |
00cb87b4 VZ |
94 | if (npixels < maxpixels) { |
95 | for (; n > 0; n -= 2) | |
96 | *op++ = (tidataval_t) lastpixel; | |
97 | } | |
b47c832e RR |
98 | if (n == -1) |
99 | *--op &= 0xf0; | |
100 | lastpixel &= 0xf; | |
101 | break; | |
102 | case THUNDER_2BITDELTAS: /* 2-bit deltas */ | |
103 | if ((delta = ((n >> 4) & 3)) != DELTA2_SKIP) | |
104 | SETPIXEL(op, lastpixel + twobitdeltas[delta]); | |
105 | if ((delta = ((n >> 2) & 3)) != DELTA2_SKIP) | |
106 | SETPIXEL(op, lastpixel + twobitdeltas[delta]); | |
107 | if ((delta = (n & 3)) != DELTA2_SKIP) | |
108 | SETPIXEL(op, lastpixel + twobitdeltas[delta]); | |
109 | break; | |
110 | case THUNDER_3BITDELTAS: /* 3-bit deltas */ | |
111 | if ((delta = ((n >> 3) & 7)) != DELTA3_SKIP) | |
112 | SETPIXEL(op, lastpixel + threebitdeltas[delta]); | |
113 | if ((delta = (n & 7)) != DELTA3_SKIP) | |
114 | SETPIXEL(op, lastpixel + threebitdeltas[delta]); | |
115 | break; | |
116 | case THUNDER_RAW: /* raw data */ | |
117 | SETPIXEL(op, n); | |
118 | break; | |
119 | } | |
120 | } | |
121 | tif->tif_rawcp = (tidata_t) bp; | |
122 | tif->tif_rawcc = cc; | |
123 | if (npixels != maxpixels) { | |
124 | TIFFError(tif->tif_name, | |
125 | "ThunderDecode: %s data at scanline %ld (%lu != %lu)", | |
126 | npixels < maxpixels ? "Not enough" : "Too much", | |
127 | (long) tif->tif_row, (long) npixels, (long) maxpixels); | |
128 | return (0); | |
129 | } | |
130 | return (1); | |
131 | } | |
132 | ||
00cb87b4 | 133 | static int |
b47c832e RR |
134 | ThunderDecodeRow(TIFF* tif, tidata_t buf, tsize_t occ, tsample_t s) |
135 | { | |
136 | tidata_t row = buf; | |
137 | ||
138 | (void) s; | |
139 | while ((long)occ > 0) { | |
140 | if (!ThunderDecode(tif, row, tif->tif_dir.td_imagewidth)) | |
141 | return (0); | |
142 | occ -= tif->tif_scanlinesize; | |
143 | row += tif->tif_scanlinesize; | |
144 | } | |
145 | return (1); | |
146 | } | |
147 | ||
148 | int | |
149 | TIFFInitThunderScan(TIFF* tif, int scheme) | |
150 | { | |
151 | (void) scheme; | |
152 | tif->tif_decoderow = ThunderDecodeRow; | |
153 | tif->tif_decodestrip = ThunderDecodeRow; | |
154 | return (1); | |
155 | } | |
156 | #endif /* THUNDER_SUPPORT */ |