1 /*
2 * Copyright (c) 1988-1997 Sam Leffler
3 * Copyright (c) 1991-1997 Silicon Graphics, Inc.
4 *
5 * Permission to use, copy, modify, distribute, and sell this software and
6 * its documentation for any purpose is hereby granted without fee, provided
7 * that (i) the above copyright notices and this permission notice appear in
8 * all copies of the software and related documentation, and (ii) the names of
9 * Sam Leffler and Silicon Graphics may not be used in any advertising or
10 * publicity relating to the software without the specific, prior written
11 * permission of Sam Leffler and Silicon Graphics.
12 *
13 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
14 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
15 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
16 *
17 * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
18 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
19 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
20 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
21 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
22 * OF THIS SOFTWARE.
23 */
24
25 #include <precomp.h>
26 #ifdef PACKBITS_SUPPORT
27 /*
28 * TIFF Library.
29 *
30 * PackBits Compression Algorithm Support
31 */
32 //#include <stdio.h>
33
34 static int
PackBitsPreEncode(TIFF * tif,uint16 s)35 PackBitsPreEncode(TIFF* tif, uint16 s)
36 {
37 (void) s;
38
39 tif->tif_data = (uint8*)_TIFFmalloc(sizeof(tmsize_t));
40 if (tif->tif_data == NULL)
41 return (0);
42 /*
43 * Calculate the scanline/tile-width size in bytes.
44 */
45 if (isTiled(tif))
46 *(tmsize_t*)tif->tif_data = TIFFTileRowSize(tif);
47 else
48 *(tmsize_t*)tif->tif_data = TIFFScanlineSize(tif);
49 return (1);
50 }
51
52 static int
PackBitsPostEncode(TIFF * tif)53 PackBitsPostEncode(TIFF* tif)
54 {
55 if (tif->tif_data)
56 _TIFFfree(tif->tif_data);
57 return (1);
58 }
59
60 /*
61 * Encode a run of pixels.
62 */
63 static int
PackBitsEncode(TIFF * tif,uint8 * buf,tmsize_t cc,uint16 s)64 PackBitsEncode(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s)
65 {
66 unsigned char* bp = (unsigned char*) buf;
67 uint8* op;
68 uint8* ep;
69 uint8* lastliteral;
70 long n, slop;
71 int b;
72 enum { BASE, LITERAL, RUN, LITERAL_RUN } state;
73
74 (void) s;
75 op = tif->tif_rawcp;
76 ep = tif->tif_rawdata + tif->tif_rawdatasize;
77 state = BASE;
78 lastliteral = 0;
79 while (cc > 0) {
80 /*
81 * Find the longest string of identical bytes.
82 */
83 b = *bp++;
84 cc--;
85 n = 1;
86 for (; cc > 0 && b == *bp; cc--, bp++)
87 n++;
88 again:
89 if (op + 2 >= ep) { /* insure space for new data */
90 /*
91 * Be careful about writing the last
92 * literal. Must write up to that point
93 * and then copy the remainder to the
94 * front of the buffer.
95 */
96 if (state == LITERAL || state == LITERAL_RUN) {
97 slop = (long)(op - lastliteral);
98 tif->tif_rawcc += (tmsize_t)(lastliteral - tif->tif_rawcp);
99 if (!TIFFFlushData1(tif))
100 return (0);
101 op = tif->tif_rawcp;
102 while (slop-- > 0)
103 *op++ = *lastliteral++;
104 lastliteral = tif->tif_rawcp;
105 } else {
106 tif->tif_rawcc += (tmsize_t)(op - tif->tif_rawcp);
107 if (!TIFFFlushData1(tif))
108 return (0);
109 op = tif->tif_rawcp;
110 }
111 }
112 switch (state) {
113 case BASE: /* initial state, set run/literal */
114 if (n > 1) {
115 state = RUN;
116 if (n > 128) {
117 *op++ = (uint8) -127;
118 *op++ = (uint8) b;
119 n -= 128;
120 goto again;
121 }
122 *op++ = (uint8)(-(n-1));
123 *op++ = (uint8) b;
124 } else {
125 lastliteral = op;
126 *op++ = 0;
127 *op++ = (uint8) b;
128 state = LITERAL;
129 }
130 break;
131 case LITERAL: /* last object was literal string */
132 if (n > 1) {
133 state = LITERAL_RUN;
134 if (n > 128) {
135 *op++ = (uint8) -127;
136 *op++ = (uint8) b;
137 n -= 128;
138 goto again;
139 }
140 *op++ = (uint8)(-(n-1)); /* encode run */
141 *op++ = (uint8) b;
142 } else { /* extend literal */
143 if (++(*lastliteral) == 127)
144 state = BASE;
145 *op++ = (uint8) b;
146 }
147 break;
148 case RUN: /* last object was run */
149 if (n > 1) {
150 if (n > 128) {
151 *op++ = (uint8) -127;
152 *op++ = (uint8) b;
153 n -= 128;
154 goto again;
155 }
156 *op++ = (uint8)(-(n-1));
157 *op++ = (uint8) b;
158 } else {
159 lastliteral = op;
160 *op++ = 0;
161 *op++ = (uint8) b;
162 state = LITERAL;
163 }
164 break;
165 case LITERAL_RUN: /* literal followed by a run */
166 /*
167 * Check to see if previous run should
168 * be converted to a literal, in which
169 * case we convert literal-run-literal
170 * to a single literal.
171 */
172 if (n == 1 && op[-2] == (uint8) -1 &&
173 *lastliteral < 126) {
174 state = (((*lastliteral) += 2) == 127 ?
175 BASE : LITERAL);
176 op[-2] = op[-1]; /* replicate */
177 } else
178 state = RUN;
179 goto again;
180 }
181 }
182 tif->tif_rawcc += (tmsize_t)(op - tif->tif_rawcp);
183 tif->tif_rawcp = op;
184 return (1);
185 }
186
187 /*
188 * Encode a rectangular chunk of pixels. We break it up
189 * into row-sized pieces to insure that encoded runs do
190 * not span rows. Otherwise, there can be problems with
191 * the decoder if data is read, for example, by scanlines
192 * when it was encoded by strips.
193 */
194 static int
PackBitsEncodeChunk(TIFF * tif,uint8 * bp,tmsize_t cc,uint16 s)195 PackBitsEncodeChunk(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
196 {
197 tmsize_t rowsize = *(tmsize_t*)tif->tif_data;
198
199 while (cc > 0) {
200 tmsize_t chunk = rowsize;
201
202 if( cc < chunk )
203 chunk = cc;
204
205 if (PackBitsEncode(tif, bp, chunk, s) < 0)
206 return (-1);
207 bp += chunk;
208 cc -= chunk;
209 }
210 return (1);
211 }
212
213 static int
PackBitsDecode(TIFF * tif,uint8 * op,tmsize_t occ,uint16 s)214 PackBitsDecode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s)
215 {
216 static const char module[] = "PackBitsDecode";
217 char *bp;
218 tmsize_t cc;
219 long n;
220 int b;
221
222 (void) s;
223 bp = (char*) tif->tif_rawcp;
224 cc = tif->tif_rawcc;
225 while (cc > 0 && occ > 0) {
226 n = (long) *bp++;
227 cc--;
228 /*
229 * Watch out for compilers that
230 * don't sign extend chars...
231 */
232 if (n >= 128)
233 n -= 256;
234 if (n < 0) { /* replicate next byte -n+1 times */
235 if (n == -128) /* nop */
236 continue;
237 n = -n + 1;
238 if( occ < (tmsize_t)n )
239 {
240 TIFFWarningExt(tif->tif_clientdata, module,
241 "Discarding %lu bytes to avoid buffer overrun",
242 (unsigned long) ((tmsize_t)n - occ));
243 n = (long)occ;
244 }
245 if( cc == 0 )
246 {
247 TIFFWarningExt(tif->tif_clientdata, module,
248 "Terminating PackBitsDecode due to lack of data.");
249 break;
250 }
251 occ -= n;
252 b = *bp++;
253 cc--;
254 while (n-- > 0)
255 *op++ = (uint8) b;
256 } else { /* copy next n+1 bytes literally */
257 if (occ < (tmsize_t)(n + 1))
258 {
259 TIFFWarningExt(tif->tif_clientdata, module,
260 "Discarding %lu bytes to avoid buffer overrun",
261 (unsigned long) ((tmsize_t)n - occ + 1));
262 n = (long)occ - 1;
263 }
264 if (cc < (tmsize_t) (n+1))
265 {
266 TIFFWarningExt(tif->tif_clientdata, module,
267 "Terminating PackBitsDecode due to lack of data.");
268 break;
269 }
270 _TIFFmemcpy(op, bp, ++n);
271 op += n; occ -= n;
272 bp += n; cc -= n;
273 }
274 }
275 tif->tif_rawcp = (uint8*) bp;
276 tif->tif_rawcc = cc;
277 if (occ > 0) {
278 TIFFErrorExt(tif->tif_clientdata, module,
279 "Not enough data for scanline %lu",
280 (unsigned long) tif->tif_row);
281 return (0);
282 }
283 return (1);
284 }
285
286 int
TIFFInitPackBits(TIFF * tif,int scheme)287 TIFFInitPackBits(TIFF* tif, int scheme)
288 {
289 (void) scheme;
290 tif->tif_decoderow = PackBitsDecode;
291 tif->tif_decodestrip = PackBitsDecode;
292 tif->tif_decodetile = PackBitsDecode;
293 tif->tif_preencode = PackBitsPreEncode;
294 tif->tif_postencode = PackBitsPostEncode;
295 tif->tif_encoderow = PackBitsEncode;
296 tif->tif_encodestrip = PackBitsEncodeChunk;
297 tif->tif_encodetile = PackBitsEncodeChunk;
298 return (1);
299 }
300 #endif /* PACKBITS_SUPPORT */
301
302 /* vim: set ts=8 sts=8 sw=8 noet: */
303 /*
304 * Local Variables:
305 * mode: c
306 * c-basic-offset: 8
307 * fill-column: 78
308 * End:
309 */
310