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 37static int 38PackBitsPreEncode(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 */ 56typedef unsigned char tidata; 57 58/* 59 * Encode a run of pixels. 60 */ 61static int 62PackBitsEncode(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 */ 188static int 189PackBitsEncodeChunk(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 227static int 228PackBitsDecode(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 287int 288TIFFInitPackBits(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