[LIBTIFF] Update to version 4.0.10. CORE-15854
[reactos.git] / dll / 3rdparty / libtiff / tif_packbits.c
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
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 tif->tif_data = (uint8*)_TIFFmalloc(sizeof(tmsize_t));
41 if (tif->tif_data == NULL)
42 return (0);
43 /*
44 * Calculate the scanline/tile-width size in bytes.
45 */
46 if (isTiled(tif))
47 *(tmsize_t*)tif->tif_data = TIFFTileRowSize(tif);
48 else
49 *(tmsize_t*)tif->tif_data = TIFFScanlineSize(tif);
50 return (1);
51 }
52
53 static int
54 PackBitsPostEncode(TIFF* tif)
55 {
56 if (tif->tif_data)
57 _TIFFfree(tif->tif_data);
58 return (1);
59 }
60
61 /*
62 * Encode a run of pixels.
63 */
64 static int
65 PackBitsEncode(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s)
66 {
67 unsigned char* bp = (unsigned char*) buf;
68 uint8* op;
69 uint8* ep;
70 uint8* lastliteral;
71 long n, slop;
72 int b;
73 enum { BASE, LITERAL, RUN, LITERAL_RUN } state;
74
75 (void) s;
76 op = tif->tif_rawcp;
77 ep = tif->tif_rawdata + tif->tif_rawdatasize;
78 state = BASE;
79 lastliteral = 0;
80 while (cc > 0) {
81 /*
82 * Find the longest string of identical bytes.
83 */
84 b = *bp++;
85 cc--;
86 n = 1;
87 for (; cc > 0 && b == *bp; cc--, bp++)
88 n++;
89 again:
90 if (op + 2 >= ep) { /* insure space for new data */
91 /*
92 * Be careful about writing the last
93 * literal. Must write up to that point
94 * and then copy the remainder to the
95 * front of the buffer.
96 */
97 if (state == LITERAL || state == LITERAL_RUN) {
98 slop = (long)(op - lastliteral);
99 tif->tif_rawcc += (tmsize_t)(lastliteral - tif->tif_rawcp);
100 if (!TIFFFlushData1(tif))
101 return (0);
102 op = tif->tif_rawcp;
103 while (slop-- > 0)
104 *op++ = *lastliteral++;
105 lastliteral = tif->tif_rawcp;
106 } else {
107 tif->tif_rawcc += (tmsize_t)(op - tif->tif_rawcp);
108 if (!TIFFFlushData1(tif))
109 return (0);
110 op = tif->tif_rawcp;
111 }
112 }
113 switch (state) {
114 case BASE: /* initial state, set run/literal */
115 if (n > 1) {
116 state = RUN;
117 if (n > 128) {
118 *op++ = (uint8) -127;
119 *op++ = (uint8) b;
120 n -= 128;
121 goto again;
122 }
123 *op++ = (uint8)(-(n-1));
124 *op++ = (uint8) b;
125 } else {
126 lastliteral = op;
127 *op++ = 0;
128 *op++ = (uint8) b;
129 state = LITERAL;
130 }
131 break;
132 case LITERAL: /* last object was literal string */
133 if (n > 1) {
134 state = LITERAL_RUN;
135 if (n > 128) {
136 *op++ = (uint8) -127;
137 *op++ = (uint8) b;
138 n -= 128;
139 goto again;
140 }
141 *op++ = (uint8)(-(n-1)); /* encode run */
142 *op++ = (uint8) b;
143 } else { /* extend literal */
144 if (++(*lastliteral) == 127)
145 state = BASE;
146 *op++ = (uint8) b;
147 }
148 break;
149 case RUN: /* last object was run */
150 if (n > 1) {
151 if (n > 128) {
152 *op++ = (uint8) -127;
153 *op++ = (uint8) b;
154 n -= 128;
155 goto again;
156 }
157 *op++ = (uint8)(-(n-1));
158 *op++ = (uint8) b;
159 } else {
160 lastliteral = op;
161 *op++ = 0;
162 *op++ = (uint8) b;
163 state = LITERAL;
164 }
165 break;
166 case LITERAL_RUN: /* literal followed by a run */
167 /*
168 * Check to see if previous run should
169 * be converted to a literal, in which
170 * case we convert literal-run-literal
171 * to a single literal.
172 */
173 if (n == 1 && op[-2] == (uint8) -1 &&
174 *lastliteral < 126) {
175 state = (((*lastliteral) += 2) == 127 ?
176 BASE : LITERAL);
177 op[-2] = op[-1]; /* replicate */
178 } else
179 state = RUN;
180 goto again;
181 }
182 }
183 tif->tif_rawcc += (tmsize_t)(op - tif->tif_rawcp);
184 tif->tif_rawcp = op;
185 return (1);
186 }
187
188 /*
189 * Encode a rectangular chunk of pixels. We break it up
190 * into row-sized pieces to insure that encoded runs do
191 * not span rows. Otherwise, there can be problems with
192 * the decoder if data is read, for example, by scanlines
193 * when it was encoded by strips.
194 */
195 static int
196 PackBitsEncodeChunk(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
197 {
198 tmsize_t rowsize = *(tmsize_t*)tif->tif_data;
199
200 while (cc > 0) {
201 tmsize_t chunk = rowsize;
202
203 if( cc < chunk )
204 chunk = cc;
205
206 if (PackBitsEncode(tif, bp, chunk, s) < 0)
207 return (-1);
208 bp += chunk;
209 cc -= chunk;
210 }
211 return (1);
212 }
213
214 static int
215 PackBitsDecode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s)
216 {
217 static const char module[] = "PackBitsDecode";
218 char *bp;
219 tmsize_t cc;
220 long n;
221 int b;
222
223 (void) s;
224 bp = (char*) tif->tif_rawcp;
225 cc = tif->tif_rawcc;
226 while (cc > 0 && occ > 0) {
227 n = (long) *bp++;
228 cc--;
229 /*
230 * Watch out for compilers that
231 * don't sign extend chars...
232 */
233 if (n >= 128)
234 n -= 256;
235 if (n < 0) { /* replicate next byte -n+1 times */
236 if (n == -128) /* nop */
237 continue;
238 n = -n + 1;
239 if( occ < (tmsize_t)n )
240 {
241 TIFFWarningExt(tif->tif_clientdata, module,
242 "Discarding %lu bytes to avoid buffer overrun",
243 (unsigned long) ((tmsize_t)n - occ));
244 n = (long)occ;
245 }
246 if( cc == 0 )
247 {
248 TIFFWarningExt(tif->tif_clientdata, module,
249 "Terminating PackBitsDecode due to lack of data.");
250 break;
251 }
252 occ -= n;
253 b = *bp++;
254 cc--;
255 while (n-- > 0)
256 *op++ = (uint8) b;
257 } else { /* copy next n+1 bytes literally */
258 if (occ < (tmsize_t)(n + 1))
259 {
260 TIFFWarningExt(tif->tif_clientdata, module,
261 "Discarding %lu bytes to avoid buffer overrun",
262 (unsigned long) ((tmsize_t)n - occ + 1));
263 n = (long)occ - 1;
264 }
265 if (cc < (tmsize_t) (n+1))
266 {
267 TIFFWarningExt(tif->tif_clientdata, module,
268 "Terminating PackBitsDecode due to lack of data.");
269 break;
270 }
271 _TIFFmemcpy(op, bp, ++n);
272 op += n; occ -= n;
273 bp += n; cc -= n;
274 }
275 }
276 tif->tif_rawcp = (uint8*) bp;
277 tif->tif_rawcc = cc;
278 if (occ > 0) {
279 TIFFErrorExt(tif->tif_clientdata, module,
280 "Not enough data for scanline %lu",
281 (unsigned long) tif->tif_row);
282 return (0);
283 }
284 return (1);
285 }
286
287 int
288 TIFFInitPackBits(TIFF* tif, int scheme)
289 {
290 (void) scheme;
291 tif->tif_decoderow = PackBitsDecode;
292 tif->tif_decodestrip = PackBitsDecode;
293 tif->tif_decodetile = PackBitsDecode;
294 tif->tif_preencode = PackBitsPreEncode;
295 tif->tif_postencode = PackBitsPostEncode;
296 tif->tif_encoderow = PackBitsEncode;
297 tif->tif_encodestrip = PackBitsEncodeChunk;
298 tif->tif_encodetile = PackBitsEncodeChunk;
299 return (1);
300 }
301 #endif /* PACKBITS_SUPPORT */
302
303 /* vim: set ts=8 sts=8 sw=8 noet: */
304 /*
305 * Local Variables:
306 * mode: c
307 * c-basic-offset: 8
308 * fill-column: 78
309 * End:
310 */