1 | /* $Header: /afs/dev.mit.edu/source/repository/third/tiff/libtiff/tif_packbits.c,v 1.1.1.1 2002-12-26 02:39:07 ghudson Exp $ */ |
---|
2 | |
---|
3 | /* |
---|
4 | * Copyright (c) 1988-1997 Sam Leffler |
---|
5 | * Copyright (c) 1991-1997 Silicon Graphics, Inc. |
---|
6 | * |
---|
7 | * Permission to use, copy, modify, distribute, and sell this software and |
---|
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. |
---|
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 | * |
---|
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, |
---|
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 |
---|
24 | * OF THIS SOFTWARE. |
---|
25 | */ |
---|
26 | |
---|
27 | #include "tiffiop.h" |
---|
28 | #ifdef PACKBITS_SUPPORT |
---|
29 | /* |
---|
30 | * TIFF Library. |
---|
31 | * |
---|
32 | * PackBits Compression Algorithm Support |
---|
33 | */ |
---|
34 | #include <assert.h> |
---|
35 | #include <stdio.h> |
---|
36 | |
---|
37 | static int |
---|
38 | PackBitsPreEncode(TIFF* tif, tsample_t s) |
---|
39 | { |
---|
40 | (void) s; |
---|
41 | /* |
---|
42 | * Calculate the scanline/tile-width size in bytes. |
---|
43 | */ |
---|
44 | if (isTiled(tif)) |
---|
45 | tif->tif_data = (tidata_t) TIFFTileRowSize(tif); |
---|
46 | else |
---|
47 | tif->tif_data = (tidata_t) TIFFScanlineSize(tif); |
---|
48 | return (1); |
---|
49 | } |
---|
50 | |
---|
51 | /* |
---|
52 | * NB: tidata is the type representing *(tidata_t); |
---|
53 | * if tidata_t is made signed then this type must |
---|
54 | * be adjusted accordingly. |
---|
55 | */ |
---|
56 | typedef unsigned char tidata; |
---|
57 | |
---|
58 | /* |
---|
59 | * Encode a run of pixels. |
---|
60 | */ |
---|
61 | static int |
---|
62 | PackBitsEncode(TIFF* tif, tidata_t buf, tsize_t cc, tsample_t s) |
---|
63 | { |
---|
64 | u_char* bp = (u_char*) buf; |
---|
65 | tidata_t op, ep, lastliteral; |
---|
66 | long n, slop; |
---|
67 | int b; |
---|
68 | enum { BASE, LITERAL, RUN, LITERAL_RUN } state; |
---|
69 | |
---|
70 | (void) s; |
---|
71 | op = tif->tif_rawcp; |
---|
72 | ep = tif->tif_rawdata + tif->tif_rawdatasize; |
---|
73 | state = BASE; |
---|
74 | lastliteral = 0; |
---|
75 | while (cc > 0) { |
---|
76 | /* |
---|
77 | * Find the longest string of identical bytes. |
---|
78 | */ |
---|
79 | b = *bp++, cc--, n = 1; |
---|
80 | for (; cc > 0 && b == *bp; cc--, bp++) |
---|
81 | n++; |
---|
82 | again: |
---|
83 | if (op + 2 >= ep) { /* insure space for new data */ |
---|
84 | /* |
---|
85 | * Be careful about writing the last |
---|
86 | * literal. Must write up to that point |
---|
87 | * and then copy the remainder to the |
---|
88 | * front of the buffer. |
---|
89 | */ |
---|
90 | if (state == LITERAL || state == LITERAL_RUN) { |
---|
91 | slop = op - lastliteral; |
---|
92 | tif->tif_rawcc += lastliteral - tif->tif_rawcp; |
---|
93 | if (!TIFFFlushData1(tif)) |
---|
94 | return (-1); |
---|
95 | op = tif->tif_rawcp; |
---|
96 | while (slop-- > 0) |
---|
97 | *op++ = *lastliteral++; |
---|
98 | lastliteral = tif->tif_rawcp; |
---|
99 | } else { |
---|
100 | tif->tif_rawcc += op - tif->tif_rawcp; |
---|
101 | if (!TIFFFlushData1(tif)) |
---|
102 | return (-1); |
---|
103 | op = tif->tif_rawcp; |
---|
104 | } |
---|
105 | } |
---|
106 | switch (state) { |
---|
107 | case BASE: /* initial state, set run/literal */ |
---|
108 | if (n > 1) { |
---|
109 | state = RUN; |
---|
110 | if (n > 128) { |
---|
111 | *op++ = (tidata) -127; |
---|
112 | *op++ = b; |
---|
113 | n -= 128; |
---|
114 | goto again; |
---|
115 | } |
---|
116 | *op++ = (tidataval_t)(-(n-1)); |
---|
117 | *op++ = b; |
---|
118 | } else { |
---|
119 | lastliteral = op; |
---|
120 | *op++ = 0; |
---|
121 | *op++ = b; |
---|
122 | state = LITERAL; |
---|
123 | } |
---|
124 | break; |
---|
125 | case LITERAL: /* last object was literal string */ |
---|
126 | if (n > 1) { |
---|
127 | state = LITERAL_RUN; |
---|
128 | if (n > 128) { |
---|
129 | *op++ = (tidata) -127; |
---|
130 | *op++ = b; |
---|
131 | n -= 128; |
---|
132 | goto again; |
---|
133 | } |
---|
134 | *op++ = (tidataval_t)(-(n-1)); /* encode run */ |
---|
135 | *op++ = b; |
---|
136 | } else { /* extend literal */ |
---|
137 | if (++(*lastliteral) == 127) |
---|
138 | state = BASE; |
---|
139 | *op++ = b; |
---|
140 | } |
---|
141 | break; |
---|
142 | case RUN: /* last object was run */ |
---|
143 | if (n > 1) { |
---|
144 | if (n > 128) { |
---|
145 | *op++ = (tidata) -127; |
---|
146 | *op++ = b; |
---|
147 | n -= 128; |
---|
148 | goto again; |
---|
149 | } |
---|
150 | *op++ = (tidataval_t)(-(n-1)); |
---|
151 | *op++ = b; |
---|
152 | } else { |
---|
153 | lastliteral = op; |
---|
154 | *op++ = 0; |
---|
155 | *op++ = b; |
---|
156 | state = LITERAL; |
---|
157 | } |
---|
158 | break; |
---|
159 | case LITERAL_RUN: /* literal followed by a run */ |
---|
160 | /* |
---|
161 | * Check to see if previous run should |
---|
162 | * be converted to a literal, in which |
---|
163 | * case we convert literal-run-literal |
---|
164 | * to a single literal. |
---|
165 | */ |
---|
166 | if (n == 1 && op[-2] == (tidata) -1 && |
---|
167 | *lastliteral < 126) { |
---|
168 | state = (((*lastliteral) += 2) == 127 ? |
---|
169 | BASE : LITERAL); |
---|
170 | op[-2] = op[-1]; /* replicate */ |
---|
171 | } else |
---|
172 | state = RUN; |
---|
173 | goto again; |
---|
174 | } |
---|
175 | } |
---|
176 | tif->tif_rawcc += op - tif->tif_rawcp; |
---|
177 | tif->tif_rawcp = op; |
---|
178 | return (1); |
---|
179 | } |
---|
180 | |
---|
181 | /* |
---|
182 | * Encode a rectangular chunk of pixels. We break it up |
---|
183 | * into row-sized pieces to insure that encoded runs do |
---|
184 | * not span rows. Otherwise, there can be problems with |
---|
185 | * the decoder if data is read, for example, by scanlines |
---|
186 | * when it was encoded by strips. |
---|
187 | */ |
---|
188 | static int |
---|
189 | PackBitsEncodeChunk(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s) |
---|
190 | { |
---|
191 | tsize_t rowsize = (tsize_t) tif->tif_data; |
---|
192 | |
---|
193 | assert(rowsize > 0); |
---|
194 | |
---|
195 | #ifdef YCBCR_SUPPORT |
---|
196 | /* |
---|
197 | * YCBCR data isn't really separable into rows, so we |
---|
198 | * might as well encode the whole tile/strip as one chunk. |
---|
199 | */ |
---|
200 | if( tif->tif_dir.td_photometric == PHOTOMETRIC_YCBCR ) |
---|
201 | rowsize = (tsize_t) tif->tif_data; |
---|
202 | #endif |
---|
203 | |
---|
204 | while ((long)cc > 0) { |
---|
205 | int chunk = rowsize; |
---|
206 | |
---|
207 | if( cc < chunk ) |
---|
208 | chunk = cc; |
---|
209 | |
---|
210 | if (PackBitsEncode(tif, bp, chunk, s) < 0) |
---|
211 | return (-1); |
---|
212 | bp += chunk; |
---|
213 | cc -= chunk; |
---|
214 | } |
---|
215 | return (1); |
---|
216 | } |
---|
217 | |
---|
218 | static int |
---|
219 | PackBitsDecode(TIFF* tif, tidata_t op, tsize_t occ, tsample_t s) |
---|
220 | { |
---|
221 | char *bp; |
---|
222 | tsize_t cc; |
---|
223 | long n; |
---|
224 | int b; |
---|
225 | |
---|
226 | (void) s; |
---|
227 | bp = (char*) tif->tif_rawcp; |
---|
228 | cc = tif->tif_rawcc; |
---|
229 | while (cc > 0 && (long)occ > 0) { |
---|
230 | n = (long) *bp++, cc--; |
---|
231 | /* |
---|
232 | * Watch out for compilers that |
---|
233 | * don't sign extend chars... |
---|
234 | */ |
---|
235 | if (n >= 128) |
---|
236 | n -= 256; |
---|
237 | if (n < 0) { /* replicate next byte -n+1 times */ |
---|
238 | if (n == -128) /* nop */ |
---|
239 | continue; |
---|
240 | n = -n + 1; |
---|
241 | if( occ < n ) |
---|
242 | { |
---|
243 | TIFFWarning(tif->tif_name, |
---|
244 | "PackBitsDecode: discarding %d bytes " |
---|
245 | "to avoid buffer overrun", |
---|
246 | n - occ); |
---|
247 | n = occ; |
---|
248 | } |
---|
249 | occ -= n; |
---|
250 | b = *bp++, cc--; |
---|
251 | while (n-- > 0) |
---|
252 | *op++ = b; |
---|
253 | } else { /* copy next n+1 bytes literally */ |
---|
254 | if (occ < n + 1) |
---|
255 | { |
---|
256 | TIFFWarning(tif->tif_name, |
---|
257 | "PackBitsDecode: discarding %d bytes " |
---|
258 | "to avoid buffer overrun", |
---|
259 | n - occ + 1); |
---|
260 | n = occ - 1; |
---|
261 | } |
---|
262 | _TIFFmemcpy(op, bp, ++n); |
---|
263 | op += n; occ -= n; |
---|
264 | bp += n; cc -= n; |
---|
265 | } |
---|
266 | } |
---|
267 | tif->tif_rawcp = (tidata_t) bp; |
---|
268 | tif->tif_rawcc = cc; |
---|
269 | if (occ > 0) { |
---|
270 | TIFFError(tif->tif_name, |
---|
271 | "PackBitsDecode: Not enough data for scanline %ld", |
---|
272 | (long) tif->tif_row); |
---|
273 | return (0); |
---|
274 | } |
---|
275 | return (1); |
---|
276 | } |
---|
277 | |
---|
278 | int |
---|
279 | TIFFInitPackBits(TIFF* tif, int scheme) |
---|
280 | { |
---|
281 | (void) scheme; |
---|
282 | tif->tif_decoderow = PackBitsDecode; |
---|
283 | tif->tif_decodestrip = PackBitsDecode; |
---|
284 | tif->tif_decodetile = PackBitsDecode; |
---|
285 | tif->tif_preencode = PackBitsPreEncode; |
---|
286 | tif->tif_encoderow = PackBitsEncode; |
---|
287 | tif->tif_encodestrip = PackBitsEncodeChunk; |
---|
288 | tif->tif_encodetile = PackBitsEncodeChunk; |
---|
289 | return (1); |
---|
290 | } |
---|
291 | #endif /* PACKBITS_SUPPORT */ |
---|