1#ifndef lint
2static char id[] = "$Id: tif2ras.c 276 2010-06-30 12:18:30Z nijtmans $";
3#endif
4/*-
5 * tif2ras.c - Converts from a Tagged Image File Format image to a Sun Raster.
6 *
7 * Copyright (c) 1990 by Sun Microsystems, Inc.
8 *
9 * Author: Patrick J. Naughton
10 * naughton@wind.sun.com
11 *
12 * Permission to use, copy, modify, and distribute this software and its
13 * documentation for any purpose and without fee is hereby granted,
14 * provided that the above copyright notice appear in all copies and that
15 * both that copyright notice and this permission notice appear in
16 * supporting documentation.
17 *
18 * This file is provided AS IS with no warranties of any kind.  The author
19 * shall have no liability with respect to the infringement of copyrights,
20 * trade secrets or any patents by this file or any part thereof.  In no
21 * event will the author be liable for any lost revenue or profits or
22 * other special, indirect and consequential damages.
23 *
24 * Comments and additions should be sent to the author:
25 *
26 *                     Patrick J. Naughton
27 *                     Sun Microsystems
28 *                     2550 Garcia Ave, MS 14-40
29 *                     Mountain View, CA 94043
30 *                     (415) 336-1080
31 *
32 * Revision History:
33 * 10-Jan-89: Created.
34 * 06-Mar-90: Change to byte encoded rasterfiles.
35 *	      fix bug in call to ReadScanline().
36 *	      fix bug in CVT() macro.
37 *	      fix assignment of td, (missing &).
38 *
39 * Description:
40 *   This program takes a MicroSoft/Aldus "Tagged Image File Format" image or
41 * "TIFF" file as input and writes a Sun Rasterfile [see rasterfile(5)].  The
42 * output file may be standard output, but the input TIFF file must be a real
43 * file since seek(2) is used.
44 */
45
46#include <stdio.h>
47#include <pixrect/pixrect_hs.h>
48#include "tiffio.h"
49
50typedef int boolean;
51#define True (1)
52#define False (0)
53#define	CVT(x)		(((x) * 255) / ((1L<<16)-1))
54
55boolean     Verbose = False;
56char       *pname;		/* program name (used for error messages) */
57
58void
59error(s1, s2)
60    char       *s1,
61               *s2;
62{
63    fprintf(stderr, s1, pname, s2);
64    exit(1);
65}
66
67void
68usage()
69{
70    error("usage: %s -[vq] TIFFfile [rasterfile]\n", NULL);
71}
72
73
74main(argc, argv)
75    int         argc;
76    char       *argv[];
77{
78    char       *inf = NULL;
79    char       *outf = NULL;
80    FILE       *fp;
81    long        width,
82                height;
83    int         depth,
84                numcolors;
85    register TIFF *tif;
86    TIFFDirectory *td;
87    register u_char *inp,
88               *outp;
89    register int col,
90                i;
91    register long row;
92    u_char     *Map = NULL;
93    u_char     *buf;
94    short	bitspersample;
95    short	samplesperpixel;
96    short	photometric;
97    u_short    *redcolormap,
98	       *bluecolormap,
99	       *greencolormap;
100
101    Pixrect    *pix;		/* The Sun Pixrect */
102    colormap_t  Colormap;	/* The Pixrect Colormap */
103    u_char      red[256],
104                green[256],
105                blue[256];
106
107    setbuf(stderr, NULL);
108    pname = argv[0];
109
110    while (--argc) {
111	if ((++argv)[0][0] == '-')
112	    switch (argv[0][1]) {
113	    case 'v':
114		Verbose = True;
115		break;
116	    case 'q':
117		usage();
118		break;
119	    default:
120		fprintf(stderr, "%s: illegal option -%c.\n", pname,
121			argv[0][1]);
122		exit(1);
123	    }
124	else if (inf == NULL)
125	    inf = argv[0];
126	else if (outf == NULL)
127	    outf = argv[0];
128	else
129	    usage();
130
131    }
132
133    if (inf == NULL)
134	error("%s: can't read input file from a stream.\n", NULL);
135
136    if (Verbose)
137	fprintf(stderr, "Reading %s...", inf);
138
139    tif = TIFFOpen(inf, "r");
140
141    if (tif == NULL)
142	error("%s: error opening TIFF file %s", inf);
143
144    if (Verbose)
145	TIFFPrintDirectory(tif, stderr, True, False, False);
146    TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &bitspersample);
147    if (bitspersample > 8)
148	error("%s: can't handle more than 8-bits per sample\n", NULL);
149
150    TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel);
151    switch (samplesperpixel) {
152    case 1:
153	if (bitspersample == 1)
154	    depth = 1;
155	else
156	    depth = 8;
157	break;
158    case 3:
159    case 4:
160	depth = 24;
161	break;
162    default:
163	error("%s: only handle 1-channel gray scale or 3-channel color\n");
164    }
165
166    TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width);
167    TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height);
168
169    if (Verbose)
170	fprintf(stderr, "%dx%dx%d image, ", width, height, depth);
171    if (Verbose)
172	fprintf(stderr, "%d bits/sample, %d samples/pixel, ",
173		bitspersample, samplesperpixel);
174
175    pix = mem_create(width, height, depth);
176    if (pix == (Pixrect *) NULL)
177	error("%s: can't allocate memory for output pixrect...\n", NULL);
178
179    numcolors = (1 << bitspersample);
180
181    TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &photometric);
182    if (numcolors == 2) {
183	if (Verbose)
184	    fprintf(stderr, "monochrome ");
185	Colormap.type = RMT_NONE;
186	Colormap.length = 0;
187	Colormap.map[0] = Colormap.map[1] = Colormap.map[2] = NULL;
188    } else {
189	switch (photometric) {
190	case PHOTOMETRIC_MINISBLACK:
191	    if (Verbose)
192		fprintf(stderr, "%d graylevels (min=black), ", numcolors);
193	    Map = (u_char *) malloc(numcolors * sizeof(u_char));
194	    for (i = 0; i < numcolors; i++)
195		Map[i] = (255 * i) / numcolors;
196	    Colormap.type = RMT_EQUAL_RGB;
197	    Colormap.length = numcolors;
198	    Colormap.map[0] = Colormap.map[1] = Colormap.map[2] = Map;
199	    break;
200	case PHOTOMETRIC_MINISWHITE:
201	    if (Verbose)
202		fprintf(stderr, "%d graylevels (min=white), ", numcolors);
203	    Map = (u_char *) malloc(numcolors * sizeof(u_char));
204	    for (i = 0; i < numcolors; i++)
205		Map[i] = 255 - ((255 * i) / numcolors);
206	    Colormap.type = RMT_EQUAL_RGB;
207	    Colormap.length = numcolors;
208	    Colormap.map[0] = Colormap.map[1] = Colormap.map[2] = Map;
209	    break;
210	case PHOTOMETRIC_RGB:
211	    if (Verbose)
212		fprintf(stderr, "truecolor ");
213	    Colormap.type = RMT_NONE;
214	    Colormap.length = 0;
215	    Colormap.map[0] = Colormap.map[1] = Colormap.map[2] = NULL;
216	    break;
217	case PHOTOMETRIC_PALETTE:
218	    if (Verbose)
219		fprintf(stderr, "colormapped ");
220	    Colormap.type = RMT_EQUAL_RGB;
221	    Colormap.length = numcolors;
222	    memset(red, 0, sizeof(red));
223	    memset(green, 0, sizeof(green));
224	    memset(blue, 0, sizeof(blue));
225	    TIFFGetField(tif, TIFFTAG_COLORMAP,
226		&redcolormap, &greencolormap, &bluecolormap);
227	    for (i = 0; i < numcolors; i++) {
228		red[i] = (u_char) CVT(redcolormap[i]);
229		green[i] = (u_char) CVT(greencolormap[i]);
230		blue[i] = (u_char) CVT(bluecolormap[i]);
231	    }
232	    Colormap.map[0] = red;
233	    Colormap.map[1] = green;
234	    Colormap.map[2] = blue;
235	    break;
236	case PHOTOMETRIC_MASK:
237	    error("%s: Don't know how to handle PHOTOMETRIC_MASK\n");
238	    break;
239	case PHOTOMETRIC_DEPTH:
240	    error("%s: Don't know how to handle PHOTOMETRIC_DEPTH\n");
241	    break;
242	default:
243	    error("%s: unknown photometric (cmap): %d\n", photometric);
244	}
245    }
246
247    buf = (u_char *) malloc(TIFFScanlineSize(tif));
248    if (buf == NULL)
249	error("%s: can't allocate memory for scanline buffer...\n", NULL);
250
251    for (row = 0; row < height; row++) {
252	if (TIFFReadScanline(tif, buf, row, 0) < 0)
253	    error("%s: bad data read on line: %d\n", row);
254	inp = buf;
255	outp = (u_char *) mprd_addr(mpr_d(pix), 0, row);
256	switch (photometric) {
257	case PHOTOMETRIC_RGB:
258	    if (samplesperpixel == 4)
259		for (col = 0; col < width; col++) {
260		    *outp++ = *inp++;	/* Blue */
261		    *outp++ = *inp++;	/* Green */
262		    *outp++ = *inp++;	/* Red */
263		    inp++;	/* skip alpha channel */
264		}
265	    else
266		for (col = 0; col < width; col++) {
267		    *outp++ = *inp++;	/* Blue */
268		    *outp++ = *inp++;	/* Green */
269		    *outp++ = *inp++;	/* Red */
270		}
271	    break;
272	case PHOTOMETRIC_MINISWHITE:
273	case PHOTOMETRIC_MINISBLACK:
274	    switch (bitspersample) {
275	    case 1:
276		for (col = 0; col < ((width + 7) / 8); col++)
277		    *outp++ = *inp++;
278		break;
279	    case 2:
280		for (col = 0; col < ((width + 3) / 4); col++) {
281		    *outp++ = (*inp >> 6) & 3;
282		    *outp++ = (*inp >> 4) & 3;
283		    *outp++ = (*inp >> 2) & 3;
284		    *outp++ = *inp++ & 3;
285		}
286		break;
287	    case 4:
288		for (col = 0; col < width / 2; col++) {
289		    *outp++ = *inp >> 4;
290		    *outp++ = *inp++ & 0xf;
291		}
292		break;
293	    case 8:
294		for (col = 0; col < width; col++)
295		    *outp++ = *inp++;
296		break;
297	    default:
298		error("%s: bad bits/sample: %d\n", bitspersample);
299	    }
300	    break;
301	case PHOTOMETRIC_PALETTE:
302	    memcpy(outp, inp, width);
303	    break;
304	default:
305	    error("%s: unknown photometric (write): %d\n", photometric);
306	}
307    }
308
309    free((char *) buf);
310
311    if (Verbose)
312	fprintf(stderr, "done.\n");
313
314    if (outf == NULL || strcmp(outf, "Standard Output") == 0) {
315	outf = "Standard Output";
316	fp = stdout;
317    } else {
318	if (!(fp = fopen(outf, "w")))
319	    error("%s: %s couldn't be opened for writing.\n", outf);
320    }
321
322    if (Verbose)
323	fprintf(stderr, "Writing rasterfile in %s...", outf);
324
325    if (pr_dump(pix, fp, &Colormap, RT_BYTE_ENCODED, 0) == PIX_ERR)
326	error("%s: error writing Sun Rasterfile: %s\n", outf);
327
328    if (Verbose)
329	fprintf(stderr, "done.\n");
330
331    pr_destroy(pix);
332
333    if (fp != stdout)
334	fclose(fp);
335
336    exit(0);
337}
338/*
339 * Local Variables:
340 * mode: c
341 * c-basic-offset: 8
342 * fill-column: 78
343 * End:
344 */
345