]>
git.saurik.com Git - wxWidgets.git/blob - src/tiff/libtiff/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 
  37 PackBitsPreEncode(TIFF
* tif
, tsample_t s
) 
  41         if (!(tif
->tif_data 
= (tidata_t
)_TIFFmalloc(sizeof(tsize_t
)))) 
  44          * Calculate the scanline/tile-width size in bytes. 
  47                 *(tsize_t
*)tif
->tif_data 
= TIFFTileRowSize(tif
); 
  49                 *(tsize_t
*)tif
->tif_data 
= TIFFScanlineSize(tif
); 
  54 PackBitsPostEncode(TIFF
* tif
) 
  57             _TIFFfree(tif
->tif_data
); 
  62  * NB: tidata is the type representing *(tidata_t); 
  63  *     if tidata_t is made signed then this type must 
  64  *     be adjusted accordingly. 
  66 typedef unsigned char tidata
; 
  69  * Encode a run of pixels. 
  72 PackBitsEncode(TIFF
* tif
, tidata_t buf
, tsize_t cc
, tsample_t s
) 
  74         unsigned char* bp 
= (unsigned char*) buf
; 
  75         tidata_t op
, ep
, lastliteral
; 
  78         enum { BASE
, LITERAL
, RUN
, LITERAL_RUN 
} state
; 
  82         ep 
= tif
->tif_rawdata 
+ tif
->tif_rawdatasize
; 
  87                  * Find the longest string of identical bytes. 
  89                 b 
= *bp
++, cc
--, n 
= 1; 
  90                 for (; cc 
> 0 && b 
== *bp
; cc
--, bp
++) 
  93                 if (op 
+ 2 >= ep
) {             /* insure space for new data */ 
  95                          * Be careful about writing the last 
  96                          * literal.  Must write up to that point 
  97                          * and then copy the remainder to the 
  98                          * front of the buffer. 
 100                         if (state 
== LITERAL 
|| state 
== LITERAL_RUN
) { 
 101                                 slop 
= op 
- lastliteral
; 
 102                                 tif
->tif_rawcc 
+= lastliteral 
- tif
->tif_rawcp
; 
 103                                 if (!TIFFFlushData1(tif
)) 
 107                                         *op
++ = *lastliteral
++; 
 108                                 lastliteral 
= tif
->tif_rawcp
; 
 110                                 tif
->tif_rawcc 
+= op 
- tif
->tif_rawcp
; 
 111                                 if (!TIFFFlushData1(tif
)) 
 117                 case BASE
:              /* initial state, set run/literal */ 
 121                                         *op
++ = (tidata
) -127; 
 122                                         *op
++ = (tidataval_t
) b
; 
 126                                 *op
++ = (tidataval_t
)(-(n
-1)); 
 127                                 *op
++ = (tidataval_t
) b
; 
 131                                 *op
++ = (tidataval_t
) b
; 
 135                 case LITERAL
:           /* last object was literal string */ 
 139                                         *op
++ = (tidata
) -127; 
 140                                         *op
++ = (tidataval_t
) b
; 
 144                                 *op
++ = (tidataval_t
)(-(n
-1));  /* encode run */ 
 145                                 *op
++ = (tidataval_t
) b
; 
 146                         } else {                        /* extend literal */ 
 147                                 if (++(*lastliteral
) == 127) 
 149                                 *op
++ = (tidataval_t
) b
; 
 152                 case RUN
:               /* last object was run */ 
 155                                         *op
++ = (tidata
) -127; 
 156                                         *op
++ = (tidataval_t
) b
; 
 160                                 *op
++ = (tidataval_t
)(-(n
-1)); 
 161                                 *op
++ = (tidataval_t
) b
; 
 165                                 *op
++ = (tidataval_t
) b
; 
 169                 case LITERAL_RUN
:       /* literal followed by a run */ 
 171                          * Check to see if previous run should 
 172                          * be converted to a literal, in which 
 173                          * case we convert literal-run-literal 
 174                          * to a single literal. 
 176                         if (n 
== 1 && op
[-2] == (tidata
) -1 && 
 177                             *lastliteral 
< 126) { 
 178                                 state 
= (((*lastliteral
) += 2) == 127 ? 
 180                                 op
[-2] = op
[-1];        /* replicate */ 
 186         tif
->tif_rawcc 
+= op 
- tif
->tif_rawcp
; 
 192  * Encode a rectangular chunk of pixels.  We break it up 
 193  * into row-sized pieces to insure that encoded runs do 
 194  * not span rows.  Otherwise, there can be problems with 
 195  * the decoder if data is read, for example, by scanlines 
 196  * when it was encoded by strips. 
 199 PackBitsEncodeChunk(TIFF
* tif
, tidata_t bp
, tsize_t cc
, tsample_t s
) 
 201         tsize_t rowsize 
= *(tsize_t
*)tif
->tif_data
; 
 203         while ((long)cc 
> 0) { 
 209                 if (PackBitsEncode(tif
, bp
, chunk
, s
) < 0) 
 218 PackBitsDecode(TIFF
* tif
, tidata_t op
, tsize_t occ
, tsample_t s
) 
 226         bp 
= (char*) tif
->tif_rawcp
; 
 228         while (cc 
> 0 && (long)occ 
> 0) { 
 229                 n 
= (long) *bp
++, cc
--; 
 231                  * Watch out for compilers that 
 232                  * don't sign extend chars... 
 236                 if (n 
< 0) {            /* replicate next byte -n+1 times */ 
 237                         if (n 
== -128)  /* nop */ 
 242                                                         TIFFWarningExt(tif
->tif_clientdata
, tif
->tif_name
, 
 243                                         "PackBitsDecode: discarding %d bytes " 
 244                                         "to avoid buffer overrun", 
 251                                 *op
++ = (tidataval_t
) b
; 
 252                 } else {                /* copy next n+1 bytes literally */ 
 255                             TIFFWarningExt(tif
->tif_clientdata
, tif
->tif_name
, 
 256                                         "PackBitsDecode: discarding %d bytes " 
 257                                         "to avoid buffer overrun", 
 261                         _TIFFmemcpy(op
, bp
, ++n
); 
 266         tif
->tif_rawcp 
= (tidata_t
) bp
; 
 269                 TIFFErrorExt(tif
->tif_clientdata
, tif
->tif_name
, 
 270                     "PackBitsDecode: Not enough data for scanline %ld", 
 271                     (long) tif
->tif_row
); 
 278 TIFFInitPackBits(TIFF
* tif
, int scheme
) 
 281         tif
->tif_decoderow 
= PackBitsDecode
; 
 282         tif
->tif_decodestrip 
= PackBitsDecode
; 
 283         tif
->tif_decodetile 
= PackBitsDecode
; 
 284         tif
->tif_preencode 
= PackBitsPreEncode
; 
 285         tif
->tif_postencode 
= PackBitsPostEncode
; 
 286         tif
->tif_encoderow 
= PackBitsEncode
; 
 287         tif
->tif_encodestrip 
= PackBitsEncodeChunk
; 
 288         tif
->tif_encodetile 
= PackBitsEncodeChunk
; 
 291 #endif /* PACKBITS_SUPPORT */ 
 293 /* vim: set ts=8 sts=8 sw=8 noet: */