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