Visualization Library 2.0.0-b5

A lightweight C++ OpenGL middleware for 2D/3D graphics

VL     Star     Watch     Fork     Issue

[Download] [Tutorials] [All Classes] [Grouped Classes]
tif_packbits.c
Go to the documentation of this file.
1 /* $Id: tif_packbits.c,v 1.13 2006/02/07 11:03:29 dron Exp $ */
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 <stdio.h>
35 
36 static int
37 PackBitsPreEncode(TIFF* tif, tsample_t s)
38 {
39  (void) s;
40 
41  if (!(tif->tif_data = (tidata_t)_TIFFmalloc(sizeof(tsize_t))))
42  return (0);
43  /*
44  * Calculate the scanline/tile-width size in bytes.
45  */
46  if (isTiled(tif))
47  *(tsize_t*)tif->tif_data = TIFFTileRowSize(tif);
48  else
49  *(tsize_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  * NB: tidata is the type representing *(tidata_t);
63  * if tidata_t is made signed then this type must
64  * be adjusted accordingly.
65  */
66 typedef unsigned char tidata;
67 
68 /*
69  * Encode a run of pixels.
70  */
71 static int
72 PackBitsEncode(TIFF* tif, tidata_t buf, tsize_t cc, tsample_t s)
73 {
74  unsigned char* bp = (unsigned char*) buf;
75  tidata_t op, ep, lastliteral;
76  long n, slop;
77  int b;
78  enum { BASE, LITERAL, RUN, LITERAL_RUN } state;
79 
80  (void) s;
81  op = tif->tif_rawcp;
82  ep = tif->tif_rawdata + tif->tif_rawdatasize;
83  state = BASE;
84  lastliteral = 0;
85  while (cc > 0) {
86  /*
87  * Find the longest string of identical bytes.
88  */
89  b = *bp++, cc--, n = 1;
90  for (; cc > 0 && b == *bp; cc--, bp++)
91  n++;
92  again:
93  if (op + 2 >= ep) { /* insure space for new data */
94  /*
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.
99  */
100  if (state == LITERAL || state == LITERAL_RUN) {
101  slop = op - lastliteral;
102  tif->tif_rawcc += lastliteral - tif->tif_rawcp;
103  if (!TIFFFlushData1(tif))
104  return (-1);
105  op = tif->tif_rawcp;
106  while (slop-- > 0)
107  *op++ = *lastliteral++;
108  lastliteral = tif->tif_rawcp;
109  } else {
110  tif->tif_rawcc += op - tif->tif_rawcp;
111  if (!TIFFFlushData1(tif))
112  return (-1);
113  op = tif->tif_rawcp;
114  }
115  }
116  switch (state) {
117  case BASE: /* initial state, set run/literal */
118  if (n > 1) {
119  state = RUN;
120  if (n > 128) {
121  *op++ = (tidata) -127;
122  *op++ = (tidataval_t) b;
123  n -= 128;
124  goto again;
125  }
126  *op++ = (tidataval_t)(-(n-1));
127  *op++ = (tidataval_t) b;
128  } else {
129  lastliteral = op;
130  *op++ = 0;
131  *op++ = (tidataval_t) b;
132  state = LITERAL;
133  }
134  break;
135  case LITERAL: /* last object was literal string */
136  if (n > 1) {
137  state = LITERAL_RUN;
138  if (n > 128) {
139  *op++ = (tidata) -127;
140  *op++ = (tidataval_t) b;
141  n -= 128;
142  goto again;
143  }
144  *op++ = (tidataval_t)(-(n-1)); /* encode run */
145  *op++ = (tidataval_t) b;
146  } else { /* extend literal */
147  if (++(*lastliteral) == 127)
148  state = BASE;
149  *op++ = (tidataval_t) b;
150  }
151  break;
152  case RUN: /* last object was run */
153  if (n > 1) {
154  if (n > 128) {
155  *op++ = (tidata) -127;
156  *op++ = (tidataval_t) b;
157  n -= 128;
158  goto again;
159  }
160  *op++ = (tidataval_t)(-(n-1));
161  *op++ = (tidataval_t) b;
162  } else {
163  lastliteral = op;
164  *op++ = 0;
165  *op++ = (tidataval_t) b;
166  state = LITERAL;
167  }
168  break;
169  case LITERAL_RUN: /* literal followed by a run */
170  /*
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.
175  */
176  if (n == 1 && op[-2] == (tidata) -1 &&
177  *lastliteral < 126) {
178  state = (((*lastliteral) += 2) == 127 ?
179  BASE : LITERAL);
180  op[-2] = op[-1]; /* replicate */
181  } else
182  state = RUN;
183  goto again;
184  }
185  }
186  tif->tif_rawcc += op - tif->tif_rawcp;
187  tif->tif_rawcp = op;
188  return (1);
189 }
190 
191 /*
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.
197  */
198 static int
199 PackBitsEncodeChunk(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s)
200 {
201  tsize_t rowsize = *(tsize_t*)tif->tif_data;
202 
203  while ((long)cc > 0) {
204  int chunk = rowsize;
205 
206  if( cc < chunk )
207  chunk = cc;
208 
209  if (PackBitsEncode(tif, bp, chunk, s) < 0)
210  return (-1);
211  bp += chunk;
212  cc -= chunk;
213  }
214  return (1);
215 }
216 
217 static int
218 PackBitsDecode(TIFF* tif, tidata_t op, tsize_t occ, tsample_t s)
219 {
220  char *bp;
221  tsize_t cc;
222  long n;
223  int b;
224 
225  (void) s;
226  bp = (char*) tif->tif_rawcp;
227  cc = tif->tif_rawcc;
228  while (cc > 0 && (long)occ > 0) {
229  n = (long) *bp++, cc--;
230  /*
231  * Watch out for compilers that
232  * don't sign extend chars...
233  */
234  if (n >= 128)
235  n -= 256;
236  if (n < 0) { /* replicate next byte -n+1 times */
237  if (n == -128) /* nop */
238  continue;
239  n = -n + 1;
240  if( occ < n )
241  {
243  "PackBitsDecode: discarding %d bytes "
244  "to avoid buffer overrun",
245  n - occ);
246  n = occ;
247  }
248  occ -= n;
249  b = *bp++, cc--;
250  while (n-- > 0)
251  *op++ = (tidataval_t) b;
252  } else { /* copy next n+1 bytes literally */
253  if (occ < n + 1)
254  {
256  "PackBitsDecode: discarding %d bytes "
257  "to avoid buffer overrun",
258  n - occ + 1);
259  n = occ - 1;
260  }
261  _TIFFmemcpy(op, bp, ++n);
262  op += n; occ -= n;
263  bp += n; cc -= n;
264  }
265  }
266  tif->tif_rawcp = (tidata_t) bp;
267  tif->tif_rawcc = cc;
268  if (occ > 0) {
270  "PackBitsDecode: Not enough data for scanline %ld",
271  (long) tif->tif_row);
272  return (0);
273  }
274  return (1);
275 }
276 
277 int
278 TIFFInitPackBits(TIFF* tif, int scheme)
279 {
280  (void) 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;
289  return (1);
290 }
291 #endif /* PACKBITS_SUPPORT */
292 
293 /* vim: set ts=8 sts=8 sw=8 noet: */
int32 tsize_t
Definition: tiffio.h:66
uint16 tsample_t
Definition: tiffio.h:63
TIFFCodeMethod tif_decoderow
Definition: tiffiop.h:146
tsize_t TIFFTileRowSize(TIFF *tif)
Definition: tif_tile.c:174
void TIFFWarningExt(thandle_t fd, const char *module, const char *fmt,...)
Definition: tif_warning.c:63
TIFFCodeMethod tif_encodestrip
Definition: tiffiop.h:149
TIFFCodeMethod tif_encoderow
Definition: tiffiop.h:147
tsize_t TIFFScanlineSize(TIFF *tif)
Definition: tif_strip.c:227
tidata_t tif_rawdata
Definition: tiffiop.h:161
thandle_t tif_clientdata
Definition: tiffiop.h:171
typedef void(APIENTRY *GLDEBUGPROCARB)(GLenum source
char * tif_name
Definition: tiffiop.h:96
Definition: tiffiop.h:95
GLboolean GLboolean GLboolean b
void _TIFFmemcpy(tdata_t d, const tdata_t s, tsize_t c)
Definition: tif_acorn.c:485
GLenum GLuint GLenum GLsizei const GLchar * buf
tidata_t tif_rawcp
Definition: tiffiop.h:163
TIFFCodeMethod tif_decodestrip
Definition: tiffiop.h:148
TIFFCodeMethod tif_encodetile
Definition: tiffiop.h:151
TIFFPreMethod tif_preencode
Definition: tiffiop.h:144
TIFFBoolMethod tif_postencode
Definition: tiffiop.h:145
typedef long(ZCALLBACK *tell_file_func) OF((voidpf opaque
GLdouble n
void TIFFErrorExt(thandle_t fd, const char *module, const char *fmt,...)
Definition: tif_error.c:63
tsize_t tif_rawdatasize
Definition: tiffiop.h:162
#define BASE
Definition: adler32.c:10
tsize_t tif_rawcc
Definition: tiffiop.h:164
TIFFCodeMethod tif_decodetile
Definition: tiffiop.h:150
unsigned char tidata
Definition: tif_packbits.c:66
#define isTiled(tif)
Definition: tiffiop.h:189
tidataval_t * tidata_t
Definition: tiffiop.h:84
int TIFFInitPackBits(TIFF *tif, int scheme)
Definition: tif_packbits.c:278
unsigned char tidataval_t
Definition: tiffiop.h:83
uint32 tif_row
Definition: tiffiop.h:126
GLdouble s
void * _TIFFmalloc(tsize_t s)
Definition: tif_acorn.c:461
void _TIFFfree(tdata_t p)
Definition: tif_acorn.c:467
png_infop int chunk
Definition: png.h:2339
tidata_t tif_data
Definition: tiffiop.h:157
int TIFFFlushData1(TIFF *tif)
Definition: tif_write.c:696