Define _CRT_NONSTDC_NO_WARNINGS for zlib compilation with MSVC.
[wxWidgets.git] / src / tiff / tools / ras2tiff.c
1
2 /*
3 * Copyright (c) 1988-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 "tif_config.h"
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <ctype.h>
32
33 #ifdef HAVE_UNISTD_H
34 # include <unistd.h>
35 #endif
36
37 #ifdef NEED_LIBPORT
38 # include "libport.h"
39 #endif
40
41 #include "rasterfile.h"
42 #include "tiffio.h"
43
44 #ifndef howmany
45 #define howmany(x, y) (((x)+((y)-1))/(y))
46 #endif
47 #define streq(a,b) (strcmp(a,b) == 0)
48 #define strneq(a,b,n) (strncmp(a,b,n) == 0)
49
50 static uint16 compression = (uint16) -1;
51 static int jpegcolormode = JPEGCOLORMODE_RGB;
52 static int quality = 75; /* JPEG quality */
53 static uint16 predictor = 0;
54
55 static void usage(void);
56 static int processCompressOptions(char*);
57
58 int
59 main(int argc, char* argv[])
60 {
61 unsigned char* buf;
62 long row;
63 tsize_t linebytes, scanline;
64 TIFF *out;
65 FILE *in;
66 struct rasterfile h;
67 uint16 photometric;
68 uint16 config = PLANARCONFIG_CONTIG;
69 uint32 rowsperstrip = (uint32) -1;
70 int c;
71 extern int optind;
72 extern char* optarg;
73
74 while ((c = getopt(argc, argv, "c:r:h")) != -1)
75 switch (c) {
76 case 'c': /* compression scheme */
77 if (!processCompressOptions(optarg))
78 usage();
79 break;
80 case 'r': /* rows/strip */
81 rowsperstrip = atoi(optarg);
82 break;
83 case 'h':
84 usage();
85 /*NOTREACHED*/
86 }
87 if (argc - optind != 2)
88 usage();
89 in = fopen(argv[optind], "rb");
90 if (in == NULL) {
91 fprintf(stderr, "%s: Can not open.\n", argv[optind]);
92 return (-1);
93 }
94 if (fread(&h, sizeof (h), 1, in) != 1) {
95 fprintf(stderr, "%s: Can not read header.\n", argv[optind]);
96 fclose(in);
97 return (-2);
98 }
99 if (strcmp(h.ras_magic, RAS_MAGIC) == 0) {
100 #ifndef WORDS_BIGENDIAN
101 TIFFSwabLong((uint32 *)&h.ras_width);
102 TIFFSwabLong((uint32 *)&h.ras_height);
103 TIFFSwabLong((uint32 *)&h.ras_depth);
104 TIFFSwabLong((uint32 *)&h.ras_length);
105 TIFFSwabLong((uint32 *)&h.ras_type);
106 TIFFSwabLong((uint32 *)&h.ras_maptype);
107 TIFFSwabLong((uint32 *)&h.ras_maplength);
108 #endif
109 } else if (strcmp(h.ras_magic, RAS_MAGIC_INV) == 0) {
110 #ifdef WORDS_BIGENDIAN
111 TIFFSwabLong((uint32 *)&h.ras_width);
112 TIFFSwabLong((uint32 *)&h.ras_height);
113 TIFFSwabLong((uint32 *)&h.ras_depth);
114 TIFFSwabLong((uint32 *)&h.ras_length);
115 TIFFSwabLong((uint32 *)&h.ras_type);
116 TIFFSwabLong((uint32 *)&h.ras_maptype);
117 TIFFSwabLong((uint32 *)&h.ras_maplength);
118 #endif
119 } else {
120 fprintf(stderr, "%s: Not a rasterfile.\n", argv[optind]);
121 fclose(in);
122 return (-3);
123 }
124 out = TIFFOpen(argv[optind+1], "w");
125 if (out == NULL)
126 {
127 fclose(in);
128 return (-4);
129 }
130 TIFFSetField(out, TIFFTAG_IMAGEWIDTH, (uint32) h.ras_width);
131 TIFFSetField(out, TIFFTAG_IMAGELENGTH, (uint32) h.ras_height);
132 TIFFSetField(out, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
133 TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, h.ras_depth > 8 ? 3 : 1);
134 TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, h.ras_depth > 1 ? 8 : 1);
135 TIFFSetField(out, TIFFTAG_PLANARCONFIG, config);
136 if (h.ras_maptype != RMT_NONE) {
137 uint16* red;
138 register uint16* map;
139 register int i, j;
140 int mapsize;
141
142 buf = (unsigned char *)_TIFFmalloc(h.ras_maplength);
143 if (buf == NULL) {
144 fprintf(stderr, "No space to read in colormap.\n");
145 return (-5);
146 }
147 if (fread(buf, h.ras_maplength, 1, in) != 1) {
148 fprintf(stderr, "%s: Read error on colormap.\n",
149 argv[optind]);
150 return (-6);
151 }
152 mapsize = 1<<h.ras_depth;
153 if (h.ras_maplength > mapsize*3) {
154 fprintf(stderr,
155 "%s: Huh, %ld colormap entries, should be %d?\n",
156 argv[optind], h.ras_maplength, mapsize*3);
157 return (-7);
158 }
159 red = (uint16*)_TIFFmalloc(mapsize * 3 * sizeof (uint16));
160 if (red == NULL) {
161 fprintf(stderr, "No space for colormap.\n");
162 return (-8);
163 }
164 map = red;
165 for (j = 0; j < 3; j++) {
166 #define SCALE(x) (((x)*((1L<<16)-1))/255)
167 for (i = h.ras_maplength/3; i-- > 0;)
168 *map++ = SCALE(*buf++);
169 if ((i = h.ras_maplength/3) < mapsize) {
170 i = mapsize - i;
171 _TIFFmemset(map, 0, i*sizeof (uint16));
172 map += i;
173 }
174 }
175 TIFFSetField(out, TIFFTAG_COLORMAP,
176 red, red + mapsize, red + 2*mapsize);
177 photometric = PHOTOMETRIC_PALETTE;
178 if (compression == (uint16) -1)
179 compression = COMPRESSION_PACKBITS;
180 TIFFSetField(out, TIFFTAG_COMPRESSION, compression);
181 } else {
182 /* XXX this is bogus... */
183 photometric = h.ras_depth == 24 ?
184 PHOTOMETRIC_RGB : PHOTOMETRIC_MINISBLACK;
185 if (compression == (uint16) -1)
186 compression = COMPRESSION_LZW;
187 TIFFSetField(out, TIFFTAG_COMPRESSION, compression);
188 }
189 switch (compression) {
190 case COMPRESSION_JPEG:
191 if (photometric == PHOTOMETRIC_RGB && jpegcolormode == JPEGCOLORMODE_RGB)
192 photometric = PHOTOMETRIC_YCBCR;
193 TIFFSetField(out, TIFFTAG_JPEGQUALITY, quality);
194 TIFFSetField(out, TIFFTAG_JPEGCOLORMODE, jpegcolormode);
195 break;
196 case COMPRESSION_LZW:
197 case COMPRESSION_DEFLATE:
198 if (predictor != 0)
199 TIFFSetField(out, TIFFTAG_PREDICTOR, predictor);
200 break;
201 }
202 TIFFSetField(out, TIFFTAG_PHOTOMETRIC, photometric);
203 linebytes = ((h.ras_depth*h.ras_width+15) >> 3) &~ 1;
204 scanline = TIFFScanlineSize(out);
205 if (scanline > linebytes) {
206 buf = (unsigned char *)_TIFFmalloc(scanline);
207 _TIFFmemset(buf+linebytes, 0, scanline-linebytes);
208 } else
209 buf = (unsigned char *)_TIFFmalloc(linebytes);
210 TIFFSetField(out, TIFFTAG_ROWSPERSTRIP,
211 TIFFDefaultStripSize(out, rowsperstrip));
212 for (row = 0; row < h.ras_height; row++) {
213 if (fread(buf, linebytes, 1, in) != 1) {
214 fprintf(stderr, "%s: scanline %ld: Read error.\n",
215 argv[optind], row);
216 break;
217 }
218 if (h.ras_type == RT_STANDARD && h.ras_depth == 24) {
219 tsize_t cc = h.ras_width;
220 unsigned char* cp = buf;
221 #define SWAP(a,b) { unsigned char t = (a); (a) = (b); (b) = t; }
222 do {
223 SWAP(cp[0], cp[2]);
224 cp += 3;
225 } while (--cc);
226 }
227 if (TIFFWriteScanline(out, buf, row, 0) < 0)
228 break;
229 }
230 (void) TIFFClose(out);
231 fclose(in);
232 return (0);
233 }
234
235 static int
236 processCompressOptions(char* opt)
237 {
238 if (streq(opt, "none"))
239 compression = COMPRESSION_NONE;
240 else if (streq(opt, "packbits"))
241 compression = COMPRESSION_PACKBITS;
242 else if (strneq(opt, "jpeg", 4)) {
243 char* cp = strchr(opt, ':');
244
245 compression = COMPRESSION_JPEG;
246 while( cp )
247 {
248 if (isdigit((int)cp[1]))
249 quality = atoi(cp+1);
250 else if (cp[1] == 'r' )
251 jpegcolormode = JPEGCOLORMODE_RAW;
252 else
253 usage();
254
255 cp = strchr(cp+1,':');
256 }
257 } else if (strneq(opt, "lzw", 3)) {
258 char* cp = strchr(opt, ':');
259 if (cp)
260 predictor = atoi(cp+1);
261 compression = COMPRESSION_LZW;
262 } else if (strneq(opt, "zip", 3)) {
263 char* cp = strchr(opt, ':');
264 if (cp)
265 predictor = atoi(cp+1);
266 compression = COMPRESSION_DEFLATE;
267 } else
268 return (0);
269 return (1);
270 }
271
272 char* stuff[] = {
273 "usage: ras2tiff [options] input.ras output.tif",
274 "where options are:",
275 " -r # make each strip have no more than # rows",
276 "",
277 " -c lzw[:opts] compress output with Lempel-Ziv & Welch encoding",
278 " -c zip[:opts] compress output with deflate encoding",
279 " -c jpeg[:opts] compress output with JPEG encoding",
280 " -c packbits compress output with packbits encoding",
281 " -c none use no compression algorithm on output",
282 "",
283 "JPEG options:",
284 " # set compression quality level (0-100, default 75)",
285 " r output color image as RGB rather than YCbCr",
286 "For example, -c jpeg:r:50 to get JPEG-encoded RGB data with 50% comp. quality",
287 "",
288 "LZW and deflate options:",
289 " # set predictor value",
290 "For example, -c lzw:2 to get LZW-encoded data with horizontal differencing",
291 " -h this help message",
292 NULL
293 };
294
295 static void
296 usage(void)
297 {
298 char buf[BUFSIZ];
299 int i;
300
301 setbuf(stderr, buf);
302 fprintf(stderr, "%s\n\n", TIFFGetVersion());
303 for (i = 0; stuff[i] != NULL; i++)
304 fprintf(stderr, "%s\n", stuff[i]);
305 exit(-1);
306 }
307
308 /* vim: set ts=8 sts=8 sw=8 noet: */
309 /*
310 * Local Variables:
311 * mode: c
312 * c-basic-offset: 8
313 * fill-column: 78
314 * End:
315 */