home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / netpbma.zip / pnm / tifftopnm.c < prev    next >
C/C++ Source or Header  |  1993-10-04  |  7KB  |  287 lines

  1. /*
  2. ** tifftopnm.c - converts a Tagged Image File to a portable anymap
  3. **
  4. ** Derived by Jef Poskanzer from tif2ras.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. #define MAXCOLORS 1024
  34. #ifndef PHOTOMETRIC_DEPTH
  35. #define PHOTOMETRIC_DEPTH 32768
  36. #endif
  37.  
  38. int
  39. main( argc, argv )
  40.     int argc;
  41.     char* argv[];
  42.     {
  43.     int argn, cols, rows, grayscale, format;
  44.     int numcolors;
  45.     register TIFF* tif;
  46.     int row, i;
  47.     register int col;
  48.     u_char* buf;
  49.     register u_char* inP;
  50.     int maxval;
  51.     xel* xelrow;
  52.     register xel* xP;
  53.     xel colormap[MAXCOLORS];
  54.     int headerdump;
  55.     register u_char sample;
  56.     register int bitsleft;
  57.     unsigned short bps, spp, photomet;
  58.     unsigned short* redcolormap;
  59.     unsigned short* greencolormap;
  60.     unsigned short* bluecolormap;
  61.     char* usage = "[-headerdump] [tifffile]";
  62.  
  63.  
  64.     pnm_init( &argc, argv );
  65.  
  66.     argn = 1;
  67.     headerdump = 0;
  68.  
  69.     if ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
  70.     {
  71.     if ( pm_keymatch( argv[argn], "-headerdump", 2 ) )
  72.         headerdump = 1;
  73.     else
  74.         pm_usage( usage );
  75.     ++argn;
  76.     }
  77.  
  78.     if ( argn != argc )
  79.     {
  80.     tif = TIFFOpen( argv[argn], "r" );
  81.     if ( tif == NULL )
  82.         pm_error( "error opening TIFF file %s", argv[argn] );
  83.     ++argn;
  84.     }
  85.     else
  86.     {
  87.     tif = TIFFFdOpen( 0, "Standard Input", "r" );
  88.     if ( tif == NULL )
  89.         pm_error( "error opening standard input as TIFF file" );
  90.     }
  91.  
  92.     if ( argn != argc )
  93.     pm_usage( usage );
  94.  
  95.     if ( headerdump )
  96.     TIFFPrintDirectory( tif, stderr, TIFFPRINT_NONE );
  97.  
  98.     if ( ! TIFFGetField( tif, TIFFTAG_BITSPERSAMPLE, &bps ) )
  99.     bps = 1;
  100.     if ( ! TIFFGetField( tif, TIFFTAG_SAMPLESPERPIXEL, &spp ) )
  101.     spp = 1;
  102.     if ( ! TIFFGetField( tif, TIFFTAG_PHOTOMETRIC, &photomet ) )
  103.     pm_error( "error getting photometric" );
  104.  
  105.     switch ( spp )
  106.     {
  107.     case 1:
  108.     case 3:
  109.     case 4:
  110.     break;
  111.  
  112.     default:
  113.     pm_error(
  114.         "can only handle 1-channel gray scale or 1- or 3-channel color" );
  115.     }
  116.  
  117.     (void) TIFFGetField( tif, TIFFTAG_IMAGEWIDTH, &cols );
  118.     (void) TIFFGetField( tif, TIFFTAG_IMAGELENGTH, &rows );
  119.  
  120.     if ( headerdump )
  121.     {
  122.     pm_message( "%dx%dx%d image", cols, rows, bps * spp );
  123.     pm_message( "%d bits/sample, %d samples/pixel", bps, spp );
  124.     }
  125.  
  126.     maxval = ( 1 << bps ) - 1;
  127.     if ( maxval == 1 && spp == 1 )
  128.     {
  129.     if ( headerdump )
  130.         pm_message("monochrome" );
  131.     grayscale = 1;
  132.     }
  133.     else
  134.     {
  135.     switch ( photomet )
  136.         {
  137.         case PHOTOMETRIC_MINISBLACK:
  138.         if ( headerdump )
  139.         pm_message( "%d graylevels (min=black)", maxval + 1 );
  140.         grayscale = 1;
  141.         break;
  142.  
  143.         case PHOTOMETRIC_MINISWHITE:
  144.         if ( headerdump )
  145.         pm_message( "%d graylevels (min=white)", maxval + 1 );
  146.         grayscale = 1;
  147.         break;
  148.  
  149.         case PHOTOMETRIC_PALETTE:
  150.         if ( headerdump )
  151.         pm_message( "colormapped" );
  152.         if ( ! TIFFGetField( tif, TIFFTAG_COLORMAP, &redcolormap, &greencolormap, &bluecolormap ) )
  153.         pm_error( "error getting colormaps" );
  154.         numcolors = maxval + 1;
  155.         if ( numcolors > MAXCOLORS )
  156.         pm_error( "too many colors" );
  157.         maxval = PNM_MAXMAXVAL;
  158.         grayscale = 0;
  159.         for ( i = 0; i < numcolors; ++i )
  160.         {
  161.         register xelval r, g, b;
  162.         r = (long) redcolormap[i] * PNM_MAXMAXVAL / 65535L;
  163.         g = (long) greencolormap[i] * PNM_MAXMAXVAL / 65535L;
  164.         b = (long) bluecolormap[i] * PNM_MAXMAXVAL / 65535L;
  165.         PPM_ASSIGN( colormap[i], r, g, b );
  166.         }
  167.         break;
  168.  
  169.         case PHOTOMETRIC_RGB:
  170.         if ( headerdump )
  171.         pm_message( "truecolor" );
  172.         grayscale = 0;
  173.         break;
  174.  
  175.         case PHOTOMETRIC_MASK:
  176.         pm_error( "don't know how to handle PHOTOMETRIC_MASK" );
  177.  
  178.         case PHOTOMETRIC_DEPTH:
  179.         pm_error( "don't know how to handle PHOTOMETRIC_DEPTH" );
  180.  
  181.         default:
  182.         pm_error( "unknown photometric: %d", photomet );
  183.         }
  184.     }
  185.     if ( maxval > PNM_MAXMAXVAL )
  186.     pm_error(
  187. "bits/sample is too large - try reconfiguring with PGM_BIGGRAYS\n    or without PPM_PACKCOLORS" );
  188.  
  189.  
  190.     if ( grayscale )
  191.     {
  192.     if ( maxval == 1 )
  193.         {
  194.         format = PBM_TYPE;
  195.         pm_message( "writing PBM file" );
  196.         }
  197.     else
  198.         {
  199.         format = PGM_TYPE;
  200.         pm_message( "writing PGM file" );
  201.         }
  202.     }
  203.     else
  204.     {
  205.     format = PPM_TYPE;
  206.     pm_message( "writing PPM file" );
  207.     }
  208.  
  209.     buf = (u_char*) malloc(TIFFScanlineSize(tif));
  210.     if ( buf == NULL )
  211.     pm_error( "can't allocate memory for scanline buffer" );
  212.     pnm_writepnminit( stdout, cols, rows, (xelval) maxval, format, 0 );
  213.     xelrow = pnm_allocrow( cols );
  214.  
  215. #define NEXTSAMPLE \
  216.     { \
  217.     if ( bitsleft == 0 ) \
  218.     { \
  219.     ++inP; \
  220.     bitsleft = 8; \
  221.     } \
  222.     bitsleft -= bps; \
  223.     sample = ( *inP >> bitsleft ) & maxval; \
  224.     }
  225.  
  226.     for ( row = 0; row < rows; ++row )
  227.     {
  228.     if ( TIFFReadScanline( tif, buf, row, 0 ) < 0 )
  229.         pm_error( "bad data read on line %d", row );
  230.     inP = buf;
  231.     bitsleft = 8;
  232.     xP = xelrow;
  233.  
  234.     switch ( photomet )
  235.         {
  236.         case PHOTOMETRIC_MINISBLACK:
  237.         for ( col = 0; col < cols; ++col, ++xP )
  238.         {
  239.         NEXTSAMPLE
  240.         PNM_ASSIGN1( *xP, sample );
  241.         }
  242.         break;
  243.  
  244.         case PHOTOMETRIC_MINISWHITE:
  245.         for ( col = 0; col < cols; ++col, ++xP )
  246.         {
  247.         NEXTSAMPLE
  248.         sample = maxval - sample;
  249.         PNM_ASSIGN1( *xP, sample );
  250.         }
  251.         break;
  252.  
  253.         case PHOTOMETRIC_PALETTE:
  254.         for ( col = 0; col < cols; ++col, ++xP )
  255.         {
  256.         NEXTSAMPLE
  257.         *xP = colormap[sample];
  258.         }
  259.         break;
  260.  
  261.         case PHOTOMETRIC_RGB:
  262.         for ( col = 0; col < cols; ++col, ++xP )
  263.         {
  264.         register xelval r, g, b;
  265.  
  266.         NEXTSAMPLE
  267.         r = sample;
  268.         NEXTSAMPLE
  269.         g = sample;
  270.         NEXTSAMPLE
  271.         b = sample;
  272.         if ( spp == 4 )
  273.             NEXTSAMPLE        /* skip alpha channel */
  274.         PPM_ASSIGN( *xP, r, g, b );
  275.         }
  276.         break;
  277.  
  278.         default:
  279.         pm_error( "unknown photometric: %d", photomet );
  280.         }
  281.     pnm_writepnmrow( stdout, xelrow, cols, (xelval) maxval, format, 0 );
  282.     }
  283.  
  284.     pm_close( stdout );
  285.     exit( 0 );
  286.     }
  287.