1/* PDFlib GmbH cvsid: $Id: tif_next.c 14574 2005-10-29 16:27:43Z bonefish $ */
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 NEXT_SUPPORT
29/*
30 * TIFF Library.
31 *
32 * NeXT 2-bit Grey Scale Compression Algorithm Support
33 */
34
35#define SETPIXEL(op, v) {			\
36	switch (npixels++ & 3) {		\
37	case 0:	op[0]  = (v) << 6; break;	\
38	case 1:	op[0] |= (v) << 4; break;	\
39	case 2:	op[0] |= (v) << 2; break;	\
40	case 3:	*op++ |= (v);	   break;	\
41	}					\
42}
43
44#define LITERALROW	0x00
45#define LITERALSPAN	0x40
46#define WHITE   	((1<<2)-1)
47
48static int
49NeXTDecode(TIFF* tif, tidata_t buf, tsize_t occ, tsample_t s)
50{
51	register tif_char *bp, *op;
52	register tsize_t cc;
53	register int n;
54	tidata_t row;
55	tsize_t scanline;
56
57	(void) s;
58	/*
59	 * Each scanline is assumed to start off as all
60	 * white (we assume a PhotometricInterpretation
61	 * of ``min-is-black'').
62	 */
63	for (op = buf, cc = occ; cc-- > 0;)
64		*op++ = 0xff;
65
66	bp = (tif_char *)tif->tif_rawcp;
67	cc = tif->tif_rawcc;
68	scanline = tif->tif_scanlinesize;
69	for (row = buf; (long)occ > 0; occ -= scanline, row += scanline) {
70		n = *bp++, cc--;
71		switch (n) {
72		case LITERALROW:
73			/*
74			 * The entire scanline is given as literal values.
75			 */
76			if (cc < scanline)
77				goto bad;
78			_TIFFmemcpy(row, bp, scanline);
79			bp += scanline;
80			cc -= scanline;
81			break;
82		case LITERALSPAN: {
83			int off;
84			/*
85			 * The scanline has a literal span
86			 * that begins at some offset.
87			 */
88			off = (bp[0] * 256) + bp[1];
89			n = (bp[2] * 256) + bp[3];
90			if (cc < 4+n)
91				goto bad;
92			_TIFFmemcpy(row+off, bp+4, n);
93			bp += 4+n;
94			cc -= 4+n;
95			break;
96		}
97		default: {
98			register int npixels = 0, grey;
99			tif_long imagewidth = tif->tif_dir.td_imagewidth;
100
101			/*
102			 * The scanline is composed of a sequence
103			 * of constant color ``runs''.  We shift
104			 * into ``run mode'' and interpret bytes
105			 * as codes of the form <color><npixels>
106			 * until we've filled the scanline.
107			 */
108			op = row;
109			for (;;) {
110				grey = (n>>6) & 0x3;
111				n &= 0x3f;
112				while (n-- > 0)
113					SETPIXEL(op, grey);
114				if (npixels >= (int) imagewidth)
115					break;
116				if (cc == 0)
117					goto bad;
118				n = *bp++, cc--;
119			}
120			break;
121		}
122		}
123	}
124	tif->tif_rawcp = (tidata_t) bp;
125	tif->tif_rawcc = cc;
126	return (1);
127bad:
128	TIFFError(tif->tif_name, "NeXTDecode: Not enough data for scanline %ld",
129	    (long) tif->tif_row);
130	return (0);
131}
132
133int
134TIFFInitNeXT(TIFF* tif, int scheme)
135{
136	(void) scheme;
137	tif->tif_decoderow = NeXTDecode;
138	tif->tif_decodestrip = NeXTDecode;
139	tif->tif_decodetile = NeXTDecode;
140	return (1);
141}
142#endif /* NEXT_SUPPORT */
143