Define _CRT_NONSTDC_NO_WARNINGS for zlib compilation with MSVC.
[wxWidgets.git] / src / tiff / tools / sgi2tiff.c
1
2 /*
3 * Copyright (c) 1991-1997 Sam Leffler
4 * Copyright (c) 1991-1997 Silicon Graphics, Inc.
5 *
6 * Permission to use, copy, modify, distribute, and sell this software and
7 * its documentation for any purpose is hereby granted without fee, provided
8 * that (i) the above copyright notices and this permission notice appear in
9 * all copies of the software and related documentation, and (ii) the names of
10 * Sam Leffler and Silicon Graphics may not be used in any advertising or
11 * publicity relating to the software without the specific, prior written
12 * permission of Sam Leffler and Silicon Graphics.
13 *
14 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
15 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
16 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
17 *
18 * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
19 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
20 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
21 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
22 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
23 * OF THIS SOFTWARE.
24 */
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <gl/image.h>
30 #include <ctype.h>
31
32 #include "tiffio.h"
33
34 #define streq(a,b) (strcmp(a,b) == 0)
35 #define strneq(a,b,n) (strncmp(a,b,n) == 0)
36
37 static short config = PLANARCONFIG_CONTIG;
38 static uint16 compression = COMPRESSION_PACKBITS;
39 static uint16 predictor = 0;
40 static uint16 fillorder = 0;
41 static uint32 rowsperstrip = (uint32) -1;
42 static int jpegcolormode = JPEGCOLORMODE_RGB;
43 static int quality = 75; /* JPEG quality */
44 static uint16 photometric;
45
46 static void usage(void);
47 static int cpContig(IMAGE*, TIFF*);
48 static int cpSeparate(IMAGE*, TIFF*);
49 static int processCompressOptions(char*);
50
51 /* XXX image library has no prototypes */
52 extern IMAGE* iopen(const char*, const char*);
53 extern void iclose(IMAGE*);
54 extern void getrow(IMAGE*, short*, int, int);
55
56 int
57 main(int argc, char* argv[])
58 {
59 IMAGE *in;
60 TIFF *out;
61 int c;
62 extern int optind;
63 extern char* optarg;
64
65 while ((c = getopt(argc, argv, "c:p:r:")) != -1)
66 switch (c) {
67 case 'c': /* compression scheme */
68 if (!processCompressOptions(optarg))
69 usage();
70 break;
71 case 'f': /* fill order */
72 if (streq(optarg, "lsb2msb"))
73 fillorder = FILLORDER_LSB2MSB;
74 else if (streq(optarg, "msb2lsb"))
75 fillorder = FILLORDER_MSB2LSB;
76 else
77 usage();
78 break;
79 case 'p': /* planar configuration */
80 if (streq(optarg, "separate"))
81 config = PLANARCONFIG_SEPARATE;
82 else if (streq(optarg, "contig"))
83 config = PLANARCONFIG_CONTIG;
84 else
85 usage();
86 break;
87 case 'r': /* rows/strip */
88 rowsperstrip = atoi(optarg);
89 break;
90 case '?':
91 usage();
92 /*NOTREACHED*/
93 }
94 if (argc - optind != 2)
95 usage();
96 in = iopen(argv[optind], "r");
97 if (in == NULL)
98 return (-1);
99 out = TIFFOpen(argv[optind+1], "w");
100 if (out == NULL)
101 return (-2);
102 TIFFSetField(out, TIFFTAG_IMAGEWIDTH, (uint32) in->xsize);
103 TIFFSetField(out, TIFFTAG_IMAGELENGTH, (uint32) in->ysize);
104 TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, 8);
105 TIFFSetField(out, TIFFTAG_COMPRESSION, compression);
106 if (in->zsize == 1)
107 photometric = PHOTOMETRIC_MINISBLACK;
108 else
109 photometric = PHOTOMETRIC_RGB;
110 switch (compression) {
111 case COMPRESSION_JPEG:
112 if (photometric == PHOTOMETRIC_RGB && jpegcolormode == JPEGCOLORMODE_RGB)
113 photometric = PHOTOMETRIC_YCBCR;
114 TIFFSetField(out, TIFFTAG_JPEGQUALITY, quality);
115 TIFFSetField(out, TIFFTAG_JPEGCOLORMODE, jpegcolormode);
116 break;
117 case COMPRESSION_LZW:
118 case COMPRESSION_DEFLATE:
119 if (predictor != 0)
120 TIFFSetField(out, TIFFTAG_PREDICTOR, predictor);
121 break;
122 }
123 TIFFSetField(out, TIFFTAG_PHOTOMETRIC, photometric);
124 if (fillorder != 0)
125 TIFFSetField(out, TIFFTAG_FILLORDER, fillorder);
126 TIFFSetField(out, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
127 TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, in->zsize);
128 if (in->zsize > 3) {
129 uint16 v[1];
130 v[0] = EXTRASAMPLE_UNASSALPHA;
131 TIFFSetField(out, TIFFTAG_EXTRASAMPLES, 1, v);
132 }
133 TIFFSetField(out, TIFFTAG_MINSAMPLEVALUE, (uint16) in->min);
134 TIFFSetField(out, TIFFTAG_MAXSAMPLEVALUE, (uint16) in->max);
135 TIFFSetField(out, TIFFTAG_PLANARCONFIG, config);
136 if (config != PLANARCONFIG_SEPARATE)
137 TIFFSetField(out, TIFFTAG_ROWSPERSTRIP,
138 TIFFDefaultStripSize(out, rowsperstrip));
139 else /* force 1 row/strip for library limitation */
140 TIFFSetField(out, TIFFTAG_ROWSPERSTRIP, 1L);
141 if (in->name[0] != '\0')
142 TIFFSetField(out, TIFFTAG_IMAGEDESCRIPTION, in->name);
143 if (config == PLANARCONFIG_CONTIG)
144 cpContig(in, out);
145 else
146 cpSeparate(in, out);
147 (void) iclose(in);
148 (void) TIFFClose(out);
149 return (0);
150 }
151
152 static int
153 processCompressOptions(char* opt)
154 {
155 if (streq(opt, "none"))
156 compression = COMPRESSION_NONE;
157 else if (streq(opt, "packbits"))
158 compression = COMPRESSION_PACKBITS;
159 else if (strneq(opt, "jpeg", 4)) {
160 char* cp = strchr(opt, ':');
161
162 defcompression = COMPRESSION_JPEG;
163 while( cp )
164 {
165 if (isdigit((int)cp[1]))
166 quality = atoi(cp+1);
167 else if (cp[1] == 'r' )
168 jpegcolormode = JPEGCOLORMODE_RAW;
169 else
170 usage();
171
172 cp = strchr(cp+1,':');
173 }
174 } else if (strneq(opt, "lzw", 3)) {
175 char* cp = strchr(opt, ':');
176 if (cp)
177 predictor = atoi(cp+1);
178 compression = COMPRESSION_LZW;
179 } else if (strneq(opt, "zip", 3)) {
180 char* cp = strchr(opt, ':');
181 if (cp)
182 predictor = atoi(cp+1);
183 compression = COMPRESSION_DEFLATE;
184 } else
185 return (0);
186 return (1);
187 }
188
189 static int
190 cpContig(IMAGE* in, TIFF* out)
191 {
192 tdata_t buf = _TIFFmalloc(TIFFScanlineSize(out));
193 short *r = NULL;
194 int x, y;
195
196 if (in->zsize == 3) {
197 short *g, *b;
198
199 r = (short *)_TIFFmalloc(3 * in->xsize * sizeof (short));
200 g = r + in->xsize;
201 b = g + in->xsize;
202 for (y = in->ysize-1; y >= 0; y--) {
203 uint8* pp = (uint8*) buf;
204
205 getrow(in, r, y, 0);
206 getrow(in, g, y, 1);
207 getrow(in, b, y, 2);
208 for (x = 0; x < in->xsize; x++) {
209 pp[0] = r[x];
210 pp[1] = g[x];
211 pp[2] = b[x];
212 pp += 3;
213 }
214 if (TIFFWriteScanline(out, buf, in->ysize-y-1, 0) < 0)
215 goto bad;
216 }
217 } else if (in->zsize == 4) {
218 short *g, *b, *a;
219
220 r = (short *)_TIFFmalloc(4 * in->xsize * sizeof (short));
221 g = r + in->xsize;
222 b = g + in->xsize;
223 a = b + in->xsize;
224 for (y = in->ysize-1; y >= 0; y--) {
225 uint8* pp = (uint8*) buf;
226
227 getrow(in, r, y, 0);
228 getrow(in, g, y, 1);
229 getrow(in, b, y, 2);
230 getrow(in, a, y, 3);
231 for (x = 0; x < in->xsize; x++) {
232 pp[0] = r[x];
233 pp[1] = g[x];
234 pp[2] = b[x];
235 pp[3] = a[x];
236 pp += 4;
237 }
238 if (TIFFWriteScanline(out, buf, in->ysize-y-1, 0) < 0)
239 goto bad;
240 }
241 } else {
242 uint8* pp = (uint8*) buf;
243
244 r = (short *)_TIFFmalloc(in->xsize * sizeof (short));
245 for (y = in->ysize-1; y >= 0; y--) {
246 getrow(in, r, y, 0);
247 for (x = in->xsize-1; x >= 0; x--)
248 pp[x] = r[x];
249 if (TIFFWriteScanline(out, buf, in->ysize-y-1, 0) < 0)
250 goto bad;
251 }
252 }
253 if (r)
254 _TIFFfree(r);
255 _TIFFfree(buf);
256 return (1);
257 bad:
258 if (r)
259 _TIFFfree(r);
260 _TIFFfree(buf);
261 return (0);
262 }
263
264 static int
265 cpSeparate(IMAGE* in, TIFF* out)
266 {
267 tdata_t buf = _TIFFmalloc(TIFFScanlineSize(out));
268 short *r = (short *)_TIFFmalloc(in->xsize * sizeof (short));
269 uint8* pp = (uint8*) buf;
270 int x, y, z;
271
272 for (z = 0; z < in->zsize; z++) {
273 for (y = in->ysize-1; y >= 0; y--) {
274 getrow(in, r, y, z);
275 for (x = 0; x < in->xsize; x++)
276 pp[x] = r[x];
277 if (TIFFWriteScanline(out, buf, in->ysize-y-1, z) < 0)
278 goto bad;
279 }
280 }
281 _TIFFfree(r);
282 _TIFFfree(buf);
283 return (1);
284 bad:
285 _TIFFfree(r);
286 _TIFFfree(buf);
287 return (0);
288 }
289
290 char* stuff[] = {
291 "usage: sgi2tiff [options] input.rgb output.tif",
292 "where options are:",
293 " -r # make each strip have no more than # rows",
294 "",
295 " -p contig pack samples contiguously (e.g. RGBRGB...)",
296 " -p separate store samples separately (e.g. RRR...GGG...BBB...)",
297 "",
298 " -f lsb2msb force lsb-to-msb FillOrder for output",
299 " -f msb2lsb force msb-to-lsb FillOrder for output",
300 "",
301 " -c lzw[:opts] compress output with Lempel-Ziv & Welch encoding",
302 " -c zip[:opts] compress output with deflate encoding",
303 " -c jpeg[:opts]compress output with JPEG encoding",
304 " -c packbits compress output with packbits encoding",
305 " -c none use no compression algorithm on output",
306 "",
307 "JPEG options:",
308 " # set compression quality level (0-100, default 75)",
309 " r output color image as RGB rather than YCbCr",
310 "",
311 "LZW and deflate options:",
312 " # set predictor value",
313 "For example, -c lzw:2 to get LZW-encoded data with horizontal differencing",
314 NULL
315 };
316
317 static void
318 usage(void)
319 {
320 char buf[BUFSIZ];
321 int i;
322
323 setbuf(stderr, buf);
324 for (i = 0; stuff[i] != NULL; i++)
325 fprintf(stderr, "%s\n", stuff[i]);
326 exit(-1);
327 }
328 /*
329 * Local Variables:
330 * mode: c
331 * c-basic-offset: 8
332 * fill-column: 78
333 * End:
334 */