1 #ifndef lint
2 static char id[] = "$Id: tif2ras.c,v 1.2 1999/11/28 20:15:36 mwelles Exp $";
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 
50 typedef int boolean;
51 #define True (1)
52 #define False (0)
53 #define	CVT(x)		(((x) * 255) / ((1L<<16)-1))
54 
55 boolean     Verbose = False;
56 char       *pname;		/* program name (used for error messages) */
57 
58 void
error(s1,s2)59 error(s1, s2)
60     char       *s1,
61                *s2;
62 {
63     fprintf(stderr, s1, pname, s2);
64     exit(1);
65 }
66 
67 void
usage()68 usage()
69 {
70     error("usage: %s -[vq] TIFFfile [rasterfile]\n", NULL);
71 }
72 
73 
main(argc,argv)74 main(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