1 /* $Header$ */
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
PackBitsPreEncode(TIFF * tif,tsample_t s)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
PackBitsEncode(TIFF * tif,tidata_t buf,tsize_t cc,tsample_t s)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++ = (tidataval_t) b;
113 					n -= 128;
114 					goto again;
115 				}
116 				*op++ = (tidataval_t)(-(n-1));
117 				*op++ = (tidataval_t) b;
118 			} else {
119 				lastliteral = op;
120 				*op++ = 0;
121 				*op++ = (tidataval_t) 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++ = (tidataval_t) b;
131 					n -= 128;
132 					goto again;
133 				}
134 				*op++ = (tidataval_t)(-(n-1));	/* encode run */
135 				*op++ = (tidataval_t) b;
136 			} else {			/* extend literal */
137 				if (++(*lastliteral) == 127)
138 					state = BASE;
139 				*op++ = (tidataval_t) 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++ = (tidataval_t) b;
147 					n -= 128;
148 					goto again;
149 				}
150 				*op++ = (tidataval_t)(-(n-1));
151 				*op++ = (tidataval_t) b;
152 			} else {
153 				lastliteral = op;
154 				*op++ = 0;
155 				*op++ = (tidataval_t) 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
PackBitsEncodeChunk(TIFF * tif,tidata_t bp,tsize_t cc,tsample_t s)189 PackBitsEncodeChunk(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s)
190 {
191 #if defined(__hpux) && defined(__LP64__)
192 	tsize_t rowsize = (tsize_t)(unsigned long) tif->tif_data;
193 #else
194 	tsize_t rowsize = (tsize_t) tif->tif_data;
195 #endif
196 
197 	assert(rowsize > 0);
198 
199 #ifdef YCBCR_SUPPORT
200 	/*
201 	 * YCBCR data isn't really separable into rows, so we
202 	 * might as well encode the whole tile/strip as one chunk.
203 	 */
204 	if( tif->tif_dir.td_photometric == PHOTOMETRIC_YCBCR ) {
205 #if defined(__hpux) && defined(__LP64__)
206 		rowsize = (tsize_t)(unsigned long) tif->tif_data;
207 #else
208 		rowsize = (tsize_t) tif->tif_data;
209 #endif
210 	}
211 #endif
212 
213 	while ((long)cc > 0) {
214 		int	chunk = rowsize;
215 
216 		if( cc < chunk )
217 		    chunk = cc;
218 
219 		if (PackBitsEncode(tif, bp, chunk, s) < 0)
220 		    return (-1);
221 		bp += chunk;
222 		cc -= chunk;
223 	}
224 	return (1);
225 }
226 
227 static int
PackBitsDecode(TIFF * tif,tidata_t op,tsize_t occ,tsample_t s)228 PackBitsDecode(TIFF* tif, tidata_t op, tsize_t occ, tsample_t s)
229 {
230 	char *bp;
231 	tsize_t cc;
232 	long n;
233 	int b;
234 
235 	(void) s;
236 	bp = (char*) tif->tif_rawcp;
237 	cc = tif->tif_rawcc;
238 	while (cc > 0 && (long)occ > 0) {
239 		n = (long) *bp++, cc--;
240 		/*
241 		 * Watch out for compilers that
242 		 * don't sign extend chars...
243 		 */
244 		if (n >= 128)
245 			n -= 256;
246 		if (n < 0) {		/* replicate next byte -n+1 times */
247 			if (n == -128)	/* nop */
248 				continue;
249                         n = -n + 1;
250                         if( occ < n )
251                         {
252                             TIFFWarning(tif->tif_name,
253                                         "PackBitsDecode: discarding %d bytes "
254                                         "to avoid buffer overrun",
255                                         n - occ);
256                             n = occ;
257                         }
258 			occ -= n;
259 			b = *bp++, cc--;
260 			while (n-- > 0)
261 				*op++ = (tidataval_t) b;
262 		} else {		/* copy next n+1 bytes literally */
263 			if (occ < n + 1)
264                         {
265                             TIFFWarning(tif->tif_name,
266                                         "PackBitsDecode: discarding %d bytes "
267                                         "to avoid buffer overrun",
268                                         n - occ + 1);
269                             n = occ - 1;
270                         }
271                         _TIFFmemcpy(op, bp, ++n);
272 			op += n; occ -= n;
273 			bp += n; cc -= n;
274 		}
275 	}
276 	tif->tif_rawcp = (tidata_t) bp;
277 	tif->tif_rawcc = cc;
278 	if (occ > 0) {
279 		TIFFError(tif->tif_name,
280 		    "PackBitsDecode: Not enough data for scanline %ld",
281 		    (long) tif->tif_row);
282 		return (0);
283 	}
284 	return (1);
285 }
286 
287 int
TIFFInitPackBits(TIFF * tif,int scheme)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_encoderow = PackBitsEncode;
296 	tif->tif_encodestrip = PackBitsEncodeChunk;
297 	tif->tif_encodetile = PackBitsEncodeChunk;
298 	return (1);
299 }
300 #endif /* PACKBITS_SUPPORT */
301