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