home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / netpbma.zip / pnm / pnmtotiff.c < prev    next >
C/C++ Source or Header  |  1994-01-27  |  9KB  |  348 lines

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