/* $Id: ppm2tiff.c,v 1.7 2004-09-02 14:51:04 dron Exp $ */ /* * Copyright (c) 1991-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. * * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ #include "tif_config.h" #include #include #include #include #ifdef HAVE_UNISTD_H # include #endif #include "tiffio.h" #if defined(_WINDOWS) || defined(MSDOS) #define BINMODE "b" #else #define BINMODE #endif #define streq(a,b) (strcmp(a,b) == 0) #define strneq(a,b,n) (strncmp(a,b,n) == 0) static uint16 compression = COMPRESSION_PACKBITS; static uint16 predictor = 0; static int quality = 75; /* JPEG quality */ static int jpegcolormode = JPEGCOLORMODE_RGB; static void usage(void); static int processCompressOptions(char*); static void BadPPM(char* file) { fprintf(stderr, "%s: Not a PPM file.\n", file); exit(-2); } int main(int argc, char* argv[]) { uint16 photometric = 0; uint32 rowsperstrip = (uint32) -1; double resolution = -1; unsigned char *buf = NULL; uint32 row; tsize_t linebytes; uint16 spp = 1; TIFF *out; FILE *in; uint32 w, h; int prec; char *infile; int c; extern int optind; extern char* optarg; if ( argc < 2 ) { fprintf(stderr, "%s: Too few arguments\n", argv[0]); usage(); } while ((c = getopt(argc, argv, "c:r:R:")) != -1) switch (c) { case 'c': /* compression scheme */ if (!processCompressOptions(optarg)) usage(); break; case 'r': /* rows/strip */ rowsperstrip = atoi(optarg); break; case 'R': /* resolution */ resolution = atof(optarg); break; case '?': usage(); /*NOTREACHED*/ } if ( optind + 2 < argc ) { fprintf(stderr, "%s: Too many arguments\n", argv[0]); usage(); } /* * If only one file is specified, read input from * stdin; otherwise usage is: ppm2tiff input output. */ if (argc - optind > 1) { infile = argv[optind++]; in = fopen(infile, "r" BINMODE); if (in == NULL) { fprintf(stderr, "%s: Can not open.\n", infile); return (-1); } } else { infile = ""; in = stdin; } if (fgetc(in) != 'P') BadPPM(infile); switch (fgetc(in)) { case '5': /* it's a PGM file */ spp = 1; photometric = PHOTOMETRIC_MINISBLACK; break; case '6': /* it's a PPM file */ spp = 3; photometric = PHOTOMETRIC_RGB; if (compression == COMPRESSION_JPEG && jpegcolormode == JPEGCOLORMODE_RGB) photometric = PHOTOMETRIC_YCBCR; break; default: BadPPM(infile); } /* Parse header */ while(1) { if (feof(in)) BadPPM(infile); c = fgetc(in); /* Skip whitespaces (blanks, TABs, CRs, LFs) */ if (strchr(" \t\r\n", c)) continue; /* Check fo comment line */ if (c == '#') { do { c = fgetc(in); } while(!strchr("\r\n", c) || feof(in)); continue; } ungetc(c, in); break; } if (fscanf(in, " %lu %lu %d", &w, &h, &prec) != 3) BadPPM(infile); if (fgetc(in) != '\n' || w <= 0 || h <= 0 || prec != 255) BadPPM(infile); out = TIFFOpen(argv[optind], "w"); if (out == NULL) return (-4); TIFFSetField(out, TIFFTAG_IMAGEWIDTH, w); TIFFSetField(out, TIFFTAG_IMAGELENGTH, h); TIFFSetField(out, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, spp); TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, 8); TIFFSetField(out, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); TIFFSetField(out, TIFFTAG_PHOTOMETRIC, photometric); TIFFSetField(out, TIFFTAG_COMPRESSION, compression); switch (compression) { case COMPRESSION_JPEG: TIFFSetField(out, TIFFTAG_JPEGQUALITY, quality); TIFFSetField(out, TIFFTAG_JPEGCOLORMODE, jpegcolormode); break; case COMPRESSION_LZW: case COMPRESSION_DEFLATE: if (predictor != 0) TIFFSetField(out, TIFFTAG_PREDICTOR, predictor); break; } linebytes = spp * w; if (TIFFScanlineSize(out) > linebytes) buf = (unsigned char *)_TIFFmalloc(linebytes); else buf = (unsigned char *)_TIFFmalloc(TIFFScanlineSize(out)); TIFFSetField(out, TIFFTAG_ROWSPERSTRIP, TIFFDefaultStripSize(out, rowsperstrip)); if (resolution > 0) { TIFFSetField(out, TIFFTAG_XRESOLUTION, resolution); TIFFSetField(out, TIFFTAG_YRESOLUTION, resolution); TIFFSetField(out, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH); } for (row = 0; row < h; row++) { if (fread(buf, linebytes, 1, in) != 1) { fprintf(stderr, "%s: scanline %lu: Read error.\n", infile, (unsigned long) row); break; } if (TIFFWriteScanline(out, buf, row, 0) < 0) break; } (void) TIFFClose(out); if (buf) _TIFFfree(buf); return (0); } static int processCompressOptions(char* opt) { if (streq(opt, "none")) compression = COMPRESSION_NONE; else if (streq(opt, "packbits")) compression = COMPRESSION_PACKBITS; else if (strneq(opt, "jpeg", 4)) { char* cp = strchr(opt, ':'); if (cp && isdigit(cp[1])) quality = atoi(cp+1); if (cp && strchr(cp, 'r')) jpegcolormode = JPEGCOLORMODE_RAW; compression = COMPRESSION_JPEG; } else if (strneq(opt, "lzw", 3)) { char* cp = strchr(opt, ':'); if (cp) predictor = atoi(cp+1); compression = COMPRESSION_LZW; } else if (strneq(opt, "zip", 3)) { char* cp = strchr(opt, ':'); if (cp) predictor = atoi(cp+1); compression = COMPRESSION_DEFLATE; } else return (0); return (1); } char* stuff[] = { "usage: ppm2tiff [options] input.ppm output.tif", "where options are:", " -r # make each strip have no more than # rows", " -R # set x&y resolution (dpi)", "", " -c jpeg[:opts] compress output with JPEG encoding", " -c lzw[:opts] compress output with Lempel-Ziv & Welch encoding", " -c zip[:opts] compress output with deflate encoding", " -c packbits compress output with packbits encoding (the default)", " -c none use no compression algorithm on output", "", "JPEG options:", " # set compression quality level (0-100, default 75)", " r output color image as RGB rather than YCbCr", "LZW and deflate options:", " # set predictor value", "For example, -c lzw:2 to get LZW-encoded data with horizontal differencing", NULL }; static void usage(void) { char buf[BUFSIZ]; int i; setbuf(stderr, buf); fprintf(stderr, "%s\n\n", TIFFGetVersion()); for (i = 0; stuff[i] != NULL; i++) fprintf(stderr, "%s\n", stuff[i]); exit(-1); } /* vim: set ts=8 sts=8 sw=8 noet: */