home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C++ / Libraries / grayimage / write_xwd.cc < prev    next >
Encoding:
Text File  |  1994-06-30  |  7.0 KB  |  276 lines  |  [TEXT/R*ch]

  1. // This may look like C code, but it is really -*- C++ -*-
  2. /*
  3.  ************************************************************************
  4.  *
  5.  *               Grayscale Image
  6.  *
  7.  *    Write the image into the file in the X11 Window dump format
  8.  *             and display it with xwud program
  9.  *
  10.  * $Id: write_xwd.cc,v 1.5 1994/01/12 19:59:48 oleg Exp oleg $
  11.  *
  12.  ************************************************************************
  13.  */
  14.  
  15. #include "image.h"
  16. #include "endian_io.h"
  17. #include "x11wd.h"
  18.  
  19. #include <ostream.h>
  20.  
  21. #pragma implementation
  22.  
  23. /*
  24.  *------------------------------------------------------------------------
  25.  *               Class XWdump
  26.  *     designed to contain the control info about the image
  27.  *        as defined in the X Window Dump file 
  28.  */
  29.  
  30. class XWdump        // All the info pertaining to the XWD file
  31.    : public X11WDFileHeader, public EndianIO {
  32.  
  33. private:
  34.      const IMAGE& image;        // Image being processed
  35.      const char * title;        // Title for the image in the file
  36.  
  37.      void write_colormap(const int ncolors);
  38.      void write_image_data();
  39.  
  40. public:
  41.      XWdump(const IMAGE& _image);            // Constructor
  42.      ~XWdump()    {}                    // Destructor
  43.      void set_title(const char * user_title);
  44.      void write_image(const char * file_name);
  45. };
  46.  
  47. /*
  48.  *------------------------------------------------------------------------
  49.  *            Construct the XWdump
  50.  *       by filling out the fields of the structure from the IMAGE 
  51.  */
  52.  
  53. XWdump::XWdump(const IMAGE& _image) : image(_image)
  54. {
  55.   title  = image.q_name();
  56.   assure(image.q_depth() <= 8,
  57.      "Sorry, the program cannot write images with depth > 8");
  58.  
  59.   header_size = sizeof(X11WDFileHeader) + strlen(title) + 1;
  60.   file_version = X11WD_FILE_VERSION;
  61.   pixmap_format = ZPixmap;
  62.   pixmap_width = image.q_ncols();
  63.   pixmap_height = image.q_nrows();
  64.   xoffset = 0;
  65.   xbyte_order = MSBFirst; set_bigendian();
  66.   bitmap_bit_order = MSBFirst;
  67.   window_width = image.q_ncols();
  68.   window_height = image.q_nrows();
  69.   window_x = 0;
  70.   window_y = 0;
  71.   window_bdrwidth = 0;
  72.  
  73.   pixmap_depth = 8;
  74.   bits_per_pixel = 8;
  75.   colormap_entries = 256;
  76.   ncolors = 256;
  77.   bytes_per_line = image.q_ncols();
  78.   
  79.   bitmap_unit = 8;
  80.   bitmap_pad = 8;
  81.   visual_class = StaticGray;
  82.   red_mask = 0;
  83.   green_mask = 0;
  84.   blue_mask = 0;
  85.  
  86.   bits_per_rgb = pixmap_depth;
  87. }
  88.  
  89. /*
  90.  *------------------------------------------------------------------------
  91.  *            Set up the title for the image
  92.  * image.name == "" && user title == ""  ---> resulting title = ""
  93.  * image.name != "" && user title == ""  ---> resulting title = image.name
  94.  * image.name == "" && user title != ""  ---> resulting title = user title
  95.  * image.name != "" && user title != ""  ---> 
  96.  *            resulting title = "image name/user title"
  97.  *
  98.  * Note that XWdump::title has been already set to image.title.
  99.  * If it is changed, the XWdump::header_size should be modified as well
  100.  */
  101.  
  102. void XWdump::set_title(const char * user_title)
  103. {
  104.   if( strlen(user_title) == 0 )
  105.     return;
  106.  
  107.   register int old_title_len = strlen(title);
  108.  
  109.   if( strlen(title) == 0 )        // No image title
  110.     title = user_title;
  111.   else
  112.     title = 
  113.      strcat(
  114.       strcat(
  115.        strcpy((char *)calloc(strlen(title)+1+strlen(user_title)+1,
  116.                  sizeof(char)),title),
  117.        "/"),
  118.       user_title);
  119.  
  120.   header_size += strlen(title) - old_title_len;
  121. }
  122.  
  123. /*
  124.  *------------------------------------------------------------------------
  125.  *            Writing the X window dump file
  126.  */
  127.  
  128. void XWdump::write_image(const char * file_name)
  129. {
  130.  
  131.   fstream::open(file_name,ios::out);
  132.                       // Writing the header
  133.   write_long( header_size );
  134.   write_long( file_version );
  135.   write_long( pixmap_format );
  136.   write_long( pixmap_depth );
  137.   write_long( pixmap_width );
  138.   write_long( pixmap_height );
  139.   write_long( xoffset );
  140.   write_long( xbyte_order );
  141.   write_long( bitmap_unit );
  142.   write_long( bitmap_bit_order );
  143.   write_long( bitmap_pad );
  144.   write_long( bits_per_pixel );
  145.   write_long( bytes_per_line );
  146.   write_long( visual_class );
  147.   write_long( red_mask );
  148.   write_long( green_mask );
  149.   write_long( blue_mask );
  150.   write_long( bits_per_rgb );
  151.   write_long( colormap_entries );
  152.   write_long( ncolors );
  153.   write_long( window_width );
  154.   write_long( window_height );
  155.   write_long( window_x );
  156.   write_long( window_y );
  157.   write_long( window_bdrwidth );
  158.   
  159.   write( (void *)title, strlen(title)+1);    // Write out the dump name
  160.   write_colormap(ncolors);
  161.   write_image_data();
  162.   
  163.   close();
  164. }
  165.  
  166. /*
  167.  *------------------------------------------------------------------------
  168.  * Build and write out the colormap table for 'ncolor' colors for the
  169.  *             gray scale (StaticGray) image    
  170.  */
  171.  
  172. void XWdump::write_colormap(const int ncolors)
  173. {
  174.   X11XColor color;
  175.   register int i;
  176.  
  177.   color.flags = 7;
  178.   color.pad = 0;
  179.   for( i = 0; i < ncolors; ++i )
  180.   {
  181.     color.pixel = i;
  182.     
  183.     color.red   = (long) i * 65535 / ( ncolors - 1 );
  184.     color.green = color.red;
  185.     color.blue  = color.red;
  186.     write_long ( color.pixel );
  187.     write_short( color.red );
  188.     write_short( color.green );
  189.     write_short( color.blue );
  190.     write_byte ( color.flags );
  191.     write_byte ( color.pad );
  192.   }
  193. }
  194.  
  195. /*
  196.  *------------------------------------------------------------------------
  197.  *            Write out the pixel matrix 
  198.  *          with 'bits_per_pixel'representation
  199.  */
  200.  
  201. void XWdump::write_image_data()
  202. {
  203.   register int row, col;
  204.   const long int maxval = (1 << image.q_depth()) - 1;
  205.   const long int bigger_maxval = (1 << bits_per_pixel) - 1;
  206.  
  207.   assure(maxval <= bigger_maxval, 
  208.      "Cannot display image with too many bits per pixel");
  209.  
  210.                 // Using simplified procedure if possible
  211.   if( bits_per_pixel == 8 && image.q_depth() == 8 )
  212.   {
  213.     for( row = 0; row < (signed)pixmap_height; ++row )
  214.       for( col = 0; col < (signed)pixmap_width; ++col )
  215.     write_byte( image(row,col) );
  216.     return;
  217.   }
  218.  
  219.                 // Handle the general case if tricks don't
  220.                 // work
  221.   for( row = 0; row < (signed)pixmap_height; ++row )
  222.   {
  223.     register  int  bitshift = 8 - bits_per_pixel;
  224.     register char byte = 0;
  225.  
  226.     for( col = 0; col < (signed)pixmap_width; ++col )
  227.     {
  228.       register long s = image(row,col);
  229.       
  230.       if( maxval != bigger_maxval )
  231.     s = (long) s * bigger_maxval / maxval;
  232.       byte |= s << bitshift;
  233.       bitshift -= bits_per_pixel;
  234.       if( bitshift < 0 )
  235.       {
  236.      write_byte( byte );
  237.      bitshift = 8 - bits_per_pixel;
  238.      byte = 0;
  239.       }
  240.       if( bitshift < 8 - (signed)bits_per_pixel )
  241.     write_byte( byte );
  242.     }
  243.   }
  244. }
  245.  
  246.  
  247. /*
  248.  *------------------------------------------------------------------------
  249.  *                   Root modules 
  250.  *        for writing the image and displaying it
  251.  */
  252.  
  253. void IMAGE::write_xwd(const char * file_name,const char * title = "") const
  254. {
  255.   is_valid();
  256.  
  257.   message("\nPreparing XWD file with name '%s'\n",file_name);
  258.   XWdump XWdump(*this);
  259.   XWdump.set_title(title);
  260.   XWdump.write_image(file_name);
  261. }
  262.  
  263.                 // Display the image with 'xwud' program
  264. void IMAGE::display(const char * title) const
  265. {
  266.   register int kid_id;            // ID of the kid process
  267.   if( getenv("DISPLAY") == (char *)0 )    // Bypass if not-X terminal
  268.     return;
  269.   assert( (kid_id = fork()) != -1 );
  270.   if( kid_id == 0 )            // We're in the kid process
  271.   {
  272.     write_xwd("| xwud",title);
  273.     exit(0);
  274.   }
  275. }
  276.