xref: /libtiff-4.0.7/archive/tools/sgi2tiff.c (revision 30366c9f)
1 /* $Id: sgi2tiff.c,v 1.1 2016-06-05 19:54:00 bfriesen Exp $ */
2 
3 /*
4  * Copyright (c) 1991-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 <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <gl/image.h>
31 #include <ctype.h>
32 
33 #include "tiffio.h"
34 
35 #define	streq(a,b)	(strcmp(a,b) == 0)
36 #define	strneq(a,b,n)	(strncmp(a,b,n) == 0)
37 
38 static	short config = PLANARCONFIG_CONTIG;
39 static	uint16 compression = COMPRESSION_PACKBITS;
40 static	uint16 predictor = 0;
41 static	uint16 fillorder = 0;
42 static	uint32 rowsperstrip = (uint32) -1;
43 static	int jpegcolormode = JPEGCOLORMODE_RGB;
44 static	int quality = 75;		/* JPEG quality */
45 static	uint16 photometric;
46 
47 static	void usage(void);
48 static	int cpContig(IMAGE*, TIFF*);
49 static	int cpSeparate(IMAGE*, TIFF*);
50 static	int processCompressOptions(char*);
51 
52 /* XXX image library has no prototypes */
53 extern	IMAGE* iopen(const char*, const char*);
54 extern	void iclose(IMAGE*);
55 extern	void getrow(IMAGE*, short*, int, int);
56 
57 int
main(int argc,char * argv[])58 main(int argc, char* argv[])
59 {
60 	IMAGE *in;
61 	TIFF *out;
62 	int c;
63 #if !HAVE_DECL_OPTARG
64 	extern int optind;
65 	extern char* optarg;
66 #endif
67 
68 	while ((c = getopt(argc, argv, "c:p:r:")) != -1)
69 		switch (c) {
70 		case 'c':		/* compression scheme */
71 			if (!processCompressOptions(optarg))
72 				usage();
73 			break;
74 		case 'f':		/* fill order */
75 			if (streq(optarg, "lsb2msb"))
76 				fillorder = FILLORDER_LSB2MSB;
77 			else if (streq(optarg, "msb2lsb"))
78 				fillorder = FILLORDER_MSB2LSB;
79 			else
80 				usage();
81 			break;
82 		case 'p':		/* planar configuration */
83 			if (streq(optarg, "separate"))
84 				config = PLANARCONFIG_SEPARATE;
85 			else if (streq(optarg, "contig"))
86 				config = PLANARCONFIG_CONTIG;
87 			else
88 				usage();
89 			break;
90 		case 'r':		/* rows/strip */
91 			rowsperstrip = atoi(optarg);
92 			break;
93 		case '?':
94 			usage();
95 			/*NOTREACHED*/
96 		}
97 	if (argc - optind != 2)
98 		usage();
99 	in = iopen(argv[optind], "r");
100 	if (in == NULL)
101 		return (-1);
102 	out = TIFFOpen(argv[optind+1], "w");
103 	if (out == NULL)
104 		return (-2);
105 	TIFFSetField(out, TIFFTAG_IMAGEWIDTH, (uint32) in->xsize);
106 	TIFFSetField(out, TIFFTAG_IMAGELENGTH, (uint32) in->ysize);
107 	TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, 8);
108 	TIFFSetField(out, TIFFTAG_COMPRESSION, compression);
109 	if (in->zsize == 1)
110 		photometric = PHOTOMETRIC_MINISBLACK;
111 	else
112 		photometric = PHOTOMETRIC_RGB;
113 	switch (compression) {
114 	case COMPRESSION_JPEG:
115 		if (photometric == PHOTOMETRIC_RGB && jpegcolormode == JPEGCOLORMODE_RGB)
116 			photometric = PHOTOMETRIC_YCBCR;
117 		TIFFSetField(out, TIFFTAG_JPEGQUALITY, quality);
118 		TIFFSetField(out, TIFFTAG_JPEGCOLORMODE, jpegcolormode);
119 		break;
120 	case COMPRESSION_LZW:
121 	case COMPRESSION_DEFLATE:
122 		if (predictor != 0)
123 			TIFFSetField(out, TIFFTAG_PREDICTOR, predictor);
124 		break;
125 	}
126 	TIFFSetField(out, TIFFTAG_PHOTOMETRIC, photometric);
127 	if (fillorder != 0)
128 		TIFFSetField(out, TIFFTAG_FILLORDER, fillorder);
129 	TIFFSetField(out, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
130 	TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, in->zsize);
131 	if (in->zsize > 3) {
132 	    uint16 v[1];
133 	    v[0] = EXTRASAMPLE_UNASSALPHA;
134 	    TIFFSetField(out, TIFFTAG_EXTRASAMPLES, 1, v);
135 	}
136 	TIFFSetField(out, TIFFTAG_MINSAMPLEVALUE, (uint16) in->min);
137 	TIFFSetField(out, TIFFTAG_MAXSAMPLEVALUE, (uint16) in->max);
138 	TIFFSetField(out, TIFFTAG_PLANARCONFIG, config);
139 	if (config != PLANARCONFIG_SEPARATE)
140 		TIFFSetField(out, TIFFTAG_ROWSPERSTRIP,
141 		    TIFFDefaultStripSize(out, rowsperstrip));
142 	else			/* force 1 row/strip for library limitation */
143 		TIFFSetField(out, TIFFTAG_ROWSPERSTRIP, 1L);
144 	if (in->name[0] != '\0')
145 		TIFFSetField(out, TIFFTAG_IMAGEDESCRIPTION, in->name);
146 	if (config == PLANARCONFIG_CONTIG)
147 		cpContig(in, out);
148 	else
149 		cpSeparate(in, out);
150 	(void) iclose(in);
151 	(void) TIFFClose(out);
152 	return (0);
153 }
154 
155 static int
processCompressOptions(char * opt)156 processCompressOptions(char* opt)
157 {
158 	if (streq(opt, "none"))
159 		compression = COMPRESSION_NONE;
160 	else if (streq(opt, "packbits"))
161 		compression = COMPRESSION_PACKBITS;
162 	else if (strneq(opt, "jpeg", 4)) {
163 		char* cp = strchr(opt, ':');
164 
165                 defcompression = COMPRESSION_JPEG;
166                 while( cp )
167                 {
168                     if (isdigit((int)cp[1]))
169 			quality = atoi(cp+1);
170                     else if (cp[1] == 'r' )
171 			jpegcolormode = JPEGCOLORMODE_RAW;
172                     else
173                         usage();
174 
175                     cp = strchr(cp+1,':');
176                 }
177 	} else if (strneq(opt, "lzw", 3)) {
178 		char* cp = strchr(opt, ':');
179 		if (cp)
180 			predictor = atoi(cp+1);
181 		compression = COMPRESSION_LZW;
182 	} else if (strneq(opt, "zip", 3)) {
183 		char* cp = strchr(opt, ':');
184 		if (cp)
185 			predictor = atoi(cp+1);
186 		compression = COMPRESSION_DEFLATE;
187 	} else
188 		return (0);
189 	return (1);
190 }
191 
192 static int
cpContig(IMAGE * in,TIFF * out)193 cpContig(IMAGE* in, TIFF* out)
194 {
195 	tdata_t buf = _TIFFmalloc(TIFFScanlineSize(out));
196 	short *r = NULL;
197 	int x, y;
198 
199 	if (in->zsize == 3) {
200 		short *g, *b;
201 
202 		r = (short *)_TIFFmalloc(3 * in->xsize * sizeof (short));
203 		g = r + in->xsize;
204 		b = g + in->xsize;
205 		for (y = in->ysize-1; y >= 0; y--) {
206 			uint8* pp = (uint8*) buf;
207 
208 			getrow(in, r, y, 0);
209 			getrow(in, g, y, 1);
210 			getrow(in, b, y, 2);
211 			for (x = 0; x < in->xsize; x++) {
212 				pp[0] = r[x];
213 				pp[1] = g[x];
214 				pp[2] = b[x];
215 				pp += 3;
216 			}
217 			if (TIFFWriteScanline(out, buf, in->ysize-y-1, 0) < 0)
218 				goto bad;
219 		}
220 	} else if (in->zsize == 4) {
221 		short *g, *b, *a;
222 
223 		r = (short *)_TIFFmalloc(4 * in->xsize * sizeof (short));
224 		g = r + in->xsize;
225 		b = g + in->xsize;
226 		a = b + in->xsize;
227 		for (y = in->ysize-1; y >= 0; y--) {
228 			uint8* pp = (uint8*) buf;
229 
230 			getrow(in, r, y, 0);
231 			getrow(in, g, y, 1);
232 			getrow(in, b, y, 2);
233 			getrow(in, a, y, 3);
234 			for (x = 0; x < in->xsize; x++) {
235 				pp[0] = r[x];
236 				pp[1] = g[x];
237 				pp[2] = b[x];
238 				pp[3] = a[x];
239 				pp += 4;
240 			}
241 			if (TIFFWriteScanline(out, buf, in->ysize-y-1, 0) < 0)
242 				goto bad;
243 		}
244 	} else {
245 		uint8* pp = (uint8*) buf;
246 
247 		r = (short *)_TIFFmalloc(in->xsize * sizeof (short));
248 		for (y = in->ysize-1; y >= 0; y--) {
249 			getrow(in, r, y, 0);
250 			for (x = in->xsize-1; x >= 0; x--)
251 				pp[x] = r[x];
252 			if (TIFFWriteScanline(out, buf, in->ysize-y-1, 0) < 0)
253 				goto bad;
254 		}
255 	}
256 	if (r)
257 		_TIFFfree(r);
258 	_TIFFfree(buf);
259 	return (1);
260 bad:
261 	if (r)
262 		_TIFFfree(r);
263 	_TIFFfree(buf);
264 	return (0);
265 }
266 
267 static int
cpSeparate(IMAGE * in,TIFF * out)268 cpSeparate(IMAGE* in, TIFF* out)
269 {
270 	tdata_t buf = _TIFFmalloc(TIFFScanlineSize(out));
271 	short *r = (short *)_TIFFmalloc(in->xsize * sizeof (short));
272 	uint8* pp = (uint8*) buf;
273 	int x, y, z;
274 
275 	for (z = 0; z < in->zsize; z++) {
276 		for (y = in->ysize-1; y >= 0; y--) {
277 			getrow(in, r, y, z);
278 			for (x = 0; x < in->xsize; x++)
279 				pp[x] = r[x];
280 			if (TIFFWriteScanline(out, buf, in->ysize-y-1, z) < 0)
281 				goto bad;
282 		}
283 	}
284 	_TIFFfree(r);
285 	_TIFFfree(buf);
286 	return (1);
287 bad:
288 	_TIFFfree(r);
289 	_TIFFfree(buf);
290 	return (0);
291 }
292 
293 char* stuff[] = {
294 "usage: sgi2tiff [options] input.rgb output.tif",
295 "where options are:",
296 " -r #		make each strip have no more than # rows",
297 "",
298 " -p contig	pack samples contiguously (e.g. RGBRGB...)",
299 " -p separate	store samples separately (e.g. RRR...GGG...BBB...)",
300 "",
301 " -f lsb2msb	force lsb-to-msb FillOrder for output",
302 " -f msb2lsb	force msb-to-lsb FillOrder for output",
303 "",
304 " -c lzw[:opts]	compress output with Lempel-Ziv & Welch encoding",
305 " -c zip[:opts]	compress output with deflate encoding",
306 " -c jpeg[:opts]compress output with JPEG encoding",
307 " -c packbits	compress output with packbits encoding",
308 " -c none	use no compression algorithm on output",
309 "",
310 "JPEG options:",
311 " #		set compression quality level (0-100, default 75)",
312 " r		output color image as RGB rather than YCbCr",
313 "",
314 "LZW and deflate options:",
315 " #		set predictor value",
316 "For example, -c lzw:2 to get LZW-encoded data with horizontal differencing",
317 NULL
318 };
319 
320 static void
usage(void)321 usage(void)
322 {
323 	char buf[BUFSIZ];
324 	int i;
325 
326 	setbuf(stderr, buf);
327 	for (i = 0; stuff[i] != NULL; i++)
328 		fprintf(stderr, "%s\n", stuff[i]);
329 	exit(-1);
330 }
331 /*
332  * Local Variables:
333  * mode: c
334  * c-basic-offset: 8
335  * fill-column: 78
336  * End:
337  */
338