ReactOS 0.4.16-dev-117-g38f21f9
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
34static int
35PackBitsPreEncode(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
52static int
53PackBitsPostEncode(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 */
63static int
64PackBitsEncode(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 */
194static int
195PackBitsEncodeChunk(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
213static int
214PackBitsDecode(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
286int
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 */
static int state
Definition: maze.c:121
unsigned short uint16
Definition: types.h:30
unsigned char uint8
Definition: types.h:28
while(CdLookupNextInitialFileDirent(IrpContext, Fcb, FileContext))
#define NULL
Definition: types.h:112
UINT op
Definition: effect.c:236
#define BASE
Definition: inflate.c:58
GLdouble s
Definition: gl.h:2039
GLdouble n
Definition: glext.h:7729
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
uint32_t cc
Definition: isohybrid.c:75
#define b
Definition: ke_i.h:79
#define LITERAL(a)
#define long
Definition: qsort.c:33
DWORD scheme
Definition: tiffiop.h:115
TIFFCodeMethod tif_encodestrip
Definition: tiffiop.h:183
TIFFCodeMethod tif_encodetile
Definition: tiffiop.h:185
TIFFPreMethod tif_preencode
Definition: tiffiop.h:178
tmsize_t tif_rawcc
Definition: tiffiop.h:200
TIFFCodeMethod tif_decodestrip
Definition: tiffiop.h:182
thandle_t tif_clientdata
Definition: tiffiop.h:207
TIFFCodeMethod tif_decoderow
Definition: tiffiop.h:180
TIFFBoolMethod tif_postencode
Definition: tiffiop.h:179
uint8 * tif_data
Definition: tiffiop.h:191
TIFFCodeMethod tif_encoderow
Definition: tiffiop.h:181
uint32 tif_row
Definition: tiffiop.h:159
tmsize_t tif_rawdatasize
Definition: tiffiop.h:196
uint8 * tif_rawcp
Definition: tiffiop.h:199
TIFFCodeMethod tif_decodetile
Definition: tiffiop.h:184
uint8 * tif_rawdata
Definition: tiffiop.h:195
#define TIFFInitPackBits
Definition: tif_codec.c:39
void TIFFErrorExt(thandle_t fd, const char *module, const char *fmt,...)
Definition: tif_error.c:65
tmsize_t TIFFScanlineSize(TIFF *tif)
Definition: tif_strip.c:314
tmsize_t TIFFTileRowSize(TIFF *tif)
Definition: tif_tile.c:180
void _TIFFfree(void *p)
Definition: tif_unix.c:326
void * _TIFFmalloc(tmsize_t s)
Definition: tif_unix.c:309
void _TIFFmemcpy(void *d, const void *s, tmsize_t c)
Definition: tif_unix.c:344
void TIFFWarningExt(thandle_t fd, const char *module, const char *fmt,...)
Definition: tif_warning.c:65
int TIFFFlushData1(TIFF *tif)
Definition: tif_write.c:803
TIFF_SSIZE_T tmsize_t
Definition: tiffio.h:65
#define isTiled(tif)
Definition: tiffiop.h:229
RUN
Definition: userinit.h:41