]>
git.saurik.com Git - wxWidgets.git/blob - src/tiff/tif_packbits.c
   4  * Copyright (c) 1988-1997 Sam Leffler 
   5  * Copyright (c) 1991-1997 Silicon Graphics, Inc. 
   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. 
  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.   
  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  
  28 #ifdef PACKBITS_SUPPORT 
  32  * PackBits Compression Algorithm Support 
  38 PackBitsPreEncode(TIFF
* tif
, tsample_t s
) 
  42          * Calculate the scanline/tile-width size in bytes. 
  45                 tif
->tif_data 
= (tidata_t
) TIFFTileRowSize(tif
); 
  47                 tif
->tif_data 
= (tidata_t
) TIFFScanlineSize(tif
); 
  52  * NB: tidata is the type representing *(tidata_t); 
  53  *     if tidata_t is made signed then this type must 
  54  *     be adjusted accordingly. 
  56 typedef unsigned char tidata
; 
  59  * Encode a run of pixels. 
  62 PackBitsEncode(TIFF
* tif
, tidata_t buf
, tsize_t cc
, tsample_t s
) 
  64         u_char
* bp 
= (u_char
*) buf
; 
  65         tidata_t op
, ep
, lastliteral
; 
  68         enum { BASE
, LITERAL
, RUN
, LITERAL_RUN 
} state
; 
  72         ep 
= tif
->tif_rawdata 
+ tif
->tif_rawdatasize
; 
  77                  * Find the longest string of identical bytes. 
  79                 b 
= *bp
++, cc
--, n 
= 1; 
  80                 for (; cc 
> 0 && b 
== *bp
; cc
--, bp
++) 
  83                 if (op 
+ 2 >= ep
) {             /* insure space for new data */ 
  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. 
  90                         if (state 
== LITERAL 
|| state 
== LITERAL_RUN
) { 
  91                                 slop 
= op 
- lastliteral
; 
  92                                 tif
->tif_rawcc 
+= lastliteral 
- tif
->tif_rawcp
; 
  93                                 if (!TIFFFlushData1(tif
)) 
  97                                         *op
++ = *lastliteral
++; 
  98                                 lastliteral 
= tif
->tif_rawcp
; 
 100                                 tif
->tif_rawcc 
+= op 
- tif
->tif_rawcp
; 
 101                                 if (!TIFFFlushData1(tif
)) 
 107                 case BASE
:              /* initial state, set run/literal */ 
 111                                         *op
++ = (tidata
) -127; 
 112                                         *op
++ = (tidataval_t
) b
; 
 116                                 *op
++ = (tidataval_t
)(-(n
-1)); 
 117                                 *op
++ = (tidataval_t
) b
; 
 121                                 *op
++ = (tidataval_t
) b
; 
 125                 case LITERAL
:           /* last object was literal string */ 
 129                                         *op
++ = (tidata
) -127; 
 130                                         *op
++ = (tidataval_t
) b
; 
 134                                 *op
++ = (tidataval_t
)(-(n
-1));  /* encode run */ 
 135                                 *op
++ = (tidataval_t
) b
; 
 136                         } else {                        /* extend literal */ 
 137                                 if (++(*lastliteral
) == 127) 
 139                                 *op
++ = (tidataval_t
) b
; 
 142                 case RUN
:               /* last object was run */ 
 145                                         *op
++ = (tidata
) -127; 
 146                                         *op
++ = (tidataval_t
) b
; 
 150                                 *op
++ = (tidataval_t
)(-(n
-1)); 
 151                                 *op
++ = (tidataval_t
) b
; 
 155                                 *op
++ = (tidataval_t
) b
; 
 159                 case LITERAL_RUN
:       /* literal followed by a run */ 
 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. 
 166                         if (n 
== 1 && op
[-2] == (tidata
) -1 && 
 167                             *lastliteral 
< 126) { 
 168                                 state 
= (((*lastliteral
) += 2) == 127 ? 
 170                                 op
[-2] = op
[-1];        /* replicate */ 
 176         tif
->tif_rawcc 
+= op 
- tif
->tif_rawcp
; 
 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. 
 189 PackBitsEncodeChunk(TIFF
* tif
, tidata_t bp
, tsize_t cc
, tsample_t s
) 
 191 #if defined(__hpux) && defined(__LP64__) 
 192         tsize_t rowsize 
= (tsize_t
)(unsigned long) tif
->tif_data
; 
 194         tsize_t rowsize 
= (tsize_t
) tif
->tif_data
; 
 201          * YCBCR data isn't really separable into rows, so we 
 202          * might as well encode the whole tile/strip as one chunk. 
 204         if( tif
->tif_dir
.td_photometric 
== PHOTOMETRIC_YCBCR 
) { 
 205 #if defined(__hpux) && defined(__LP64__) 
 206                 rowsize 
= (tsize_t
)(unsigned long) tif
->tif_data
; 
 208                 rowsize 
= (tsize_t
) tif
->tif_data
; 
 213         while ((long)cc 
> 0) { 
 219                 if (PackBitsEncode(tif
, bp
, chunk
, s
) < 0) 
 228 PackBitsDecode(TIFF
* tif
, tidata_t op
, tsize_t occ
, tsample_t s
) 
 236         bp 
= (char*) tif
->tif_rawcp
; 
 238         while (cc 
> 0 && (long)occ 
> 0) { 
 239                 n 
= (long) *bp
++, cc
--; 
 241                  * Watch out for compilers that 
 242                  * don't sign extend chars... 
 246                 if (n 
< 0) {            /* replicate next byte -n+1 times */ 
 247                         if (n 
== -128)  /* nop */ 
 252                             TIFFWarning(tif
->tif_name
, 
 253                                         "PackBitsDecode: discarding %d bytes " 
 254                                         "to avoid buffer overrun", 
 261                                 *op
++ = (tidataval_t
) b
; 
 262                 } else {                /* copy next n+1 bytes literally */ 
 265                             TIFFWarning(tif
->tif_name
, 
 266                                         "PackBitsDecode: discarding %d bytes " 
 267                                         "to avoid buffer overrun", 
 271                         _TIFFmemcpy(op
, bp
, ++n
); 
 276         tif
->tif_rawcp 
= (tidata_t
) bp
; 
 279                 TIFFError(tif
->tif_name
, 
 280                     "PackBitsDecode: Not enough data for scanline %ld", 
 281                     (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_encoderow 
= PackBitsEncode
; 
 296         tif
->tif_encodestrip 
= PackBitsEncodeChunk
; 
 297         tif
->tif_encodetile 
= PackBitsEncodeChunk
; 
 300 #endif /* PACKBITS_SUPPORT */