1/* $Id: sgisv.c 276 2010-06-30 12:18:30Z nijtmans $ */ 2 3/* 4 * Copyright (c) 1990-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 31#include <gl.h> 32#include <ctype.h> 33 34#include "tiffio.h" 35 36typedef unsigned char unsigned char; 37typedef unsigned long uint32; 38 39#define streq(a,b) (strcmp(a,b) == 0) 40#define strneq(a,b,n) (strncmp(a,b,n) == 0) 41 42uint32 rowsperstrip = (uint32) -1; 43uint16 compression = COMPRESSION_PACKBITS; 44uint16 config = PLANARCONFIG_CONTIG; 45uint16 predictor = 0; 46int xmaxscreen; 47int ymaxscreen; 48uint16 photometric = PHOTOMETRIC_RGB; 49int jpegcolormode = JPEGCOLORMODE_RGB; 50int quality = 75; /* JPEG quality */ 51 52static void usage(void); 53static void tiffsv(char*, int, int, int, int); 54 55int 56main(int argc, char* argv[]) 57{ 58 int c; 59 extern int optind; 60 extern char* optarg; 61 62 while ((c = getopt(argc, argv, "c:p:r:")) != -1) 63 switch (c) { 64 case 'b': /* save as b&w */ 65 photometric = PHOTOMETRIC_MINISBLACK; 66 break; 67 case 'c': /* compression scheme */ 68 if (streq(optarg, "none")) 69 compression = COMPRESSION_NONE; 70 else if (streq(optarg, "packbits")) 71 compression = COMPRESSION_PACKBITS; 72 else if (strneq(optarg, "jpeg", 4)) { 73 char* cp = strchr(optarg, ':'); 74 if (cp && isdigit(cp[1])) 75 quality = atoi(cp+1); 76 if (cp && strchr(cp, 'r')) 77 jpegcolormode = JPEGCOLORMODE_RAW; 78 compression = COMPRESSION_JPEG; 79 } else if (strneq(optarg, "lzw", 3)) { 80 char* cp = strchr(optarg, ':'); 81 if (cp) 82 predictor = atoi(cp+1); 83 compression = COMPRESSION_LZW; 84 } else 85 usage(); 86 break; 87 case 'p': /* planar configuration */ 88 if (streq(optarg, "separate")) 89 config = PLANARCONFIG_SEPARATE; 90 else if (streq(optarg, "contig")) 91 config = PLANARCONFIG_CONTIG; 92 else 93 usage(); 94 break; 95 case 'r': /* rows/strip */ 96 rowsperstrip = atoi(optarg); 97 break; 98 case '?': 99 usage(); 100 /*NOTREACHED*/ 101 } 102 if (argc - optind != 1 && argc - optind != 5) 103 usage(); 104 xmaxscreen = getgdesc(GD_XPMAX)-1; 105 ymaxscreen = getgdesc(GD_YPMAX)-1; 106 foreground(); 107 noport(); 108 winopen("tiffsv"); 109 if (argc - optind == 5) 110 tiffsv(argv[optind], 111 atoi(argv[optind+1]), atoi(argv[optind+2]), 112 atoi(argv[optind+3]), atoi(argv[optind+4])); 113 else 114 tiffsv(argv[optind], 0, xmaxscreen, 0, ymaxscreen); 115 return (0); 116} 117 118char* stuff[] = { 119"usage: tiffsv [options] outimage.tif [x1 x2 y1 y2] [-b]", 120"where options are:", 121" -p contig pack samples contiguously (e.g. RGBRGB...)", 122" -p separate store samples separately (e.g. RRR...GGG...BBB...)", 123"", 124" -r # make each strip have no more than # rows", 125"", 126" -c lzw[:opts] compress output with Lempel-Ziv & Welch encoding", 127" -c jpeg[:opts]compress output with JPEG encoding", 128" -c packbits compress output with packbits encoding", 129" -c none use no compression algorithm on output", 130"", 131"JPEG options:", 132" # set compression quality level (0-100, default 75)", 133" r output color image as RGB rather than YCbCr", 134"", 135"LZW options:", 136" # set predictor value for Lempel-Ziv & Welch encoding", 137"For example, -c lzw:2 to get LZW-encoded data with horizontal differencing", 138NULL 139}; 140 141static void 142usage(void) 143{ 144 char buf[BUFSIZ]; 145 int i; 146 147 setbuf(stderr, buf); 148 for (i = 0; stuff[i] != NULL; i++) 149 fprintf(stderr, "%s\n", stuff[i]); 150 exit(-1); 151} 152 153static void 154svRGBSeparate(TIFF* tif, uint32* ss, int xsize, int ysize) 155{ 156 tsize_t stripsize = TIFFStripSize(tif); 157 unsigned char *rbuf = (unsigned char *)_TIFFmalloc(3*stripsize); 158 unsigned char *gbuf = rbuf + stripsize; 159 unsigned char *bbuf = gbuf + stripsize; 160 register int y; 161 162 for (y = 0; y <= ysize; y += rowsperstrip) { 163 unsigned char *rp, *gp, *bp; 164 register int x; 165 register uint32 n; 166 167 n = rowsperstrip; 168 if (n > ysize-y+1) 169 n = ysize-y+1; 170 rp = rbuf; gp = gbuf; bp = bbuf; 171 do { 172 for (x = 0; x <= xsize; x++) { 173 uint32 v = ss[x]; 174 rp[x] = v; 175 gp[x] = v >> 8; 176 bp[x] = v >> 16; 177 } 178 rp += xsize+1, gp += xsize+1, bp += xsize+1; 179 ss += xsize+1; 180 } while (--n); 181 if (TIFFWriteEncodedStrip(tif, TIFFComputeStrip(tif,y,0), 182 rbuf, stripsize) < 0) 183 break; 184 if (TIFFWriteEncodedStrip(tif, TIFFComputeStrip(tif,y,1), 185 gbuf, stripsize) < 0) 186 break; 187 if (TIFFWriteEncodedStrip(tif, TIFFComputeStrip(tif,y,2), 188 bbuf, stripsize) < 0) 189 break; 190 } 191 _TIFFfree(rbuf); 192} 193 194static void 195svRGBContig(TIFF* tif, uint32* ss, int xsize, int ysize) 196{ 197 register int x, y; 198 tsize_t stripsize = TIFFStripSize(tif); 199 unsigned char *strip = (unsigned char *)_TIFFmalloc(stripsize); 200 201 for (y = 0; y <= ysize; y += rowsperstrip) { 202 register unsigned char *pp = strip; 203 register uint32 n; 204 205 n = rowsperstrip; 206 if (n > ysize-y+1) 207 n = ysize-y+1; 208 do { 209 for (x = 0; x <= xsize; x++) { 210 uint32 v = ss[x]; 211 pp[0] = v; 212 pp[1] = v >> 8; 213 pp[2] = v >> 16; 214 pp += 3; 215 } 216 ss += xsize+1; 217 } while (--n); 218 if (TIFFWriteEncodedStrip(tif, TIFFComputeStrip(tif,y,0), 219 strip, stripsize) < 0) 220 break; 221 } 222 _TIFFfree(strip); 223} 224 225#undef RED 226#undef GREEN 227#undef BLUE 228#define CVT(x) (((x)*255)/100) 229#define RED CVT(28) /* 28% */ 230#define GREEN CVT(59) /* 59% */ 231#define BLUE CVT(11) /* 11% */ 232 233static void 234svGrey(TIFF* tif, uint32* ss, int xsize, int ysize) 235{ 236 register int x, y; 237 unsigned char *buf = (unsigned char *)_TIFFmalloc(TIFFScanlineSize(tif)); 238 239 for (y = 0; y <= ysize; y++) { 240 for (x = 0; x <= xsize; x++) { 241 unsigned char *cp = (unsigned char *)&ss[x]; 242 buf[x] = (RED*cp[3] + GREEN*cp[2] + BLUE*cp[1]) >> 8; 243 } 244 if (TIFFWriteScanline(tif, buf, (uint32) y, 0) < 0) 245 break; 246 ss += xsize+1; 247 } 248 _TIFFfree(buf); 249} 250 251#define MIN(a,b) ((a)<(b)?(a):(b)) 252#define ABS(x) ((x)<0?-(x):(x)) 253 254static void 255tiffsv(char* name, int x1, int x2, int y1, int y2) 256{ 257 TIFF *tif; 258 int xsize, ysize; 259 int xorg, yorg; 260 uint32 *scrbuf; 261 262 xorg = MIN(x1,x2); 263 yorg = MIN(y1,y2); 264 if (xorg<0) 265 xorg = 0; 266 if (yorg<0) 267 yorg = 0; 268 xsize = ABS(x2-x1); 269 ysize = ABS(y2-y1); 270 if (xorg+xsize > xmaxscreen) 271 xsize = xmaxscreen-xorg; 272 if (yorg+ysize > ymaxscreen) 273 ysize = ymaxscreen-yorg; 274 tif = TIFFOpen(name, "w"); 275 TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, (uint32) (xsize+1)); 276 TIFFSetField(tif, TIFFTAG_IMAGELENGTH, (uint32) (ysize+1)); 277 TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8); 278 TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 279 photometric == PHOTOMETRIC_RGB ? 3 : 1); 280 TIFFSetField(tif, TIFFTAG_PLANARCONFIG, config); 281 TIFFSetField(tif, TIFFTAG_COMPRESSION, compression); 282 switch (compression) { 283 case COMPRESSION_JPEG: 284 if (photometric == PHOTOMETRIC_RGB && jpegcolormode == JPEGCOLORMODE_RGB) 285 photometric = PHOTOMETRIC_YCBCR; 286 TIFFSetField(tif, TIFFTAG_JPEGQUALITY, quality); 287 TIFFSetField(tif, TIFFTAG_JPEGCOLORMODE, jpegcolormode); 288 break; 289 case COMPRESSION_LZW: 290 if (predictor != 0) 291 TIFFSetField(tif, TIFFTAG_PREDICTOR, predictor); 292 break; 293 } 294 TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, photometric); 295 TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_BOTLEFT); 296 rowsperstrip = TIFFDefaultStripSize(tif, rowsperstrip); 297 TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, rowsperstrip); 298 scrbuf = (uint32 *)_TIFFmalloc((xsize+1)*(ysize+1)*sizeof (uint32)); 299 readdisplay(xorg, yorg, xorg+xsize, yorg+ysize, scrbuf, RD_FREEZE); 300 if (photometric == PHOTOMETRIC_RGB) { 301 if (config == PLANARCONFIG_SEPARATE) 302 svRGBSeparate(tif, scrbuf, xsize, ysize); 303 else 304 svRGBContig(tif, scrbuf, xsize, ysize); 305 } else 306 svGrey(tif, scrbuf, xsize, ysize); 307 (void) TIFFClose(tif); 308 _TIFFfree((char *)scrbuf); 309} 310/* 311 * Local Variables: 312 * mode: c 313 * c-basic-offset: 8 314 * fill-column: 78 315 * End: 316 */ 317