home *** CD-ROM | disk | FTP | other *** search
/ Crawly Crypt Collection 1 / crawlyvol1.bin / program / grfx_snd / tifflib / source / pnm2tiff.c < prev    next >
C/C++ Source or Header  |  1993-02-28  |  12KB  |  360 lines

  1. #pragma warn -use
  2. static char    *sccsid = "@(#)PBMplus/pnm2tiff 1.21, Copyright (c) Jef Poskanzer, Dieter Linde, "__DATE__;
  3. #pragma warn .use
  4. /*
  5.  * pnm2tiff.c - converts a portable anymap to a Tagged Image File
  6.  *
  7.  * Derived by Jef Poskanzer from ras2tif.c, which is:
  8.  *
  9.  * Copyright ©1990 by Sun Microsystems, Inc.
  10.  *
  11.  * Author: Patrick J. Naughton
  12.  * naughton@wind.sun.com
  13.  *
  14.  * Permission to use, copy, modify, and distribute this software and its
  15.  * documentation for any purpose and without fee is hereby granted,
  16.  * provided that the above copyright notice appear in all copies and that
  17.  * both that copyright notice and this permission notice appear in
  18.  * supporting documentation.
  19.  *
  20.  * This file is provided AS IS with no warranties of any kind.  The author
  21.  * shall have no liability with respect to the infringement of copyrights,
  22.  * trade secrets or any patents by this file or any part thereof.  In no
  23.  * event will the author be liable for any lost revenue or profits or
  24.  * other special, indirect and consequential damages.
  25.  */
  26. #include "pnm.h"
  27. #include "tiffio.h"
  28.  
  29. #ifdef    PPM
  30. #include "..\ppm\ppmcmap.h"
  31. #define MAXCOLORS    256
  32. #endif     /* PPM */
  33.  
  34. #define    COMPRESSION_UNDEF    0
  35.  
  36. /****************************************************************************
  37.  *
  38.  */
  39. void
  40. main(
  41.     int  argc, 
  42.          char *argv[]
  43.          )
  44. {
  45.         register int         col;
  46.         register xel        *xP;
  47.         char            *scomp, *ids;
  48.         unsigned char        *buf, *tP;
  49.         int             i, cols, rows, format, row, argn, grayscale, bytesperrow;
  50.         short             photometric, samplesperpixel, bitspersample;
  51.         u_short            comp;
  52.         long             rowsperstrip, colors;
  53.         xelval             maxval;
  54.         FILE            *ifp;
  55.         xel            **xels;
  56.         TIFF            *tif;
  57. #ifdef     PPM
  58.         unsigned short         red[MAXCOLORS], grn[MAXCOLORS], blu[MAXCOLORS];
  59.         colorhist_vector    chv;
  60.         colorhash_table     cht;
  61. #endif     /* PPM */
  62.         char            *inf = NULL;
  63.         char            *usage = "[-none|-dump|-ccittrle|-rle|-ccittfax3|-fax3|-ccittfax4|-fax4|-ccittrlew|-rlew|-packbits|-lzw|-picio|-sgirle] [<pnmfile>]";
  64.  
  65.     pnm_init("pnm2tiff", &argc, argv);
  66.     ids = getenv("TIFF_IMAGEDESCRIPTION");
  67.  
  68.         argn = 1;
  69.         comp = COMPRESSION_UNDEF;
  70.  
  71.         while (argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0') {
  72.         if (pm_keymatch(argv[argn], "-none", 2) || pm_keymatch(argv[argn], "-dump", 2)) {
  73.                 if (comp != COMPRESSION_UNDEF)
  74.                 pm_error("only one compression method may be specified");
  75.                 comp = COMPRESSION_NONE;
  76.                 scomp = "none";
  77.             }
  78.         else if (pm_keymatch(argv[argn], "-ccittrle", 9) || pm_keymatch(argv[argn], "-rle", 4)) {
  79.                 if (comp != COMPRESSION_UNDEF)
  80.                 pm_error("only one compression method may be specified");
  81.                 comp = COMPRESSION_CCITTRLE;
  82.                     scomp = "CCITT modified Huffman";
  83.             }
  84.         else if (pm_keymatch(argv[argn], "-ccittrlew", 10) || pm_keymatch(argv[argn], "-rlew", 5)) {
  85.                 if (comp != COMPRESSION_UNDEF)
  86.                 pm_error("only one compression method may be specified");
  87.                 comp = COMPRESSION_CCITTRLEW;
  88.                     scomp = "CCITT modified Huffman w/ word alignment";
  89.             }
  90.         else if (pm_keymatch(argv[argn], "-ccittfax3", 10) || pm_keymatch(argv[argn], "-fax3", 5)) {
  91.                 if (comp != COMPRESSION_UNDEF)
  92.                 pm_error("only one compression method may be specified");
  93.                 comp = COMPRESSION_CCITTFAX3;
  94.                     scomp = "CCITT Group 3 facsimile";
  95.             }
  96.         else if (pm_keymatch(argv[argn], "-ccittfax4", 10) || pm_keymatch(argv[argn], "-fax4", 5)) {
  97.                 if (comp != COMPRESSION_UNDEF)
  98.                 pm_error("only one compression method may be specified");
  99.                 comp = COMPRESSION_CCITTFAX4;
  100.                         scomp = "CCITT Group 4 facsimile";
  101.             }
  102.         else if (pm_keymatch(argv[argn], "-packbits", 3)) {
  103.                 if (comp != COMPRESSION_UNDEF)
  104.                 pm_error("only one compression method may be specified");
  105.                 comp = COMPRESSION_PACKBITS;
  106.                     scomp = "Macintosh PackBits";
  107.             }
  108.         else if (pm_keymatch(argv[argn], "-lzw", 2)) {
  109.                 if (comp != COMPRESSION_UNDEF)
  110.                 pm_error("only one compression method may be specified");
  111.                 comp = COMPRESSION_LZW;
  112.                     scomp = "Lempel-Ziv & Welch";
  113.             }
  114.         else if (pm_keymatch(argv[argn], "-picio", 3)) {
  115.                 if (comp != COMPRESSION_UNDEF)
  116.                 pm_error("only one compression method may be specified");
  117.                 comp = COMPRESSION_PICIO;
  118.                     scomp = "Pixar picio";
  119.             }
  120.         else if (pm_keymatch(argv[argn], "-sgirle", 2)) {
  121.                 if (comp != COMPRESSION_UNDEF)
  122.                 pm_error("only one compression method may be specified");
  123.                 comp = COMPRESSION_SGIRLE;
  124.             scomp = "Silicon Graphics run-length";
  125.             }
  126.         else
  127.                 pm_usage(usage);
  128.         argn++;
  129.     }
  130.         if (comp == COMPRESSION_UNDEF) {
  131.             comp = COMPRESSION_NONE;
  132.             scomp = "none";
  133.         }
  134.  
  135.         if (argn != argc) {
  136.             inf = argv[argn];
  137.             ifp = pm_openr(inf);
  138.         argn++;
  139.     }
  140.     else {
  141.             inf = "stdin";
  142.             ifp = stdin;
  143.         if (setvbuf(ifp, NULL, _IOFBF, stdbufsize))
  144.                     pm_error("out of memory allocating a filebuffer");
  145.         fsetmode(ifp, IO_BINARY);
  146.         fclrmode(ifp, IO_NBF);
  147.     }
  148.         if (argn != argc)
  149.         pm_usage(usage);
  150.  
  151.         xels = pnm_readpnm(ifp, &cols, &rows, &maxval, &format);
  152.         pm_close(ifp);
  153.  
  154.     /* 
  155.      * Check for grayscale. 
  156.      */
  157.         switch (PNM_FORMAT_TYPE(format)) {
  158.  
  159. #ifdef     PPM
  160.             case PPM_TYPE:
  161.                 pm_message("computing colormap...");
  162.                 if ((chv = ppm_computecolorhist(xels, cols, rows, MAXCOLORS, &colors)) == NULL) {
  163.                         pm_message("too many colors -- proceeding to write a 24-bit RGB file.");
  164.                         pm_message("If you want an 8-bit palette file, try doing a \"ppmquant %d\".", MAXCOLORS);
  165.                         grayscale = 0;
  166.                     }
  167.                 else {
  168.                         pm_message("%ld colors found", colors);
  169.                         grayscale = 1;
  170.                         for (i = 0; i < colors; i++) {
  171.                             register xelval    r, g, b;
  172.  
  173.                             r = PPM_GETR(chv[i].color);
  174.                             g = PPM_GETG(chv[i].color);
  175.                             b = PPM_GETB(chv[i].color);
  176.                             if (r != g || g != b) {
  177.                                     grayscale = 0;
  178.                                     break;
  179.                                 }
  180.                         }
  181.                     }
  182.                 break;
  183. #endif     /* PPM */
  184.  
  185.             default:
  186.                 grayscale = 1;
  187.                 break;
  188.         }
  189.  
  190.      /* 
  191.      * Open output file. 
  192.      */
  193.  
  194.     pm_message("using encoding method \'%s\'", scomp);
  195.  
  196.         if ((tif = TIFFFdOpen(1, "stdout", "wb")) == NULL)
  197.             pm_error("error opening stdout as TIFF file");
  198.  
  199.     /* 
  200.      * Figure out TIFF parameters. 
  201.      */
  202.         switch (PNM_FORMAT_TYPE(format)) {
  203.  
  204. #ifdef     PPM
  205.             case PPM_TYPE:
  206.                 if (chv == NULL) {
  207.                         samplesperpixel = 3;
  208.                         bitspersample = 8;
  209.                         photometric = PHOTOMETRIC_RGB;
  210.                         bytesperrow = cols * 3;
  211.                     }
  212.                 else if (grayscale) {
  213.                         samplesperpixel = 1;
  214.                         bitspersample = pm_maxvaltobits(maxval);
  215.                         photometric = PHOTOMETRIC_MINISBLACK;
  216.                         bytesperrow = (cols + i - 1) / i;
  217.                     }
  218.                 else {
  219.                         samplesperpixel = 1;
  220.                         bitspersample = 8;
  221.                         photometric = PHOTOMETRIC_PALETTE;
  222.                         bytesperrow = cols;
  223.                     }
  224.                 break;
  225. #endif     /* PPM */
  226.  
  227. #ifdef     PGM
  228.             case PGM_TYPE:
  229.                 samplesperpixel = 1;
  230.                 bitspersample = pm_maxvaltobits(maxval);
  231.                 photometric = PHOTOMETRIC_MINISBLACK;
  232.                 i = 8 / bitspersample;
  233.                 bytesperrow = (cols + i - 1) / i;
  234.                 break;
  235. #endif     /* PGM */
  236.  
  237.             default:
  238.                 samplesperpixel = 1;
  239.                 bitspersample = 1;
  240.                 photometric = PHOTOMETRIC_MINISBLACK;
  241.                 bytesperrow = (cols + 7) / 8;
  242.                 break;
  243.         }
  244.         rowsperstrip = (8 * 1024) / bytesperrow;
  245.         if ((buf = (unsigned char *)malloc(bytesperrow)) == NULL)
  246.             pm_error("out of memory allocating row buffer");
  247.  
  248.     /* 
  249.      * Set TIFF parameters. 
  250.      */
  251.         TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, cols);
  252.         TIFFSetField(tif, TIFFTAG_IMAGELENGTH, rows);
  253.         TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, bitspersample);
  254.         TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
  255.         TIFFSetField(tif, TIFFTAG_COMPRESSION, comp);
  256.         TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, photometric);
  257.         TIFFSetField(tif, TIFFTAG_DOCUMENTNAME, inf);
  258.     if (ids != NULL)
  259.             TIFFSetField(tif, TIFFTAG_IMAGEDESCRIPTION, ids);
  260.         TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, samplesperpixel);
  261.         TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, rowsperstrip);
  262.         TIFFSetField(tif, TIFFTAG_STRIPBYTECOUNTS, rows / rowsperstrip);
  263.         TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
  264.  
  265. #ifdef     PPM
  266.         if (chv == NULL)
  267.             cht = NULL;
  268.         else {
  269.  
  270.     /* 
  271.      * Make TIFF colormap. 
  272.      */
  273.             for (i = 0; i < colors; i++) {
  274.                     red[i] = (long)PPM_GETR(chv[i].color) * 65535L / maxval;
  275.                     grn[i] = (long)PPM_GETG(chv[i].color) * 65535L / maxval;
  276.                     blu[i] = (long)PPM_GETB(chv[i].color) * 65535L / maxval;
  277.                 }
  278.             TIFFSetField(tif, TIFFTAG_COLORMAP, red, grn, blu);
  279.  
  280.     /* 
  281.      * Convert color vector to color hash table, for fast lookup. 
  282.      */
  283.             cht = ppm_colorhisttocolorhash(chv, colors);
  284.             ppm_freecolorhist(chv);
  285.           }
  286. #endif     /* PPM */
  287.  
  288.     /* 
  289.      * Now write the TIFF data. 
  290.      */
  291.         for (row = 0; row < rows; row++) {
  292.  
  293. #ifdef     PPM
  294.             if (PNM_FORMAT_TYPE(format) == PPM_TYPE && !grayscale) {
  295.                     if (cht == NULL) {
  296.                         for (col = 0, xP = xels[row], tP = buf; col < cols; col++, xP++) {
  297.                                 register unsigned char    s;
  298.  
  299.                                 s = PPM_GETR(*xP);
  300.                                 if (maxval != 255)
  301.                                     s = (long)s * 255 / maxval;
  302.                                 *tP++ = s;
  303.                                 s = PPM_GETG(*xP);
  304.                                 if (maxval != 255)
  305.                                     s = (long)s * 255 / maxval;
  306.                                 *tP++ = s;
  307.                                 s = PPM_GETB(*xP);
  308.                                 if (maxval != 255)
  309.                                     s = (long)s * 255 / maxval;
  310.                                 *tP++ = s;
  311.                             }
  312.                     }
  313.                     else {
  314.                         for (col = 0, xP = xels[row], tP = buf; col < cols; col++, xP++) {
  315.                                 register long    s;
  316.  
  317.                                 s = ppm_lookupcolor(cht, xP);
  318.                                 if (s == -1)
  319.                                     pm_error("color not found?!? (row=%d, col=%d, r=%d, g=%d, b=%d)", row, col, PPM_GETR(*xP), PPM_GETG(*xP), PPM_GETB(*xP));
  320.                                 *tP++ = (unsigned char)s;
  321.                             }
  322.                     }
  323.                 }
  324.             else
  325. #endif    /* PPM */
  326.                 {
  327.                     register xelval        bigger_maxval;
  328.                     register int         bitshift;
  329.                     register unsigned char    byte;
  330.                     register xelval     s;
  331.  
  332.                     bigger_maxval = pm_bitstomaxval(bitspersample);
  333.                     bitshift = 8 - bitspersample;
  334.                     byte = 0;
  335.                     for (col = 0, xP = xels[row], tP = buf; col < cols; col++, xP++) {
  336.                         s = PNM_GET1(*xP);
  337.                         if (maxval != bigger_maxval)
  338.                                 s = (long)s * bigger_maxval / maxval;
  339.                         byte |= (s << bitshift);
  340.                         bitshift -= bitspersample;
  341.                         if (bitshift < 0) {
  342.                                 *tP++ = byte;
  343.                                 bitshift = 8 - bitspersample;
  344.                                 byte = 0;
  345.                             }
  346.                     }
  347.                     if (bitshift != 8 - bitspersample)
  348.                         *tP++ = byte;
  349.                 }
  350.  
  351.             if (TIFFWriteScanline(tif, buf, row, 0) < 0)
  352.                     pm_error("failed a scanline write on row %d", row);
  353.            }
  354.         TIFFFlushData(tif);
  355.         TIFFClose(tif);
  356.  
  357.     fflush(stdout);
  358.         exit(0);
  359. }
  360.