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
26 #ifdef PACKBITS_SUPPORT
30 * PackBits Compression Algorithm Support
34 static int PackBitsPreEncode(TIFF
*tif
, uint16_t s
)
38 tif
->tif_data
= (uint8_t *)_TIFFmallocExt(tif
, sizeof(tmsize_t
));
39 if (tif
->tif_data
== NULL
)
42 * Calculate the scanline/tile-width size in bytes.
45 *(tmsize_t
*)tif
->tif_data
= TIFFTileRowSize(tif
);
47 *(tmsize_t
*)tif
->tif_data
= TIFFScanlineSize(tif
);
51 static int PackBitsPostEncode(TIFF
*tif
)
54 _TIFFfreeExt(tif
, tif
->tif_data
);
59 * Encode a run of pixels.
61 static int PackBitsEncode(TIFF
*tif
, uint8_t *buf
, tmsize_t cc
, uint16_t s
)
63 unsigned char *bp
= (unsigned char *)buf
;
79 ep
= tif
->tif_rawdata
+ tif
->tif_rawdatasize
;
85 * Find the longest string of identical bytes.
90 for (; cc
> 0 && b
== *bp
; cc
--, bp
++)
94 { /* insure space for new data */
96 * Be careful about writing the last
97 * literal. Must write up to that point
98 * and then copy the remainder to the
99 * front of the buffer.
101 if (state
== LITERAL
|| state
== LITERAL_RUN
)
103 slop
= (long)(op
- lastliteral
);
104 tif
->tif_rawcc
+= (tmsize_t
)(lastliteral
- tif
->tif_rawcp
);
105 if (!TIFFFlushData1(tif
))
109 *op
++ = *lastliteral
++;
110 lastliteral
= tif
->tif_rawcp
;
114 tif
->tif_rawcc
+= (tmsize_t
)(op
- tif
->tif_rawcp
);
115 if (!TIFFFlushData1(tif
))
122 case BASE
: /* initial state, set run/literal */
128 *op
++ = (uint8_t)-127;
133 *op
++ = (uint8_t)(-(n
- 1));
144 case LITERAL
: /* last object was literal string */
150 *op
++ = (uint8_t)-127;
155 *op
++ = (uint8_t)(-(n
- 1)); /* encode run */
159 { /* extend literal */
160 if (++(*lastliteral
) == 127)
165 case RUN
: /* last object was run */
170 *op
++ = (uint8_t)-127;
175 *op
++ = (uint8_t)(-(n
- 1));
186 case LITERAL_RUN
: /* literal followed by a run */
188 * Check to see if previous run should
189 * be converted to a literal, in which
190 * case we convert literal-run-literal
191 * to a single literal.
193 if (n
== 1 && op
[-2] == (uint8_t)-1 && *lastliteral
< 126)
195 state
= (((*lastliteral
) += 2) == 127 ? BASE
: LITERAL
);
196 op
[-2] = op
[-1]; /* replicate */
203 tif
->tif_rawcc
+= (tmsize_t
)(op
- tif
->tif_rawcp
);
209 * Encode a rectangular chunk of pixels. We break it up
210 * into row-sized pieces to insure that encoded runs do
211 * not span rows. Otherwise, there can be problems with
212 * the decoder if data is read, for example, by scanlines
213 * when it was encoded by strips.
215 static int PackBitsEncodeChunk(TIFF
*tif
, uint8_t *bp
, tmsize_t cc
, uint16_t s
)
217 tmsize_t rowsize
= *(tmsize_t
*)tif
->tif_data
;
221 tmsize_t chunk
= rowsize
;
226 if (PackBitsEncode(tif
, bp
, chunk
, s
) < 0)
234 static int PackBitsDecode(TIFF
*tif
, uint8_t *op
, tmsize_t occ
, uint16_t s
)
236 static const char module
[] = "PackBitsDecode";
243 bp
= (int8_t *)tif
->tif_rawcp
;
245 while (cc
> 0 && occ
> 0)
250 { /* replicate next byte -n+1 times */
251 if (n
== -128) /* nop */
254 if (occ
< (tmsize_t
)n
)
256 TIFFWarningExtR(tif
, module
,
257 "Discarding %" TIFF_SSIZE_FORMAT
258 " bytes to avoid buffer overrun",
266 "Terminating PackBitsDecode due to lack of data.");
276 { /* copy next n+1 bytes literally */
277 if (occ
< (tmsize_t
)(n
+ 1))
279 TIFFWarningExtR(tif
, module
,
280 "Discarding %" TIFF_SSIZE_FORMAT
281 " bytes to avoid buffer overrun",
282 (tmsize_t
)n
- occ
+ 1);
285 if (cc
< (tmsize_t
)(n
+ 1))
289 "Terminating PackBitsDecode due to lack of data.");
292 _TIFFmemcpy(op
, bp
, ++n
);
299 tif
->tif_rawcp
= (uint8_t *)bp
;
303 TIFFErrorExtR(tif
, module
, "Not enough data for scanline %" PRIu32
,
310 int TIFFInitPackBits(TIFF
*tif
, int scheme
)
313 tif
->tif_decoderow
= PackBitsDecode
;
314 tif
->tif_decodestrip
= PackBitsDecode
;
315 tif
->tif_decodetile
= PackBitsDecode
;
316 tif
->tif_preencode
= PackBitsPreEncode
;
317 tif
->tif_postencode
= PackBitsPostEncode
;
318 tif
->tif_encoderow
= PackBitsEncode
;
319 tif
->tif_encodestrip
= PackBitsEncodeChunk
;
320 tif
->tif_encodetile
= PackBitsEncodeChunk
;
323 #endif /* PACKBITS_SUPPORT */