ReactOS  0.4.15-dev-341-g17c5fb8
tif_packbits.c
Go to the documentation of this file.
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 #ifdef PACKBITS_SUPPORT
27 /*
28  * TIFF Library.
29  *
30  * PackBits Compression Algorithm Support
31  */
32 //#include <stdio.h>
33 
34 static int
35 PackBitsPreEncode(TIFF* tif, uint16 s)
36 {
37  (void) s;
38 
39  tif->tif_data = (uint8*)_TIFFmalloc(sizeof(tmsize_t));
40  if (tif->tif_data == NULL)
41  return (0);
42  /*
43  * Calculate the scanline/tile-width size in bytes.
44  */
45  if (isTiled(tif))
46  *(tmsize_t*)tif->tif_data = TIFFTileRowSize(tif);
47  else
48  *(tmsize_t*)tif->tif_data = TIFFScanlineSize(tif);
49  return (1);
50 }
51 
52 static int
53 PackBitsPostEncode(TIFF* tif)
54 {
55  if (tif->tif_data)
56  _TIFFfree(tif->tif_data);
57  return (1);
58 }
59 
60 /*
61  * Encode a run of pixels.
62  */
63 static int
64 PackBitsEncode(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s)
65 {
66  unsigned char* bp = (unsigned char*) buf;
67  uint8* op;
68  uint8* ep;
69  uint8* lastliteral;
70  long n, slop;
71  int b;
72  enum { BASE, LITERAL, RUN, LITERAL_RUN } state;
73 
74  (void) s;
75  op = tif->tif_rawcp;
76  ep = tif->tif_rawdata + tif->tif_rawdatasize;
77  state = BASE;
78  lastliteral = 0;
79  while (cc > 0) {
80  /*
81  * Find the longest string of identical bytes.
82  */
83  b = *bp++;
84  cc--;
85  n = 1;
86  for (; cc > 0 && b == *bp; cc--, bp++)
87  n++;
88  again:
89  if (op + 2 >= ep) { /* insure space for new data */
90  /*
91  * Be careful about writing the last
92  * literal. Must write up to that point
93  * and then copy the remainder to the
94  * front of the buffer.
95  */
96  if (state == LITERAL || state == LITERAL_RUN) {
97  slop = (long)(op - lastliteral);
98  tif->tif_rawcc += (tmsize_t)(lastliteral - tif->tif_rawcp);
99  if (!TIFFFlushData1(tif))
100  return (0);
101  op = tif->tif_rawcp;
102  while (slop-- > 0)
103  *op++ = *lastliteral++;
104  lastliteral = tif->tif_rawcp;
105  } else {
106  tif->tif_rawcc += (tmsize_t)(op - tif->tif_rawcp);
107  if (!TIFFFlushData1(tif))
108  return (0);
109  op = tif->tif_rawcp;
110  }
111  }
112  switch (state) {
113  case BASE: /* initial state, set run/literal */
114  if (n > 1) {
115  state = RUN;
116  if (n > 128) {
117  *op++ = (uint8) -127;
118  *op++ = (uint8) b;
119  n -= 128;
120  goto again;
121  }
122  *op++ = (uint8)(-(n-1));
123  *op++ = (uint8) b;
124  } else {
125  lastliteral = op;
126  *op++ = 0;
127  *op++ = (uint8) b;
128  state = LITERAL;
129  }
130  break;
131  case LITERAL: /* last object was literal string */
132  if (n > 1) {
133  state = LITERAL_RUN;
134  if (n > 128) {
135  *op++ = (uint8) -127;
136  *op++ = (uint8) b;
137  n -= 128;
138  goto again;
139  }
140  *op++ = (uint8)(-(n-1)); /* encode run */
141  *op++ = (uint8) b;
142  } else { /* extend literal */
143  if (++(*lastliteral) == 127)
144  state = BASE;
145  *op++ = (uint8) b;
146  }
147  break;
148  case RUN: /* last object was run */
149  if (n > 1) {
150  if (n > 128) {
151  *op++ = (uint8) -127;
152  *op++ = (uint8) b;
153  n -= 128;
154  goto again;
155  }
156  *op++ = (uint8)(-(n-1));
157  *op++ = (uint8) b;
158  } else {
159  lastliteral = op;
160  *op++ = 0;
161  *op++ = (uint8) b;
162  state = LITERAL;
163  }
164  break;
165  case LITERAL_RUN: /* literal followed by a run */
166  /*
167  * Check to see if previous run should
168  * be converted to a literal, in which
169  * case we convert literal-run-literal
170  * to a single literal.
171  */
172  if (n == 1 && op[-2] == (uint8) -1 &&
173  *lastliteral < 126) {
174  state = (((*lastliteral) += 2) == 127 ?
175  BASE : LITERAL);
176  op[-2] = op[-1]; /* replicate */
177  } else
178  state = RUN;
179  goto again;
180  }
181  }
182  tif->tif_rawcc += (tmsize_t)(op - tif->tif_rawcp);
183  tif->tif_rawcp = op;
184  return (1);
185 }
186 
187 /*
188  * Encode a rectangular chunk of pixels. We break it up
189  * into row-sized pieces to insure that encoded runs do
190  * not span rows. Otherwise, there can be problems with
191  * the decoder if data is read, for example, by scanlines
192  * when it was encoded by strips.
193  */
194 static int
195 PackBitsEncodeChunk(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
196 {
197  tmsize_t rowsize = *(tmsize_t*)tif->tif_data;
198 
199  while (cc > 0) {
200  tmsize_t chunk = rowsize;
201 
202  if( cc < chunk )
203  chunk = cc;
204 
205  if (PackBitsEncode(tif, bp, chunk, s) < 0)
206  return (-1);
207  bp += chunk;
208  cc -= chunk;
209  }
210  return (1);
211 }
212 
213 static int
214 PackBitsDecode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s)
215 {
216  static const char module[] = "PackBitsDecode";
217  char *bp;
218  tmsize_t cc;
219  long n;
220  int b;
221 
222  (void) s;
223  bp = (char*) tif->tif_rawcp;
224  cc = tif->tif_rawcc;
225  while (cc > 0 && occ > 0) {
226  n = (long) *bp++;
227  cc--;
228  /*
229  * Watch out for compilers that
230  * don't sign extend chars...
231  */
232  if (n >= 128)
233  n -= 256;
234  if (n < 0) { /* replicate next byte -n+1 times */
235  if (n == -128) /* nop */
236  continue;
237  n = -n + 1;
238  if( occ < (tmsize_t)n )
239  {
241  "Discarding %lu bytes to avoid buffer overrun",
242  (unsigned long) ((tmsize_t)n - occ));
243  n = (long)occ;
244  }
245  if( cc == 0 )
246  {
248  "Terminating PackBitsDecode due to lack of data.");
249  break;
250  }
251  occ -= n;
252  b = *bp++;
253  cc--;
254  while (n-- > 0)
255  *op++ = (uint8) b;
256  } else { /* copy next n+1 bytes literally */
257  if (occ < (tmsize_t)(n + 1))
258  {
260  "Discarding %lu bytes to avoid buffer overrun",
261  (unsigned long) ((tmsize_t)n - occ + 1));
262  n = (long)occ - 1;
263  }
264  if (cc < (tmsize_t) (n+1))
265  {
267  "Terminating PackBitsDecode due to lack of data.");
268  break;
269  }
270  _TIFFmemcpy(op, bp, ++n);
271  op += n; occ -= n;
272  bp += n; cc -= n;
273  }
274  }
275  tif->tif_rawcp = (uint8*) bp;
276  tif->tif_rawcc = cc;
277  if (occ > 0) {
279  "Not enough data for scanline %lu",
280  (unsigned long) tif->tif_row);
281  return (0);
282  }
283  return (1);
284 }
285 
286 int
287 TIFFInitPackBits(TIFF* tif, int scheme)
288 {
289  (void) scheme;
290  tif->tif_decoderow = PackBitsDecode;
291  tif->tif_decodestrip = PackBitsDecode;
292  tif->tif_decodetile = PackBitsDecode;
293  tif->tif_preencode = PackBitsPreEncode;
294  tif->tif_postencode = PackBitsPostEncode;
295  tif->tif_encoderow = PackBitsEncode;
296  tif->tif_encodestrip = PackBitsEncodeChunk;
297  tif->tif_encodetile = PackBitsEncodeChunk;
298  return (1);
299 }
300 #endif /* PACKBITS_SUPPORT */
301 
302 /* vim: set ts=8 sts=8 sw=8 noet: */
303 /*
304  * Local Variables:
305  * mode: c
306  * c-basic-offset: 8
307  * fill-column: 78
308  * End:
309  */
TIFFCodeMethod tif_decoderow
Definition: tiffiop.h:180
uint8 * tif_rawcp
Definition: tiffiop.h:199
struct png_info_def **typedef void(__cdecl typeof(png_destroy_read_struct))(struct png_struct_def **
Definition: typeof.h:49
void TIFFWarningExt(thandle_t fd, const char *module, const char *fmt,...)
Definition: tif_warning.c:65
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
TIFFCodeMethod tif_encodestrip
Definition: tiffiop.h:183
TIFFCodeMethod tif_encoderow
Definition: tiffiop.h:181
GLdouble n
Definition: glext.h:7729
DWORD scheme
uint8 * tif_rawdata
Definition: tiffiop.h:195
thandle_t tif_clientdata
Definition: tiffiop.h:207
tmsize_t tif_rawcc
Definition: tiffiop.h:200
Definition: tiffiop.h:115
while(1)
Definition: macro.lex.yy.c:740
TIFF_SSIZE_T tmsize_t
Definition: tiffio.h:65
smooth NULL
Definition: ftsmooth.c:416
TIFFCodeMethod tif_decodestrip
Definition: tiffiop.h:182
TIFFCodeMethod tif_encodetile
Definition: tiffiop.h:185
void * _TIFFmalloc(tmsize_t s)
Definition: tif_unix.c:309
#define b
Definition: ke_i.h:79
TIFFPreMethod tif_preencode
Definition: tiffiop.h:178
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
TIFFBoolMethod tif_postencode
Definition: tiffiop.h:179
UINT op
Definition: effect.c:224
unsigned char uint8
Definition: types.h:28
RUN
Definition: userinit.h:40
void TIFFErrorExt(thandle_t fd, const char *module, const char *fmt,...)
Definition: tif_error.c:65
tmsize_t tif_rawdatasize
Definition: tiffiop.h:196
#define BASE
Definition: adler32.c:10
TIFFCodeMethod tif_decodetile
Definition: tiffiop.h:184
uint8 * tif_data
Definition: tiffiop.h:191
static int state
Definition: maze.c:121
GLdouble s
Definition: gl.h:2039
#define isTiled(tif)
Definition: tiffiop.h:229
tmsize_t TIFFTileRowSize(TIFF *tif)
Definition: tif_tile.c:180
uint32_t cc
Definition: isohybrid.c:75
int TIFFInitPackBits(TIFF *, int)
uint32 tif_row
Definition: tiffiop.h:159
tmsize_t TIFFScanlineSize(TIFF *tif)
Definition: tif_strip.c:314
unsigned short uint16
Definition: types.h:30
#define long
Definition: qsort.c:33
void _TIFFfree(void *p)
Definition: tif_unix.c:326
int TIFFFlushData1(TIFF *tif)
Definition: tif_write.c:803
void _TIFFmemcpy(void *d, const void *s, tmsize_t c)
Definition: tif_unix.c:344