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 */ 311