Remove obsolete VisualAge-related files.
[wxWidgets.git] / src / tiff / libtiff / tif_packbits.c
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 #ifdef PACKBITS_SUPPORT
28 /*
29 * TIFF Library.
30 *
31 * PackBits Compression Algorithm Support
32 */
33 #include <stdio.h>
34
35 static int
36 PackBitsPreEncode(TIFF* tif, uint16 s)
37 {
38 (void) s;
39
40 if (!(tif->tif_data = (uint8*)_TIFFmalloc(sizeof(tmsize_t))))
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
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
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++, cc--, n = 1;
84 for (; cc > 0 && b == *bp; cc--, bp++)
85 n++;
86 again:
87 if (op + 2 >= ep) { /* insure space for new data */
88 /*
89 * Be careful about writing the last
90 * literal. Must write up to that point
91 * and then copy the remainder to the
92 * front of the buffer.
93 */
94 if (state == LITERAL || state == LITERAL_RUN) {
95 slop = (long)(op - lastliteral);
96 tif->tif_rawcc += (tmsize_t)(lastliteral - tif->tif_rawcp);
97 if (!TIFFFlushData1(tif))
98 return (-1);
99 op = tif->tif_rawcp;
100 while (slop-- > 0)
101 *op++ = *lastliteral++;
102 lastliteral = tif->tif_rawcp;
103 } else {
104 tif->tif_rawcc += (tmsize_t)(op - tif->tif_rawcp);
105 if (!TIFFFlushData1(tif))
106 return (-1);
107 op = tif->tif_rawcp;
108 }
109 }
110 switch (state) {
111 case BASE: /* initial state, set run/literal */
112 if (n > 1) {
113 state = RUN;
114 if (n > 128) {
115 *op++ = (uint8) -127;
116 *op++ = (uint8) b;
117 n -= 128;
118 goto again;
119 }
120 *op++ = (uint8)(-(n-1));
121 *op++ = (uint8) b;
122 } else {
123 lastliteral = op;
124 *op++ = 0;
125 *op++ = (uint8) b;
126 state = LITERAL;
127 }
128 break;
129 case LITERAL: /* last object was literal string */
130 if (n > 1) {
131 state = LITERAL_RUN;
132 if (n > 128) {
133 *op++ = (uint8) -127;
134 *op++ = (uint8) b;
135 n -= 128;
136 goto again;
137 }
138 *op++ = (uint8)(-(n-1)); /* encode run */
139 *op++ = (uint8) b;
140 } else { /* extend literal */
141 if (++(*lastliteral) == 127)
142 state = BASE;
143 *op++ = (uint8) b;
144 }
145 break;
146 case RUN: /* last object was run */
147 if (n > 1) {
148 if (n > 128) {
149 *op++ = (uint8) -127;
150 *op++ = (uint8) b;
151 n -= 128;
152 goto again;
153 }
154 *op++ = (uint8)(-(n-1));
155 *op++ = (uint8) b;
156 } else {
157 lastliteral = op;
158 *op++ = 0;
159 *op++ = (uint8) b;
160 state = LITERAL;
161 }
162 break;
163 case LITERAL_RUN: /* literal followed by a run */
164 /*
165 * Check to see if previous run should
166 * be converted to a literal, in which
167 * case we convert literal-run-literal
168 * to a single literal.
169 */
170 if (n == 1 && op[-2] == (uint8) -1 &&
171 *lastliteral < 126) {
172 state = (((*lastliteral) += 2) == 127 ?
173 BASE : LITERAL);
174 op[-2] = op[-1]; /* replicate */
175 } else
176 state = RUN;
177 goto again;
178 }
179 }
180 tif->tif_rawcc += (tmsize_t)(op - tif->tif_rawcp);
181 tif->tif_rawcp = op;
182 return (1);
183 }
184
185 /*
186 * Encode a rectangular chunk of pixels. We break it up
187 * into row-sized pieces to insure that encoded runs do
188 * not span rows. Otherwise, there can be problems with
189 * the decoder if data is read, for example, by scanlines
190 * when it was encoded by strips.
191 */
192 static int
193 PackBitsEncodeChunk(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
194 {
195 tmsize_t rowsize = *(tmsize_t*)tif->tif_data;
196
197 while (cc > 0) {
198 tmsize_t chunk = rowsize;
199
200 if( cc < chunk )
201 chunk = cc;
202
203 if (PackBitsEncode(tif, bp, chunk, s) < 0)
204 return (-1);
205 bp += chunk;
206 cc -= chunk;
207 }
208 return (1);
209 }
210
211 static int
212 PackBitsDecode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s)
213 {
214 static const char module[] = "PackBitsDecode";
215 char *bp;
216 tmsize_t cc;
217 long n;
218 int b;
219
220 (void) s;
221 bp = (char*) tif->tif_rawcp;
222 cc = tif->tif_rawcc;
223 while (cc > 0 && occ > 0) {
224 n = (long) *bp++, cc--;
225 /*
226 * Watch out for compilers that
227 * don't sign extend chars...
228 */
229 if (n >= 128)
230 n -= 256;
231 if (n < 0) { /* replicate next byte -n+1 times */
232 if (n == -128) /* nop */
233 continue;
234 n = -n + 1;
235 if( occ < (tmsize_t)n )
236 {
237 TIFFWarningExt(tif->tif_clientdata, module,
238 "Discarding %lu bytes to avoid buffer overrun",
239 (unsigned long) ((tmsize_t)n - occ));
240 n = (long)occ;
241 }
242 occ -= n;
243 b = *bp++, cc--;
244 while (n-- > 0)
245 *op++ = (uint8) b;
246 } else { /* copy next n+1 bytes literally */
247 if (occ < (tmsize_t)(n + 1))
248 {
249 TIFFWarningExt(tif->tif_clientdata, module,
250 "Discarding %lu bytes to avoid buffer overrun",
251 (unsigned long) ((tmsize_t)n - occ + 1));
252 n = (long)occ - 1;
253 }
254 if (cc < (tmsize_t) (n+1))
255 {
256 TIFFWarningExt(tif->tif_clientdata, module,
257 "Terminating PackBitsDecode due to lack of data.");
258 break;
259 }
260 _TIFFmemcpy(op, bp, ++n);
261 op += n; occ -= n;
262 bp += n; cc -= n;
263 }
264 }
265 tif->tif_rawcp = (uint8*) bp;
266 tif->tif_rawcc = cc;
267 if (occ > 0) {
268 TIFFErrorExt(tif->tif_clientdata, module,
269 "Not enough data for scanline %lu",
270 (unsigned long) tif->tif_row);
271 return (0);
272 }
273 return (1);
274 }
275
276 int
277 TIFFInitPackBits(TIFF* tif, int scheme)
278 {
279 (void) scheme;
280 tif->tif_decoderow = PackBitsDecode;
281 tif->tif_decodestrip = PackBitsDecode;
282 tif->tif_decodetile = PackBitsDecode;
283 tif->tif_preencode = PackBitsPreEncode;
284 tif->tif_postencode = PackBitsPostEncode;
285 tif->tif_encoderow = PackBitsEncode;
286 tif->tif_encodestrip = PackBitsEncodeChunk;
287 tif->tif_encodetile = PackBitsEncodeChunk;
288 return (1);
289 }
290 #endif /* PACKBITS_SUPPORT */
291
292 /* vim: set ts=8 sts=8 sw=8 noet: */
293 /*
294 * Local Variables:
295 * mode: c
296 * c-basic-offset: 8
297 * fill-column: 78
298 * End:
299 */