2 * Copyright (c) 1988-1997 Sam Leffler
3 * Copyright (c) 1991-1997 Silicon Graphics, Inc.
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.
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.
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
27 #ifdef PACKBITS_SUPPORT
31 * PackBits Compression Algorithm Support
36 PackBitsPreEncode(TIFF
* tif
, uint16 s
)
40 tif
->tif_data
= (uint8
*)_TIFFmalloc(sizeof(tmsize_t
));
41 if (tif
->tif_data
== NULL
)
44 * Calculate the scanline/tile-width size in bytes.
47 *(tmsize_t
*)tif
->tif_data
= TIFFTileRowSize(tif
);
49 *(tmsize_t
*)tif
->tif_data
= TIFFScanlineSize(tif
);
54 PackBitsPostEncode(TIFF
* tif
)
57 _TIFFfree(tif
->tif_data
);
62 * Encode a run of pixels.
65 PackBitsEncode(TIFF
* tif
, uint8
* buf
, tmsize_t cc
, uint16 s
)
67 unsigned char* bp
= (unsigned char*) buf
;
73 enum { BASE
, LITERAL
, RUN
, LITERAL_RUN
} state
;
77 ep
= tif
->tif_rawdata
+ tif
->tif_rawdatasize
;
82 * Find the longest string of identical bytes.
87 for (; cc
> 0 && b
== *bp
; cc
--, bp
++)
90 if (op
+ 2 >= ep
) { /* insure space for new data */
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.
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
))
104 *op
++ = *lastliteral
++;
105 lastliteral
= tif
->tif_rawcp
;
107 tif
->tif_rawcc
+= (tmsize_t
)(op
- tif
->tif_rawcp
);
108 if (!TIFFFlushData1(tif
))
114 case BASE
: /* initial state, set run/literal */
118 *op
++ = (uint8
) -127;
123 *op
++ = (uint8
)(-(n
-1));
132 case LITERAL
: /* last object was literal string */
136 *op
++ = (uint8
) -127;
141 *op
++ = (uint8
)(-(n
-1)); /* encode run */
143 } else { /* extend literal */
144 if (++(*lastliteral
) == 127)
149 case RUN
: /* last object was run */
152 *op
++ = (uint8
) -127;
157 *op
++ = (uint8
)(-(n
-1));
166 case LITERAL_RUN
: /* literal followed by a run */
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.
173 if (n
== 1 && op
[-2] == (uint8
) -1 &&
174 *lastliteral
< 126) {
175 state
= (((*lastliteral
) += 2) == 127 ?
177 op
[-2] = op
[-1]; /* replicate */
183 tif
->tif_rawcc
+= (tmsize_t
)(op
- tif
->tif_rawcp
);
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.
196 PackBitsEncodeChunk(TIFF
* tif
, uint8
* bp
, tmsize_t cc
, uint16 s
)
198 tmsize_t rowsize
= *(tmsize_t
*)tif
->tif_data
;
201 tmsize_t chunk
= rowsize
;
206 if (PackBitsEncode(tif
, bp
, chunk
, s
) < 0)
215 PackBitsDecode(TIFF
* tif
, uint8
* op
, tmsize_t occ
, uint16 s
)
217 static const char module
[] = "PackBitsDecode";
224 bp
= (char*) tif
->tif_rawcp
;
226 while (cc
> 0 && occ
> 0) {
230 * Watch out for compilers that
231 * don't sign extend chars...
235 if (n
< 0) { /* replicate next byte -n+1 times */
236 if (n
== -128) /* nop */
239 if( occ
< (tmsize_t
)n
)
241 TIFFWarningExt(tif
->tif_clientdata
, module
,
242 "Discarding %lu bytes to avoid buffer overrun",
243 (unsigned long) ((tmsize_t
)n
- occ
));
248 TIFFWarningExt(tif
->tif_clientdata
, module
,
249 "Terminating PackBitsDecode due to lack of data.");
257 } else { /* copy next n+1 bytes literally */
258 if (occ
< (tmsize_t
)(n
+ 1))
260 TIFFWarningExt(tif
->tif_clientdata
, module
,
261 "Discarding %lu bytes to avoid buffer overrun",
262 (unsigned long) ((tmsize_t
)n
- occ
+ 1));
265 if (cc
< (tmsize_t
) (n
+1))
267 TIFFWarningExt(tif
->tif_clientdata
, module
,
268 "Terminating PackBitsDecode due to lack of data.");
271 _TIFFmemcpy(op
, bp
, ++n
);
276 tif
->tif_rawcp
= (uint8
*) bp
;
279 TIFFErrorExt(tif
->tif_clientdata
, module
,
280 "Not enough data for scanline %lu",
281 (unsigned long) tif
->tif_row
);
288 TIFFInitPackBits(TIFF
* tif
, int 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
;
301 #endif /* PACKBITS_SUPPORT */
303 /* vim: set ts=8 sts=8 sw=8 noet: */