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