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

  1. /* xwdtopnm.c - read an X11 or X10 window dump file and write a portable anymap
  2. **
  3. ** Copyright (C) 1989, 1991 by Jef Poskanzer.
  4. **
  5. ** Permission to use, copy, modify, and distribute this software and its
  6. ** documentation for any purpose and without fee is hereby granted, provided
  7. ** that the above copyright notice appear in all copies and that both that
  8. ** copyright notice and this permission notice appear in supporting
  9. ** documentation.  This software is provided "as is" without express or
  10. ** implied warranty.
  11. */
  12.  
  13. #include "pnm.h"
  14. #include "x10wd.h"
  15. #include "x11wd.h"
  16.  
  17. static void getinit ARGS(( FILE* file, int* colsP, int* rowsP, int* padrightP, long* maxvalP, long* visualclassP, int* formatP, xel** colorsP ));
  18. static unsigned long getpixnum ARGS(( FILE* file ));
  19. static short bs_short ARGS(( short s ));
  20. static long bs_long ARGS(( long l ));
  21.  
  22. static unsigned long red_mask, green_mask, blue_mask;
  23. static int bits_per_item, bits_used, bit_shift, bits_per_pixel;
  24. static char buf[4];
  25. static char* byteP;
  26. static short* shortP;
  27. static long* longP;
  28. static unsigned long pixel_mask;
  29. static int byte_swap, byte_order, bit_order;
  30.  
  31. int
  32. main( argc, argv )
  33.     int argc;
  34.     char* argv[];
  35.     {
  36.     FILE* ifp;
  37.     xel* xelrow;
  38.     register xel* xP;
  39.     xel* colors;
  40.     int rows, cols, format, padright, row;
  41.     register int col;
  42.     long maxval, visualclass;
  43.  
  44.     pnm_init( &argc, argv );
  45.  
  46.     if ( argc > 2 )
  47.     pm_usage( "[xwdfile]" );
  48.  
  49.     if ( argc == 2 )
  50.     ifp = pm_openr( argv[1] );
  51.     else
  52.     ifp = stdin;
  53.  
  54.     getinit( ifp, &cols, &rows, &padright, &maxval, &visualclass, &format, &colors );
  55.  
  56.     pnm_writepnminit( stdout, cols, rows, (xelval) maxval, format, 0 );
  57.     xelrow = pnm_allocrow( cols );
  58.     switch ( PNM_FORMAT_TYPE(format) )
  59.     {
  60.     case PBM_TYPE:
  61.     pm_message( "writing PBM file" );
  62.     break;
  63.  
  64.     case PGM_TYPE:
  65.     pm_message( "writing PGM file" );
  66.     break;
  67.  
  68.     case PPM_TYPE:
  69.     pm_message( "writing PPM file" );
  70.     break;
  71.  
  72.     default:
  73.     pm_error( "shouldn't happen" );
  74.     }
  75.  
  76.     for ( row = 0; row < rows; ++row )
  77.     {
  78.     switch ( visualclass )
  79.         {
  80.         case StaticGray:
  81.             case GrayScale:
  82.         case StaticColor:
  83.         case PseudoColor:
  84.         for ( col = 0, xP = xelrow; col < cols; ++col, ++xP )
  85.         *xP = colors[getpixnum( ifp )];
  86.         break;
  87.  
  88.         case TrueColor:
  89.             case DirectColor:
  90.         for ( col = 0, xP = xelrow; col < cols; ++col, ++xP )
  91.         {
  92.         register unsigned long ul;
  93.  
  94.         ul = getpixnum( ifp );
  95.         switch ( bits_per_pixel )
  96.             {
  97.             case 16:
  98.             PPM_ASSIGN( *xP,
  99.             ( ( ul & red_mask ) >> 0 ),
  100.             ( ( ul & green_mask ) >> 5 ),
  101.             ( ( ul & blue_mask ) >> 10 ) );
  102.             break;
  103.  
  104.             case 24:
  105.             case 32:
  106.             PPM_ASSIGN( *xP, ( ( ul & 0xff0000 ) >> 16 ),
  107.             ( ( ul & 0xff00 ) >> 8 ),
  108.             ( ul & 0xff ) );
  109.             break;
  110.  
  111.             default:
  112.             pm_error( "True/Direct only supports 16, 24, and 32 bits" );
  113.             }
  114.         }
  115.         break;
  116.  
  117.         default:
  118.         pm_error( "unknown visual class" );
  119.         }
  120.         for ( col = 0; col < padright; ++col )
  121.         (void) getpixnum( ifp );
  122.     pnm_writepnmrow( stdout, xelrow, cols, (xelval) maxval, format, 0 );
  123.     }
  124.  
  125.     pm_close( ifp );
  126.     pm_close( stdout );
  127.  
  128.     exit( 0 );
  129.     }
  130.  
  131. static void
  132. getinit( file, colsP, rowsP, padrightP, maxvalP, visualclassP, formatP, colorsP )
  133.     FILE* file;
  134.     int* colsP;
  135.     int* rowsP;
  136.     int* padrightP;
  137.     long* maxvalP;
  138.     long* visualclassP;
  139.     int* formatP;
  140.     xel** colorsP;
  141.     {
  142.     int grayscale;
  143.     /* Assume X11 headers are larger than X10 ones. */
  144.     unsigned char header[sizeof(X11WDFileHeader)];
  145.     X10WDFileHeader* h10P;
  146.     X11WDFileHeader* h11P;
  147.  
  148.     byte_swap = 0;
  149.     if ( PNM_MAXMAXVAL < 65535L )
  150.     *maxvalP = PNM_MAXMAXVAL;
  151.     else
  152.     *maxvalP = 65535L;
  153.     h10P = (X10WDFileHeader*) header;
  154.     h11P = (X11WDFileHeader*) header;
  155.     if ( sizeof(*h10P) > sizeof(*h11P) )
  156.     pm_error(
  157. "ARGH!  On this machine, X10 headers are larger than X11 headers!\n    You will have to re-write xwdtopnm." );
  158.  
  159.     /* Read an X10 header. */
  160.     if ( fread( &header[0], sizeof(*h10P), 1, file ) != 1 )
  161.     pm_error( "couldn't read XWD file header" );
  162.  
  163.     if ( h10P->file_version == X10WD_FILE_VERSION ||
  164.      bs_long( h10P->file_version ) == X10WD_FILE_VERSION )
  165.     {
  166.     int i;
  167.     X10Color* x10colors;
  168.  
  169.     if ( h10P->file_version != X10WD_FILE_VERSION )
  170.         {
  171.         byte_swap = 1;
  172.         h10P->header_size = bs_long( h10P->header_size );
  173.         h10P->file_version = bs_long( h10P->file_version );
  174.         h10P->display_type = bs_long( h10P->display_type );
  175.         h10P->display_planes = bs_long( h10P->display_planes );
  176.         h10P->pixmap_format = bs_long( h10P->pixmap_format );
  177.         h10P->pixmap_width = bs_long( h10P->pixmap_width );
  178.         h10P->pixmap_height = bs_long( h10P->pixmap_height );
  179.         h10P->window_width = bs_short( h10P->window_width );
  180.         h10P->window_height = bs_short( h10P->window_height );
  181.         h10P->window_x = bs_short( h10P->window_x );
  182.         h10P->window_y = bs_short( h10P->window_y );
  183.         h10P->window_bdrwidth = bs_short( h10P->window_bdrwidth );
  184.         h10P->window_ncolors = bs_short( h10P->window_ncolors );
  185.         }
  186.     for ( i = 0; i < h10P->header_size - sizeof(*h10P); ++i )
  187.         if ( getc( file ) == EOF )
  188.         pm_error( "couldn't read rest of X10 XWD file header" );
  189.  
  190.     /* Check whether we can handle this dump. */
  191.     if ( h10P->window_ncolors > 256 )
  192.         pm_error( "can't handle X10 window_ncolors > %d", 256 );
  193.     if ( h10P->pixmap_format != ZFormat && h10P->display_planes != 1 )
  194.         pm_error(
  195.         "can't handle X10 pixmap_format %d with planes != 1",
  196.         h10P->pixmap_format );
  197.  
  198.     grayscale = 1;
  199.     if ( h10P->window_ncolors != 0 )
  200.         {
  201.         /* Read X10 colormap. */
  202.         x10colors = (X10Color*) malloc(
  203.         h10P->window_ncolors * sizeof(X10Color) );
  204.         if ( x10colors == 0 )
  205.         pm_error( "out of memory" );
  206.         for ( i = 0; i < h10P->window_ncolors; ++i )
  207.         {
  208.         if ( fread( &x10colors[i], sizeof(X10Color), 1, file ) != 1 )
  209.             pm_error( "couldn't read X10 XWD colormap" );
  210.         if ( byte_swap )
  211.             {
  212.             x10colors[i].red = bs_short( x10colors[i].red );
  213.             x10colors[i].green = bs_short( x10colors[i].green );
  214.             x10colors[i].blue = bs_short( x10colors[i].blue );
  215.             }
  216.         if ( *maxvalP != 65535L )
  217.             {
  218.             x10colors[i].red =
  219.             (long) x10colors[i].red * (long) *maxvalP / 65535L;
  220.             x10colors[i].green =
  221.             (long) x10colors[i].green * (long) *maxvalP / 65535L;
  222.             x10colors[i].blue =
  223.             (long) x10colors[i].blue * (long) *maxvalP / 65535L;
  224.             }
  225.         if ( x10colors[i].red != x10colors[i].green ||
  226.              x10colors[i].green != x10colors[i].blue )
  227.             grayscale = 0;
  228.         }
  229.         }
  230.  
  231.     if ( h10P->display_planes == 1 )
  232.         {
  233.         *formatP = PBM_TYPE;
  234.         *visualclassP = StaticGray;
  235.         *maxvalP = 1;
  236.         *colorsP = pnm_allocrow( 2 );
  237.         PNM_ASSIGN1( (*colorsP)[0], 0 );
  238.         PNM_ASSIGN1( (*colorsP)[1], *maxvalP );
  239.         *padrightP =
  240.         ( ( h10P->pixmap_width + 15 ) / 16 ) * 16 - h10P->pixmap_width;
  241.         bits_per_item = 16;
  242.         bits_per_pixel = 1;
  243.         }
  244.     else if ( h10P->window_ncolors == 0 )
  245.         { /* Must be grayscale. */
  246.         *formatP = PGM_TYPE;
  247.         *visualclassP = StaticGray;
  248.         *maxvalP = ( 1 << h10P->display_planes ) - 1;
  249.         *colorsP = pnm_allocrow( *maxvalP + 1 );
  250.         for ( i = 0; i <= *maxvalP; ++i )
  251.         PNM_ASSIGN1( (*colorsP)[i], i );
  252.         *padrightP =
  253.         ( ( h10P->pixmap_width + 15 ) / 16 ) * 16 - h10P->pixmap_width;
  254.         bits_per_item = 16;
  255.         bits_per_pixel = 1;
  256.         }
  257.     else
  258.         {
  259.         *colorsP = pnm_allocrow( h10P->window_ncolors );
  260.         *visualclassP = PseudoColor;
  261.             if ( grayscale )
  262.                 {
  263.                 *formatP = PGM_TYPE;
  264.         for ( i = 0; i < h10P->window_ncolors; ++i )
  265.             PNM_ASSIGN1( (*colorsP)[i], x10colors[i].red );
  266.                 }
  267.             else
  268.                 {
  269.                 *formatP = PPM_TYPE;
  270.         for ( i = 0; i < h10P->window_ncolors; ++i )
  271.             PPM_ASSIGN(
  272.             (*colorsP)[i], x10colors[i].red, x10colors[i].green,
  273.             x10colors[i].blue);
  274.                 }
  275.  
  276.         *padrightP = h10P->pixmap_width & 1;
  277.         bits_per_item = 8;
  278.         bits_per_pixel = 8;
  279.         }
  280.     bits_used = bits_per_item;
  281.     *colsP = h10P->pixmap_width;
  282.     *rowsP = h10P->pixmap_height;
  283.     if ( bits_per_pixel == sizeof(pixel_mask) * 8 )
  284.         pixel_mask = -1;
  285.     else
  286.         pixel_mask = ( 1 << bits_per_pixel ) - 1;
  287.     byte_order = MSBFirst;
  288.     bit_order = LSBFirst;
  289.     }
  290.     else if ( h11P->file_version == X11WD_FILE_VERSION ||
  291.          bs_long( h11P->file_version ) == X11WD_FILE_VERSION )
  292.     {
  293.     int i;
  294.     X11XColor* x11colors;
  295.  
  296.     if ( fread( &header[sizeof(*h10P)], sizeof(*h11P) - sizeof(*h10P), 1, file ) != 1 )
  297.         pm_error( "couldn't read X11 XWD file header" );
  298.     if ( h11P->file_version != X11WD_FILE_VERSION )
  299.         {
  300.         byte_swap = 1;
  301.         h11P->header_size = bs_long( h11P->header_size );
  302.         h11P->file_version = bs_long( h11P->file_version );
  303.         h11P->pixmap_format = bs_long( h11P->pixmap_format );
  304.         h11P->pixmap_depth = bs_long( h11P->pixmap_depth );
  305.         h11P->pixmap_width = bs_long( h11P->pixmap_width );
  306.         h11P->pixmap_height = bs_long( h11P->pixmap_height );
  307.         h11P->xoffset = bs_long( h11P->xoffset );
  308.         h11P->byte_order = bs_long( h11P->byte_order );
  309.         h11P->bitmap_unit = bs_long( h11P->bitmap_unit );
  310.         h11P->bitmap_bit_order = bs_long( h11P->bitmap_bit_order );
  311.         h11P->bitmap_pad = bs_long( h11P->bitmap_pad );
  312.         h11P->bits_per_pixel = bs_long( h11P->bits_per_pixel );
  313.         h11P->bytes_per_line = bs_long( h11P->bytes_per_line );
  314.         h11P->visual_class = bs_long( h11P->visual_class );
  315.         h11P->red_mask = bs_long( h11P->red_mask );
  316.         h11P->green_mask = bs_long( h11P->green_mask );
  317.         h11P->blue_mask = bs_long( h11P->blue_mask );
  318.         h11P->bits_per_rgb = bs_long( h11P->bits_per_rgb );
  319.         h11P->colormap_entries = bs_long( h11P->colormap_entries );
  320.         h11P->ncolors = bs_long( h11P->ncolors );
  321.         h11P->window_width = bs_long( h11P->window_width );
  322.         h11P->window_height = bs_long( h11P->window_height );
  323.         h11P->window_x = bs_long( h11P->window_x );
  324.         h11P->window_y = bs_long( h11P->window_y );
  325.         h11P->window_bdrwidth = bs_long( h11P->window_bdrwidth );
  326.         }
  327.     for ( i = 0; i < h11P->header_size - sizeof(*h11P); ++i )
  328.         if ( getc( file ) == EOF )
  329.         pm_error( "couldn't read rest of X11 XWD file header" );
  330.  
  331.     /* Check whether we can handle this dump. */
  332.     if ( h11P->pixmap_depth > 24 )
  333.         pm_error( "can't handle X11 pixmap_depth > 24" );
  334.     if ( h11P->bits_per_rgb > 24 )
  335.         pm_error( "can't handle X11 bits_per_rgb > 24" );
  336.     if ( h11P->pixmap_format != ZPixmap && h11P->pixmap_depth != 1 )
  337.         pm_error(
  338.         "can't handle X11 pixmap_format %d with depth != 1",
  339.         h11P->pixmap_format );
  340.     if ( h11P->bitmap_unit != 8 && h11P->bitmap_unit != 16 &&
  341.          h11P->bitmap_unit != 32 )
  342.         pm_error(
  343.         "X11 bitmap_unit (%d) is non-standard - can't handle",
  344.         h11P->bitmap_unit );
  345.  
  346.     grayscale = 1;
  347.     if ( h11P->ncolors > 0 )
  348.         {
  349.         /* Read X11 colormap. */
  350.         x11colors = (X11XColor*) malloc(
  351.         h11P->ncolors * sizeof(X11XColor) );
  352.         if ( x11colors == 0 )
  353.         pm_error( "out of memory" );
  354.         if ( fread( x11colors, sizeof(X11XColor), h11P->ncolors, file ) !=
  355.             h11P->ncolors )
  356.         pm_error( "couldn't read X11 XWD colormap" );
  357.         for ( i = 0; i < h11P->ncolors; ++i )
  358.         {
  359.         if ( byte_swap )
  360.             {
  361.             x11colors[i].red = bs_short( x11colors[i].red );
  362.             x11colors[i].green = bs_short( x11colors[i].green );
  363.             x11colors[i].blue = bs_short( x11colors[i].blue );
  364.             }
  365.         if ( *maxvalP != 65535L )
  366.             {
  367.             x11colors[i].red =
  368.             (long) x11colors[i].red * (long) *maxvalP / 65535L;
  369.             x11colors[i].green =
  370.             (long) x11colors[i].green * (long) *maxvalP / 65535L;
  371.             x11colors[i].blue =
  372.             (long) x11colors[i].blue * (long) *maxvalP / 65535L;
  373.             }
  374.         if ( x11colors[i].red != x11colors[i].green ||
  375.              x11colors[i].green != x11colors[i].blue )
  376.             grayscale = 0;
  377.         }
  378.         }
  379.  
  380.     *visualclassP = h11P->visual_class;
  381.     if ( *visualclassP == TrueColor || *visualclassP == DirectColor )
  382.         {
  383.         *formatP = PPM_TYPE;
  384.         if ( h11P->bits_per_pixel == 16 )
  385.             *maxvalP = 31;
  386.             else
  387.         *maxvalP = 255;
  388.         }
  389.     else if ( *visualclassP == StaticGray && h11P->bits_per_pixel == 1 )
  390.         {
  391.         *formatP = PBM_TYPE;
  392.         *maxvalP = 1;
  393.         *colorsP = pnm_allocrow( 2 );
  394.         PNM_ASSIGN1( (*colorsP)[0], *maxvalP );
  395.         PNM_ASSIGN1( (*colorsP)[1], 0 );
  396.         }
  397.     else if ( *visualclassP == StaticGray )
  398.         {
  399.         *formatP = PGM_TYPE;
  400.         *maxvalP = ( 1 << h11P->bits_per_pixel ) - 1;
  401.         *colorsP = pnm_allocrow( *maxvalP + 1 );
  402.         for ( i = 0; i <= *maxvalP; ++i )
  403.         PNM_ASSIGN1( (*colorsP)[i], i );
  404.         }
  405.     else
  406.         {
  407.         *colorsP = pnm_allocrow( h11P->ncolors );
  408.             if ( grayscale )
  409.                 {
  410.                 *formatP = PGM_TYPE;
  411.         for ( i = 0; i < h11P->ncolors; ++i )
  412.             PNM_ASSIGN1( (*colorsP)[i], x11colors[i].red );
  413.                 }
  414.             else
  415.                 {
  416.                 *formatP = PPM_TYPE;
  417.         for ( i = 0; i < h11P->ncolors; ++i )
  418.             PPM_ASSIGN(
  419.             (*colorsP)[i], x11colors[i].red, x11colors[i].green,
  420.             x11colors[i].blue);
  421.                 }
  422.         }
  423.  
  424.     *colsP = h11P->pixmap_width;
  425.     *rowsP = h11P->pixmap_height;
  426.     *padrightP =
  427.         h11P->bytes_per_line * 8 / h11P->bits_per_pixel -
  428.         h11P->pixmap_width;
  429.     bits_per_item = h11P->bitmap_unit;
  430.     bits_used = bits_per_item;
  431.     bits_per_pixel = h11P->bits_per_pixel;
  432.     byte_order = h11P->byte_order;
  433.     bit_order = h11P->bitmap_bit_order;
  434.     if ( bits_per_pixel == sizeof(pixel_mask) * 8 )
  435.         pixel_mask = -1;
  436.     else
  437.         pixel_mask = ( 1 << bits_per_pixel ) - 1;
  438.         red_mask = h11P->red_mask;
  439.         green_mask = h11P->green_mask;
  440.         blue_mask = h11P->blue_mask;
  441.     }
  442.     else
  443.     pm_error( "unknown XWD file version: %d", h11P->file_version );
  444.  
  445.     byteP = (char*) buf;
  446.     shortP = (short*) buf;
  447.     longP = (long*) buf;
  448.     }
  449.  
  450. static unsigned long
  451. getpixnum( file )
  452.     FILE* file;
  453.     {
  454.     int n;
  455.  
  456.     if ( bits_used == bits_per_item )
  457.     {
  458.     switch ( bits_per_item )
  459.         {
  460.         case 8:
  461.         *byteP = getc( file );
  462.         break;
  463.  
  464.         case 16:
  465.         if ( byte_order == MSBFirst )
  466.         {
  467.         if ( pm_readbigshort( file, shortP ) == -1 )
  468.             pm_error( "error reading image" );
  469.         }
  470.         else
  471.         {
  472.         if ( pm_readlittleshort( file, shortP ) == -1 )
  473.             pm_error( "error reading image" );
  474.         }
  475.         break;
  476.  
  477.         case 32:
  478.         if ( byte_order == MSBFirst )
  479.         {
  480.         if ( pm_readbiglong( file, longP ) == -1 )
  481.             pm_error( "error reading image" );
  482.         }
  483.         else
  484.         {
  485.         if ( pm_readlittlelong( file, longP ) == -1 )
  486.             pm_error( "error reading image" );
  487.         }
  488.         break;
  489.  
  490.         default:
  491.         pm_error( "can't happen" );
  492.         }
  493.     bits_used = 0;
  494.  
  495.     if ( bit_order == MSBFirst )
  496.         bit_shift = bits_per_item - bits_per_pixel;
  497.     else
  498.         bit_shift = 0;
  499.     }
  500.  
  501.     switch ( bits_per_item )
  502.     {
  503.     case 8:
  504.     n = ( *byteP >> bit_shift) & pixel_mask;
  505.     break;
  506.  
  507.     case 16:
  508.     n = ( *shortP >> bit_shift) & pixel_mask;
  509.     break;
  510.  
  511.     case 32:
  512.     n = ( *longP >> bit_shift) & pixel_mask;
  513.     break;
  514.  
  515.     default:
  516.     pm_error( "can't happen" );
  517.     }
  518.  
  519.     if ( bit_order == MSBFirst )
  520.     bit_shift -= bits_per_pixel;
  521.     else
  522.     bit_shift += bits_per_pixel;
  523.     bits_used += bits_per_pixel;
  524.  
  525.     return n;
  526.     }
  527.  
  528. /* Byte-swapping junk. */
  529.  
  530. union cheat {
  531.     long l;
  532.     short s;
  533.     unsigned char c[4];
  534.     };
  535.  
  536. #if __STDC__
  537. static short
  538. bs_short( short s )
  539. #else /*__STDC__*/
  540. static short
  541. bs_short( s )
  542.     short s;
  543. #endif /*__STDC__*/
  544.     {
  545.     union cheat u;
  546.     unsigned char t;
  547.  
  548.     u.s = s;
  549.     t = u.c[0];
  550.     u.c[0] = u.c[1];
  551.     u.c[1] = t;
  552.     return u.s;
  553.     }
  554.  
  555. #if __STDC__
  556. static long
  557. bs_long( long l )
  558. #else /*__STDC__*/
  559. static long
  560. bs_long( l )
  561.     long l;
  562. #endif /*__STDC__*/
  563.     {
  564.     union cheat u;
  565.     unsigned char t;
  566.  
  567.     u.l = l;
  568.     t = u.c[0];
  569.     u.c[0] = u.c[3];
  570.     u.c[3] = t;
  571.     t = u.c[1];
  572.     u.c[1] = u.c[2];
  573.     u.c[2] = t;
  574.     return u.l;
  575.     }
  576.