home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / ImageMagick / magick / encode.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  196.0 KB  |  7,148 lines

  1. /*
  2. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  3. %                                                                             %
  4. %                                                                             %
  5. %                   EEEEE  N   N   CCCC   OOO   DDDD   EEEEE                  %
  6. %                   E      NN  N  C      O   O  D   D  E                      %
  7. %                   EEE    N N N  C      O   O  D   D  EEE                    %
  8. %                   E      N  NN  C      O   O  D   D  E                      %
  9. %                   EEEEE  N   N   CCCC   OOO   DDDD   EEEEE                  %
  10. %                                                                             %
  11. %                                                                             %
  12. %                    Utility Routines to Write Image Formats                  %
  13. %                                                                             %
  14. %                                                                             %
  15. %                                                                             %
  16. %                             Software Design                                 %
  17. %                               John Cristy                                   %
  18. %                              January 1992                                   %
  19. %                                                                             %
  20. %                                                                             %
  21. %  Copyright 1994 E. I. du Pont de Nemours & Company                          %
  22. %                                                                             %
  23. %  Permission to use, copy, modify, distribute, and sell this software and    %
  24. %  its documentation for any purpose is hereby granted without fee,           %
  25. %  provided that the above Copyright notice appear in all copies and that     %
  26. %  both that Copyright notice and this permission notice appear in            %
  27. %  supporting documentation, and that the name of E. I. du Pont de Nemours    %
  28. %  & Company not be used in advertising or publicity pertaining to            %
  29. %  distribution of the software without specific, written prior               %
  30. %  permission.  E. I. du Pont de Nemours & Company makes no representations   %
  31. %  about the suitability of this software for any purpose.  It is provided    %
  32. %  "as is" without express or implied warranty.                               %
  33. %                                                                             %
  34. %  E. I. du Pont de Nemours & Company disclaims all warranties with regard    %
  35. %  to this software, including all implied warranties of merchantability      %
  36. %  and fitness, in no event shall E. I. du Pont de Nemours & Company be       %
  37. %  liable for any special, indirect or consequential damages or any           %
  38. %  damages whatsoever resulting from loss of use, data or profits, whether    %
  39. %  in an action of contract, negligence or other tortuous action, arising     %
  40. %  out of or in connection with the use or performance of this software.      %
  41. %                                                                             %
  42. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  43. %
  44. %  Functions in this library convert to and from `alien' image formats to the
  45. %  MIFF image format.
  46. %
  47. %
  48. */
  49.  
  50. /*
  51.   Include declarations.
  52. */
  53. #include "magick.h"
  54. #include "image.h"
  55. #include "X.h"
  56. #include "compress.h"
  57. #include "utility.h"
  58. #include "XWDFile.h"
  59.  
  60. /*
  61.   Forward declarations.
  62. */
  63. static unsigned int
  64.   WriteMIFFImage _Declare((Image *));
  65.  
  66. /*
  67. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  68. %                                                                             %
  69. %                                                                             %
  70. %                                                                             %
  71. %   W r i t e A L P H A I m a g e                                             %
  72. %                                                                             %
  73. %                                                                             %
  74. %                                                                             %
  75. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  76. %
  77. %  Function WriteALPHAImage writes an mage of alpha bytes to a file.  It
  78. %  consists of data from the alpha component of the image [0..255].
  79. %
  80. %  The format of the WriteALPHAImage routine is:
  81. %
  82. %      status=WriteALPHAImage(image)
  83. %
  84. %  A description of each parameter follows.
  85. %
  86. %    o status: Function WriteALPHAImage return True if the image is written.
  87. %      False is returned is there is a memory shortage or if the image file
  88. %      fails to write.
  89. %
  90. %    o image:  A pointer to a Image structure.
  91. %
  92. %
  93. */
  94. static unsigned int WriteALPHAImage(image)
  95. Image
  96.   *image;
  97. {
  98.   register int
  99.     i,
  100.     j;
  101.  
  102.   register RunlengthPacket
  103.     *p;
  104.  
  105.   register unsigned char
  106.     *q;
  107.  
  108.   unsigned char
  109.     *alpha_pixels;
  110.  
  111.   if (!image->alpha)
  112.     {
  113.       Warning("Image does not have an alpha channel",image->filename);
  114.       return(False);
  115.     }
  116.   /*
  117.     Open output image file.
  118.   */
  119.   OpenImage(image,"w");
  120.   if (image->file == (FILE *) NULL)
  121.     {
  122.       Warning("Unable to open file",image->filename);
  123.       return(False);
  124.     }
  125.   /*
  126.     Allocate alpha pixels.
  127.   */
  128.   alpha_pixels=(unsigned char *)
  129.     malloc(image->columns*image->rows*sizeof(unsigned char));
  130.   if (alpha_pixels == (unsigned char *) NULL)
  131.     {
  132.       Warning("Unable to allocate memory",(char *) NULL);
  133.       return(False);
  134.     }
  135.   p=image->pixels;
  136.   q=alpha_pixels;
  137.   for (i=0; i < image->packets; i++)
  138.   {
  139.     for (j=0; j <= ((int) p->length); j++)
  140.       *q++=(unsigned char) p->index;
  141.     p++;
  142.   }
  143.   (void) fwrite((char *) alpha_pixels,1,(int) (image->columns*image->rows),
  144.     image->file);
  145.   (void) free((char *) alpha_pixels);
  146.   CloseImage(image);
  147.   return(True);
  148. }
  149.  
  150. /*
  151. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  152. %                                                                             %
  153. %                                                                             %
  154. %                                                                             %
  155. %   W r i t e A V S I m a g e                                                 %
  156. %                                                                             %
  157. %                                                                             %
  158. %                                                                             %
  159. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  160. %
  161. %  Function WriteAVSImage writes an image to a file in AVS X image format.
  162. %
  163. %  The format of the WriteAVSImage routine is:
  164. %
  165. %      status=WriteAVSImage(image)
  166. %
  167. %  A description of each parameter follows.
  168. %
  169. %    o status: Function WriteAVSImage return True if the image is written.
  170. %      False is returned is there is a memory shortage or if the image file
  171. %      fails to write.
  172. %
  173. %    o image:  A pointer to a Image structure.
  174. %
  175. %
  176. */
  177. static unsigned int WriteAVSImage(image)
  178. Image
  179.   *image;
  180. {
  181.   typedef struct _AVSHeader
  182.   {
  183.     int
  184.       width,
  185.       height;
  186.   } AVSHeader;
  187.  
  188.   AVSHeader
  189.     avs_header;
  190.  
  191.   register int
  192.     i,
  193.     j;
  194.  
  195.   register RunlengthPacket
  196.     *p;
  197.  
  198.   register unsigned char
  199.     *q;
  200.  
  201.   unsigned char
  202.     *avs_pixels;
  203.  
  204.   /*
  205.     Open output image file.
  206.   */
  207.   OpenImage(image,"w");
  208.   if (image->file == (FILE *) NULL)
  209.     {
  210.       Warning("Unable to open file",image->filename);
  211.       return(False);
  212.     }
  213.   /*
  214.     Initialize raster file header.
  215.   */
  216.   avs_header.width=image->columns;
  217.   avs_header.height=image->rows;
  218.   avs_pixels=(unsigned char *)
  219.     malloc(4*image->columns*image->rows*sizeof(unsigned char));
  220.   if (avs_pixels == (unsigned char *) NULL)
  221.     {
  222.       Warning("Unable to allocate memory",(char *) NULL);
  223.       return(False);
  224.     }
  225.   (void) fwrite((char *) &avs_header,sizeof(AVSHeader),1,image->file);
  226.   p=image->pixels;
  227.   q=avs_pixels;
  228.   for (i=0; i < image->packets; i++)
  229.   {
  230.     for (j=0; j <= (int) p->length; j++)
  231.     {
  232.       *q++=(unsigned char) (image->alpha ? p->index : 0);
  233.       *q++=p->red;
  234.       *q++=p->green;
  235.       *q++=p->blue;
  236.     }
  237.     p++;
  238.   }
  239.   (void) fwrite((char *) avs_pixels,4,(int)(image->columns*image->rows),
  240.     image->file);
  241.   CloseImage(image);
  242.   return(True);
  243. }
  244.  
  245. /*
  246. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  247. %                                                                             %
  248. %                                                                             %
  249. %                                                                             %
  250. %   W r i t e B M P I m a g e                                                 %
  251. %                                                                             %
  252. %                                                                             %
  253. %                                                                             %
  254. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  255. %
  256. %  Function WriteBMPImage writes an image in Microsoft Windows bitmap encoded
  257. %  image format.
  258. %
  259. %  The format of the WriteBMPImage routine is:
  260. %
  261. %      status=WriteBMPImage(image)
  262. %
  263. %  A description of each parameter follows.
  264. %
  265. %    o status: Function WriteBMPImage return True if the image is written.
  266. %      False is returned is there is a memory shortage or if the image file
  267. %      fails to write.
  268. %
  269. %    o image:  A pointer to a Image structure.
  270. %
  271. %
  272. */
  273. static unsigned int WriteBMPImage(image)
  274. Image
  275.   *image;
  276. {
  277.   typedef struct _BMPHeader
  278.   {
  279.     unsigned long
  280.       file_size;
  281.  
  282.     unsigned short
  283.       reserved[2];
  284.  
  285.     unsigned long
  286.       offset_bits,
  287.       size,
  288.       width,
  289.       height;
  290.  
  291.     unsigned short
  292.       planes,
  293.       bit_count;
  294.  
  295.     unsigned long
  296.       compression,
  297.       image_size,
  298.       x_pixels,
  299.       y_pixels,
  300.       number_colors,
  301.       colors_important;
  302.   } BMPHeader;
  303.  
  304.   BMPHeader
  305.     bmp_header;
  306.  
  307.   register int
  308.     i,
  309.     j,
  310.     x,
  311.     y;
  312.  
  313.   register RunlengthPacket
  314.     *p;
  315.  
  316.   register unsigned char
  317.     *q;
  318.  
  319.   unsigned char
  320.     *bmp_data,
  321.     *bmp_pixels;
  322.  
  323.   unsigned int
  324.     bytes_per_line;
  325.  
  326.   /*
  327.     Open output image file.
  328.   */
  329.   OpenImage(image,"w");
  330.   if (image->file == (FILE *) NULL)
  331.     {
  332.       Warning("Unable to open file",image->filename);
  333.       return(False);
  334.     }
  335.   if (image->class == DirectClass)
  336.     if (NumberColors(image,(FILE *) NULL) <= 256)
  337.       {
  338.         /*
  339.           Demote DirectClass to PseudoClass.
  340.         */
  341.         QuantizeImage(image,256,8,False,RGBColorspace,True);
  342.         SyncImage(image);
  343.       }
  344.   /*
  345.     Initialize BMP raster file header.
  346.   */
  347.   bmp_header.file_size=14+40;
  348.   bmp_header.offset_bits=14+40;
  349.   if ((image->class == DirectClass) || (image->colors > 256))
  350.     {
  351.       /*
  352.         Full color BMP raster.
  353.       */
  354.       bmp_header.bit_count=24;
  355.       bmp_header.number_colors=0;
  356.     }
  357.   else
  358.     {
  359.       /*
  360.         Colormapped BMP raster.
  361.       */
  362.       bmp_header.bit_count=8;
  363.       if (IsGrayImage(image) && (image->colors == 2))
  364.         bmp_header.bit_count=1;
  365.       bmp_header.file_size+=image->colors*4;
  366.       bmp_header.offset_bits+=image->colors*4;
  367.       bmp_header.number_colors=image->colors;
  368.     }
  369.   bmp_header.reserved[0]=0;
  370.   bmp_header.reserved[1]=0;
  371.   bmp_header.size=40;
  372.   bmp_header.width=image->columns;
  373.   bmp_header.height=image->rows;
  374.   bmp_header.planes=1;
  375.   bmp_header.compression=0;
  376.   bytes_per_line=((image->columns*bmp_header.bit_count+31)/32)*4;
  377.   bmp_header.image_size=bytes_per_line*image->rows;
  378.   bmp_header.file_size+=bmp_header.image_size;
  379.   bmp_header.x_pixels=75*39;
  380.   bmp_header.y_pixels=75*39;
  381.   bmp_header.colors_important=bmp_header.number_colors;
  382.   /*
  383.     Convert MIFF to BMP raster pixels.
  384.   */
  385.   bmp_pixels=(unsigned char *)
  386.     malloc(bmp_header.image_size*sizeof(unsigned char));
  387.   if (bmp_pixels == (unsigned char *) NULL)
  388.     {
  389.       Warning("Unable to allocate memory",(char *) NULL);
  390.       return(False);
  391.     }
  392.   p=image->pixels;
  393.   x=0;
  394.   y=image->rows-1;
  395.   switch (bmp_header.bit_count)
  396.   {
  397.     case 1:
  398.     {
  399.       register unsigned char
  400.         bit,
  401.         byte;
  402.  
  403.       /*
  404.         Convert PseudoClass image to a BMP monochrome image.
  405.       */
  406.       bit=0;
  407.       byte=0;
  408.       q=bmp_pixels+y*bytes_per_line;
  409.       for (i=0; i < image->packets; i++)
  410.       {
  411.         for (j=0; j <= (int) p->length; j++)
  412.         {
  413.           byte<<=1;
  414.           if (p->index == 0)
  415.             byte|=0x01;
  416.           bit++;
  417.           if (bit == 8)
  418.             {
  419.               *q++=byte;
  420.               bit=0;
  421.               byte=0;
  422.             }
  423.           x++;
  424.           if (x == image->columns)
  425.             {
  426.               /*
  427.                 Advance to the next scanline.
  428.               */
  429.               if (bit != 0)
  430.                 *q++=byte << (8-bit);
  431.               bit=0;
  432.               byte=0;
  433.               x=0;
  434.               y--;
  435.               q=bmp_pixels+y*bytes_per_line;
  436.            }
  437.         }
  438.         p++;
  439.       }
  440.       break;
  441.     }
  442.     case 8:
  443.     {
  444.       /*
  445.         Convert PseudoClass packet to BMP pixel.
  446.       */
  447.       q=bmp_pixels+y*bytes_per_line;
  448.       for (i=0; i < image->packets; i++)
  449.       {
  450.         for (j=0; j <= (int) p->length; j++)
  451.         {
  452.           *q++=p->index;
  453.           x++;
  454.           if (x == image->columns)
  455.             {
  456.               x=0;
  457.               y--;
  458.               q=bmp_pixels+y*bytes_per_line;
  459.             }
  460.         }
  461.         p++;
  462.       }
  463.       break;
  464.     }
  465.     case 24:
  466.     {
  467.       /*
  468.         Convert DirectClass packet to BMP RGB pixel.
  469.       */
  470.       q=bmp_pixels+y*bytes_per_line;
  471.       for (i=0; i < image->packets; i++)
  472.       {
  473.         for (j=0; j <= (int) p->length; j++)
  474.         {
  475.           *q++=p->blue;
  476.           *q++=p->green;
  477.           *q++=p->red;
  478.           x++;
  479.           if (x == image->columns)
  480.             {
  481.               x=0;
  482.               y--;
  483.               q=bmp_pixels+y*bytes_per_line;
  484.             }
  485.         }
  486.         p++;
  487.       }
  488.       break;
  489.     }
  490.   }
  491.   if (bmp_header.bit_count == 8)
  492.     {
  493.       if (image->compression == RunlengthEncodedCompression)
  494.         CompressImage(image);
  495.       if (image->compression == RunlengthEncodedCompression)
  496.         {
  497.           unsigned int
  498.             packets;
  499.  
  500.           /*
  501.             Convert run-length encoded raster pixels.
  502.           */
  503.           packets=(bytes_per_line*(bmp_header.height+2)+1) << 1;
  504.           bmp_data=(unsigned char *) malloc(packets*sizeof(unsigned char));
  505.           if (bmp_pixels == (unsigned char *) NULL)
  506.             {
  507.               Warning("Memory allocation error",(char *) NULL);
  508.               (void) free((char *) bmp_pixels);
  509.               return(False);
  510.             }
  511.           bmp_header.image_size=
  512.             BMPEncodeImage(bmp_pixels,bmp_data,image->columns,image->rows);
  513.           (void) free((char *) bmp_pixels);
  514.           bmp_pixels=bmp_data;
  515.           bmp_header.compression=1;
  516.         }
  517.     }
  518.   /*
  519.     Write BMP header.
  520.   */
  521.   (void) fwrite("BM",1,2,image->file);
  522.   LSBFirstWriteLong(bmp_header.file_size,image->file);
  523.   LSBFirstWriteShort(bmp_header.reserved[0],image->file);
  524.   LSBFirstWriteShort(bmp_header.reserved[1],image->file);
  525.   LSBFirstWriteLong(bmp_header.offset_bits,image->file);
  526.   LSBFirstWriteLong(bmp_header.size,image->file);
  527.   LSBFirstWriteLong(bmp_header.width,image->file);
  528.   LSBFirstWriteLong(bmp_header.height,image->file);
  529.   LSBFirstWriteShort(bmp_header.planes,image->file);
  530.   LSBFirstWriteShort(bmp_header.bit_count,image->file);
  531.   LSBFirstWriteLong(bmp_header.compression,image->file);
  532.   LSBFirstWriteLong(bmp_header.image_size,image->file);
  533.   LSBFirstWriteLong(bmp_header.x_pixels,image->file);
  534.   LSBFirstWriteLong(bmp_header.y_pixels,image->file);
  535.   LSBFirstWriteLong(bmp_header.number_colors,image->file);
  536.   LSBFirstWriteLong(bmp_header.colors_important,image->file);
  537.   if (image->class == PseudoClass)
  538.     {
  539.       unsigned char
  540.         *bmp_colormap;
  541.  
  542.       /*
  543.         Dump colormap to file.
  544.       */
  545.       bmp_colormap=(unsigned char *)
  546.         malloc(4*image->colors*sizeof(unsigned char));
  547.       if (bmp_colormap == (unsigned char *) NULL)
  548.         {
  549.           Warning("Unable to allocate memory",(char *) NULL);
  550.           return(False);
  551.         }
  552.       q=bmp_colormap;
  553.       for (i=0; i < image->colors; i++)
  554.       {
  555.         *q++=image->colormap[i].blue;
  556.         *q++=image->colormap[i].green;
  557.         *q++=image->colormap[i].red;
  558.         q++;
  559.       }
  560.       (void) fwrite((char *) bmp_colormap,4,(int) image->colors,image->file);
  561.       (void) free((char *) bmp_colormap);
  562.     }
  563.   (void) fwrite((char *) bmp_pixels,1,(int) bmp_header.image_size,image->file);
  564.   (void) free((char *) bmp_pixels);
  565.   CloseImage(image);
  566.   return(True);
  567. }
  568.  
  569. /*
  570. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  571. %                                                                             %
  572. %                                                                             %
  573. %                                                                             %
  574. %   W r i t e C M Y K I m a g e                                               %
  575. %                                                                             %
  576. %                                                                             %
  577. %                                                                             %
  578. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  579. %
  580. %  Function WriteCMYKImage writes an image to a file in cyan, magenta,
  581. %  yellow, and black rasterfile format.
  582. %
  583. %  The format of the WriteCMYKImage routine is:
  584. %
  585. %      status=WriteCMYKImage(image,interlace,undercolor_geometry)
  586. %
  587. %  A description of each parameter follows.
  588. %
  589. %    o status: Function WriteCMYKImage return True if the image is written.
  590. %      False is returned is there is a memory shortage or if the image file
  591. %      fails to write.
  592. %
  593. %    o image:  A pointer to a Image structure.
  594. %
  595. %    o interlace:  An unsigned integer that specifies the interlacing
  596. %      scheme.
  597. %
  598. %    o undercolor_geometry: Specifies a pointer to a undercolor geometry
  599. %      string.  The specified undercolor removal and black generation of this
  600. %      geometry string are relative.
  601. %
  602. %
  603. */
  604. static unsigned int WriteCMYKImage(image,interlace,undercolor_geometry)
  605. Image
  606.   *image;
  607.  
  608. unsigned int
  609.   interlace;
  610.  
  611. char
  612.   *undercolor_geometry;
  613. {
  614.   float
  615.     black_generation,
  616.     undercolor;
  617.  
  618.   register int
  619.     i,
  620.     j;
  621.  
  622.   register RunlengthPacket
  623.     *p;
  624.  
  625.   register unsigned char
  626.     *q;
  627.  
  628.   unsigned char
  629.     black,
  630.     cyan,
  631.     magenta,
  632.     *cmyk_pixels,
  633.     yellow;
  634.  
  635.   /*
  636.     Open output image file.
  637.   */
  638.   OpenImage(image,"w");
  639.   if (image->file == (FILE *) NULL)
  640.     {
  641.       Warning("Unable to open file",image->filename);
  642.       return(False);
  643.     }
  644.   /*
  645.     Convert MIFF to CMYK raster pixels.
  646.   */
  647.   cmyk_pixels=(unsigned char *)
  648.     malloc(4*image->columns*image->rows*sizeof(unsigned char));
  649.   if (cmyk_pixels == (unsigned char *) NULL)
  650.     {
  651.       Warning("Unable to allocate memory",(char *) NULL);
  652.       return(False);
  653.     }
  654.   undercolor=1.0;
  655.   black_generation=1.0;
  656.   if (undercolor_geometry != (char *) NULL)
  657.     {
  658.       (void) sscanf(undercolor_geometry,"%fx%f",&undercolor,&black_generation);
  659.       if (black_generation == 1.0)
  660.         black_generation=undercolor;
  661.     }
  662.   q=cmyk_pixels;
  663.   switch (interlace)
  664.   {
  665.     case NoneInterlace:
  666.     default:
  667.     {
  668.       /*
  669.         No interlacing:  CMYKCMYKCMYKCMYKCMYKCMYK...
  670.       */
  671.       p=image->pixels;
  672.       for (i=0; i < image->packets; i++)
  673.       {
  674.         for (j=0; j <= ((int) p->length); j++)
  675.         {
  676.           cyan=MaxRGB-p->red;
  677.           magenta=MaxRGB-p->green;
  678.           yellow=MaxRGB-p->blue;
  679.           black=cyan;
  680.           if (magenta < black)
  681.             black=magenta;
  682.           if (yellow < black)
  683.             black=yellow;
  684.           *q++=cyan-undercolor*black;
  685.           *q++=magenta-undercolor*black;
  686.           *q++=yellow-undercolor*black;
  687.           *q++=black_generation*black;
  688.         }
  689.         p++;
  690.       }
  691.       break;
  692.     }
  693.     case LineInterlace:
  694.     {
  695.       register int
  696.         x,
  697.         y;
  698.  
  699.       /*
  700.         Line interlacing:  CCC...MMM...YYY...CCC...MMM...YYY...
  701.       */
  702.       if (!UncompressImage(image))
  703.         return(False);
  704.       for (y=0; y < image->rows; y++)
  705.       {
  706.         p=image->pixels+(y*image->columns);
  707.         for (x=0; x < image->columns; x++)
  708.         {
  709.           cyan=MaxRGB-p->red;
  710.           magenta=MaxRGB-p->green;
  711.           yellow=MaxRGB-p->blue;
  712.           black=cyan;
  713.           if (magenta < black)
  714.             black=magenta;
  715.           if (yellow < black)
  716.             black=yellow;
  717.           *q++=cyan-undercolor*black;
  718.           p++;
  719.         }
  720.         p=image->pixels+(y*image->columns);
  721.         for (x=0; x < image->columns; x++)
  722.         {
  723.           cyan=MaxRGB-p->red;
  724.           magenta=MaxRGB-p->green;
  725.           yellow=MaxRGB-p->blue;
  726.           black=cyan;
  727.           if (magenta < black)
  728.             black=magenta;
  729.           if (yellow < black)
  730.             black=yellow;
  731.           *q++=magenta-undercolor*black;
  732.           p++;
  733.         }
  734.         p=image->pixels+(y*image->columns);
  735.         for (x=0; x < image->columns; x++)
  736.         {
  737.           cyan=MaxRGB-p->red;
  738.           magenta=MaxRGB-p->green;
  739.           yellow=MaxRGB-p->blue;
  740.           black=cyan;
  741.           if (magenta < black)
  742.             black=magenta;
  743.           if (yellow < black)
  744.             black=yellow;
  745.           *q++=yellow-undercolor*black;
  746.           p++;
  747.         }
  748.         p=image->pixels+(y*image->columns);
  749.         for (x=0; x < image->columns; x++)
  750.         {
  751.           cyan=MaxRGB-p->red;
  752.           magenta=MaxRGB-p->green;
  753.           yellow=MaxRGB-p->blue;
  754.           black=cyan;
  755.           if (magenta < black)
  756.             black=magenta;
  757.           if (yellow < black)
  758.             black=yellow;
  759.           *q++=black_generation*black;
  760.           p++;
  761.         }
  762.       }
  763.       break;
  764.     }
  765.     case PlaneInterlace:
  766.     {
  767.       /*
  768.         Plane interlacing:  CCCCCC...MMMMMM...YYYYYY...KKKKKK...
  769.       */
  770.       p=image->pixels;
  771.       for (i=0; i < image->packets; i++)
  772.       {
  773.         for (j=0; j <= ((int) p->length); j++)
  774.         {
  775.           cyan=MaxRGB-p->red;
  776.           magenta=MaxRGB-p->green;
  777.           yellow=MaxRGB-p->blue;
  778.           black=cyan;
  779.           if (magenta < black)
  780.             black=magenta;
  781.           if (yellow < black)
  782.             black=yellow;
  783.           *q++=cyan-undercolor*black;
  784.         }
  785.         p++;
  786.       }
  787.       p=image->pixels;
  788.       for (i=0; i < image->packets; i++)
  789.       {
  790.         for (j=0; j <= ((int) p->length); j++)
  791.         {
  792.           cyan=MaxRGB-p->red;
  793.           magenta=MaxRGB-p->green;
  794.           yellow=MaxRGB-p->blue;
  795.           black=cyan;
  796.           if (magenta < black)
  797.             black=magenta;
  798.           if (yellow < black)
  799.             black=yellow;
  800.           *q++=magenta-undercolor*black;
  801.         }
  802.         p++;
  803.       }
  804.       p=image->pixels;
  805.       for (i=0; i < image->packets; i++)
  806.       {
  807.         for (j=0; j <= ((int) p->length); j++)
  808.         {
  809.            cyan=MaxRGB-p->red;
  810.            magenta=MaxRGB-p->green;
  811.            yellow=MaxRGB-p->blue;
  812.            black=cyan;
  813.            if (magenta < black)
  814.              black=magenta;
  815.            if (yellow < black)
  816.              black=yellow;
  817.            *q++=yellow-undercolor*black;
  818.         }
  819.         p++;
  820.       }
  821.       p=image->pixels;
  822.       for (i=0; i < image->packets; i++)
  823.       {
  824.         for (j=0; j <= ((int) p->length); j++)
  825.         {
  826.           cyan=MaxRGB-p->red;
  827.           magenta=MaxRGB-p->green;
  828.           yellow=MaxRGB-p->blue;
  829.           black=cyan;
  830.           if (magenta < black)
  831.             black=magenta;
  832.           if (yellow < black)
  833.             black=yellow;
  834.           *q++=black_generation*black;
  835.         }
  836.         p++;
  837.       }
  838.       break;
  839.     }
  840.   }
  841.   (void) fwrite((char *) cmyk_pixels,4,(int) (image->columns*image->rows),
  842.     image->file);
  843.   (void) free((char *) cmyk_pixels);
  844.   CloseImage(image);
  845.   return(True);
  846. }
  847.  
  848. /*
  849. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  850. %                                                                             %
  851. %                                                                             %
  852. %                                                                             %
  853. %   W r i t e F A X I m a g e                                                 %
  854. %                                                                             %
  855. %                                                                             %
  856. %                                                                             %
  857. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  858. %
  859. %  Procedure WriteFAXImage writes an image to a file in 1 dimensional Huffman
  860. %  encoded format.
  861. %
  862. %  The format of the WriteFAXImage routine is:
  863. %
  864. %      status=WriteFAXImage(image)
  865. %
  866. %  A description of each parameter follows.
  867. %
  868. %    o status: Function WriteFAXImage return True if the image is written.
  869. %      False is returned is there is a memory shortage or if the image file
  870. %      fails to write.
  871. %
  872. %    o image:  A pointer to a Image structure.
  873. %
  874. %
  875. */
  876. static unsigned int WriteFAXImage(image)
  877. Image
  878.   *image;
  879. {
  880.   unsigned int
  881.     status;
  882.  
  883.   /*
  884.     Open output image file.
  885.   */
  886.   OpenImage(image,"w");
  887.   if (image->file == (FILE *) NULL)
  888.     {
  889.       Warning("Unable to open file",image->filename);
  890.       return(False);
  891.     }
  892.   /*
  893.     Convert MIFF to monochrome.
  894.   */
  895.   QuantizeImage(image,2,8,False,GRAYColorspace,True);
  896.   SyncImage(image);
  897.   status=HuffmanEncodeImage(image);
  898.   CloseImage(image);
  899.   return(status);
  900. }
  901.  
  902. /*
  903. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  904. %                                                                             %
  905. %                                                                             %
  906. %                                                                             %
  907. %   W r i t e F I T S I m a g e                                               %
  908. %                                                                             %
  909. %                                                                             %
  910. %                                                                             %
  911. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  912. %
  913. %  Function WriteFITSImage writes a Flexible Image Transport System image to a
  914. %  file as gray scale intensities [0..255].
  915. %
  916. %  The format of the WriteFITSImage routine is:
  917. %
  918. %      status=WriteFITSImage(image)
  919. %
  920. %  A description of each parameter follows.
  921. %
  922. %    o status: Function WriteFITSImage return True if the image is written.
  923. %      False is returned is there is a memory shortage or if the image file
  924. %      fails to write.
  925. %
  926. %    o image:  A pointer to a Image structure.
  927. %
  928. %
  929. */
  930. static unsigned int WriteFITSImage(image)
  931. Image
  932.   *image;
  933. {
  934.   char
  935.     buffer[81],
  936.     *fits_header;
  937.  
  938.   register int
  939.     i,
  940.     j;
  941.  
  942.   register RunlengthPacket
  943.     *p;
  944.  
  945.   register unsigned char
  946.     *q;
  947.  
  948.   unsigned char
  949.     *fits_pixels;
  950.  
  951.   /*
  952.     Open output image file.
  953.   */
  954.   OpenImage(image,"w");
  955.   if (image->file == (FILE *) NULL)
  956.     {
  957.       Warning("Unable to open file",image->filename);
  958.       return(False);
  959.     }
  960.   /*
  961.     Allocate image header.
  962.   */
  963.   fits_header=(char *) malloc(2880*sizeof(unsigned char));
  964.   if (fits_header == (char *) NULL)
  965.     {
  966.       Warning("Unable to write image","Memory allocation failed");
  967.       return(False);
  968.     }
  969.   /*
  970.     Initialize image header.
  971.   */
  972.   for (i=0; i < 2880; i++)
  973.     fits_header[i]=' ';
  974.   (void) strcpy(buffer,"SIMPLE  =                    T");
  975.   (void) strncpy(fits_header+0,buffer,strlen(buffer));
  976.   (void) strcpy(buffer,"BITPIX  =                    8");
  977.   (void) strncpy(fits_header+80,buffer,strlen(buffer));
  978.   (void) strcpy(buffer,"NAXIS  =                     2");
  979.   (void) strncpy(fits_header+160,buffer,strlen(buffer));
  980.   (void) sprintf(buffer,"NAXIS1  =           %10u",image->columns);
  981.   (void) strncpy(fits_header+240,buffer,strlen(buffer));
  982.   (void) sprintf(buffer,"NAXIS2  =           %10u",image->rows);
  983.   (void) strncpy(fits_header+320,buffer,strlen(buffer));
  984.   (void) strcpy(buffer,"HISTORY Created by ImageMagick.");
  985.   (void) strncpy(fits_header+400,buffer,strlen(buffer));
  986.   (void) strcpy(buffer,"END");
  987.   (void) strncpy(fits_header+480,buffer,strlen(buffer));
  988.   (void) fwrite((char *) fits_header,1,2880,image->file);
  989.   (void) free((char *) fits_header);
  990.   /*
  991.     Convert image to fits scale PseudoColor class.
  992.   */
  993.   fits_pixels=(unsigned char *)
  994.     malloc(image->columns*image->rows*sizeof(unsigned char));
  995.   if (fits_pixels == (unsigned char *) NULL)
  996.     {
  997.       Warning("Unable to allocate memory",(char *) NULL);
  998.       return(False);
  999.     }
  1000.   p=image->pixels;
  1001.   q=fits_pixels;
  1002.   for (i=0; i < image->packets; i++)
  1003.   {
  1004.     for (j=0; j <= ((int) p->length); j++)
  1005.       *q++=Intensity(*p);
  1006.     p++;
  1007.   }
  1008.   (void) fwrite((char *) fits_pixels,1,(int) (image->columns*image->rows),
  1009.     image->file);
  1010.   (void) free((char *) fits_pixels);
  1011.   CloseImage(image);
  1012.   return(True);
  1013. }
  1014.  
  1015. /*
  1016. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1017. %                                                                             %
  1018. %                                                                             %
  1019. %                                                                             %
  1020. %   W r i t e G I F I m a g e                                                 %
  1021. %                                                                             %
  1022. %                                                                             %
  1023. %                                                                             %
  1024. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1025. %
  1026. %  Function WriteGIFImage writes an image to a file in the Compuserve Graphics
  1027. %  image format.
  1028. %
  1029. %  The format of the WriteGIFImage routine is:
  1030. %
  1031. %      status=WriteGIFImage(image)
  1032. %
  1033. %  A description of each parameter follows.
  1034. %
  1035. %    o status: Function WriteGIFImage return True if the image is written.
  1036. %      False is returned is there is a memory shortage or if the image file
  1037. %      fails to write.
  1038. %
  1039. %    o image:  A pointer to a Image structure.
  1040. %
  1041. %
  1042. */
  1043. static unsigned int WriteGIFImage(image)
  1044. Image
  1045.   *image;
  1046. {
  1047.   int
  1048.     transparency_index;
  1049.  
  1050.   register int
  1051.     i;
  1052.  
  1053.   register RunlengthPacket
  1054.     *p;
  1055.  
  1056.   unsigned char
  1057.     bits_per_pixel,
  1058.     c;
  1059.  
  1060.   unsigned int
  1061.     status;
  1062.  
  1063.   /*
  1064.     Open output image file.
  1065.   */
  1066.   OpenImage(image,"w");
  1067.   if (image->file == (FILE *) NULL)
  1068.     {
  1069.       Warning("Unable to open file",image->filename);
  1070.       return(False);
  1071.     }
  1072.   transparency_index=(-1);
  1073.   if (image->alpha)
  1074.     {
  1075.       /*
  1076.         Determine transparency index.
  1077.       */
  1078.       transparency_index=0;
  1079.       p=image->pixels;
  1080.       image->runlength=p->length+1;
  1081.       for (i=0; i < (image->columns*image->rows); i++)
  1082.       {
  1083.         if (image->runlength != 0)
  1084.           image->runlength--;
  1085.         else
  1086.           {
  1087.             p++;
  1088.             image->runlength=p->length;
  1089.           }
  1090.         if (p->index)
  1091.           {
  1092.             transparency_index=i;
  1093.             break;
  1094.           }
  1095.       }
  1096.     }
  1097.   if ((image->class == DirectClass) || (image->colors > 256))
  1098.     {
  1099.       /*
  1100.         Demote DirectClass to PseudoClass.
  1101.       */
  1102.       QuantizeImage(image,256,8,True,RGBColorspace,True);
  1103.       SyncImage(image);
  1104.     }
  1105.   for (bits_per_pixel=1; bits_per_pixel < 8; bits_per_pixel++)
  1106.     if ((1 << bits_per_pixel) >= image->colors)
  1107.       break;
  1108.   /*
  1109.     Write GIF header.
  1110.   */
  1111.   if (strcmp(image->magick,"GIF87") == 0)
  1112.     (void) fwrite("GIF87a",1,6,image->file);
  1113.   else
  1114.     (void) fwrite("GIF89a",1,6,image->file);
  1115.   LSBFirstWriteShort(image->columns,image->file);
  1116.   LSBFirstWriteShort(image->rows,image->file);
  1117.   c=0x80;  /* global colormap */
  1118.   c|=(8-1) << 4;  /* color resolution */
  1119.   c|=(bits_per_pixel-1);   /* size of global colormap */
  1120.   (void) fputc((char) c,image->file);
  1121.   (void) fputc(0x0,image->file);  /* background color */
  1122.   (void) fputc(0x0,image->file);  /* reserved */
  1123.   /*
  1124.     Write colormap.
  1125.   */
  1126.   for (i=0; i < image->colors; i++)
  1127.   {
  1128.     (void) fputc((char) image->colormap[i].red,image->file);
  1129.     (void) fputc((char) image->colormap[i].green,image->file);
  1130.     (void) fputc((char) image->colormap[i].blue,image->file);
  1131.   }
  1132.   for ( ; i < (int) (1 << bits_per_pixel); i++)
  1133.   {
  1134.     (void) fputc(0x0,image->file);
  1135.     (void) fputc(0x0,image->file);
  1136.     (void) fputc(0x0,image->file);
  1137.   }
  1138.   if (strcmp(image->magick,"GIF87") != 0)
  1139.     {
  1140.       if (transparency_index >= 0)
  1141.         {
  1142.           /*
  1143.             Write out extension for transparent color index.
  1144.           */
  1145.           p=image->pixels;
  1146.           image->runlength=p->length+1;
  1147.           for (i=0; i < transparency_index; i++)
  1148.             if (image->runlength != 0)
  1149.               image->runlength--;
  1150.             else
  1151.               {
  1152.                 p++;
  1153.                 image->runlength=p->length;
  1154.               }
  1155.           (void) fputc(0x21,image->file);
  1156.           (void) fputc(0xf9,image->file);
  1157.           (void) fputc(0x4,image->file);
  1158.           (void) fputc(0x1,image->file);
  1159.           (void) fputc(0x0,image->file);
  1160.           (void) fputc(0x0,image->file);
  1161.           (void) fputc((char) p->index,image->file);
  1162.           (void) fputc(0x0,image->file);
  1163.         }
  1164.       if (image->comments != (char *) NULL)
  1165.         {
  1166.           register char
  1167.             *p;
  1168.  
  1169.           register unsigned int
  1170.             count;
  1171.  
  1172.           /*
  1173.             Write comment extension block.
  1174.           */
  1175.           (void) fputc(0x21,image->file);
  1176.           (void) fputc(0xfe,image->file);
  1177.           p=image->comments;
  1178.           while ((int) strlen(p) > 0)
  1179.           {
  1180.             count=Min((int) strlen(p),255);
  1181.             (void) fputc(count,image->file);
  1182.             for (i=0; i < count; i++)
  1183.               (void) fputc(*p++,image->file);
  1184.           }
  1185.           (void) fputc(0x0,image->file);
  1186.         }
  1187.     }
  1188.   (void) fputc(',',image->file);  /* image separator */
  1189.   /*
  1190.     Write the image header.
  1191.   */
  1192.   LSBFirstWriteShort(0,image->file);
  1193.   LSBFirstWriteShort(0,image->file);
  1194.   LSBFirstWriteShort(image->columns,image->file);
  1195.   LSBFirstWriteShort(image->rows,image->file);
  1196.   (void) fputc(0x0,image->file);
  1197.   c=Max(bits_per_pixel,2);
  1198.   (void) fputc((char) c,image->file);
  1199.   status=LZWEncodeImage(image,Max(bits_per_pixel,2)+1);
  1200.   if (status == False)
  1201.     {
  1202.       Warning("Unable to write image","Memory allocation failed");
  1203.       return(False);
  1204.     }
  1205.   (void) fputc(0x0,image->file);
  1206.   (void) fputc(';',image->file); /* terminator */
  1207.   CloseImage(image);
  1208.   return(True);
  1209. }
  1210.  
  1211. /*
  1212. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1213. %                                                                             %
  1214. %                                                                             %
  1215. %                                                                             %
  1216. %   W r i t e G R A Y I m a g e                                               %
  1217. %                                                                             %
  1218. %                                                                             %
  1219. %                                                                             %
  1220. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1221. %
  1222. %  Function WriteGRAYImage writes an image to a file as gray scale intensity
  1223. %  values [0..255].
  1224. %
  1225. %  The format of the WriteGRAYImage routine is:
  1226. %
  1227. %      status=WriteGRAYImage(image)
  1228. %
  1229. %  A description of each parameter follows.
  1230. %
  1231. %    o status: Function WriteGRAYImage return True if the image is written.
  1232. %      False is returned is there is a memory shortage or if the image file
  1233. %      fails to write.
  1234. %
  1235. %    o image:  A pointer to a Image structure.
  1236. %
  1237. %
  1238. */
  1239. static unsigned int WriteGRAYImage(image)
  1240. Image
  1241.   *image;
  1242. {
  1243.   register int
  1244.     i,
  1245.     j;
  1246.  
  1247.   register RunlengthPacket
  1248.     *p;
  1249.  
  1250.   register unsigned char
  1251.     *q;
  1252.  
  1253.   unsigned char
  1254.     *gray_pixels;
  1255.  
  1256.   /*
  1257.     Open output image file.
  1258.   */
  1259.   OpenImage(image,"w");
  1260.   if (image->file == (FILE *) NULL)
  1261.     {
  1262.       Warning("Unable to open file",image->filename);
  1263.       return(False);
  1264.     }
  1265.   /*
  1266.     Convert image to gray scale PseudoColor class.
  1267.   */
  1268.   gray_pixels=(unsigned char *)
  1269.     malloc(image->columns*image->rows*sizeof(unsigned char));
  1270.   if (gray_pixels == (unsigned char *) NULL)
  1271.     {
  1272.       Warning("Unable to allocate memory",(char *) NULL);
  1273.       return(False);
  1274.     }
  1275.   p=image->pixels;
  1276.   q=gray_pixels;
  1277.   for (i=0; i < image->packets; i++)
  1278.   {
  1279.     for (j=0; j <= ((int) p->length); j++)
  1280.       *q++=Intensity(*p);
  1281.     p++;
  1282.   }
  1283.   (void) fwrite((char *) gray_pixels,1,(int) (image->columns*image->rows),
  1284.     image->file);
  1285.   (void) free((char *) gray_pixels);
  1286.   CloseImage(image);
  1287.   return(True);
  1288. }
  1289.  
  1290. /*
  1291. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1292. %                                                                             %
  1293. %                                                                             %
  1294. %                                                                             %
  1295. %   W r i t e H I S T O G R A M I m a g e                                     %
  1296. %                                                                             %
  1297. %                                                                             %
  1298. %                                                                             %
  1299. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1300. %
  1301. %  Function WriteHISTOGRAMImage writes an image to a file in HISTOGRAM format.
  1302. %  A list of unique pixel values and the number of times each occurs in the
  1303. %  image is written to the file.
  1304. %
  1305. %  The format of the WriteHISTOGRAMImage routine is:
  1306. %
  1307. %      status=WriteHISTOGRAMImage(image)
  1308. %
  1309. %  A description of each parameter follows.
  1310. %
  1311. %    o status: Function WriteHISTOGRAMImage return True if the image is written.
  1312. %      False is returned is there is a memory shortage or if the image file
  1313. %      fails to write.
  1314. %
  1315. %    o image:  A pointer to a Image structure.
  1316. %
  1317. %
  1318. */
  1319. static unsigned int WriteHISTOGRAMImage(image)
  1320. Image
  1321.   *image;
  1322. {
  1323.   /*
  1324.     Open output image file.
  1325.   */
  1326.   OpenImage(image,"w");
  1327.   if (image->file == (FILE *) NULL)
  1328.     {
  1329.       Warning("Unable to open file",image->filename);
  1330.       return(False);
  1331.     }
  1332.   (void) NumberColors(image,image->file);
  1333.   CloseImage(image);
  1334.   return(True);
  1335. }
  1336.  
  1337. /*
  1338. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1339. %                                                                             %
  1340. %                                                                             %
  1341. %                                                                             %
  1342. %   W r i t e I R I S I m a g e                                               %
  1343. %                                                                             %
  1344. %                                                                             %
  1345. %                                                                             %
  1346. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1347. %
  1348. %  Function WriteIRISImage writes an image in SGI RGB encoded image format.
  1349. %
  1350. %  The format of the WriteIRISImage routine is:
  1351. %
  1352. %      status=WriteIRISImage(image)
  1353. %
  1354. %  A description of each parameter follows.
  1355. %
  1356. %    o status: Function WriteIRISImage return True if the image is written.
  1357. %      False is returned is there is a memory shortage or if the image file
  1358. %      fails to write.
  1359. %
  1360. %    o image:  A pointer to a Image structure.
  1361. %
  1362. %
  1363. */
  1364.  
  1365. static int IRISEncode(pixels,count,packets)
  1366. unsigned char
  1367.   *pixels;
  1368.  
  1369. int
  1370.   count;
  1371.  
  1372. unsigned char
  1373.   *packets;
  1374. {
  1375.   short
  1376.     runlength;
  1377.  
  1378.   unsigned char
  1379.     *limit,
  1380.     *mark,
  1381.     *p,
  1382.     *q;
  1383.  
  1384.   p=pixels;
  1385.   limit=p+count*4;
  1386.   q=packets;
  1387.   while (p < limit)
  1388.   {
  1389.     mark=p;
  1390.     p+=8;
  1391.     while ((p < limit) && ((*(p-8) != *(p-4)) || (*(p-4) != *p)))
  1392.       p+=4;
  1393.     p-=8;
  1394.     count=((p-mark) >> 2);
  1395.     while (count)
  1396.     {
  1397.       runlength=count > 126 ? 126 : count;
  1398.       count-=runlength;
  1399.       *q++=0x80 | runlength;
  1400.       for ( ; runlength > 0; runlength--)
  1401.       {
  1402.         *q++=(*mark);
  1403.         mark+=4;
  1404.       }
  1405.     }
  1406.     mark=p;
  1407.     p+=4;
  1408.     while ((p < limit) && (*p == *mark))
  1409.       p+=4;
  1410.     count=((p-mark) >> 2);
  1411.     while (count)
  1412.     {
  1413.       runlength=count > 126 ? 126 : count;
  1414.       count-=runlength;
  1415.       *q++=runlength;
  1416.       *q++=(*mark);
  1417.     }
  1418.   }
  1419.   *q++=0;
  1420.   return(q-packets);
  1421. }
  1422.  
  1423. static unsigned int WriteIRISImage(image)
  1424. Image
  1425.   *image;
  1426. {
  1427.   typedef struct _IRISHeader
  1428.   {
  1429.     unsigned short
  1430.       magic;
  1431.  
  1432.     unsigned char
  1433.       storage,
  1434.       bytes_per_pixel;
  1435.  
  1436.     unsigned short
  1437.       dimension,
  1438.       columns,
  1439.       rows,
  1440.       depth;
  1441.  
  1442.     unsigned long
  1443.       minimum_value,
  1444.       maximum_value;
  1445.  
  1446.     unsigned char
  1447.       filler[492];
  1448.   } IRISHeader;
  1449.  
  1450.   IRISHeader
  1451.     iris_header;
  1452.  
  1453.   register int
  1454.     i,
  1455.     j,
  1456.     x,
  1457.     y,
  1458.     z;
  1459.  
  1460.   register RunlengthPacket
  1461.     *p;
  1462.  
  1463.   register unsigned char
  1464.     *q;
  1465.  
  1466.   unsigned char
  1467.     *iris_pixels,
  1468.     *packets;
  1469.  
  1470.   /*
  1471.     Open output image file.
  1472.   */
  1473.   OpenImage(image,"w");
  1474.   if (image->file == (FILE *) NULL)
  1475.     {
  1476.       Warning("Unable to open file",image->filename);
  1477.       return(False);
  1478.     }
  1479.   /*
  1480.     Initialize IRIS raster file header.
  1481.   */
  1482.   iris_header.magic=0x01DA;
  1483.   if (image->compression == NoCompression)
  1484.     iris_header.storage=0x01;
  1485.   else
  1486.     iris_header.storage=0x01;
  1487.   iris_header.bytes_per_pixel=1;  /* one byte per pixel */
  1488.   iris_header.dimension=3;
  1489.   iris_header.columns=image->columns;
  1490.   iris_header.rows=image->rows;
  1491.   iris_header.depth=image->alpha ? 4 : 3;
  1492.   if (IsGrayImage(image))
  1493.     {
  1494.       iris_header.dimension=2;
  1495.       iris_header.depth=1;
  1496.     }
  1497.   iris_header.minimum_value=0;
  1498.   iris_header.maximum_value=MaxRGB;
  1499.   for (i=0; i < sizeof(iris_header.filler); i++)
  1500.     iris_header.filler[i]=0;
  1501.   /*
  1502.     Write IRIS header.
  1503.   */
  1504.   MSBFirstWriteShort(iris_header.magic,image->file);
  1505.   (void) fputc(iris_header.storage,image->file);
  1506.   (void) fputc(iris_header.bytes_per_pixel,image->file);
  1507.   MSBFirstWriteShort(iris_header.dimension,image->file);
  1508.   MSBFirstWriteShort(iris_header.columns,image->file);
  1509.   MSBFirstWriteShort(iris_header.rows,image->file);
  1510.   MSBFirstWriteShort(iris_header.depth,image->file);
  1511.   MSBFirstWriteLong(iris_header.minimum_value,image->file);
  1512.   MSBFirstWriteLong(iris_header.maximum_value,image->file);
  1513.   (void) fwrite(iris_header.filler,1,sizeof(iris_header.filler),image->file);
  1514.   /*
  1515.     Allocate IRIS pixels.
  1516.   */
  1517.   iris_pixels=(unsigned char *)
  1518.     malloc(4*image->columns*image->rows*sizeof(unsigned char));
  1519.   if (iris_pixels == (unsigned char *) NULL)
  1520.     {
  1521.       Warning("Memory allocation error",image->filename);
  1522.       return(False);
  1523.     }
  1524.   /*
  1525.     Convert runlength-encoded packets to uncompressed IRIS pixels.
  1526.   */
  1527.   x=0;
  1528.   y=0;
  1529.   p=image->pixels;
  1530.   q=iris_pixels+(iris_header.rows-1)*(iris_header.columns*4);
  1531.   for (i=0; i < image->packets; i++)
  1532.   {
  1533.     for (j=0; j <= ((int) p->length); j++)
  1534.     {
  1535.       *q++=p->red;
  1536.       *q++=p->green;
  1537.       *q++=p->blue;
  1538.       *q++=(unsigned char) p->index;
  1539.       x++;
  1540.       if (x == image->columns)
  1541.         {
  1542.           y++;
  1543.           q=iris_pixels+((iris_header.rows-1)-y)*(iris_header.columns*4);
  1544.           x=0;
  1545.         }
  1546.     }
  1547.     p++;
  1548.   }
  1549.   if (image->compression == NoCompression)
  1550.     {
  1551.       unsigned char
  1552.         *scanline;
  1553.  
  1554.       /*
  1555.         Write uncompressed IRIS pixels.
  1556.       */
  1557.       scanline=(unsigned char *)
  1558.         malloc(iris_header.columns*sizeof(unsigned char));
  1559.       if (scanline == (unsigned char *) NULL)
  1560.         {
  1561.           Warning("Memory allocation error",image->filename);
  1562.           return(False);
  1563.         }
  1564.       for (z=0; z < (int) iris_header.depth; z++)
  1565.       {
  1566.         q=iris_pixels+z;
  1567.         for (y=0; y < (int) iris_header.rows; y++)
  1568.         {
  1569.           for (x=0; x < (int) iris_header.columns; x++)
  1570.           {
  1571.             scanline[x]=(*q);
  1572.             q+=4;
  1573.           }
  1574.           (void) fwrite(scanline,sizeof(unsigned char),iris_header.columns,
  1575.             image->file);
  1576.         }
  1577.       }
  1578.       (void) free(scanline);
  1579.     }
  1580.   else
  1581.     {
  1582.       unsigned long
  1583.         length,
  1584.         number_packets,
  1585.         offset,
  1586.         *offsets,
  1587.         *runlength;
  1588.  
  1589.       /*
  1590.         Convert IRIS uncompressed pixels to runlength-encoded pixels.
  1591.       */
  1592.       offsets=(unsigned long *)
  1593.         malloc(iris_header.rows*iris_header.depth*sizeof(unsigned long));
  1594.       packets=(unsigned char *) malloc(4*((iris_header.columns << 1)+10)*
  1595.         image->rows*sizeof(unsigned char));
  1596.       runlength=(unsigned long *)
  1597.         malloc(iris_header.rows*iris_header.depth*sizeof(unsigned long));
  1598.       if ((offsets == (unsigned long *) NULL) ||
  1599.           (packets == (unsigned char *) NULL) ||
  1600.           (runlength == (unsigned long *) NULL))
  1601.         {
  1602.           Warning("Memory allocation error",image->filename);
  1603.           return(False);
  1604.         }
  1605.       offset=512+
  1606.         ((iris_header.rows*iris_header.depth) << 1)*sizeof(unsigned long);
  1607.       number_packets=0;
  1608.       q=iris_pixels;
  1609.       for (y=0; y < (int) iris_header.rows; y++)
  1610.       {
  1611.         for (z=0; z < (int) iris_header.depth; z++)
  1612.         {
  1613.           length=
  1614.             IRISEncode(q+z,(int) iris_header.columns,packets+number_packets);
  1615.           number_packets+=length;
  1616.           offsets[y+z*iris_header.rows]=offset;
  1617.           runlength[y+z*iris_header.rows]=length;
  1618.           offset+=length;
  1619.         }
  1620.         q+=(iris_header.columns*4);
  1621.       }
  1622.       /*
  1623.         Write out line start and length tables and runlength-encoded pixels.
  1624.       */
  1625.       (void) fwrite(offsets,sizeof(unsigned long),
  1626.         iris_header.rows*iris_header.depth,image->file);
  1627.       (void) fwrite(runlength,sizeof(unsigned long),
  1628.         iris_header.rows*iris_header.depth,image->file);
  1629.       (void) fwrite(packets,sizeof(unsigned char),number_packets,image->file);
  1630.       /*
  1631.         Free memory.
  1632.       */
  1633.       (void) free(runlength);
  1634.       (void) free(packets);
  1635.       (void) free(offsets);
  1636.     }
  1637.   (void) free(iris_pixels);
  1638.   CloseImage(image);
  1639.   return(True);
  1640. }
  1641.  
  1642. #ifdef HasJPEG
  1643. #undef FREAD
  1644. #undef FWRITE
  1645. #undef const
  1646. #include "jinclude.h"
  1647. static Image
  1648.   *jpeg_image;
  1649. /*
  1650. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1651. %                                                                             %
  1652. %                                                                             %
  1653. %                                                                             %
  1654. %  W r i t e J P E G I m a g e                                                %
  1655. %                                                                             %
  1656. %                                                                             %
  1657. %                                                                             %
  1658. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1659. %
  1660. %  Function WriteJPEGImage writes a JPEG image file and returns it.  It
  1661. %  allocates the memory necessary for the new Image structure and returns a
  1662. %  pointer to the new image.
  1663. %
  1664. %  The format of the WriteJPEGImage routine is:
  1665. %
  1666. %      status=WriteJPEGImage(image,quality)
  1667. %
  1668. %  A description of each parameter follows:
  1669. %
  1670. %    o status:  Function WriteJPEGImage return True if the image is written.
  1671. %      False is returned is there is of a memory shortage or if the image
  1672. %      file cannot be opened for writing.
  1673. %
  1674. %    o jpeg_image:  A pointer to a Image structure.
  1675. %
  1676. %    o quality:  Specifies quality setting.  Quality is 0 (worst) to 100 (best).
  1677. %
  1678. %
  1679. */
  1680.  
  1681. METHODDEF void JPEGInitializeImage(jpeg_info)
  1682. compress_info_ptr
  1683.   jpeg_info;
  1684. {
  1685.   /*
  1686.     Initialize JPEG image.
  1687.   */
  1688.   jpeg_info->image_width=jpeg_image->columns;
  1689.   jpeg_info->image_height=jpeg_image->rows;
  1690.   jpeg_info->data_precision=8;
  1691.   jpeg_info->input_components=3;
  1692.   jpeg_info->in_color_space=CS_RGB;
  1693.   if (IsGrayImage(jpeg_image))
  1694.     {
  1695.       jpeg_info->input_components=1;
  1696.       jpeg_info->in_color_space=CS_GRAYSCALE;
  1697.     }
  1698.   jpeg_image->packet=jpeg_image->pixels;
  1699.   jpeg_image->runlength=jpeg_image->packet->length+1;
  1700. }
  1701.  
  1702. static void JPEGInputTermMethod(jpeg_info)
  1703. compress_info_ptr
  1704.   jpeg_info;
  1705. {
  1706. }
  1707.  
  1708. static void JPEGWriteGRAY(jpeg_info,pixel_data)
  1709. compress_info_ptr
  1710.   jpeg_info;
  1711.  
  1712. JSAMPARRAY
  1713.   pixel_data;
  1714. {
  1715.   register int
  1716.     column;
  1717.  
  1718.   register JSAMPROW
  1719.     gray;
  1720.  
  1721.   register RunlengthPacket
  1722.     *p;
  1723.  
  1724.   /*
  1725.     Convert run-length encoded grayscale MIFF packets to JPEG pixels.
  1726.   */
  1727.   gray=pixel_data[0];
  1728.   p=jpeg_image->packet;
  1729.   for (column=jpeg_info->image_width; column > 0; column--)
  1730.   {
  1731.     if (jpeg_image->runlength > 0)
  1732.       jpeg_image->runlength--;
  1733.     else
  1734.       {
  1735.         p++;
  1736.         jpeg_image->runlength=p->length;
  1737.       }
  1738.     *gray++=(JSAMPLE) p->red;
  1739.   }
  1740.   jpeg_image->packet=p;
  1741. }
  1742.  
  1743. static void JPEGWriteRGB(jpeg_info,pixel_data)
  1744. compress_info_ptr
  1745.   jpeg_info;
  1746.  
  1747. JSAMPARRAY
  1748.   pixel_data;
  1749. {
  1750.   register int
  1751.     column;
  1752.  
  1753.   register JSAMPROW
  1754.     blue,
  1755.     green,
  1756.     red;
  1757.  
  1758.   register RunlengthPacket
  1759.     *p;
  1760.  
  1761.   /*
  1762.     Convert run-length encoded MIFF packets to JPEG pixels.
  1763.   */
  1764.   red=pixel_data[0];
  1765.   green=pixel_data[1];
  1766.   blue=pixel_data[2];
  1767.   p=jpeg_image->packet;
  1768.   for (column=jpeg_info->image_width; column > 0; column--)
  1769.   {
  1770.     if (jpeg_image->runlength > 0)
  1771.       jpeg_image->runlength--;
  1772.     else
  1773.       {
  1774.         p++;
  1775.         jpeg_image->runlength=p->length;
  1776.       }
  1777.     *red++=(JSAMPLE) p->red;
  1778.     *green++=(JSAMPLE) p->green;
  1779.     *blue++=(JSAMPLE) p->blue;
  1780.   }
  1781.   jpeg_image->packet=p;
  1782. }
  1783.  
  1784. static void JPEGSelectMethod(jpeg_info)
  1785. compress_info_ptr
  1786.   jpeg_info;
  1787. {
  1788.   jpeg_info->methods->get_input_row=JPEGWriteRGB;
  1789.   if (jpeg_info->in_color_space == CS_GRAYSCALE)
  1790.     {
  1791.       j_monochrome_default(jpeg_info);
  1792.       jpeg_info->methods->get_input_row=JPEGWriteGRAY;
  1793.     }
  1794. }
  1795.  
  1796. static unsigned int WriteJPEGImage(image,quality)
  1797. Image
  1798.   *image;
  1799.  
  1800. unsigned int
  1801.   quality;
  1802. {
  1803.   struct Compress_info_struct
  1804.     jpeg_info;
  1805.  
  1806.   struct Compress_methods_struct
  1807.     jpeg_methods;
  1808.  
  1809.   struct External_methods_struct
  1810.     external_methods;
  1811.  
  1812.   /*
  1813.     Open image file.
  1814.   */
  1815.   OpenImage(image,"w");
  1816.   if (image->file == (FILE *) NULL)
  1817.     {
  1818.       Warning("Unable to open file",image->filename);
  1819.       return(False);
  1820.     }
  1821.   if (image->class == DirectClass)
  1822.     if (NumberColors(image,(FILE *) NULL) <= 256)
  1823.       {
  1824.         /*
  1825.           Demote DirectClass to PseudoClass.
  1826.         */
  1827.         QuantizeImage(image,256,8,False,RGBColorspace,True);
  1828.         SyncImage(image);
  1829.       }
  1830.   /*
  1831.     Initialize the JPEG system-dependent methods.
  1832.   */
  1833.   jpeg_image=image;
  1834.   jpeg_info.methods=(&jpeg_methods);
  1835.   jpeg_info.emethods=(&external_methods);
  1836.   jselerror(&external_methods);
  1837.   jselmemmgr(&external_methods);
  1838.   jpeg_info.methods->input_init=JPEGInitializeImage;
  1839.   jpeg_info.methods->input_term=JPEGInputTermMethod;
  1840.   jpeg_methods.c_ui_method_selection=JPEGSelectMethod;
  1841.   j_c_defaults(&jpeg_info,quality,False);
  1842.   jpeg_info.optimize_coding=True;
  1843.   jpeg_info.restart_in_rows=1;
  1844.   if ((image->class == PseudoClass) && (image->colors <= 256))
  1845.     jpeg_info.smoothing_factor=25;
  1846.   /*
  1847.     Write a JFIF JPEG file.
  1848.   */
  1849. #ifdef HUFF_LOOKAHEAD
  1850.   jpeg_info.comment_text=jpeg_image->comments;
  1851. #endif
  1852.   jpeg_info.input_file=(FILE *) NULL;
  1853.   jpeg_info.output_file=image->file;
  1854.   jselwjfif(&jpeg_info);
  1855.   jpeg_compress(&jpeg_info);
  1856.   CloseImage(image);
  1857.   return(True);
  1858. }
  1859. #else
  1860. static unsigned int WriteJPEGImage(image,quality)
  1861. Image
  1862.   *image;
  1863.  
  1864. unsigned int
  1865.   quality;
  1866. {
  1867.   unsigned int
  1868.     status;
  1869.  
  1870.   Warning("JPEG library is not available",image->filename);
  1871.   status=WriteMIFFImage(image);
  1872.   return(status);
  1873. }
  1874. #endif
  1875.  
  1876. /*
  1877. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1878. %                                                                             %
  1879. %                                                                             %
  1880. %                                                                             %
  1881. %   W r i t e M A P I m a g e                                                 %
  1882. %                                                                             %
  1883. %                                                                             %
  1884. %                                                                             %
  1885. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1886. %
  1887. %  Function WriteMAPImage writes an image to a file as red, green, and blue
  1888. %  colormap bytes followed by the colormap indexes.
  1889. %
  1890. %  The format of the WriteMAPImage routine is:
  1891. %
  1892. %      status=WriteMAPImage(image)
  1893. %
  1894. %  A description of each parameter follows.
  1895. %
  1896. %    o status: Function WriteMAPImage return True if the image is written.
  1897. %      False is returned is there is a memory shortage or if the image file
  1898. %      fails to write.
  1899. %
  1900. %    o image:  A pointer to a Image structure.
  1901. %
  1902. %
  1903. */
  1904. static unsigned int WriteMAPImage(image)
  1905. Image
  1906.   *image;
  1907. {
  1908.   register int
  1909.     i;
  1910.  
  1911.   register unsigned char
  1912.     *q;
  1913.  
  1914.   unsigned char
  1915.     *colormap;
  1916.  
  1917.   /*
  1918.     Open output image file.
  1919.   */
  1920.   OpenImage(image,"w");
  1921.   if (image->file == (FILE *) NULL)
  1922.     {
  1923.       Warning("Unable to open file",image->filename);
  1924.       return(False);
  1925.     }
  1926.   /*
  1927.     Allocate colormap.
  1928.   */
  1929.   if (image->class == DirectClass)
  1930.     {
  1931.       /*
  1932.         Demote DirectClass to PseudoClass.
  1933.       */
  1934.       QuantizeImage(image,MaxColormapSize,8,False,RGBColorspace,True);
  1935.       SyncImage(image);
  1936.     }
  1937.   colormap=(unsigned char *) malloc(3*image->colors*sizeof(unsigned char));
  1938.   if (colormap == (unsigned char *) NULL)
  1939.     {
  1940.       Warning("Unable to write image","Memory allocation failed");
  1941.       return(False);
  1942.     }
  1943.   /*
  1944.     Write colormap to file.
  1945.   */
  1946.   q=colormap;
  1947.   for (i=0; i < image->colors; i++)
  1948.   {
  1949.     *q++=image->colormap[i].red;
  1950.     *q++=image->colormap[i].green;
  1951.     *q++=image->colormap[i].blue;
  1952.   }
  1953.   (void) fwrite((char *) colormap,3,(int) image->colors,image->file);
  1954.   (void) free((char *) colormap);
  1955.   /*
  1956.     Write image pixels to file.
  1957.   */
  1958.   image->compression=NoCompression;
  1959.   (void) RunlengthEncodeImage(image);
  1960.   (void) fwrite((char *) image->packed_pixels,(int) image->packet_size,
  1961.     (int) image->packets,image->file);
  1962.   (void) free((char *) image->packed_pixels);
  1963.   image->packed_pixels=(unsigned char *) NULL;
  1964.   CloseImage(image);
  1965.   return(True);
  1966. }
  1967.  
  1968. /*
  1969. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1970. %                                                                             %
  1971. %                                                                             %
  1972. %                                                                             %
  1973. %   W r i t e M I F F I m a g e                                               %
  1974. %                                                                             %
  1975. %                                                                             %
  1976. %                                                                             %
  1977. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1978. %
  1979. %  Function WriteMIFFImage writes an image to a file.
  1980. %
  1981. %  The format of the WriteMIFFImage routine is:
  1982. %
  1983. %      status=WriteMIFFImage(image)
  1984. %
  1985. %  A description of each parameter follows:
  1986. %
  1987. %    o status: Function WriteMIFFImage return True if the image is written.
  1988. %      False is returned if there is a memory shortage or if the image file
  1989. %      fails to write.
  1990. %
  1991. %    o image: A pointer to a Image structure.
  1992. %
  1993. %
  1994. */
  1995. static unsigned int WriteMIFFImage(image)
  1996. Image
  1997.   *image;
  1998. {
  1999.   register int
  2000.     i;
  2001.  
  2002.   unsigned long
  2003.     packets;
  2004.  
  2005.   if ((image->class != DirectClass) && (image->class != PseudoClass))
  2006.     {
  2007.       Warning("Unable to write image","unknown image class");
  2008.       return(False);
  2009.     }
  2010.   if ((image->compression != RunlengthEncodedCompression) &&
  2011.       (image->compression != QEncodedCompression) &&
  2012.       (image->compression != NoCompression))
  2013.     {
  2014.       Warning("Unable to write image","unknown image compression");
  2015.       return(False);
  2016.     }
  2017.   /*
  2018.     Open output image file.
  2019.   */
  2020.   OpenImage(image,"w");
  2021.   if (image->file == (FILE *) NULL)
  2022.     {
  2023.       Warning("Unable to open file",image->filename);
  2024.       return(False);
  2025.     }
  2026.   if (image->class == DirectClass)
  2027.     if (NumberColors(image,(FILE *) NULL) <= 256)
  2028.       {
  2029.         /*
  2030.           Demote DirectClass to PseudoClass.
  2031.         */
  2032.         QuantizeImage(image,256,8,False,RGBColorspace,True);
  2033.         SyncImage(image);
  2034.       }
  2035.   /*
  2036.     Pack image pixels.
  2037.   */
  2038.   if ((image->class == PseudoClass) &&
  2039.       (image->compression == QEncodedCompression))
  2040.     image->class=DirectClass;
  2041.   (void) RunlengthEncodeImage(image);
  2042.   packets=image->packets;
  2043.   if (image->compression == QEncodedCompression)
  2044.     {
  2045.       unsigned char
  2046.         *compressed_pixels;
  2047.  
  2048.       /*
  2049.         Compress image pixels with Q encoding.
  2050.       */
  2051.       compressed_pixels=(unsigned char *)
  2052.         malloc((unsigned int) packets*image->packet_size*sizeof(unsigned char));
  2053.       if (compressed_pixels == (unsigned char *) NULL)
  2054.         {
  2055.           Warning("Unable to write image","Memory allocation failed");
  2056.           return(False);
  2057.         }
  2058.       packets=QEncodeImage(image->packed_pixels,compressed_pixels,
  2059.         image->columns*(int) image->packet_size,image->rows);
  2060.       (void) free((char *) image->packed_pixels);
  2061.       image->packed_pixels=compressed_pixels;
  2062.       image->packet_size=1;
  2063.     }
  2064.   if (image->class == PseudoClass)
  2065.     ColormapSignature(image);
  2066.   /*
  2067.     Write header to file.
  2068.   */
  2069.   if (image->comments != (char *) NULL)
  2070.     (void) fprintf(image->file,"{\n%s\n}\n",image->comments);
  2071.   (void) fprintf(image->file,"id=ImageMagick\n");
  2072.   if (image->class == PseudoClass)
  2073.     (void) fprintf(image->file,"class=PseudoClass  colors=%u  signature=%s\n",
  2074.       image->colors,image->signature);
  2075.   else
  2076.     if (image->alpha)
  2077.       (void) fprintf(image->file,"class=DirectClass  alpha=True\n");
  2078.     else
  2079.       (void) fprintf(image->file,"class=DirectClass\n");
  2080.   if (image->compression == RunlengthEncodedCompression)
  2081.     (void) fprintf(image->file,"compression=RunlengthEncoded  packets=%lu\n",
  2082.       packets);
  2083.   else
  2084.     if (image->compression == QEncodedCompression)
  2085.       (void) fprintf(image->file,"compression=QEncoded  packets=%lu\n",packets);
  2086.   (void) fprintf(image->file,"columns=%u  rows=%u\n",image->columns,
  2087.     image->rows);
  2088.   if (image->scene != 0)
  2089.     (void) fprintf(image->file,"scene=%u\n",image->scene);
  2090.   if (image->montage != (char *) NULL)
  2091.     (void) fprintf(image->file,"montage=%s\n",image->montage);
  2092.   (void) fprintf(image->file,"\f\n:\n");
  2093.   if (image->montage != (char *) NULL)
  2094.     {
  2095.       /*
  2096.         Write montage tile directory.
  2097.       */
  2098.       if (image->directory != (char *) NULL)
  2099.         (void) fprintf(image->file,"%s",image->directory);
  2100.       (void) fputc('\0',image->file);
  2101.     }
  2102.   if (image->class == PseudoClass)
  2103.     {
  2104.       register unsigned char
  2105.         *q;
  2106.  
  2107.       unsigned char
  2108.         *colormap;
  2109.  
  2110.       /*
  2111.         Allocate colormap.
  2112.       */
  2113.       colormap=(unsigned char *) malloc(3*image->colors*sizeof(unsigned char));
  2114.       if (colormap == (unsigned char *) NULL)
  2115.         {
  2116.           Warning("Unable to write image","Memory allocation failed");
  2117.           return(False);
  2118.         }
  2119.       q=colormap;
  2120.       for (i=0; i < image->colors; i++)
  2121.       {
  2122.         *q++=image->colormap[i].red;
  2123.         *q++=image->colormap[i].green;
  2124.         *q++=image->colormap[i].blue;
  2125.       }
  2126.       /*
  2127.         Write colormap to file.
  2128.       */
  2129.       (void) fwrite((char *) colormap,3,(int) image->colors,image->file);
  2130.       (void) free((char *) colormap);
  2131.     }
  2132.   /*
  2133.     Write image pixels to file.
  2134.   */
  2135.   (void) fwrite((char *) image->packed_pixels,(int) image->packet_size,
  2136.     (int) packets,image->file);
  2137.   (void) free((char *) image->packed_pixels);
  2138.   image->packed_pixels=(unsigned char *) NULL;
  2139.   CloseImage(image);
  2140.   return(True);
  2141. }
  2142.  
  2143. /*
  2144. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  2145. %                                                                             %
  2146. %                                                                             %
  2147. %                                                                             %
  2148. %   W r i t e M T V I m a g e                                                 %
  2149. %                                                                             %
  2150. %                                                                             %
  2151. %                                                                             %
  2152. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  2153. %
  2154. %  Function WriteMTVImage writes an image to a file in red, green, and blue
  2155. %  MTV rasterfile format.
  2156. %
  2157. %  The format of the WriteMTVImage routine is:
  2158. %
  2159. %      status=WriteMTVImage(image)
  2160. %
  2161. %  A description of each parameter follows.
  2162. %
  2163. %    o status: Function WriteMTVImage return True if the image is written.
  2164. %      False is returned is there is a memory shortage or if the image file
  2165. %      fails to write.
  2166. %
  2167. %    o image:  A pointer to a Image structure.
  2168. %
  2169. %
  2170. */
  2171. static unsigned int WriteMTVImage(image)
  2172. Image
  2173.   *image;
  2174. {
  2175.   register int
  2176.     i,
  2177.     j;
  2178.  
  2179.   register RunlengthPacket
  2180.     *p;
  2181.  
  2182.   register unsigned char
  2183.     *q;
  2184.  
  2185.   unsigned char
  2186.     *mtv_pixels;
  2187.  
  2188.   /*
  2189.     Open output image file.
  2190.   */
  2191.   OpenImage(image,"w");
  2192.   if (image->file == (FILE *) NULL)
  2193.     {
  2194.       Warning("Unable to open file",image->filename);
  2195.       return(False);
  2196.     }
  2197.   /*
  2198.     Convert MIFF to MTV raster pixels.
  2199.   */
  2200.   mtv_pixels=(unsigned char *)
  2201.     malloc(3*image->columns*image->rows*sizeof(unsigned char));
  2202.   if (mtv_pixels == (unsigned char *) NULL)
  2203.     {
  2204.       Warning("Unable to allocate memory",(char *) NULL);
  2205.       return(False);
  2206.     }
  2207.   p=image->pixels;
  2208.   q=mtv_pixels;
  2209.   for (i=0; i < image->packets; i++)
  2210.   {
  2211.     for (j=0; j <= ((int) p->length); j++)
  2212.     {
  2213.       *q++=p->red;
  2214.       *q++=p->green;
  2215.       *q++=p->blue;
  2216.     }
  2217.     p++;
  2218.   }
  2219.   (void) fprintf(image->file,"%u %u\n",image->columns,image->rows);
  2220.   (void) fwrite((char *) mtv_pixels,3,(int) (image->columns*image->rows),
  2221.     image->file);
  2222.   (void) free((char *) mtv_pixels);
  2223.   CloseImage(image);
  2224.   return(True);
  2225. }
  2226.  
  2227. /*
  2228. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  2229. %                                                                             %
  2230. %                                                                             %
  2231. %                                                                             %
  2232. %   W r i t e P C D I m a g e                                                 %
  2233. %                                                                             %
  2234. %                                                                             %
  2235. %                                                                             %
  2236. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  2237. %
  2238. %  Function WritePCDImage writes an image in the Photo CD encoded image
  2239. %  format.
  2240. %
  2241. %  The format of the WritePCDImage routine is:
  2242. %
  2243. %      status=WritePCDImage(image)
  2244. %
  2245. %  A description of each parameter follows.
  2246. %
  2247. %    o status: Function WritePCDImage return True if the image is written.
  2248. %      False is returned is there is a memory shortage or if the image file
  2249. %      fails to write.
  2250. %
  2251. %    o image:  A pointer to a Image structure.
  2252. %
  2253. %
  2254. */
  2255. static unsigned int WritePCDImage(image)
  2256. Image
  2257.   *image;
  2258. {
  2259.   unsigned int
  2260.     status;
  2261.  
  2262.   Warning("Cannot write PCD images",image->filename);
  2263.   status=WriteMIFFImage(image);
  2264.   return(status);
  2265. }
  2266.  
  2267. /*
  2268. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  2269. %                                                                             %
  2270. %                                                                             %
  2271. %                                                                             %
  2272. %   W r i t e P C X I m a g e                                                 %
  2273. %                                                                             %
  2274. %                                                                             %
  2275. %                                                                             %
  2276. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  2277. %
  2278. %  Function WritePCXImage writes an image in the ZSoft IBM PC Paintbrush file
  2279. %  format.
  2280. %
  2281. %  The format of the WritePCXImage routine is:
  2282. %
  2283. %      status=WritePCXImage(image)
  2284. %
  2285. %  A description of each parameter follows.
  2286. %
  2287. %    o status: Function WritePCXImage return True if the image is written.
  2288. %      False is returned is there is a memory shortage or if the image file
  2289. %      fails to write.
  2290. %
  2291. %    o image:  A pointer to a Image structure.
  2292. %
  2293. %
  2294. */
  2295. static unsigned int WritePCXImage(image)
  2296. Image
  2297.   *image;
  2298. {
  2299.   typedef struct _PCXHeader
  2300.   {
  2301.     unsigned char
  2302.       identifier,
  2303.       version,
  2304.       encoding,
  2305.       bits_per_pixel;
  2306.  
  2307.     short int
  2308.       left,
  2309.       top,
  2310.       right,
  2311.       bottom,
  2312.       horizontal_resolution,
  2313.       vertical_resolution;
  2314.  
  2315.     unsigned char
  2316.       reserved,
  2317.       planes;
  2318.  
  2319.     short int
  2320.       bytes_per_line,
  2321.       palette_info;
  2322.  
  2323.     unsigned char
  2324.       colormap_signature;
  2325.   } PCXHeader;
  2326.  
  2327.   PCXHeader
  2328.     pcx_header;
  2329.  
  2330.   register int
  2331.     i,
  2332.     j,
  2333.     x,
  2334.     y;
  2335.  
  2336.   register RunlengthPacket
  2337.     *p;
  2338.  
  2339.   register unsigned char
  2340.     *q;
  2341.  
  2342.   unsigned char
  2343.     count,
  2344.     packet,
  2345.     *pcx_colormap,
  2346.     *pcx_pixels,
  2347.     previous;
  2348.  
  2349.   /*
  2350.     Open output image file.
  2351.   */
  2352.   OpenImage(image,"w");
  2353.   if (image->file == (FILE *) NULL)
  2354.     {
  2355.       Warning("Unable to open file",image->filename);
  2356.       return(False);
  2357.     }
  2358.   if ((image->class == DirectClass) || (image->colors > 256))
  2359.     {
  2360.       /*
  2361.         Demote DirectClass to PseudoClass.
  2362.       */
  2363.       QuantizeImage(image,256,8,True,RGBColorspace,True);
  2364.       SyncImage(image);
  2365.     }
  2366.   /*
  2367.     Initialize PCX raster file header.
  2368.   */
  2369.   pcx_header.identifier=0x0a;
  2370.   pcx_header.version=5;
  2371.   pcx_header.encoding=1;
  2372.   pcx_header.bits_per_pixel=8;
  2373.   if (IsGrayImage(image) && (image->colors == 2))
  2374.     pcx_header.bits_per_pixel=1;
  2375.   pcx_header.left=0;
  2376.   pcx_header.top=0;
  2377.   pcx_header.right=image->columns-1;
  2378.   pcx_header.bottom=image->rows-1;
  2379.   pcx_header.horizontal_resolution=image->columns;
  2380.   pcx_header.vertical_resolution=image->rows;
  2381.   pcx_header.reserved=0;
  2382.   pcx_header.planes=1;
  2383.   pcx_header.bytes_per_line=(image->columns*pcx_header.bits_per_pixel+7)/8;
  2384.   pcx_header.palette_info=1;
  2385.   pcx_header.colormap_signature=0x0c;
  2386.   /*
  2387.     Write PCX header.
  2388.   */
  2389.   (void) fwrite(&pcx_header.identifier,1,1,image->file);
  2390.   (void) fwrite(&pcx_header.version,1,1,image->file);
  2391.   (void) fwrite(&pcx_header.encoding,1,1,image->file);
  2392.   (void) fwrite(&pcx_header.bits_per_pixel,1,1,image->file);
  2393.   LSBFirstWriteShort((unsigned int) pcx_header.left,image->file);
  2394.   LSBFirstWriteShort((unsigned int) pcx_header.top,image->file);
  2395.   LSBFirstWriteShort((unsigned int) pcx_header.right,image->file);
  2396.   LSBFirstWriteShort((unsigned int) pcx_header.bottom,image->file);
  2397.   LSBFirstWriteShort((unsigned int) pcx_header.horizontal_resolution,
  2398.     image->file);
  2399.   LSBFirstWriteShort((unsigned int) pcx_header.vertical_resolution,image->file);
  2400.   /*
  2401.     Dump colormap to file.
  2402.   */
  2403.   pcx_colormap=(unsigned char *) malloc(3*256*sizeof(unsigned char));
  2404.   if (pcx_colormap == (unsigned char *) NULL)
  2405.     {
  2406.       Warning("Unable to allocate memory",(char *) NULL);
  2407.       return(False);
  2408.     }
  2409.   q=pcx_colormap;
  2410.   for (i=0; i < image->colors; i++)
  2411.   {
  2412.     *q++=image->colormap[i].red;
  2413.     *q++=image->colormap[i].green;
  2414.     *q++=image->colormap[i].blue;
  2415.   }
  2416.   (void) fwrite((char *) pcx_colormap,3,16,image->file);
  2417.   (void) fwrite(&pcx_header.reserved,1,1,image->file);
  2418.   (void) fwrite(&pcx_header.planes,1,1,image->file);
  2419.   LSBFirstWriteShort((unsigned int) pcx_header.bytes_per_line,image->file);
  2420.   LSBFirstWriteShort((unsigned int) pcx_header.palette_info,image->file);
  2421.   for (i=0; i < 58; i++)
  2422.     (void) fwrite("\0",1,1,image->file);
  2423.   /*
  2424.     Convert MIFF to PCX raster pixels.
  2425.   */
  2426.   pcx_pixels=(unsigned char *)
  2427.     malloc(pcx_header.bytes_per_line*image->rows*sizeof(unsigned char));
  2428.   if (pcx_pixels == (unsigned char *) NULL)
  2429.     {
  2430.       Warning("Unable to allocate memory",(char *) NULL);
  2431.       return(False);
  2432.     }
  2433.   x=0;
  2434.   y=0;
  2435.   p=image->pixels;
  2436.   q=pcx_pixels;
  2437.   if (pcx_header.bits_per_pixel > 1)
  2438.     for (i=0; i < image->packets; i++)
  2439.     {
  2440.       for (j=0; j <= (int) p->length; j++)
  2441.       {
  2442.         *q++=p->index;
  2443.         x++;
  2444.         if (x == image->columns)
  2445.           {
  2446.             x=0;
  2447.             y++;
  2448.             q=pcx_pixels+y*pcx_header.bytes_per_line;
  2449.           }
  2450.       }
  2451.       p++;
  2452.     }
  2453.   else
  2454.     {
  2455.       register unsigned char
  2456.         bit,
  2457.         byte;
  2458.  
  2459.       /*
  2460.         Convert PseudoClass image to a PCX monochrome image.
  2461.       */
  2462.       bit=0;
  2463.       byte=0;
  2464.       for (i=0; i < image->packets; i++)
  2465.       {
  2466.         for (j=0; j <= (int) p->length; j++)
  2467.         {
  2468.           byte<<=1;
  2469.           if (p->index == 1)
  2470.             byte|=0x01;
  2471.           bit++;
  2472.           if (bit == 8)
  2473.             {
  2474.               *q++=byte;
  2475.               bit=0;
  2476.               byte=0;
  2477.             }
  2478.           x++;
  2479.           if (x == image->columns)
  2480.             {
  2481.               /*
  2482.                 Advance to the next scanline.
  2483.               */
  2484.               if (bit != 0)
  2485.                 *q++=byte << (8-bit);
  2486.               bit=0;
  2487.               byte=0;
  2488.               x=0;
  2489.               y++;
  2490.               q=pcx_pixels+y*pcx_header.bytes_per_line;
  2491.            }
  2492.         }
  2493.         p++;
  2494.       }
  2495.     }
  2496.   /*
  2497.     Runlength-encoded PCX pixels.
  2498.   */
  2499.   for (y=0; y < image->rows; y++)
  2500.   {
  2501.     q=pcx_pixels+y*pcx_header.bytes_per_line;
  2502.     previous=(*q++);
  2503.     count=1;
  2504.     for (x=0; x < (pcx_header.bytes_per_line-1); x++)
  2505.     {
  2506.       packet=(*q++);
  2507.       if ((packet == previous) && (count < 63))
  2508.         {
  2509.           count++;
  2510.           continue;
  2511.         }
  2512.       if ((count > 1) || ((previous & 0xc0) == 0xc0))
  2513.         {
  2514.           count|=0xc0;
  2515.           (void) fwrite(&count,1,1,image->file);
  2516.         }
  2517.       (void) fwrite(&previous,1,1,image->file);
  2518.       previous=packet;
  2519.       count=1;
  2520.     }
  2521.     if ((count > 1) || ((previous & 0xc0) == 0xc0))
  2522.       {
  2523.         count|=0xc0;
  2524.         (void) fwrite(&count,1,1,image->file);
  2525.       }
  2526.     (void) fwrite(&previous,1,1,image->file);
  2527.   }
  2528.   if (image->colors > 16)
  2529.     {
  2530.       (void) fwrite(&pcx_header.colormap_signature,1,1,image->file);
  2531.       (void) fwrite((char *) pcx_colormap,3,256,image->file);
  2532.     }
  2533.   (void) free((char *) pcx_pixels);
  2534.   (void) free((char *) pcx_colormap);
  2535.   CloseImage(image);
  2536.   return(True);
  2537. }
  2538.  
  2539. /*
  2540. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  2541. %                                                                             %
  2542. %                                                                             %
  2543. %                                                                             %
  2544. %   W r i t e P I C T I m a g e                                               %
  2545. %                                                                             %
  2546. %                                                                             %
  2547. %                                                                             %
  2548. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  2549. %
  2550. %  Function WritePICTImage writes an image to a file in the Apple Macintosh
  2551. %  QuickDraw/PICT image format.
  2552. %
  2553. %  The format of the WritePICTImage routine is:
  2554. %
  2555. %      status=WritePICTImage(image)
  2556. %
  2557. %  A description of each parameter follows.
  2558. %
  2559. %    o status: Function WritePICTImage return True if the image is written.
  2560. %      False is returned is there is a memory shortage or if the image file
  2561. %      fails to write.
  2562. %
  2563. %    o image:  A pointer to a Image structure.
  2564. %
  2565. %
  2566. */
  2567. static unsigned int WritePICTImage(image)
  2568. Image
  2569.   *image;
  2570. {
  2571. #define MaxCount  128
  2572. #define PictClipRegionOp  0x01
  2573. #define PictEndOfPictureOp  0xff
  2574. #define PictHeaderOp  0x0C00
  2575. #define PictHeaderSize  512
  2576. #define PictPixmapOp  0x9A
  2577. #define PictPackbitsOp  0x98
  2578. #define PictVersion  0x11
  2579.  
  2580.   typedef struct _PICTRectangle
  2581.   {
  2582.     unsigned short
  2583.       top,
  2584.       left,
  2585.       bottom,
  2586.       right;
  2587.   } PICTRectangle;
  2588.  
  2589.   typedef struct _PICTPixmap
  2590.   {
  2591.     unsigned short
  2592.       base_address,
  2593.       row_bytes;
  2594.  
  2595.     PICTRectangle
  2596.       bounds;
  2597.  
  2598.     unsigned short
  2599.       version,
  2600.       pack_type;
  2601.  
  2602.     unsigned long
  2603.       pack_size,
  2604.       horizontal_resolution,
  2605.       vertical_resolution;
  2606.  
  2607.     unsigned short
  2608.       pixel_type,
  2609.       pixel_size,
  2610.       component_count,
  2611.       component_size;
  2612.  
  2613.     unsigned short
  2614.       plane_bytes,
  2615.       table,
  2616.       reserved;
  2617.   } PICTPixmap;
  2618.  
  2619.   int
  2620.     count;
  2621.  
  2622.   PICTPixmap
  2623.     pixmap;
  2624.  
  2625.   PICTRectangle
  2626.     clip_rectangle,
  2627.     destination_rectangle,
  2628.     frame_rectangle,
  2629.     size_rectangle,
  2630.     source_rectangle;
  2631.  
  2632.   register int
  2633.     i,
  2634.     j,
  2635.     x;
  2636.  
  2637.   register RunlengthPacket
  2638.     *p;
  2639.  
  2640.   unsigned char
  2641.     *buffer,
  2642.     *packed_scanline,
  2643.     *scanline;
  2644.  
  2645.   unsigned int
  2646.     bytes_per_line;
  2647.  
  2648.   unsigned short
  2649.     transfer_mode;
  2650.  
  2651.   unsigned long
  2652.     horizontal_resolution,
  2653.     vertical_resolution;
  2654.  
  2655.   /*
  2656.     Open output image file.
  2657.   */
  2658.   OpenImage(image,"w");
  2659.   if (image->file == (FILE *) NULL)
  2660.     {
  2661.       Warning("Unable to open file",image->filename);
  2662.       return(False);
  2663.     }
  2664.   if (image->class == DirectClass)
  2665.     if (NumberColors(image,(FILE *) NULL) <= 256)
  2666.       {
  2667.         /*
  2668.           Demote DirectClass to PseudoClass.
  2669.         */
  2670.         QuantizeImage(image,256,8,False,RGBColorspace,True);
  2671.         SyncImage(image);
  2672.       }
  2673.   /*
  2674.     Allocate memory.
  2675.   */
  2676.   bytes_per_line=image->columns;
  2677.   if (image->class == DirectClass)
  2678.     bytes_per_line*=3;
  2679.   buffer=(unsigned char *) malloc(PictHeaderSize*sizeof(unsigned char));
  2680.   packed_scanline=(unsigned char *)
  2681.     malloc((bytes_per_line+bytes_per_line/MaxCount+1)*sizeof(unsigned char));
  2682.   scanline=(unsigned char *) malloc(bytes_per_line*sizeof(unsigned char));
  2683.   if ((buffer == (unsigned char *) NULL) ||
  2684.       (packed_scanline == (unsigned char *) NULL) ||
  2685.       (scanline == (unsigned char *) NULL))
  2686.     {
  2687.       Warning("Unable to allocate memory",(char *) NULL);
  2688.       return(False);
  2689.     }
  2690.   /*
  2691.     Initialize image info.
  2692.   */
  2693.   size_rectangle.top=0;
  2694.   size_rectangle.left=0;
  2695.   size_rectangle.right=image->rows;
  2696.   size_rectangle.bottom=image->columns;
  2697.   frame_rectangle=size_rectangle;
  2698.   clip_rectangle=size_rectangle;
  2699.   source_rectangle=size_rectangle;
  2700.   destination_rectangle=size_rectangle;
  2701.   horizontal_resolution=0x00480000;
  2702.   vertical_resolution=0x00480000;
  2703.   pixmap.base_address=0xff;
  2704.   pixmap.row_bytes=
  2705.     ((image->class == DirectClass ? 4 : 1)*image->columns) | 0x8000;
  2706.   pixmap.version=0;
  2707.   pixmap.bounds.top=0;
  2708.   pixmap.bounds.left=0;
  2709.   pixmap.bounds.right=image->rows;
  2710.   pixmap.bounds.bottom=image->columns;
  2711.   pixmap.pack_type=(image->class == DirectClass ? 0x4 : 0x0);
  2712.   pixmap.pack_size=0;
  2713.   pixmap.horizontal_resolution=horizontal_resolution;
  2714.   pixmap.vertical_resolution=vertical_resolution;
  2715.   pixmap.pixel_type=(image->class == DirectClass ? 16 : 0);
  2716.   pixmap.pixel_size=(image->class == DirectClass ? 32 : 8);
  2717.   pixmap.component_count=(image->class == DirectClass ? 3 : 1);
  2718.   pixmap.component_size=8;
  2719.   pixmap.plane_bytes=0;
  2720.   pixmap.table=0;
  2721.   pixmap.reserved=0;
  2722.   transfer_mode=(image->class == DirectClass ? 0x40 : 0);
  2723.   /*
  2724.     Write header, header size, size bounding box, version, and reserved.
  2725.   */
  2726.   for (i=0; i < PictHeaderSize; i++)
  2727.     buffer[i]=0;
  2728.   (void) fwrite((char *) buffer,1,PictHeaderSize,image->file);
  2729.   MSBFirstWriteShort(0,image->file);
  2730.   MSBFirstWriteShort(size_rectangle.top,image->file);
  2731.   MSBFirstWriteShort(size_rectangle.left,image->file);
  2732.   MSBFirstWriteShort(size_rectangle.right,image->file);
  2733.   MSBFirstWriteShort(size_rectangle.bottom,image->file);
  2734.   MSBFirstWriteShort(PictVersion,image->file);
  2735.   MSBFirstWriteShort(0x02FF,image->file);
  2736.   MSBFirstWriteShort(PictHeaderOp,image->file);
  2737.   /*
  2738.     Write full size of the file, resolution, frame bounding box, and reserved.
  2739.   */
  2740.   MSBFirstWriteLong(0xFFFE0000L,image->file);
  2741.   MSBFirstWriteLong(horizontal_resolution,image->file);
  2742.   MSBFirstWriteLong(vertical_resolution,image->file);
  2743.   MSBFirstWriteShort(frame_rectangle.top,image->file);
  2744.   MSBFirstWriteShort(frame_rectangle.left,image->file);
  2745.   MSBFirstWriteShort(frame_rectangle.right,image->file);
  2746.   MSBFirstWriteShort(frame_rectangle.bottom,image->file);
  2747.   MSBFirstWriteLong(0L,image->file);
  2748.   /*
  2749.     Write clip region opcode and clip bounding box.
  2750.   */
  2751.   MSBFirstWriteShort(PictClipRegionOp,image->file);
  2752.   MSBFirstWriteShort(0xA,image->file);
  2753.   MSBFirstWriteShort(clip_rectangle.top,image->file);
  2754.   MSBFirstWriteShort(clip_rectangle.left,image->file);
  2755.   MSBFirstWriteShort(clip_rectangle.right,image->file);
  2756.   MSBFirstWriteShort(clip_rectangle.bottom,image->file);
  2757.   /*
  2758.     Write picture opcode, row bytes, and picture bounding box, and version.
  2759.   */
  2760.   if (image->class == PseudoClass)
  2761.     MSBFirstWriteShort(PictPackbitsOp,image->file);
  2762.   else
  2763.     {
  2764.       MSBFirstWriteShort(PictPixmapOp,image->file);
  2765.       MSBFirstWriteLong((unsigned long) pixmap.base_address,image->file);
  2766.     }
  2767.   if (pixmap.row_bytes & 0x01)
  2768.     pixmap.row_bytes++;
  2769.   MSBFirstWriteShort(pixmap.row_bytes | 0x8000,image->file);
  2770.   MSBFirstWriteShort(pixmap.bounds.top,image->file);
  2771.   MSBFirstWriteShort(pixmap.bounds.left,image->file);
  2772.   MSBFirstWriteShort(pixmap.bounds.right,image->file);
  2773.   MSBFirstWriteShort(pixmap.bounds.bottom,image->file);
  2774.   MSBFirstWriteShort(pixmap.version,image->file);
  2775.   /*
  2776.     Write pack type, pack size, resolution, pixel type, and pixel size.
  2777.   */
  2778.   MSBFirstWriteShort(pixmap.pack_type,image->file);
  2779.   MSBFirstWriteLong(pixmap.pack_size,image->file);
  2780.   MSBFirstWriteLong(pixmap.horizontal_resolution,image->file);
  2781.   MSBFirstWriteLong(pixmap.vertical_resolution,image->file);
  2782.   MSBFirstWriteShort(pixmap.pixel_type,image->file);
  2783.   MSBFirstWriteShort(pixmap.pixel_size,image->file);
  2784.   /*
  2785.     Write component count, size, plane bytes, table size, and reserved.
  2786.   */
  2787.   MSBFirstWriteShort(pixmap.component_count,image->file);
  2788.   MSBFirstWriteShort(pixmap.component_size,image->file);
  2789.   MSBFirstWriteLong((unsigned long) pixmap.plane_bytes,image->file);
  2790.   MSBFirstWriteLong((unsigned long) pixmap.table,image->file);
  2791.   MSBFirstWriteLong((unsigned long) pixmap.reserved,image->file);
  2792.   if (image->class == PseudoClass)
  2793.     {
  2794.       unsigned short
  2795.         red,
  2796.         green,
  2797.         blue;
  2798.  
  2799.       /*
  2800.         Write image colormap.
  2801.       */
  2802.       MSBFirstWriteLong(0L,image->file);  /* color seed */
  2803.       MSBFirstWriteShort(0L,image->file);  /* color flags */
  2804.       MSBFirstWriteShort((unsigned short) (image->colors-1),image->file);
  2805.       for (i=0; i < image->colors; i++)
  2806.       {
  2807.         red=(image->colormap[i].red*65535)/(unsigned int) MaxRGB;
  2808.         green=(image->colormap[i].green*65535)/(unsigned int) MaxRGB;
  2809.         blue=(image->colormap[i].blue*65535)/(unsigned int) MaxRGB;
  2810.         MSBFirstWriteShort((unsigned int) i,image->file);
  2811.         MSBFirstWriteShort(red,image->file);
  2812.         MSBFirstWriteShort(green,image->file);
  2813.         MSBFirstWriteShort(blue,image->file);
  2814.       }
  2815.     }
  2816.   /*
  2817.     Write source and destination rectangle.
  2818.   */
  2819.   MSBFirstWriteShort(source_rectangle.top,image->file);
  2820.   MSBFirstWriteShort(source_rectangle.left,image->file);
  2821.   MSBFirstWriteShort(source_rectangle.right,image->file);
  2822.   MSBFirstWriteShort(source_rectangle.bottom,image->file);
  2823.   MSBFirstWriteShort(destination_rectangle.top,image->file);
  2824.   MSBFirstWriteShort(destination_rectangle.left,image->file);
  2825.   MSBFirstWriteShort(destination_rectangle.right,image->file);
  2826.   MSBFirstWriteShort(destination_rectangle.bottom,image->file);
  2827.   MSBFirstWriteShort(transfer_mode,image->file);
  2828.   /*
  2829.     Write picture data.
  2830.   */
  2831.   count=0;
  2832.   x=0;
  2833.   p=image->pixels;
  2834.   if (image->class == PseudoClass)
  2835.     {
  2836.       register unsigned char
  2837.         *index;
  2838.  
  2839.       index=scanline;
  2840.       for (i=0; i < image->packets; i++)
  2841.       {
  2842.         for (j=0; j <= (int) p->length; j++)
  2843.         {
  2844.           *index++=(unsigned char) p->index;
  2845.           x++;
  2846.           if (x == image->columns)
  2847.             {
  2848.               count+=PackbitsEncodeImage(image,scanline,packed_scanline);
  2849.               index=scanline;
  2850.               x=0;
  2851.             }
  2852.         }
  2853.         p++;
  2854.       }
  2855.     }
  2856.   else
  2857.     {
  2858.       register unsigned char
  2859.         *blue,
  2860.         *red,
  2861.         *green;
  2862.  
  2863.       red=scanline;
  2864.       green=scanline+image->columns;
  2865.       blue=scanline+(image->columns << 1);
  2866.       for (i=0; i < image->packets; i++)
  2867.       {
  2868.         for (j=0; j <= (int) p->length; j++)
  2869.         {
  2870.           *red++=p->red;
  2871.           *green++=p->green;
  2872.           *blue++=p->blue;
  2873.           x++;
  2874.           if (x == image->columns)
  2875.             {
  2876.               red=scanline;
  2877.               green=scanline+image->columns;
  2878.               blue=scanline+(image->columns << 1);
  2879.               count+=PackbitsEncodeImage(image,red,packed_scanline);
  2880.               x=0;
  2881.             }
  2882.         }
  2883.         p++;
  2884.       }
  2885.     }
  2886.   if (count & 0x1)
  2887.     (void) fputc('\0',image->file);
  2888.   MSBFirstWriteShort(PictEndOfPictureOp,image->file);
  2889.   (void) free((char *) scanline);
  2890.   (void) free((char *) packed_scanline);
  2891.   (void) free((char *) buffer);
  2892.   CloseImage(image);
  2893.   return(True);
  2894. }
  2895.  
  2896. /*
  2897. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  2898. %                                                                             %
  2899. %                                                                             %
  2900. %                                                                             %
  2901. %   W r i t e P N M I m a g e                                                 %
  2902. %                                                                             %
  2903. %                                                                             %
  2904. %                                                                             %
  2905. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  2906. %
  2907. %  Procedure WritePNMImage writes an image to a file in the PNM rasterfile
  2908. %  format.
  2909. %
  2910. %  The format of the WritePNMImage routine is:
  2911. %
  2912. %      status=WritePNMImage(image)
  2913. %
  2914. %  A description of each parameter follows.
  2915. %
  2916. %    o status: Function WritePNMImage return True if the image is written.
  2917. %      False is returned is there is a memory shortage or if the image file
  2918. %      fails to write.
  2919. %
  2920. %    o image:  A pointer to a Image structure.
  2921. %
  2922. %
  2923. */
  2924. static unsigned int WritePNMImage(image)
  2925. Image
  2926.   *image;
  2927. {
  2928.   register int
  2929.     i,
  2930.     j;
  2931.  
  2932.   register RunlengthPacket
  2933.     *p;
  2934.  
  2935.   register unsigned char
  2936.     *q;
  2937.  
  2938.   unsigned char
  2939.     format,
  2940.     *pnm_pixels;
  2941.  
  2942.   unsigned int
  2943.     packets;
  2944.  
  2945.   /*
  2946.     Open output image file.
  2947.   */
  2948.   OpenImage(image,"w");
  2949.   if (image->file == (FILE *) NULL)
  2950.     {
  2951.       Warning("Unable to open file",image->filename);
  2952.       return(False);
  2953.     }
  2954.   /*
  2955.     Promote/Demote image based on image type.
  2956.   */
  2957.   if (strcmp(image->magick,"PPM") == 0)
  2958.     image->class=DirectClass;
  2959.   else
  2960.     if (strcmp(image->magick,"PGM") == 0)
  2961.       {
  2962.         QuantizeImage(image,256,8,False,GRAYColorspace,True);
  2963.         SyncImage(image);
  2964.       }
  2965.     else
  2966.       if (strcmp(image->magick,"PBM") == 0)
  2967.         {
  2968.           QuantizeImage(image,2,8,False,GRAYColorspace,True);
  2969.           SyncImage(image);
  2970.         }
  2971.       else
  2972.         if (image->class == DirectClass)
  2973.           if (NumberColors(image,(FILE *) NULL) <= 256)
  2974.             {
  2975.               /*
  2976.                 Demote DirectClass to PseudoClass.
  2977.               */
  2978.               QuantizeImage(image,256,8,False,RGBColorspace,True);
  2979.               SyncImage(image);
  2980.             }
  2981.   /*
  2982.     Write PNM file header.
  2983.   */
  2984.   packets=image->columns*image->rows;
  2985.   if ((image->class == DirectClass) || (image->colors > 256))
  2986.     {
  2987.       /*
  2988.         Full color PNM image.
  2989.       */
  2990.       format='6';
  2991.       packets*=3;
  2992.     }
  2993.   else
  2994.     {
  2995.       /*
  2996.         Colormapped PNM image.
  2997.       */
  2998.       format='6';
  2999.       if (!IsGrayImage(image))
  3000.         packets*=3;
  3001.       else
  3002.         {
  3003.           /*
  3004.             Grayscale PNM image.
  3005.           */
  3006.           format='5';
  3007.           if (image->colors == 2)
  3008.             format='4';
  3009.         }
  3010.     }
  3011.   (void) fprintf(image->file,"P%c\n",format);
  3012.   if (image->comments != (char *) NULL)
  3013.     {
  3014.       register char
  3015.         *p;
  3016.  
  3017.       /*
  3018.         Write comments to file.
  3019.       */
  3020.       (void) fprintf(image->file,"# ");
  3021.       for (p=image->comments; *p != '\0'; p++)
  3022.       {
  3023.         (void) fputc(*p,image->file);
  3024.         if (*p == '\n')
  3025.           (void) fprintf(image->file,"# ");
  3026.       }
  3027.       (void) fputc('\n',image->file);
  3028.     }
  3029.   (void) fprintf(image->file,"%u %u\n",image->columns,image->rows);
  3030.   /*
  3031.     Convert MIFF to PNM raster pixels.
  3032.   */
  3033.   pnm_pixels=(unsigned char *) malloc(packets*sizeof(unsigned char));
  3034.   if (pnm_pixels == (unsigned char *) NULL)
  3035.     {
  3036.       Warning("Unable to allocate memory",(char *) NULL);
  3037.       return(False);
  3038.     }
  3039.   p=image->pixels;
  3040.   q=pnm_pixels;
  3041.   switch (format)
  3042.   {
  3043.     case '4':
  3044.     {
  3045.       register unsigned char
  3046.         bit,
  3047.         byte;
  3048.  
  3049.       unsigned int
  3050.         x;
  3051.  
  3052.       /*
  3053.         Convert image to a PBM image.
  3054.       */
  3055.       bit=0;
  3056.       byte=0;
  3057.       x=0;
  3058.       for (i=0; i < image->packets; i++)
  3059.       {
  3060.         for (j=0; j <= (int) p->length; j++)
  3061.         {
  3062.           byte<<=1;
  3063.           if (p->index == 0)
  3064.             byte|=0x01;
  3065.           bit++;
  3066.           if (bit == 8)
  3067.             {
  3068.               *q++=byte;
  3069.               bit=0;
  3070.               byte=0;
  3071.             }
  3072.           x++;
  3073.           if (x == image->columns)
  3074.             {
  3075.               /*
  3076.                 Advance to the next scanline.
  3077.               */
  3078.               if (bit != 0)
  3079.                 *q++=byte << (8-bit);
  3080.               bit=0;
  3081.               byte=0;
  3082.               x=0;
  3083.            }
  3084.         }
  3085.         p++;
  3086.       }
  3087.       packets=q-pnm_pixels;
  3088.       break;
  3089.     }
  3090.     case '5':
  3091.     {
  3092.       /*
  3093.         Convert image to a PGM image.
  3094.       */
  3095.       (void) fprintf(image->file,"%d\n",MaxRGB);
  3096.       for (i=0; i < image->packets; i++)
  3097.       {
  3098.         for (j=0; j <= ((int) p->length); j++)
  3099.           *q++=image->colormap[p->index].red;
  3100.         p++;
  3101.       }
  3102.       break;
  3103.     }
  3104.     case '6':
  3105.     {
  3106.       /*
  3107.         Convert image to a PNM image.
  3108.       */
  3109.       (void) fprintf(image->file,"%d\n",MaxRGB);
  3110.       for (i=0; i < image->packets; i++)
  3111.       {
  3112.         for (j=0; j <= ((int) p->length); j++)
  3113.         {
  3114.           *q++=p->red;
  3115.           *q++=p->green;
  3116.           *q++=p->blue;
  3117.         }
  3118.         p++;
  3119.       }
  3120.       break;
  3121.     }
  3122.   }
  3123.   (void) fwrite((char *) pnm_pixels,1,(int) packets,image->file);
  3124.   (void) free((char *) pnm_pixels);
  3125.   CloseImage(image);
  3126.   return(True);
  3127. }
  3128.  
  3129. /*
  3130. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  3131. %                                                                             %
  3132. %                                                                             %
  3133. %                                                                             %
  3134. %   W r i t e R L E I m a g e                                                 %
  3135. %                                                                             %
  3136. %                                                                             %
  3137. %                                                                             %
  3138. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  3139. %
  3140. %  Function WriteRLEImage writes an image in the Utah Run length encoded image
  3141. %  format.
  3142. %
  3143. %  The format of the WriteRLEImage routine is:
  3144. %
  3145. %      status=WriteRLEImage(image)
  3146. %
  3147. %  A description of each parameter follows.
  3148. %
  3149. %    o status: Function WriteRLEImage return True if the image is written.
  3150. %      False is returned is there is a memory shortage or if the image file
  3151. %      fails to write.
  3152. %
  3153. %    o image:  A pointer to a Image structure.
  3154. %
  3155. %
  3156. */
  3157. static unsigned int WriteRLEImage(image)
  3158. Image
  3159.   *image;
  3160. {
  3161.   unsigned int
  3162.     status;
  3163.  
  3164.   Warning("Cannot write RLE images",image->filename);
  3165.   status=WriteMIFFImage(image);
  3166.   return(status);
  3167. }
  3168.  
  3169. /*
  3170. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  3171. %                                                                             %
  3172. %                                                                             %
  3173. %                                                                             %
  3174. %   W r i t e P S I m a g e                                                   %
  3175. %                                                                             %
  3176. %                                                                             %
  3177. %                                                                             %
  3178. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  3179. %
  3180. %  Function WritePSImage translates an image to encapsulated Postscript
  3181. %  Level I for printing.  If the supplied geometry is null, the image is
  3182. %  centered on the Postscript page.  Otherwise, the image is positioned as
  3183. %  specified by the geometry.
  3184. %
  3185. %  The format of the WritePSImage routine is:
  3186. %
  3187. %      status=WritePSImage(image,geometry,density)
  3188. %
  3189. %  A description of each parameter follows:
  3190. %
  3191. %    o status: Function WritePSImage return True if the image is printed.
  3192. %      False is returned if the image file cannot be opened for printing.
  3193. %
  3194. %    o image: The address of a structure of type Image;  returned from
  3195. %      ReadImage.
  3196. %
  3197. %    o geometry: A pointer to a geometry string.  Specifies the width and
  3198. %      height of the Postscript image.
  3199. %
  3200. %    o density: A pointer to a density string.  Specifies the dots-per-inch
  3201. %      of the Postscript image.
  3202. %
  3203. %
  3204. */
  3205. static unsigned int WritePSImage(image,geometry,density)
  3206. Image
  3207.   *image;
  3208.  
  3209. char
  3210.   *geometry,
  3211.   *density;
  3212. {
  3213.   static char
  3214.     *Postscript[]=
  3215.     {
  3216.       "%%BeginProlog",
  3217.       "%",
  3218.       "% Display a color image.  The image is displayed in color on",
  3219.       "% Postscript viewers or printers that support color, otherwise",
  3220.       "% it is displayed as grayscale.",
  3221.       "%",
  3222.       "/buffer 512 string def",
  3223.       "/byte 1 string def",
  3224.       "/color_packet 3 string def",
  3225.       "/pixels 768 string def",
  3226.       "",
  3227.       "/DirectClassPacket",
  3228.       "{",
  3229.       "  %",
  3230.       "  % Get a DirectClass packet.",
  3231.       "  %",
  3232.       "  % Parameters: ",
  3233.       "  %   red.",
  3234.       "  %   green.",
  3235.       "  %   blue.",
  3236.       "  %   length: number of pixels minus one of this color (optional).",
  3237.       "  %",
  3238.       "  currentfile color_packet readhexstring pop pop",
  3239.       "  compression 0 gt",
  3240.       "  {",
  3241.       "    /number_pixels 3 def",
  3242.       "  }",
  3243.       "  {",
  3244.       "    currentfile byte readhexstring pop 0 get",
  3245.       "    /number_pixels exch 1 add 3 mul def",
  3246.       "  } ifelse",
  3247.       "  0 3 number_pixels 1 sub",
  3248.       "  {",
  3249.       "    pixels exch color_packet putinterval",
  3250.       "  } for",
  3251.       "  pixels 0 number_pixels getinterval",
  3252.       "} bind def",
  3253.       "",
  3254.       "/DirectClassImage",
  3255.       "{",
  3256.       "  %",
  3257.       "  % Display a DirectClass image.",
  3258.       "  %",
  3259.       "  systemdict /colorimage known",
  3260.       "  {",
  3261.       "    columns rows 8",
  3262.       "    [",
  3263.       "      columns 0 0",
  3264.       "      rows neg 0 rows",
  3265.       "    ]",
  3266.       "    { DirectClassPacket } false 3 colorimage",
  3267.       "  }",
  3268.       "  {",
  3269.       "    %",
  3270.       "    % No colorimage operator;  convert to grayscale.",
  3271.       "    %",
  3272.       "    columns rows 8",
  3273.       "    [",
  3274.       "      columns 0 0",
  3275.       "      rows neg 0 rows",
  3276.       "    ]",
  3277.       "    { GrayDirectClassPacket } image",
  3278.       "  } ifelse",
  3279.       "} bind def",
  3280.       "",
  3281.       "/GrayDirectClassPacket",
  3282.       "{",
  3283.       "  %",
  3284.       "  % Get a DirectClass packet;  convert to grayscale.",
  3285.       "  %",
  3286.       "  % Parameters: ",
  3287.       "  %   red",
  3288.       "  %   green",
  3289.       "  %   blue",
  3290.       "  %   length: number of pixels minus one of this color (optional).",
  3291.       "  %",
  3292.       "  currentfile color_packet readhexstring pop pop",
  3293.       "  color_packet 0 get 0.299 mul",
  3294.       "  color_packet 1 get 0.587 mul add",
  3295.       "  color_packet 2 get 0.114 mul add",
  3296.       "  cvi",
  3297.       "  /gray_packet exch def",
  3298.       "  compression 0 gt",
  3299.       "  {",
  3300.       "    /number_pixels 1 def",
  3301.       "  }",
  3302.       "  {",
  3303.       "    currentfile byte readhexstring pop 0 get",
  3304.       "    /number_pixels exch 1 add def",
  3305.       "  } ifelse",
  3306.       "  0 1 number_pixels 1 sub",
  3307.       "  {",
  3308.       "    pixels exch gray_packet put",
  3309.       "  } for",
  3310.       "  pixels 0 number_pixels getinterval",
  3311.       "} bind def",
  3312.       "",
  3313.       "/GrayPseudoClassPacket",
  3314.       "{",
  3315.       "  %",
  3316.       "  % Get a PseudoClass packet;  convert to grayscale.",
  3317.       "  %",
  3318.       "  % Parameters: ",
  3319.       "  %   index: index into the colormap.",
  3320.       "  %   length: number of pixels minus one of this color (optional).",
  3321.       "  %",
  3322.       "  currentfile byte readhexstring pop 0 get",
  3323.       "  /offset exch 3 mul def",
  3324.       "  /color_packet colormap offset 3 getinterval def",
  3325.       "  color_packet 0 get 0.299 mul",
  3326.       "  color_packet 1 get 0.587 mul add",
  3327.       "  color_packet 2 get 0.114 mul add",
  3328.       "  cvi",
  3329.       "  /gray_packet exch def",
  3330.       "  compression 0 gt",
  3331.       "  {",
  3332.       "    /number_pixels 1 def",
  3333.       "  }",
  3334.       "  {",
  3335.       "    currentfile byte readhexstring pop 0 get",
  3336.       "    /number_pixels exch 1 add def",
  3337.       "  } ifelse",
  3338.       "  0 1 number_pixels 1 sub",
  3339.       "  {",
  3340.       "    pixels exch gray_packet put",
  3341.       "  } for",
  3342.       "  pixels 0 number_pixels getinterval",
  3343.       "} bind def",
  3344.       "",
  3345.       "/PseudoClassPacket",
  3346.       "{",
  3347.       "  %",
  3348.       "  % Get a PseudoClass packet.",
  3349.       "  %",
  3350.       "  % Parameters: ",
  3351.       "  %   index: index into the colormap.",
  3352.       "  %   length: number of pixels minus one of this color (optional).",
  3353.       "  %",
  3354.       "  currentfile byte readhexstring pop 0 get",
  3355.       "  /offset exch 3 mul def",
  3356.       "  /color_packet colormap offset 3 getinterval def",
  3357.       "  compression 0 gt",
  3358.       "  {",
  3359.       "    /number_pixels 3 def",
  3360.       "  }",
  3361.       "  {",
  3362.       "    currentfile byte readhexstring pop 0 get",
  3363.       "    /number_pixels exch 1 add 3 mul def",
  3364.       "  } ifelse",
  3365.       "  0 3 number_pixels 1 sub",
  3366.       "  {",
  3367.       "    pixels exch color_packet putinterval",
  3368.       "  } for",
  3369.       "  pixels 0 number_pixels getinterval",
  3370.       "} bind def",
  3371.       "",
  3372.       "/PseudoClassImage",
  3373.       "{",
  3374.       "  %",
  3375.       "  % Display a PseudoClass image.",
  3376.       "  %",
  3377.       "  % Parameters: ",
  3378.       "  %   colors: number of colors in the colormap.",
  3379.       "  %   colormap: red, green, blue color packets.",
  3380.       "  %",
  3381.       "  currentfile buffer readline pop",
  3382.       "  token pop /colors exch def pop",
  3383.       "  /colors colors 3 mul def",
  3384.       "  /colormap colors string def",
  3385.       "  currentfile colormap readhexstring pop pop",
  3386.       "  systemdict /colorimage known",
  3387.       "  {",
  3388.       "    columns rows 8",
  3389.       "    [",
  3390.       "      columns 0 0",
  3391.       "      rows neg 0 rows",
  3392.       "    ]",
  3393.       "    { PseudoClassPacket } false 3 colorimage",
  3394.       "  }",
  3395.       "  {",
  3396.       "    %",
  3397.       "    % No colorimage operator;  convert to grayscale.",
  3398.       "    %",
  3399.       "    columns rows 8",
  3400.       "    [",
  3401.       "      columns 0 0",
  3402.       "      rows neg 0 rows",
  3403.       "    ]",
  3404.       "    { GrayPseudoClassPacket } image",
  3405.       "  } ifelse",
  3406.       "} bind def",
  3407.       "",
  3408.       "/DisplayImage",
  3409.       "{",
  3410.       "  %",
  3411.       "  % Display a DirectClass or PseudoClass image.",
  3412.       "  %",
  3413.       "  % Parameters: ",
  3414.       "  %   x & y translation.",
  3415.       "  %   x & y scale.",
  3416.       "  %   image label.",
  3417.       "  %   image columns & rows.",
  3418.       "  %   class: 0-DirectClass or 1-PseudoClass.",
  3419.       "  %   compression: 0-RunlengthEncodedCompression or 1-NoCompression.",
  3420.       "  %   hex color packets.",
  3421.       "  %",
  3422.       "  gsave",
  3423.       "  currentfile buffer readline pop",
  3424.       "  token pop /x exch def",
  3425.       "  token pop /y exch def pop",
  3426.       "  x y translate",
  3427.       "  currentfile buffer readline pop",
  3428.       "  token pop /x exch def",
  3429.       "  token pop /y exch def pop",
  3430.       "  /NewCenturySchlbk-Roman findfont 24 scalefont setfont",
  3431.       "  currentfile buffer readline pop",
  3432.       "  0 y 12 add moveto buffer show",
  3433.       "  x y scale",
  3434.       "  currentfile buffer readline pop",
  3435.       "  token pop /columns exch def",
  3436.       "  token pop /rows exch def pop",
  3437.       "  currentfile buffer readline pop",
  3438.       "  token pop /class exch def pop",
  3439.       "  currentfile buffer readline pop",
  3440.       "  token pop /compression exch def pop",
  3441.       "  class 0 gt { PseudoClassImage } { DirectClassImage } ifelse",
  3442.       "  grestore",
  3443.       "  showpage",
  3444.       "} bind def",
  3445.       "%%EndProlog",
  3446.       "%%Page:  1 1",
  3447.       NULL
  3448.     };
  3449.  
  3450.   char
  3451.     *label,
  3452.     **q;
  3453.  
  3454.   int
  3455.     sans_offset,
  3456.     x,
  3457.     y;
  3458.  
  3459.   register RunlengthPacket
  3460.     *p;
  3461.  
  3462.   register int
  3463.     i,
  3464.     j;
  3465.  
  3466.   time_t
  3467.     timer;
  3468.  
  3469.   unsigned int
  3470.     dx_resolution,
  3471.     dy_resolution,
  3472.     height,
  3473.     text_size,
  3474.     x_resolution,
  3475.     y_resolution,
  3476.     width;
  3477.  
  3478.   /*
  3479.     Open output image file.
  3480.   */
  3481.   OpenImage(image,"w");
  3482.   if (image->file == (FILE *) NULL)
  3483.     {
  3484.       Warning("Unable to open file",image->filename);
  3485.       return(False);
  3486.     }
  3487.   if (image->class == DirectClass)
  3488.     if (NumberColors(image,(FILE *) NULL) <= 256)
  3489.       {
  3490.         /*
  3491.           Demote DirectClass to PseudoClass.
  3492.         */
  3493.         QuantizeImage(image,256,8,False,RGBColorspace,True);
  3494.         SyncImage(image);
  3495.       }
  3496.   /*
  3497.     Scale image to size of Postscript page.
  3498.   */
  3499.   text_size=image->label == (char *) NULL ? 0 : 36;
  3500.   x=0;
  3501.   y=0;
  3502.   width=image->columns;
  3503.   height=image->rows;
  3504.   if (strcmp(image->magick,"PS") == 0)
  3505.     {
  3506.       int
  3507.         flags;
  3508.  
  3509.       unsigned int
  3510.         page_height,
  3511.         page_width;
  3512.  
  3513.       unsigned long
  3514.         scale_factor;
  3515.  
  3516.       /*
  3517.         Center image on Postscript page.
  3518.       */
  3519.       (void) XParseGeometry(PSPageGeometry,&x,&y,&page_width,&page_height);
  3520.       flags=XParseGeometry(geometry,&x,&y,&page_width,&page_height);
  3521.       scale_factor=UpShift(page_width-(x << 1))/image->columns;
  3522.       if (scale_factor > (UpShift(page_height-(y << 1)-text_size)/image->rows))
  3523.         scale_factor=UpShift(page_height-(y << 1)-text_size)/image->rows;
  3524.       width=DownShift(image->columns*scale_factor);
  3525.       height=DownShift(image->rows*scale_factor);
  3526.       if (((flags & XValue) == 0) && ((flags & YValue) == 0))
  3527.         {
  3528.           int
  3529.             delta_x,
  3530.             delta_y;
  3531.  
  3532.           delta_x=page_width-(width+(x << 1));
  3533.           delta_y=page_height-(height+(y << 1))-text_size;
  3534.           if (delta_x >= 0)
  3535.             x=(delta_x >> 1)+x;
  3536.           if (delta_y >= 0)
  3537.             y=(delta_y >> 1)+y;
  3538.         }
  3539.     }
  3540.   /*
  3541.     Scale relative to dots-per-inch.
  3542.   */
  3543.   (void) XParseGeometry(PSDensityGeometry,&sans_offset,&sans_offset,
  3544.     &dx_resolution,&dy_resolution);
  3545.   x_resolution=dx_resolution;
  3546.   y_resolution=dy_resolution;
  3547.   (void) XParseGeometry(density,&sans_offset,&sans_offset,&x_resolution,
  3548.     &y_resolution);
  3549.   width=(width*dx_resolution)/x_resolution;
  3550.   height=(height*dy_resolution)/y_resolution;
  3551.   /*
  3552.     Output Postscript header.
  3553.   */
  3554.   if (strcmp(image->magick,"PS") == 0)
  3555.     (void) fprintf(image->file,"%%!PS-Adobe-3.0\n");
  3556.   else
  3557.     (void) fprintf(image->file,"%%!PS-Adobe-3.0 EPSF-3.0\n");
  3558.   (void) fprintf(image->file,"%%%%Title: %s\n",image->filename);
  3559.   (void) fprintf(image->file,"%%%%Creator: ImageMagick\n");
  3560.   timer=time((time_t *) NULL);
  3561.   (void) localtime(&timer);
  3562.   (void) fprintf(image->file,"%%%%CreationDate: %s",ctime(&timer));
  3563.   (void) fprintf(image->file,"%%%%BoundingBox: %d %d %d %d\n",x,y,x+(int) width,
  3564.     y+(int) height+text_size);
  3565.   if (strcmp(image->magick,"PS") == 0)
  3566.     {
  3567.       (void) fprintf(image->file,"%%%%Orientation: Portrait\n");
  3568.       (void) fprintf(image->file,"%%%%PageOrder: Ascend\n");
  3569.     }
  3570.   (void) fprintf(image->file,"%%%%Pages: %d\n",strcmp(image->magick,"PS") == 0);
  3571.   (void) fprintf(image->file,"%%%%EndComments\n");
  3572.   if (strcmp(image->magick,"EPSI") == 0)
  3573.     {
  3574.       Image
  3575.         *preview_image;
  3576.  
  3577.       register unsigned char
  3578.         bit,
  3579.         byte,
  3580.         polarity;
  3581.  
  3582.       unsigned int
  3583.         count;
  3584.  
  3585.       /*
  3586.         Initialize bordered image attributes.
  3587.       */
  3588.       image->orphan=True;
  3589.       preview_image=CopyImage(image,image->columns,image->rows,True);
  3590.       image->orphan=False;
  3591.       if (preview_image == (Image *) NULL)
  3592.         {
  3593.           Warning("Unable to include preview image","Memory allocation failed");
  3594.           return(False);
  3595.         }
  3596.       /*
  3597.         Convert MIFF to bitmap pixels.
  3598.       */
  3599.       QuantizeImage(preview_image,2,8,False,GRAYColorspace,True);
  3600.       polarity=0;
  3601.       if (image->colors == 2)
  3602.         polarity=Intensity(image->colormap[0]) > Intensity(image->colormap[1]);
  3603.       bit=0;
  3604.       byte=0;
  3605.       count=0;
  3606.       x=0;
  3607.       p=preview_image->pixels;
  3608.       (void) fprintf(image->file,"%%%%BeginPreview: %u %u %u %u\n%%  ",
  3609.         preview_image->columns,preview_image->rows,(unsigned int) 1,
  3610.         (((preview_image->columns+7) >> 3)*preview_image->rows+35)/36);
  3611.       for (i=0; i < preview_image->packets; i++)
  3612.       {
  3613.         for (j=0; j <= ((int) p->length); j++)
  3614.         {
  3615.           byte<<=1;
  3616.           if (p->index == polarity)
  3617.             byte|=0x01;
  3618.           bit++;
  3619.           if (bit == 8)
  3620.             {
  3621.               /*
  3622.                 Write a bitmap byte to the image file.
  3623.               */
  3624.               (void) fprintf(image->file,"%02x",byte & 0xff);
  3625.               count++;
  3626.               if (count == 36)
  3627.                 {
  3628.                   (void) fprintf(image->file,"\n%%  ");
  3629.                   count=0;
  3630.                 };
  3631.               bit=0;
  3632.               byte=0;
  3633.             }
  3634.           x++;
  3635.           if (x == preview_image->columns)
  3636.             {
  3637.               if (bit != 0)
  3638.                 {
  3639.                   /*
  3640.                     Write a bitmap byte to the image file.
  3641.                   */
  3642.                   byte<<=(8-bit);
  3643.                   (void) fprintf(image->file,"%02x",byte & 0xff);
  3644.                   count++;
  3645.                   if (count == 36)
  3646.                     {
  3647.                       (void) fprintf(image->file,"\n%%  ");
  3648.                       count=0;
  3649.                     };
  3650.                   bit=0;
  3651.                   byte=0;
  3652.                 };
  3653.               x=0;
  3654.             }
  3655.           }
  3656.           p++;
  3657.         }
  3658.         (void) fprintf(image->file,"\n%%%%EndPreview\n");
  3659.         DestroyImage(preview_image);
  3660.       }
  3661.   /*
  3662.     Output Postscript commands.
  3663.   */
  3664.   for (q=Postscript; *q; q++)
  3665.     (void) fprintf(image->file,"%s\n",*q);
  3666.   if (strcmp(image->magick,"PS") != 0)
  3667.     (void) fprintf(image->file,"userdict begin\n");
  3668.   (void) fprintf(image->file,"%%%%BeginData:\n");
  3669.   (void) fprintf(image->file,"DisplayImage\n");
  3670.   /*
  3671.     Output image data.
  3672.   */
  3673.   if (image->compression == RunlengthEncodedCompression)
  3674.     CompressImage(image);
  3675.   label=image->label;
  3676.   if (label == (char *) NULL)
  3677.     label=" ";
  3678.   p=image->pixels;
  3679.   switch (image->class)
  3680.   {
  3681.     case DirectClass:
  3682.     {
  3683.       (void) fprintf(image->file,"%d %d\n%u %u\n%s           \n%u %u\n%d\n%d\n",
  3684.         x,y,width,height,label,image->columns,image->rows,
  3685.         image->class == PseudoClass,image->compression == NoCompression);
  3686.       switch (image->compression)
  3687.       {
  3688.         case RunlengthEncodedCompression:
  3689.         default:
  3690.         {
  3691.           /*
  3692.             Dump runlength-encoded DirectColor packets.
  3693.           */
  3694.           x=0;
  3695.           for (i=0; i < image->packets; i++)
  3696.           {
  3697.             x++;
  3698.             (void) fprintf(image->file,"%02x%02x%02x%02x",p->red,p->green,
  3699.               p->blue,p->length);
  3700.             if (x == 9)
  3701.               {
  3702.                 x=0;
  3703.                 (void) fprintf(image->file,"\n");
  3704.               }
  3705.             p++;
  3706.           }
  3707.           break;
  3708.         }
  3709.         case NoCompression:
  3710.         {
  3711.           /*
  3712.             Dump uncompressed DirectColor packets.
  3713.           */
  3714.           x=0;
  3715.           for (i=0; i < image->packets; i++)
  3716.           {
  3717.             for (j=0; j <= ((int) p->length); j++)
  3718.             {
  3719.               x++;
  3720.               (void) fprintf(image->file,"%02x%02x%02x",p->red,p->green,
  3721.                 p->blue);
  3722.               if (x == 12)
  3723.                 {
  3724.                   x=0;
  3725.                   (void) fprintf(image->file,"\n");
  3726.                 }
  3727.             }
  3728.             p++;
  3729.           }
  3730.           break;
  3731.         }
  3732.       }
  3733.       break;
  3734.     }
  3735.     case PseudoClass:
  3736.     {
  3737.       (void) fprintf(image->file,"%d %d\n%u %u\n%s           \n%u %u\n%d\n%d\n",
  3738.         x,y,width,height,label,image->columns,image->rows,
  3739.         image->class == PseudoClass,image->compression == NoCompression);
  3740.       /*
  3741.         Dump number of colors and colormap.
  3742.       */
  3743.       (void) fprintf(image->file,"%u\n",image->colors);
  3744.       for (i=0; i < image->colors; i++)
  3745.         (void) fprintf(image->file,"%02x%02x%02x\n",image->colormap[i].red,
  3746.           image->colormap[i].green,image->colormap[i].blue);
  3747.       switch (image->compression)
  3748.       {
  3749.         case RunlengthEncodedCompression:
  3750.         default:
  3751.         {
  3752.           /*
  3753.             Dump runlength-encoded PseudoColor packets.
  3754.           */
  3755.           x=0;
  3756.           for (i=0; i < image->packets; i++)
  3757.           {
  3758.             x++;
  3759.             (void) fprintf(image->file,"%02x%02x",p->index,p->length);
  3760.             if (x == 18)
  3761.               {
  3762.                 x=0;
  3763.                 (void) fprintf(image->file,"\n");
  3764.               }
  3765.             p++;
  3766.           }
  3767.           break;
  3768.         }
  3769.         case NoCompression:
  3770.         {
  3771.           /*
  3772.             Dump uncompressed PseudoColor packets.
  3773.           */
  3774.           x=0;
  3775.           for (i=0; i < image->packets; i++)
  3776.           {
  3777.             for (j=0; j <= ((int) p->length); j++)
  3778.             {
  3779.               x++;
  3780.               (void) fprintf(image->file,"%02x",p->index);
  3781.               if (x == 36)
  3782.                 {
  3783.                   x=0;
  3784.                   (void) fprintf(image->file,"\n");
  3785.                 }
  3786.             }
  3787.             p++;
  3788.           }
  3789.           break;
  3790.         }
  3791.       }
  3792.     }
  3793.   }
  3794.   (void) fprintf(image->file,"\n");
  3795.   (void) fprintf(image->file,"%%%%EndData\n");
  3796.   if (strcmp(image->magick,"PS") != 0)
  3797.     (void) fprintf(image->file,"end\n");
  3798.   (void) fprintf(image->file,"%%%%PageTrailer\n");
  3799.   (void) fprintf(image->file,"%%%%Trailer\n");
  3800.   (void) fprintf(image->file,"%%%%EOF\n");
  3801.   CloseImage(image);
  3802.   return(True);
  3803. }
  3804.  
  3805. /*
  3806. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  3807. %                                                                             %
  3808. %                                                                             %
  3809. %                                                                             %
  3810. %   W r i t e P S 2 I m a g e                                                 %
  3811. %                                                                             %
  3812. %                                                                             %
  3813. %                                                                             %
  3814. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  3815. %
  3816. %  Function WritePS2Image translates an image to encapsulated Postscript
  3817. %  Level II for printing.  If the supplied geometry is null, the image is
  3818. %  centered on the Postscript page.  Otherwise, the image is positioned as
  3819. %  specified by the geometry.
  3820. %
  3821. %  The format of the WritePS2Image routine is:
  3822. %
  3823. %      status=WritePS2Image(image,geometry,density)
  3824. %
  3825. %  A description of each parameter follows:
  3826. %
  3827. %    o status: Function WritePS2Image return True if the image is printed.
  3828. %      False is returned if the image file cannot be opened for printing.
  3829. %
  3830. %    o image: The address of a structure of type Image;  returned from
  3831. %      ReadImage.
  3832. %
  3833. %    o geometry: A pointer to a geometry string.  Specifies the width and
  3834. %      height of the Postscript image.
  3835. %
  3836. %    o density: A pointer to a density string.  Specifies the dots-per-inch
  3837. %      of the Postscript image.
  3838. %
  3839. %
  3840. */
  3841. static unsigned int WritePS2Image(image,geometry,density)
  3842. Image
  3843.   *image;
  3844.  
  3845. char
  3846.   *geometry,
  3847.   *density;
  3848. {
  3849.   static char
  3850.     *Postscript[]=
  3851.     {
  3852.       "%%BeginProlog",
  3853.       "%",
  3854.       "% Display a color image.  The image is displayed in color on",
  3855.       "% Postscript viewers or printers that support color, otherwise",
  3856.       "% it is displayed as grayscale.",
  3857.       "%",
  3858.       "/buffer 512 string def",
  3859.       "",
  3860.       "/DirectClassImage",
  3861.       "{",
  3862.       "  %",
  3863.       "  % Display a DirectClass image.",
  3864.       "  %",
  3865.       "  /DeviceRGB setcolorspace",
  3866.       "  <<",
  3867.       "    /ImageType 1",
  3868.       "    /Interpolate true",
  3869.       "    /Width columns",
  3870.       "    /Height rows",
  3871.       "    /BitsPerComponent 8",
  3872.       "    /Decode [0 1 0 1 0 1]",
  3873.       "    /ImageMatrix [columns 0 0 rows neg 0 rows]",
  3874.       "    compression 0 gt",
  3875.       "    {",
  3876.       "      /DataSource currentfile /ASCIIHexDecode filter",
  3877.       "    }",
  3878.       "    {",
  3879.       "      /DataSource currentfile /ASCIIHexDecode filter /LZWDecode filter",
  3880.       "    } ifelse",
  3881.       "  >> image",
  3882.       "} bind def",
  3883.       "",
  3884.       "/PseudoClassImage",
  3885.       "{",
  3886.       "  %",
  3887.       "  % Display a PseudoClass image.",
  3888.       "  %",
  3889.       "  % Parameters: ",
  3890.       "  %   colors: number of colors in the colormap.",
  3891.       "  %   colormap: red, green, blue color packets.",
  3892.       "  %",
  3893.       "  currentfile buffer readline pop",
  3894.       "  token pop /colors exch def pop",
  3895.       "  /colormap colors 3 mul string def",
  3896.       "  currentfile colormap readhexstring pop pop",
  3897.       "  [ /Indexed /DeviceRGB colors 1 sub colormap ] setcolorspace",
  3898.       "  <<",
  3899.       "    /ImageType 1",
  3900.       "    /Interpolate true",
  3901.       "    /Width columns",
  3902.       "    /Height rows",
  3903.       "    /BitsPerComponent 8",
  3904.       "    /Decode [0 255]",
  3905.       "    /ImageMatrix [columns 0 0 rows neg 0 rows]",
  3906.       "    compression 0 gt",
  3907.       "    {",
  3908.       "      /DataSource currentfile /ASCIIHexDecode filter",
  3909.       "    }",
  3910.       "    {",
  3911.       "      /DataSource currentfile /ASCIIHexDecode filter /LZWDecode filter",
  3912.       "    } ifelse",
  3913.       "  >> image",
  3914.       "} bind def",
  3915.       "",
  3916.       "/DisplayImage",
  3917.       "{",
  3918.       "  %",
  3919.       "  % Display a DirectClass or PseudoClass image.",
  3920.       "  %",
  3921.       "  % Parameters: ",
  3922.       "  %   x & y translation.",
  3923.       "  %   x & y scale.",
  3924.       "  %   image label.",
  3925.       "  %   image columns & rows.",
  3926.       "  %   class: 0-DirectClass or 1-PseudoClass.",
  3927.       "  %   compression: 0-RunlengthEncodedCompression or 1-NoCompression.",
  3928.       "  %   hex color packets.",
  3929.       "  %",
  3930.       "  gsave",
  3931.       "  currentfile buffer readline pop",
  3932.       "  token pop /x exch def",
  3933.       "  token pop /y exch def pop",
  3934.       "  x y translate",
  3935.       "  currentfile buffer readline pop",
  3936.       "  token pop /x exch def",
  3937.       "  token pop /y exch def pop",
  3938.       "  /NewCenturySchlbk-Roman findfont 24 scalefont setfont",
  3939.       "  currentfile buffer readline pop",
  3940.       "  0 y 12 add moveto buffer show",
  3941.       "  x y scale",
  3942.       "  currentfile buffer readline pop",
  3943.       "  token pop /columns exch def",
  3944.       "  token pop /rows exch def pop",
  3945.       "  currentfile buffer readline pop",
  3946.       "  token pop /class exch def pop",
  3947.       "  currentfile buffer readline pop",
  3948.       "  token pop /compression exch def pop",
  3949.       "  class 0 gt { PseudoClassImage } { DirectClassImage } ifelse",
  3950.       "  grestore",
  3951.       "  showpage",
  3952.       "} bind def",
  3953.       "%%EndProlog",
  3954.       "%%Page:  1 1",
  3955.       NULL
  3956.     };
  3957.  
  3958.   char
  3959.     *label,
  3960.     **q;
  3961.  
  3962.   int
  3963.     sans_offset,
  3964.     x,
  3965.     y;
  3966.  
  3967.   register RunlengthPacket
  3968.     *p;
  3969.  
  3970.   register int
  3971.     i,
  3972.     j;
  3973.  
  3974.   time_t
  3975.     timer;
  3976.  
  3977.   unsigned char
  3978.     *pixels;
  3979.  
  3980.   unsigned int
  3981.     dx_resolution,
  3982.     dy_resolution,
  3983.     height,
  3984.     number_packets,
  3985.     text_size,
  3986.     x_resolution,
  3987.     y_resolution,
  3988.     width;
  3989.  
  3990.   /*
  3991.     Open output image file.
  3992.   */
  3993.   OpenImage(image,"w");
  3994.   if (image->file == (FILE *) NULL)
  3995.     {
  3996.       Warning("Unable to open file",image->filename);
  3997.       return(False);
  3998.     }
  3999.   if (image->class == DirectClass)
  4000.     if (NumberColors(image,(FILE *) NULL) <= 256)
  4001.       {
  4002.         /*
  4003.           Demote DirectClass to PseudoClass.
  4004.         */
  4005.         QuantizeImage(image,256,8,False,RGBColorspace,True);
  4006.         SyncImage(image);
  4007.       }
  4008.   /*
  4009.     Scale image to size of Postscript page.
  4010.   */
  4011.   text_size=image->label == (char *) NULL ? 0 : 36;
  4012.   x=0;
  4013.   y=0;
  4014.   width=image->columns;
  4015.   height=image->rows;
  4016.   if (strcmp(image->magick,"PS") == 0)
  4017.     {
  4018.       int
  4019.         flags;
  4020.  
  4021.       unsigned int
  4022.         page_height,
  4023.         page_width;
  4024.  
  4025.       unsigned long
  4026.         scale_factor;
  4027.  
  4028.       /*
  4029.         Center image on Postscript page.
  4030.       */
  4031.       (void) XParseGeometry(PSPageGeometry,&x,&y,&page_width,&page_height);
  4032.       flags=XParseGeometry(geometry,&x,&y,&page_width,&page_height);
  4033.       scale_factor=UpShift(page_width-(x << 1))/image->columns;
  4034.       if (scale_factor > (UpShift(page_height-(y << 1)-text_size)/image->rows))
  4035.         scale_factor=UpShift(page_height-(y << 1)-text_size)/image->rows;
  4036.       width=DownShift(image->columns*scale_factor);
  4037.       height=DownShift(image->rows*scale_factor);
  4038.       if (((flags & XValue) == 0) && ((flags & YValue) == 0))
  4039.         {
  4040.           int
  4041.             delta_x,
  4042.             delta_y;
  4043.  
  4044.           delta_x=page_width-(width+(x << 1));
  4045.           delta_y=page_height-(height+(y << 1))-text_size;
  4046.           if (delta_x >= 0)
  4047.             x=(delta_x >> 1)+x;
  4048.           if (delta_y >= 0)
  4049.             y=(delta_y >> 1)+y;
  4050.         }
  4051.     }
  4052.   /*
  4053.     Scale relative to dots-per-inch.
  4054.   */
  4055.   (void) XParseGeometry(PSDensityGeometry,&sans_offset,&sans_offset,
  4056.     &dx_resolution,&dy_resolution);
  4057.   x_resolution=dx_resolution;
  4058.   y_resolution=dy_resolution;
  4059.   (void) XParseGeometry(density,&sans_offset,&sans_offset,&x_resolution,
  4060.     &y_resolution);
  4061.   width=(width*dx_resolution)/x_resolution;
  4062.   height=(height*dy_resolution)/y_resolution;
  4063.   /*
  4064.     Output Postscript header.
  4065.   */
  4066.   if (strcmp(image->magick,"PS") == 0)
  4067.     (void) fprintf(image->file,"%%!PS-Adobe-3.0\n");
  4068.   else
  4069.     (void) fprintf(image->file,"%%!PS-Adobe-3.0 EPSF-3.0\n");
  4070.   (void) fprintf(image->file,"%%%%Title: %s\n",image->filename);
  4071.   (void) fprintf(image->file,"%%%%Creator: ImageMagick\n");
  4072.   timer=time((time_t *) NULL);
  4073.   (void) localtime(&timer);
  4074.   (void) fprintf(image->file,"%%%%CreationDate: %s",ctime(&timer));
  4075.   (void) fprintf(image->file,"%%%%BoundingBox: %d %d %d %d\n",x,y,x+(int) width,
  4076.     y+(int) height+text_size);
  4077.   if (strcmp(image->magick,"PS") == 0)
  4078.     {
  4079.       (void) fprintf(image->file,"%%%%Orientation: Portrait\n");
  4080.       (void) fprintf(image->file,"%%%%PageOrder: Ascend\n");
  4081.     }
  4082.   (void) fprintf(image->file,"%%%%Pages: %d\n",strcmp(image->magick,"PS") == 0);
  4083.   (void) fprintf(image->file,"%%%%EndComments\n");
  4084.   /*
  4085.     Output Postscript commands.
  4086.   */
  4087.   for (q=Postscript; *q; q++)
  4088.     (void) fprintf(image->file,"%s\n",*q);
  4089.   if (strcmp(image->magick,"PS") != 0)
  4090.     (void) fprintf(image->file,"userdict begin\n");
  4091.   (void) fprintf(image->file,"%%%%BeginData:\n");
  4092.   (void) fprintf(image->file,"DisplayImage\n");
  4093.   /*
  4094.     Output image data.
  4095.   */
  4096.   label=image->label;
  4097.   if (label == (char *) NULL)
  4098.     label=" ";
  4099.   p=image->pixels;
  4100.   if ((image->class == DirectClass) || (image->colors > 256))
  4101.     {
  4102.       (void) fprintf(image->file,"%d %d\n%u %u\n%s           \n%u %u\n%d\n%d\n",
  4103.         x,y,width,height,label,image->columns,image->rows,
  4104.         image->class == PseudoClass,image->compression == NoCompression);
  4105.       switch (image->compression)
  4106.       {
  4107.         case RunlengthEncodedCompression:
  4108.         default:
  4109.         {
  4110.           register unsigned char
  4111.             *q;
  4112.  
  4113.           /*
  4114.             Allocate pixel array.
  4115.           */
  4116.           number_packets=3*image->columns*image->rows;
  4117.           pixels=(unsigned char *) malloc(number_packets*sizeof(unsigned char));
  4118.           if (pixels == (unsigned char *) NULL)
  4119.             {
  4120.               Warning("Memory allocation error",(char *) NULL);
  4121.               return(False);
  4122.             }
  4123.           /*
  4124.             Dump LZW encoded pixels.
  4125.           */
  4126.           q=pixels;
  4127.           for (i=0; i < image->packets; i++)
  4128.           {
  4129.             for (j=0; j <= (int) p->length; j++)
  4130.             {
  4131.               *q++=p->red;
  4132.               *q++=p->green;
  4133.               *q++=p->blue;
  4134.             }
  4135.             p++;
  4136.           }
  4137.           (void) LZWEncodeFilter(image->file,pixels,number_packets);
  4138.           (void) fprintf(image->file,">");
  4139.           (void) free((char *) pixels);
  4140.           break;
  4141.         }
  4142.         case NoCompression:
  4143.         {
  4144.           /*
  4145.             Dump uncompressed DirectColor packets.
  4146.           */
  4147.           x=0;
  4148.           for (i=0; i < image->packets; i++)
  4149.           {
  4150.             for (j=0; j <= ((int) p->length); j++)
  4151.             {
  4152.               x++;
  4153.               (void) fprintf(image->file,"%02x%02x%02x",p->red,p->green,
  4154.                 p->blue);
  4155.               if (x == 12)
  4156.                 {
  4157.                   x=0;
  4158.                   (void) fprintf(image->file,"\n");
  4159.                 }
  4160.             }
  4161.             p++;
  4162.           }
  4163.           break;
  4164.         }
  4165.       }
  4166.     }
  4167.   else
  4168.     {
  4169.       (void) fprintf(image->file,"%d %d\n%u %u\n%s           \n%u %u\n%d\n%d\n",
  4170.         x,y,width,height,label,image->columns,image->rows,
  4171.         image->class == PseudoClass,image->compression == NoCompression);
  4172.       /*
  4173.         Dump number of colors and colormap.
  4174.       */
  4175.       (void) fprintf(image->file,"%u\n",image->colors);
  4176.       for (i=0; i < image->colors; i++)
  4177.         (void) fprintf(image->file,"%02x%02x%02x\n",image->colormap[i].red,
  4178.           image->colormap[i].green,image->colormap[i].blue);
  4179.       switch (image->compression)
  4180.       {
  4181.         case RunlengthEncodedCompression:
  4182.         default:
  4183.         {
  4184.           register unsigned char
  4185.             *q;
  4186.  
  4187.           /*
  4188.             Allocate pixel array.
  4189.           */
  4190.           number_packets=image->columns*image->rows;
  4191.           pixels=(unsigned char *) malloc(number_packets*sizeof(unsigned char));
  4192.           if (pixels == (unsigned char *) NULL)
  4193.             {
  4194.               Warning("Memory allocation error",(char *) NULL);
  4195.               return(False);
  4196.             }
  4197.           /*
  4198.             Dump LZW encoded pixels.
  4199.           */
  4200.           q=pixels;
  4201.           for (i=0; i < image->packets; i++)
  4202.           {
  4203.             for (j=0; j <= (int) p->length; j++)
  4204.               *q++=(unsigned char) p->index;
  4205.             p++;
  4206.           }
  4207.           (void) LZWEncodeFilter(image->file,pixels,number_packets);
  4208.           (void) fprintf(image->file,">");
  4209.           (void) free((char *) pixels);
  4210.           break;
  4211.         }
  4212.         case NoCompression:
  4213.         {
  4214.           /*
  4215.             Dump uncompressed PseudoColor packets.
  4216.           */
  4217.           x=0;
  4218.           for (i=0; i < image->packets; i++)
  4219.           {
  4220.             for (j=0; j <= ((int) p->length); j++)
  4221.             {
  4222.               x++;
  4223.               (void) fprintf(image->file,"%02x",p->index);
  4224.               if (x == 36)
  4225.                 {
  4226.                   x=0;
  4227.                   (void) fprintf(image->file,"\n");
  4228.                 }
  4229.             }
  4230.             p++;
  4231.           }
  4232.           break;
  4233.         }
  4234.       }
  4235.     }
  4236.   (void) fprintf(image->file,"\n");
  4237.   (void) fprintf(image->file,"%%%%EndData\n");
  4238.   if (strcmp(image->magick,"PS") != 0)
  4239.     (void) fprintf(image->file,"end\n");
  4240.   (void) fprintf(image->file,"%%%%PageTrailer\n");
  4241.   (void) fprintf(image->file,"%%%%Trailer\n");
  4242.   (void) fprintf(image->file,"%%%%EOF\n");
  4243.   CloseImage(image);
  4244.   return(True);
  4245. }
  4246.  
  4247. /*
  4248. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  4249. %                                                                             %
  4250. %                                                                             %
  4251. %                                                                             %
  4252. %   W r i t e R G B I m a g e                                                 %
  4253. %                                                                             %
  4254. %                                                                             %
  4255. %                                                                             %
  4256. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  4257. %
  4258. %  Function WriteRGBImage writes an image to a file in red, green, and
  4259. %  blue rasterfile format.
  4260. %
  4261. %  The format of the WriteRGBImage routine is:
  4262. %
  4263. %      status=WriteRGBImage(image,interlace)
  4264. %
  4265. %  A description of each parameter follows.
  4266. %
  4267. %    o status: Function WriteRGBImage return True if the image is written.
  4268. %      False is returned is there is a memory shortage or if the image file
  4269. %      fails to write.
  4270. %
  4271. %    o image:  A pointer to a Image structure.
  4272. %
  4273. %    o interlace:  An unsigned integer that specifies the interlacing
  4274. %      scheme.
  4275. %
  4276. %
  4277. */
  4278. static unsigned int WriteRGBImage(image,interlace)
  4279. Image
  4280.   *image;
  4281.  
  4282. unsigned int
  4283.   interlace;
  4284. {
  4285.   register int
  4286.     i,
  4287.     j;
  4288.  
  4289.   register RunlengthPacket
  4290.     *p;
  4291.  
  4292.   register unsigned char
  4293.     *q;
  4294.  
  4295.   unsigned char
  4296.     *rgb_pixels;
  4297.  
  4298.   /*
  4299.     Open output image file.
  4300.   */
  4301.   OpenImage(image,"w");
  4302.   if (image->file == (FILE *) NULL)
  4303.     {
  4304.       Warning("Unable to open file",image->filename);
  4305.       return(False);
  4306.     }
  4307.   /*
  4308.     Convert MIFF to RGB raster pixels.
  4309.   */
  4310.   rgb_pixels=(unsigned char *)
  4311.     malloc(3*image->columns*image->rows*sizeof(unsigned char));
  4312.   if (rgb_pixels == (unsigned char *) NULL)
  4313.     {
  4314.       Warning("Unable to allocate memory",(char *) NULL);
  4315.       return(False);
  4316.     }
  4317.   q=rgb_pixels;
  4318.   switch (interlace)
  4319.   {
  4320.     case NoneInterlace:
  4321.     default:
  4322.     {
  4323.       /*
  4324.         No interlacing:  RGBRGBRGBRGBRGBRGB...
  4325.       */
  4326.       p=image->pixels;
  4327.       for (i=0; i < image->packets; i++)
  4328.       {
  4329.         for (j=0; j <= ((int) p->length); j++)
  4330.         {
  4331.           *q++=p->red;
  4332.           *q++=p->green;
  4333.           *q++=p->blue;
  4334.         }
  4335.         p++;
  4336.       }
  4337.       break;
  4338.     }
  4339.     case LineInterlace:
  4340.     {
  4341.       register int
  4342.         x,
  4343.         y;
  4344.  
  4345.       /*
  4346.         Line interlacing:  RRR...GGG...BBB...RRR...GGG...BBB...
  4347.       */
  4348.       if (!UncompressImage(image))
  4349.         return(False);
  4350.       for (y=0; y < image->rows; y++)
  4351.       {
  4352.         p=image->pixels+(y*image->columns);
  4353.         for (x=0; x < image->columns; x++)
  4354.         {
  4355.           *q++=p->red;
  4356.           p++;
  4357.         }
  4358.         p=image->pixels+(y*image->columns);
  4359.         for (x=0; x < image->columns; x++)
  4360.         {
  4361.           *q++=p->green;
  4362.           p++;
  4363.         }
  4364.         p=image->pixels+(y*image->columns);
  4365.         for (x=0; x < image->columns; x++)
  4366.         {
  4367.           *q++=p->blue;
  4368.           p++;
  4369.         }
  4370.       }
  4371.       break;
  4372.     }
  4373.     case PlaneInterlace:
  4374.     {
  4375.       /*
  4376.         Plane interlacing:  RRRRRR...GGGGGG...BBBBBB...
  4377.       */
  4378.       p=image->pixels;
  4379.       for (i=0; i < image->packets; i++)
  4380.       {
  4381.         for (j=0; j <= ((int) p->length); j++)
  4382.           *q++=p->red;
  4383.         p++;
  4384.       }
  4385.       p=image->pixels;
  4386.       for (i=0; i < image->packets; i++)
  4387.       {
  4388.         for (j=0; j <= ((int) p->length); j++)
  4389.           *q++=p->green;
  4390.         p++;
  4391.       }
  4392.       p=image->pixels;
  4393.       for (i=0; i < image->packets; i++)
  4394.       {
  4395.         for (j=0; j <= ((int) p->length); j++)
  4396.           *q++=p->blue;
  4397.         p++;
  4398.       }
  4399.       break;
  4400.     }
  4401.   }
  4402.   (void) fwrite((char *) rgb_pixels,3,(int) (image->columns*image->rows),
  4403.     image->file);
  4404.   (void) free((char *) rgb_pixels);
  4405.   CloseImage(image);
  4406.   return(True);
  4407. }
  4408.  
  4409. /*
  4410. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  4411. %                                                                             %
  4412. %                                                                             %
  4413. %                                                                             %
  4414. %   W r i t e S U N I m a g e                                                 %
  4415. %                                                                             %
  4416. %                                                                             %
  4417. %                                                                             %
  4418. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  4419. %
  4420. %  Function WriteSUNImage writes an image in the SUN rasterfile format.
  4421. %
  4422. %  The format of the WriteSUNImage routine is:
  4423. %
  4424. %      status=WriteSUNImage(image)
  4425. %
  4426. %  A description of each parameter follows.
  4427. %
  4428. %    o status: Function WriteSUNImage return True if the image is written.
  4429. %      False is returned is there is a memory shortage or if the image file
  4430. %      fails to write.
  4431. %
  4432. %    o image:  A pointer to a Image structure.
  4433. %
  4434. %
  4435. */
  4436. static unsigned int WriteSUNImage(image)
  4437. Image
  4438.   *image;
  4439. {
  4440. #define RMT_EQUAL_RGB  1
  4441. #define RMT_NONE  0
  4442. #define RMT_RAW  2
  4443. #define RT_STANDARD  1
  4444. #define RT_FORMAT_RGB  3
  4445.  
  4446.   typedef struct _SUNHeader
  4447.   {
  4448.     unsigned long
  4449.       magic,
  4450.       width,
  4451.       height,
  4452.       depth,
  4453.       length,
  4454.       type,
  4455.       maptype,
  4456.       maplength;
  4457.   } SUNHeader;
  4458.  
  4459.   register int
  4460.     i,
  4461.     j,
  4462.     x;
  4463.  
  4464.   register RunlengthPacket
  4465.     *p;
  4466.  
  4467.   register unsigned char
  4468.     *q;
  4469.  
  4470.   SUNHeader
  4471.     sun_header;
  4472.  
  4473.   unsigned char
  4474.     *sun_pixels;
  4475.  
  4476.   /*
  4477.     Open output image file.
  4478.   */
  4479.   OpenImage(image,"w");
  4480.   if (image->file == (FILE *) NULL)
  4481.     {
  4482.       Warning("Unable to open file",image->filename);
  4483.       return(False);
  4484.     }
  4485.   if (image->class == DirectClass)
  4486.     if (NumberColors(image,(FILE *) NULL) <= 256)
  4487.       {
  4488.         /*
  4489.           Demote DirectClass to PseudoClass.
  4490.         */
  4491.         QuantizeImage(image,256,8,False,RGBColorspace,True);
  4492.         SyncImage(image);
  4493.       }
  4494.   /*
  4495.     Initialize SUN raster file header.
  4496.   */
  4497.   sun_header.magic=0x59a66a95;
  4498.   sun_header.width=image->columns;
  4499.   sun_header.height=image->rows;
  4500.   sun_header.type=(image->class == DirectClass ? RT_FORMAT_RGB : RT_STANDARD);
  4501.   sun_header.maptype=RMT_NONE;
  4502.   sun_header.maplength=0;
  4503.   if ((image->class == DirectClass) || (image->colors > 256))
  4504.     {
  4505.       /*
  4506.         Full color SUN raster.
  4507.       */
  4508.       sun_header.depth=(image->alpha ? 32 : 24);
  4509.       sun_header.length=image->columns*image->rows*(image->alpha ? 4 : 3);
  4510.       sun_header.length+=image->columns % 2 ? image->rows : 0;
  4511.     }
  4512.   else
  4513.     if (IsGrayImage(image) && (image->colors == 2))
  4514.       {
  4515.         /*
  4516.           Monochrome SUN raster.
  4517.         */
  4518.         sun_header.depth=1;
  4519.         sun_header.length=((image->columns+7) >> 3)*image->rows;
  4520.         sun_header.length+=((image->columns/8)+(image->columns % 8 ? 1 : 0)) %
  4521.           2 ? image->rows : 0;
  4522.       }
  4523.     else
  4524.       {
  4525.         /*
  4526.           Colormapped SUN raster.
  4527.         */
  4528.         sun_header.depth=8;
  4529.         sun_header.length=image->columns*image->rows;
  4530.         sun_header.length+=image->columns % 2 ? image->rows : 0;
  4531.         sun_header.maptype=RMT_EQUAL_RGB;
  4532.         sun_header.maplength=image->colors*3;
  4533.       }
  4534.   /*
  4535.     Write SUN header.
  4536.   */
  4537.   MSBFirstWriteLong(sun_header.magic,image->file);
  4538.   MSBFirstWriteLong(sun_header.width,image->file);
  4539.   MSBFirstWriteLong(sun_header.height,image->file);
  4540.   MSBFirstWriteLong(sun_header.depth,image->file);
  4541.   MSBFirstWriteLong(sun_header.length,image->file);
  4542.   MSBFirstWriteLong(sun_header.type,image->file);
  4543.   MSBFirstWriteLong(sun_header.maptype,image->file);
  4544.   MSBFirstWriteLong(sun_header.maplength,image->file);
  4545.   /*
  4546.     Convert MIFF to SUN raster pixels.
  4547.   */
  4548.   sun_pixels=(unsigned char *) malloc(sun_header.length*sizeof(unsigned char));
  4549.   if (sun_pixels == (unsigned char *) NULL)
  4550.     {
  4551.       Warning("Unable to allocate memory",(char *) NULL);
  4552.       return(False);
  4553.     }
  4554.   p=image->pixels;
  4555.   q=sun_pixels;
  4556.   x=0;
  4557.   if ((image->class == DirectClass) || (image->colors > 256))
  4558.     {
  4559.       /*
  4560.         Convert DirectClass packet to SUN RGB pixel.
  4561.       */
  4562.       for (i=0; i < image->packets; i++)
  4563.       {
  4564.         for (j=0; j <= (int) p->length; j++)
  4565.         {
  4566.           if (image->alpha)
  4567.             *q++=(unsigned char) p->index;
  4568.           *q++=p->red;
  4569.           *q++=p->green;
  4570.           *q++=p->blue;
  4571.           x++;
  4572.           if (x == image->columns)
  4573.             {
  4574.               if ((image->columns % 2) != 0)
  4575.                 q++;  /* pad scanline */
  4576.               x=0;
  4577.             }
  4578.         }
  4579.         p++;
  4580.       }
  4581.     }
  4582.   else
  4583.     if (IsGrayImage(image) && (image->colors == 2))
  4584.       {
  4585.         register unsigned char
  4586.           bit,
  4587.           byte;
  4588.  
  4589.         /*
  4590.           Convert PseudoClass image to a SUN monochrome image.
  4591.         */
  4592.         bit=0;
  4593.         byte=0;
  4594.         for (i=0; i < image->packets; i++)
  4595.         {
  4596.           for (j=0; j <= (int) p->length; j++)
  4597.           {
  4598.             byte<<=1;
  4599.             if (p->index == 0)
  4600.               byte|=0x01;
  4601.             bit++;
  4602.             if (bit == 8)
  4603.               {
  4604.                 *q++=byte;
  4605.                 bit=0;
  4606.                 byte=0;
  4607.               }
  4608.             x++;
  4609.             if (x == image->columns)
  4610.               {
  4611.                 /*
  4612.                   Advance to the next scanline.
  4613.                 */
  4614.                 if (bit != 0)
  4615.                   *q++=byte << (8-bit);
  4616.                 if ((((image->columns/8)+
  4617.                     (image->columns % 8 ? 1 : 0)) % 2) != 0)
  4618.                   q++;  /* pad scanline */
  4619.                 bit=0;
  4620.                 byte=0;
  4621.                 x=0;
  4622.              }
  4623.           }
  4624.           p++;
  4625.         }
  4626.       }
  4627.     else
  4628.       {
  4629.         unsigned char
  4630.           *sun_colormap;
  4631.  
  4632.         /*
  4633.           Dump colormap to file.
  4634.         */
  4635.         sun_colormap=(unsigned char *)
  4636.           malloc(sun_header.maplength*sizeof(unsigned char));
  4637.         if (sun_colormap == (unsigned char *) NULL)
  4638.           {
  4639.             Warning("Unable to allocate memory",(char *) NULL);
  4640.             return(False);
  4641.           }
  4642.         q=sun_colormap;
  4643.         for (i=0; i < image->colors; i++)
  4644.           *q++=image->colormap[i].red;
  4645.         for (i=0; i < image->colors; i++)
  4646.           *q++=image->colormap[i].green;
  4647.         for (i=0; i < image->colors; i++)
  4648.           *q++=image->colormap[i].blue;
  4649.         (void) fwrite((char *) sun_colormap,1,(int) sun_header.maplength,
  4650.           image->file);
  4651.         (void) free((char *) sun_colormap);
  4652.         /*
  4653.           Convert PseudoClass packet to SUN colormapped pixel.
  4654.         */
  4655.         q=sun_pixels;
  4656.         for (i=0; i < image->packets; i++)
  4657.         {
  4658.           for (j=0; j <= (int) p->length; j++)
  4659.           {
  4660.             *q++=p->index;
  4661.             x++;
  4662.             if (x == image->columns)
  4663.               {
  4664.                 if ((image->columns % 2) != 0)
  4665.                   q++;  /* pad scanline */
  4666.                 x=0;
  4667.               }
  4668.           }
  4669.           p++;
  4670.         }
  4671.       }
  4672.   (void) fwrite((char *) sun_pixels,1,(int) sun_header.length,image->file);
  4673.   (void) free((char *) sun_pixels);
  4674.   CloseImage(image);
  4675.   return(True);
  4676. }
  4677.  
  4678. /*
  4679. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  4680. %                                                                             %
  4681. %                                                                             %
  4682. %                                                                             %
  4683. %   W r i t e T A R G A I m a g e                                             %
  4684. %                                                                             %
  4685. %                                                                             %
  4686. %                                                                             %
  4687. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  4688. %
  4689. %  Function WriteTARGAImage writes a image in the Truevision Targa rasterfile
  4690. %  format.
  4691. %
  4692. %  The format of the WriteTARGAImage routine is:
  4693. %
  4694. %      status=WriteTARGAImage(image)
  4695. %
  4696. %  A description of each parameter follows.
  4697. %
  4698. %    o status: Function WriteTARGAImage return True if the image is written.
  4699. %      False is returned is there is a memory shortage or if the image file
  4700. %      fails to write.
  4701. %
  4702. %    o image:  A pointer to a Image structure.
  4703. %
  4704. %
  4705. */
  4706. static unsigned int WriteTARGAImage(image)
  4707. Image
  4708.   *image;
  4709. {
  4710. #define TargaColormap 1
  4711. #define TargaRGB 2
  4712. #define TargaMonochrome 3
  4713. #define TargaRLEColormap  9
  4714. #define TargaRLERGB  10
  4715. #define TargaRLEMonochrome  11
  4716.  
  4717.   typedef struct _TargaHeader
  4718.   {
  4719.     unsigned char
  4720.       id_length,
  4721.       colormap_type,
  4722.       image_type;
  4723.  
  4724.     unsigned short
  4725.       colormap_index,
  4726.       colormap_length;
  4727.  
  4728.     unsigned char
  4729.       colormap_size;
  4730.  
  4731.     unsigned short
  4732.       x_origin,
  4733.       y_origin,
  4734.       width,
  4735.       height;
  4736.  
  4737.     unsigned char
  4738.       pixel_size,
  4739.       attributes;
  4740.   } TargaHeader;
  4741.  
  4742.   int
  4743.     count,
  4744.     runlength;
  4745.  
  4746.   register int
  4747.     i,
  4748.     j;
  4749.  
  4750.   register RunlengthPacket
  4751.     *p;
  4752.  
  4753.   register unsigned char
  4754.     *q,
  4755.     *r;
  4756.  
  4757.   TargaHeader
  4758.     targa_header;
  4759.  
  4760.   unsigned char
  4761.     *targa_pixels;
  4762.  
  4763.   /*
  4764.     Open output image file.
  4765.   */
  4766.   OpenImage(image,"w");
  4767.   if (image->file == (FILE *) NULL)
  4768.     {
  4769.       Warning("Unable to open file",image->filename);
  4770.       return(False);
  4771.     }
  4772.   if (image->class == DirectClass)
  4773.     if (NumberColors(image,(FILE *) NULL) <= 256)
  4774.       {
  4775.         /*
  4776.           Demote DirectClass to PseudoClass.
  4777.         */
  4778.         QuantizeImage(image,256,8,False,RGBColorspace,True);
  4779.         SyncImage(image);
  4780.       }
  4781.   /*
  4782.     Reflect image.
  4783.   */
  4784.   image=ReflectImage(image);
  4785.   if (image == (Image *) NULL)
  4786.     {
  4787.       Warning("Unable to reflect file",image->filename);
  4788.       return(False);
  4789.     }
  4790.   if (image->compression == RunlengthEncodedCompression)
  4791.     CompressImage(image);
  4792.   /*
  4793.     Initialize TARGA raster file header.
  4794.   */
  4795.   targa_header.id_length=0;
  4796.   if (image->comments != (char *) NULL)
  4797.     targa_header.id_length=Min((int) strlen(image->comments),255);
  4798.   targa_header.colormap_type=0;
  4799.   targa_header.colormap_index=0;
  4800.   targa_header.colormap_length=0;
  4801.   targa_header.colormap_size=0;
  4802.   targa_header.x_origin=0;
  4803.   targa_header.y_origin=0;
  4804.   targa_header.width=image->columns;
  4805.   targa_header.height=image->rows;
  4806.   targa_header.pixel_size=8;
  4807.   targa_header.attributes=0;
  4808.   if ((image->class == DirectClass) || (image->colors > 256))
  4809.     {
  4810.       /*
  4811.         Full color TARGA raster.
  4812.       */
  4813.       targa_header.image_type=TargaRGB;
  4814.       if (image->compression == RunlengthEncodedCompression)
  4815.         targa_header.image_type=TargaRLERGB;
  4816.       targa_header.pixel_size=image->alpha ? 32 : 24;
  4817.     }
  4818.   else
  4819.     {
  4820.       /*
  4821.         Colormapped TARGA raster.
  4822.       */
  4823.       targa_header.image_type=TargaColormap;
  4824.       if (image->compression == RunlengthEncodedCompression)
  4825.         targa_header.image_type=TargaRLEColormap;
  4826.       if (!IsGrayImage(image) || (image->colors != 2))
  4827.         {
  4828.           targa_header.colormap_type=1;
  4829.           targa_header.colormap_index=0;
  4830.           targa_header.colormap_length=image->colors;
  4831.           targa_header.colormap_size=24;
  4832.         }
  4833.       else
  4834.         {
  4835.           /*
  4836.             Monochrome TARGA raster.
  4837.           */
  4838.           targa_header.image_type=TargaMonochrome;
  4839.           if (image->compression == RunlengthEncodedCompression)
  4840.             targa_header.image_type=TargaRLEMonochrome;
  4841.         }
  4842.     }
  4843.   /*
  4844.     Write TARGA header.
  4845.   */
  4846.   (void) fputc((char) targa_header.id_length,image->file);
  4847.   (void) fputc((char) targa_header.colormap_type,image->file);
  4848.   (void) fputc((char) targa_header.image_type,image->file);
  4849.   LSBFirstWriteShort(targa_header.colormap_index,image->file);
  4850.   LSBFirstWriteShort(targa_header.colormap_length,image->file);
  4851.   (void) fputc((char) targa_header.colormap_size,image->file);
  4852.   LSBFirstWriteShort(targa_header.x_origin,image->file);
  4853.   LSBFirstWriteShort(targa_header.y_origin,image->file);
  4854.   LSBFirstWriteShort(targa_header.width,image->file);
  4855.   LSBFirstWriteShort(targa_header.height,image->file);
  4856.   (void) fputc((char) targa_header.pixel_size,image->file);
  4857.   (void) fputc((char) targa_header.attributes,image->file);
  4858.   if (targa_header.id_length != 0)
  4859.     (void) fwrite((char *) image->comments,1,targa_header.id_length,
  4860.       image->file);
  4861.   /*
  4862.     Convert MIFF to TARGA raster pixels.
  4863.   */
  4864.   count=(unsigned int)
  4865.     (targa_header.pixel_size*targa_header.width*targa_header.height) >> 3;
  4866.   if (image->compression == RunlengthEncodedCompression)
  4867.     count+=(count/128)+1;
  4868.   targa_pixels=(unsigned char *) malloc(count*sizeof(unsigned char));
  4869.   if (targa_pixels == (unsigned char *) NULL)
  4870.     {
  4871.       Warning("Unable to allocate memory",(char *) NULL);
  4872.       return(False);
  4873.     }
  4874.   p=image->pixels+(image->packets-1);
  4875.   q=targa_pixels;
  4876.   if ((image->class == DirectClass) || (image->colors > 256))
  4877.     {
  4878.       /*
  4879.         Convert DirectClass packet to TARGA RGB pixel.
  4880.       */
  4881.       if (image->compression != RunlengthEncodedCompression)
  4882.         for (i=0; i < image->packets; i++)
  4883.         {
  4884.           for (j=0; j <= (int) p->length; j++)
  4885.           {
  4886.             *q++=p->blue;
  4887.             *q++=p->green;
  4888.             *q++=p->red;
  4889.             if (image->alpha)
  4890.               *q++=p->index;
  4891.           }
  4892.           p--;
  4893.         }
  4894.       else
  4895.         for (i=0; i < image->packets; i++)
  4896.         {
  4897.           runlength=p->length+1;
  4898.           if (runlength > 128)
  4899.             {
  4900.               *q++=0xff;
  4901.               *q++=p->blue;
  4902.               *q++=p->green;
  4903.               *q++=p->red;
  4904.               if (image->alpha)
  4905.                 *q++=p->index;
  4906.               runlength-=128;
  4907.             }
  4908.           r=q;
  4909.           *q++=0x80+(runlength-1);
  4910.           *q++=p->blue;
  4911.           *q++=p->green;
  4912.           *q++=p->red;
  4913.           if (image->alpha)
  4914.             *q++=p->index;
  4915.           if (runlength != 1)
  4916.             p--;
  4917.           else
  4918.             {
  4919.               for ( ; i < image->packets; i++)
  4920.               {
  4921.                 p--;
  4922.                 if ((p->length != 0) || (runlength == 128))
  4923.                   break;
  4924.                 *q++=p->blue;
  4925.                 *q++=p->green;
  4926.                 *q++=p->red;
  4927.                 if (image->alpha)
  4928.                   *q++=p->index;
  4929.                 runlength++;
  4930.               }
  4931.               *r=runlength-1;
  4932.             }
  4933.         }
  4934.     }
  4935.   else
  4936.     if (!IsGrayImage(image) || (image->colors != 2))
  4937.       {
  4938.         unsigned char
  4939.           *targa_colormap;
  4940.  
  4941.         /*
  4942.           Dump colormap to file (blue, green, red byte order).
  4943.         */
  4944.         targa_colormap=(unsigned char *)
  4945.           malloc(3*targa_header.colormap_length*sizeof(unsigned char));
  4946.         if (targa_colormap == (unsigned char *) NULL)
  4947.           {
  4948.             Warning("Unable to allocate memory",(char *) NULL);
  4949.             return(False);
  4950.           }
  4951.         q=targa_colormap;
  4952.         for (i=0; i < image->colors; i++)
  4953.         {
  4954.           *q++=image->colormap[i].blue;
  4955.           *q++=image->colormap[i].green;
  4956.           *q++=image->colormap[i].red;
  4957.         }
  4958.         (void) fwrite((char *) targa_colormap,1,
  4959.           (int) 3*targa_header.colormap_length,image->file);
  4960.         (void) free((char *) targa_colormap);
  4961.         /*
  4962.           Convert PseudoClass packet to TARGA colormapped pixel.
  4963.         */
  4964.         q=targa_pixels;
  4965.         if (image->compression != RunlengthEncodedCompression)
  4966.           for (i=0; i < image->packets; i++)
  4967.           {
  4968.             for (j=0; j <= (int) p->length; j++)
  4969.               *q++=p->index;
  4970.             p--;
  4971.           }
  4972.         else
  4973.           for (i=0; i < image->packets; i++)
  4974.           {
  4975.             runlength=p->length+1;
  4976.             if (runlength > 128)
  4977.               {
  4978.                 *q++=0xff;
  4979.                 *q++=p->index;
  4980.                 runlength-=128;
  4981.               }
  4982.             r=q;
  4983.             *q++=0x80+(runlength-1);
  4984.             *q++=p->index;
  4985.             if (runlength != 1)
  4986.               p--;
  4987.             else
  4988.               {
  4989.                 for ( ; i < image->packets; i++)
  4990.                 {
  4991.                   p--;
  4992.                   if ((p->length != 0) || (runlength == 128))
  4993.                     break;
  4994.                   *q++=p->index;
  4995.                   runlength++;
  4996.                 }
  4997.                 *r=runlength-1;
  4998.               }
  4999.           }
  5000.       }
  5001.     else
  5002.       {
  5003.         /*
  5004.           Convert PseudoClass image to a TARGA monochrome image.
  5005.         */
  5006.         if (image->compression != RunlengthEncodedCompression)
  5007.           for (i=0; i < image->packets; i++)
  5008.           {
  5009.             for (j=0; j <= (int) p->length; j++)
  5010.               *q++=p->index == 1 ? 0 : MaxRGB;
  5011.             p--;
  5012.           }
  5013.         else
  5014.           for (i=0; i < image->packets; i++)
  5015.           {
  5016.             runlength=p->length+1;
  5017.             if (runlength > 128)
  5018.               {
  5019.                 *q++=0xff;
  5020.                 *q++=p->index == 1 ? 0 : MaxRGB;
  5021.                 runlength-=128;
  5022.               }
  5023.             r=q;
  5024.             *q++=0x80+(runlength-1);
  5025.             *q++=p->index == 1 ? 0 : MaxRGB;
  5026.             if (runlength != 1)
  5027.               p--;
  5028.             else
  5029.               {
  5030.                 for ( ; i < image->packets; i++)
  5031.                 {
  5032.                   p--;
  5033.                   if ((p->length != 0) || (runlength == 128))
  5034.                     break;
  5035.                   *q++=p->index == 1 ? 0 : MaxRGB;
  5036.                   runlength++;
  5037.                 }
  5038.                 *r=runlength-1;
  5039.               }
  5040.           }
  5041.       }
  5042.   (void) fwrite((char *) targa_pixels,1,(int) (q-targa_pixels),image->file);
  5043.   (void) free((char *) targa_pixels);
  5044.   CloseImage(image);
  5045.   return(True);
  5046. }
  5047.  
  5048. /*
  5049. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  5050. %                                                                             %
  5051. %                                                                             %
  5052. %                                                                             %
  5053. %   W r i t e T E X T I m a g e                                               %
  5054. %                                                                             %
  5055. %                                                                             %
  5056. %                                                                             %
  5057. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  5058. %
  5059. %  Function WriteTEXTImage writes an image in the TEXT image forma.
  5060. %
  5061. %  The format of the WriteTEXTImage routine is:
  5062. %
  5063. %      status=WriteTEXTImage(image)
  5064. %
  5065. %  A description of each parameter follows.
  5066. %
  5067. %    o status: Function WriteTEXTImage return True if the image is written.
  5068. %      False is returned is there is a memory shortage or if the image file
  5069. %      fails to write.
  5070. %
  5071. %    o image:  A pointer to a Image structure.
  5072. %
  5073. %
  5074. */
  5075. static unsigned int WriteTEXTImage(image)
  5076. Image
  5077.   *image;
  5078. {
  5079.   unsigned int
  5080.     status;
  5081.  
  5082.   Warning("Cannot write TEXT images",image->filename);
  5083.   status=WriteMIFFImage(image);
  5084.   return(status);
  5085. }
  5086.  
  5087. #ifdef HasTIFF
  5088. #include "tiff.h"
  5089. #include "tiffio.h"
  5090. /*
  5091. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  5092. %                                                                             %
  5093. %                                                                             %
  5094. %                                                                             %
  5095. %   W r i t e T I F F I m a g e                                               %
  5096. %                                                                             %
  5097. %                                                                             %
  5098. %                                                                             %
  5099. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  5100. %
  5101. %  Function WriteTIFFImage writes an image in the Tagged image file format.
  5102. %
  5103. %  The format of the WriteTIFFImage routine is:
  5104. %
  5105. %      status=WriteTIFFImage(image,verbose)
  5106. %
  5107. %  A description of each parameter follows:
  5108. %
  5109. %    o status:  Function WriteTIFFImage return True if the image is written.
  5110. %      False is returned is there is of a memory shortage or if the image
  5111. %      file cannot be opened for writing.
  5112. %
  5113. %    o image:  A pointer to a Image structure.
  5114. %
  5115. %    o verbose:  A value greater than zero prints detailed information about
  5116. %      the image.
  5117. %
  5118. %
  5119. */
  5120. static unsigned int WriteTIFFImage(image,verbose)
  5121. Image
  5122.   *image;
  5123.  
  5124. unsigned int
  5125.   verbose;
  5126. {
  5127.   register RunlengthPacket
  5128.     *p;
  5129.  
  5130.   register int
  5131.     i,
  5132.     j,
  5133.     x,
  5134.     y;
  5135.  
  5136.   register unsigned char
  5137.     *q;
  5138.  
  5139.   TIFF
  5140.     *tiff;
  5141.  
  5142.   unsigned char
  5143.     *scanline;
  5144.  
  5145.   unsigned short
  5146.     photometric,
  5147.     rows_per_strip;
  5148.  
  5149.   /*
  5150.     Open TIFF file.
  5151.   */
  5152.   tiff=TIFFOpen(image->filename,"w");
  5153.   if (tiff == (TIFF *) NULL)
  5154.     return(False);
  5155.   if (image->class == DirectClass)
  5156.     if (NumberColors(image,(FILE *) NULL) <= 256)
  5157.       {
  5158.         /*
  5159.           Demote DirectClass to PseudoClass.
  5160.         */
  5161.         QuantizeImage(image,256,8,False,RGBColorspace,True);
  5162.         SyncImage(image);
  5163.       }
  5164.   /*
  5165.     Initialize TIFF fields.
  5166.   */
  5167.   TIFFSetField(tiff,TIFFTAG_DOCUMENTNAME,image->filename);
  5168.   TIFFSetField(tiff,TIFFTAG_SOFTWARE,"ImageMagick");
  5169.   if (image->comments != (char *) NULL)
  5170.     TIFFSetField(tiff,TIFFTAG_IMAGEDESCRIPTION,image->comments);
  5171.   if ((image->class == DirectClass) || (image->colors > 256))
  5172.     {
  5173.       /*
  5174.         Full color TIFF raster.
  5175.       */
  5176.       photometric=PHOTOMETRIC_RGB;
  5177.       TIFFSetField(tiff,TIFFTAG_BITSPERSAMPLE,8);
  5178.       TIFFSetField(tiff,TIFFTAG_SAMPLESPERPIXEL,(image->alpha ? 4 : 3));
  5179.     }
  5180.   else
  5181.     {
  5182.       /*
  5183.         Colormapped TIFF raster.
  5184.       */
  5185.       photometric=PHOTOMETRIC_PALETTE;
  5186.       TIFFSetField(tiff,TIFFTAG_SAMPLESPERPIXEL,1);
  5187.       TIFFSetField(tiff,TIFFTAG_BITSPERSAMPLE,8);
  5188.       if (IsGrayImage(image))
  5189.         {
  5190.           /*
  5191.             Grayscale TIFF raster.
  5192.           */
  5193.           photometric=PHOTOMETRIC_MINISBLACK;
  5194.           if (image->colors == 2)
  5195.             TIFFSetField(tiff,TIFFTAG_BITSPERSAMPLE,1);
  5196.         }
  5197.     }
  5198.   TIFFSetField(tiff,TIFFTAG_PHOTOMETRIC,photometric);
  5199.   TIFFSetField(tiff,TIFFTAG_IMAGELENGTH,image->rows);
  5200.   TIFFSetField(tiff,TIFFTAG_IMAGEWIDTH,image->columns);
  5201.   TIFFSetField(tiff,TIFFTAG_FILLORDER,FILLORDER_MSB2LSB);
  5202.   TIFFSetField(tiff,TIFFTAG_ORIENTATION,ORIENTATION_TOPLEFT);
  5203.   TIFFSetField(tiff,TIFFTAG_PLANARCONFIG,PLANARCONFIG_CONTIG);
  5204.   TIFFSetField(tiff,TIFFTAG_COMPRESSION,COMPRESSION_LZW);
  5205.   if (image->compression == NoCompression)
  5206.     TIFFSetField(tiff,TIFFTAG_COMPRESSION,COMPRESSION_NONE);
  5207.   rows_per_strip=8192/TIFFScanlineSize(tiff);
  5208.   if (rows_per_strip == 0)
  5209.     rows_per_strip=1;
  5210.   TIFFSetField(tiff,TIFFTAG_ROWSPERSTRIP,rows_per_strip);
  5211.   scanline=(unsigned char *) malloc(TIFFScanlineSize(tiff));
  5212.   if (scanline == (unsigned char *) NULL)
  5213.     {
  5214.       Warning("Memory allocation error",(char *) NULL);
  5215.       return(False);
  5216.     }
  5217.   p=image->pixels;
  5218.   q=scanline;
  5219.   x=0;
  5220.   y=0;
  5221.   if (photometric == PHOTOMETRIC_RGB)
  5222.     for (i=0; i < image->packets; i++)
  5223.     {
  5224.       for (j=0; j <= (int) p->length; j++)
  5225.       {
  5226.         /*
  5227.           Convert DirectClass packets to contiguous RGB scanlines.
  5228.         */
  5229.         *q++=p->red;
  5230.         *q++=p->green;
  5231.         *q++=p->blue;
  5232.         if (image->alpha)
  5233.           *q++=(unsigned char) p->index;
  5234.         x++;
  5235.         if (x == image->columns)
  5236.           {
  5237.             if (TIFFWriteScanline(tiff,scanline,y,0) < 0)
  5238.               break;
  5239.             q=scanline;
  5240.             x=0;
  5241.             y++;
  5242.           }
  5243.       }
  5244.       p++;
  5245.     }
  5246.   else
  5247.     if (photometric == PHOTOMETRIC_PALETTE)
  5248.       {
  5249.         unsigned short
  5250.           blue[256],
  5251.           green[256],
  5252.           red[256];
  5253.  
  5254.         /*
  5255.           Initialize TIFF colormap.
  5256.         */
  5257.         for (i=0; i < image->colors; i++)
  5258.         {
  5259.           red[i]=(unsigned short)
  5260.             ((image->colormap[i].red*65535)/(unsigned int) MaxRGB);
  5261.           green[i]=(unsigned short)
  5262.             ((image->colormap[i].green*65535)/(unsigned int) MaxRGB);
  5263.           blue[i]=(unsigned short)
  5264.             ((image->colormap[i].blue*65535)/(unsigned int) MaxRGB);
  5265.         }
  5266.         TIFFSetField(tiff,TIFFTAG_COLORMAP,red,green,blue);
  5267.         /*
  5268.           Convert PseudoClass packets to contiguous colormap indexed scanlines.
  5269.         */
  5270.         for (i=0; i < image->packets; i++)
  5271.         {
  5272.           for (j=0; j <= (int) p->length; j++)
  5273.           {
  5274.             *q++=(unsigned char) p->index;
  5275.             x++;
  5276.             if (x == image->columns)
  5277.               {
  5278.                 if (TIFFWriteScanline(tiff,scanline,y,0) < 0)
  5279.                   break;
  5280.                 q=scanline;
  5281.                 x=0;
  5282.                 y++;
  5283.               }
  5284.           }
  5285.           p++;
  5286.         }
  5287.       }
  5288.     else
  5289.       if (image->colors > 2)
  5290.         for (i=0; i < image->packets; i++)
  5291.         {
  5292.           for (j=0; j <= (int) p->length; j++)
  5293.           {
  5294.             /*
  5295.               Convert PseudoClass packets to contiguous grayscale scanlines.
  5296.             */
  5297.             *q++=(unsigned char) image->colormap[p->index].red;
  5298.             x++;
  5299.             if (x == image->columns)
  5300.               {
  5301.                 if (TIFFWriteScanline(tiff,scanline,y,0) < 0)
  5302.                   break;
  5303.                 q=scanline;
  5304.                 x=0;
  5305.                 y++;
  5306.               }
  5307.           }
  5308.           p++;
  5309.         }
  5310.       else
  5311.         {
  5312.           register unsigned char
  5313.             bit,
  5314.             byte;
  5315.  
  5316.           /*
  5317.             Convert PseudoClass packets to contiguous monochrome scanlines.
  5318.           */
  5319.           bit=0;
  5320.           byte=0;
  5321.           x=0;
  5322.           for (i=0; i < image->packets; i++)
  5323.           {
  5324.             for (j=0; j <= (int) p->length; j++)
  5325.             {
  5326.               byte<<=1;
  5327.               if (p->index == 0)
  5328.                 byte|=0x01;
  5329.               bit++;
  5330.               if (bit == 8)
  5331.                 {
  5332.                   *q++=byte;
  5333.                   bit=0;
  5334.                   byte=0;
  5335.                 }
  5336.               x++;
  5337.               if (x == image->columns)
  5338.                 {
  5339.                   /*
  5340.                     Advance to the next scanline.
  5341.                   */
  5342.                   if (bit != 0)
  5343.                     *q++=byte << (8-bit);
  5344.                   if (TIFFWriteScanline(tiff,scanline,y,0) < 0)
  5345.                     break;
  5346.                   q=scanline;
  5347.                   bit=0;
  5348.                   byte=0;
  5349.                   x=0;
  5350.                   y++;
  5351.                }
  5352.             }
  5353.             p++;
  5354.           }
  5355.         }
  5356.   (void) free((char *) scanline);
  5357.   (void) TIFFFlushData(tiff);
  5358.   if (verbose == True)
  5359.     TIFFPrintDirectory(tiff,stderr,False);
  5360.   (void) TIFFClose(tiff);
  5361.   return(True);
  5362. }
  5363. #else
  5364. static unsigned int WriteTIFFImage(image,verbose)
  5365. Image
  5366.   *image;
  5367.  
  5368. unsigned int
  5369.   verbose;
  5370. {
  5371.   unsigned int
  5372.     status;
  5373.  
  5374.   Warning("TIFF library is not available",image->filename);
  5375.   status=WriteMIFFImage(image);
  5376.   return(status);
  5377. }
  5378. #endif
  5379.  
  5380. /*
  5381. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  5382. %                                                                             %
  5383. %                                                                             %
  5384. %                                                                             %
  5385. %   W r i t e V I C A R I m a g e                                             %
  5386. %                                                                             %
  5387. %                                                                             %
  5388. %                                                                             %
  5389. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  5390. %
  5391. %  Function WriteVICARImage writes an image in the VICAR rasterfile format.
  5392. %
  5393. %  The format of the WriteVICARImage routine is:
  5394. %
  5395. %      status=WriteVICARImage(image)
  5396. %
  5397. %  A description of each parameter follows.
  5398. %
  5399. %    o status: Function WriteVICARImage return True if the image is written.
  5400. %      False is returned is there is a memory shortage or if the image file
  5401. %      fails to write.
  5402. %
  5403. %    o image:  A pointer to a Image structure.
  5404. %
  5405. %
  5406. */
  5407. static unsigned int WriteVICARImage(image)
  5408. Image
  5409.   *image;
  5410. {
  5411.   unsigned int
  5412.     status;
  5413.  
  5414.   Warning("Cannot write VICAR images",image->filename);
  5415.   status=WriteMIFFImage(image);
  5416.   return(status);
  5417. }
  5418.  
  5419. /*
  5420. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  5421. %                                                                             %
  5422. %                                                                             %
  5423. %                                                                             %
  5424. %   W r i t e V I F F I m a g e                                               %
  5425. %                                                                             %
  5426. %                                                                             %
  5427. %                                                                             %
  5428. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  5429. %
  5430. %  Function WriteVIFFImage writes an image to a file in the VIFF image format.
  5431. %
  5432. %  The format of the WriteVIFFImage routine is:
  5433. %
  5434. %      status=WriteVIFFImage(image)
  5435. %
  5436. %  A description of each parameter follows.
  5437. %
  5438. %    o status: Function WriteVIFFImage return True if the image is written.
  5439. %      False is returned is there is a memory shortage or if the image file
  5440. %      fails to write.
  5441. %
  5442. %    o image:  A pointer to a Image structure.
  5443. %
  5444. %
  5445. */
  5446. static unsigned int WriteVIFFImage(image)
  5447. Image
  5448.   *image;
  5449. {
  5450. #define VFF_CM_genericRGB  15
  5451. #define VFF_CM_NONE  0
  5452. #define VFF_DEP_IEEEORDER  0x2
  5453. #define VFF_DES_RAW  0
  5454. #define VFF_LOC_IMPLICIT  1
  5455. #define VFF_MAPTYP_NONE  0
  5456. #define VFF_MAPTYP_1_BYTE  1
  5457. #define VFF_MS_NONE  0
  5458. #define VFF_MS_ONEPERBAND  1
  5459. #define VFF_TYP_BIT  0
  5460. #define VFF_TYP_1_BYTE  1
  5461.  
  5462.   typedef struct _ViffHeader
  5463.   {
  5464.     char
  5465.       identifier,
  5466.       file_type,
  5467.       release,
  5468.       version,
  5469.       machine_dependency,
  5470.       reserve[3],
  5471.       comment[512];
  5472.  
  5473.     unsigned long
  5474.       rows,
  5475.       columns,
  5476.       subrows;
  5477.  
  5478.     long
  5479.       x_offset,
  5480.       y_offset;
  5481.  
  5482.     unsigned int
  5483.       x_pixel_size,
  5484.       y_pixel_size;
  5485.  
  5486.     unsigned long
  5487.       location_type,
  5488.       location_dimension,
  5489.       number_of_images,
  5490.       number_data_bands,
  5491.       data_storage_type,
  5492.       data_encode_scheme,
  5493.       map_scheme,
  5494.       map_storage_type,
  5495.       map_rows,
  5496.       map_columns,
  5497.       map_subrows,
  5498.       map_enable,
  5499.       maps_per_cycle,
  5500.       color_space_model;
  5501.   } ViffHeader;
  5502.  
  5503.   register int
  5504.     i,
  5505.     j;
  5506.  
  5507.   register RunlengthPacket
  5508.     *p;
  5509.  
  5510.   register unsigned char
  5511.     *q;
  5512.  
  5513.   unsigned char
  5514.     buffer[8],
  5515.     *viff_pixels;
  5516.  
  5517.   unsigned long
  5518.     packets;
  5519.  
  5520.   ViffHeader
  5521.     viff_header;
  5522.  
  5523.   /*
  5524.     Open output image file.
  5525.   */
  5526.   OpenImage(image,"w");
  5527.   if (image->file == (FILE *) NULL)
  5528.     {
  5529.       Warning("Unable to open file",image->filename);
  5530.       return(False);
  5531.     }
  5532.   if (image->class == DirectClass)
  5533.     if (NumberColors(image,(FILE *) NULL) <= 256)
  5534.       {
  5535.         /*
  5536.           Demote DirectClass to PseudoClass.
  5537.         */
  5538.         QuantizeImage(image,256,8,False,RGBColorspace,True);
  5539.         SyncImage(image);
  5540.       }
  5541.   /*
  5542.     Initialize VIFF image structure.
  5543.   */
  5544.   viff_header.identifier=0xab;
  5545.   viff_header.file_type=1;
  5546.   viff_header.release=1;
  5547.   viff_header.version=3;
  5548.   viff_header.machine_dependency=VFF_DEP_IEEEORDER;  /* IEEE byte ordering */
  5549.   *viff_header.comment='\0';
  5550.   if (image->comments != (char *) NULL)
  5551.     {
  5552.       (void) strncpy(viff_header.comment,image->comments,
  5553.         Min((int) strlen(image->comments),511));
  5554.       viff_header.comment[Min((int) strlen(image->comments),511)]='\0';
  5555.     }
  5556.   viff_header.rows=image->columns;
  5557.   viff_header.columns=image->rows;
  5558.   viff_header.subrows=0;
  5559.   viff_header.x_offset=(~0);
  5560.   viff_header.y_offset=(~0);
  5561.   viff_header.x_pixel_size=0;
  5562.   viff_header.y_pixel_size=0;
  5563.   viff_header.location_type=VFF_LOC_IMPLICIT;
  5564.   viff_header.location_dimension=0;
  5565.   viff_header.number_of_images=1;
  5566.   viff_header.data_encode_scheme=VFF_DES_RAW;
  5567.   viff_header.map_scheme=VFF_MS_NONE;
  5568.   viff_header.map_storage_type=VFF_MAPTYP_NONE;
  5569.   viff_header.map_rows=0;
  5570.   viff_header.map_columns=0;
  5571.   viff_header.map_subrows=0;
  5572.   viff_header.map_enable=1;  /* no colormap */
  5573.   viff_header.maps_per_cycle=0;
  5574.   if ((image->class == DirectClass) || (image->colors > 256))
  5575.     {
  5576.       /*
  5577.         Full color VIFF raster.
  5578.       */
  5579.       viff_header.number_data_bands=image->alpha ? 4 : 3;
  5580.       viff_header.color_space_model=VFF_CM_genericRGB;
  5581.       viff_header.data_storage_type=VFF_TYP_1_BYTE;
  5582.       packets=image->columns*image->rows*viff_header.number_data_bands;
  5583.     }
  5584.   else
  5585.     {
  5586.       viff_header.number_data_bands=1;
  5587.       viff_header.color_space_model=VFF_CM_NONE;
  5588.       viff_header.data_storage_type=VFF_TYP_1_BYTE;
  5589.       packets=image->columns*image->rows;
  5590.       if (!IsGrayImage(image))
  5591.         {
  5592.           /*
  5593.             Colormapped VIFF raster.
  5594.           */
  5595.           viff_header.map_scheme=VFF_MS_ONEPERBAND;
  5596.           viff_header.map_storage_type=VFF_MAPTYP_1_BYTE;
  5597.           viff_header.map_rows=3;
  5598.           viff_header.map_columns=image->colors;
  5599.         }
  5600.       else
  5601.         if (image->colors == 2)
  5602.           {
  5603.             /*
  5604.               Monochrome VIFF raster.
  5605.             */
  5606.             viff_header.data_storage_type=VFF_TYP_BIT;
  5607.             packets=((image->columns+7) >> 3)*image->rows;
  5608.           }
  5609.     }
  5610.   /*
  5611.     Write VIFF image header (pad to 1024 bytes).
  5612.   */
  5613.   buffer[0]=viff_header.identifier;
  5614.   buffer[1]=viff_header.file_type;
  5615.   buffer[2]=viff_header.release;
  5616.   buffer[3]=viff_header.version;
  5617.   buffer[4]=viff_header.machine_dependency;
  5618.   buffer[5]=viff_header.reserve[0];
  5619.   buffer[6]=viff_header.reserve[1];
  5620.   buffer[7]=viff_header.reserve[2];
  5621.   (void) fwrite((char *) buffer,1,8,image->file);
  5622.   (void) fwrite((char *) viff_header.comment,1,512,image->file);
  5623.   MSBFirstWriteLong(viff_header.rows,image->file);
  5624.   MSBFirstWriteLong(viff_header.columns,image->file);
  5625.   MSBFirstWriteLong(viff_header.subrows,image->file);
  5626.   MSBFirstWriteLong((unsigned long) viff_header.x_offset,image->file);
  5627.   MSBFirstWriteLong((unsigned long) viff_header.y_offset,image->file);
  5628.   MSBFirstWriteLong((unsigned long) viff_header.x_pixel_size,image->file);
  5629.   MSBFirstWriteLong((unsigned long) viff_header.y_pixel_size,image->file);
  5630.   MSBFirstWriteLong(viff_header.location_type,image->file);
  5631.   MSBFirstWriteLong(viff_header.location_dimension,image->file);
  5632.   MSBFirstWriteLong(viff_header.number_of_images,image->file);
  5633.   MSBFirstWriteLong(viff_header.number_data_bands,image->file);
  5634.   MSBFirstWriteLong(viff_header.data_storage_type,image->file);
  5635.   MSBFirstWriteLong(viff_header.data_encode_scheme,image->file);
  5636.   MSBFirstWriteLong(viff_header.map_scheme,image->file);
  5637.   MSBFirstWriteLong(viff_header.map_storage_type,image->file);
  5638.   MSBFirstWriteLong(viff_header.map_rows,image->file);
  5639.   MSBFirstWriteLong(viff_header.map_columns,image->file);
  5640.   MSBFirstWriteLong(viff_header.map_subrows,image->file);
  5641.   MSBFirstWriteLong(viff_header.map_enable,image->file);
  5642.   MSBFirstWriteLong(viff_header.maps_per_cycle,image->file);
  5643.   MSBFirstWriteLong(viff_header.color_space_model,image->file);
  5644.   for (i=0; i < 420; i++)
  5645.     (void) fputc('\0',image->file);
  5646.   /*
  5647.     Convert MIFF to VIFF raster pixels.
  5648.   */
  5649.   viff_pixels=(unsigned char *) malloc(packets*sizeof(unsigned char));
  5650.   if (viff_pixels == (unsigned char *) NULL)
  5651.     {
  5652.       Warning("Unable to allocate memory",(char *) NULL);
  5653.       return(False);
  5654.     }
  5655.   p=image->pixels;
  5656.   q=viff_pixels;
  5657.   if ((image->class == DirectClass) || (image->colors > 256))
  5658.     {
  5659.       unsigned long
  5660.         offset;
  5661.  
  5662.       /*
  5663.         Convert DirectClass packet to VIFF RGB pixel.
  5664.       */
  5665.       offset=image->columns*image->rows;
  5666.       for (i=0; i < image->packets; i++)
  5667.       {
  5668.         for (j=0; j <= (int) p->length; j++)
  5669.         {
  5670.           *q=p->red;
  5671.           *(q+offset)=p->green;
  5672.           *(q+offset*2)=p->blue;
  5673.           if (image->alpha)
  5674.             *(q+offset*3)=(unsigned char) p->index;
  5675.           q++;
  5676.         }
  5677.         p++;
  5678.       }
  5679.     }
  5680.   else
  5681.     if (!IsGrayImage(image))
  5682.       {
  5683.         unsigned char
  5684.           *viff_colormap;
  5685.  
  5686.         /*
  5687.           Dump colormap to file.
  5688.         */
  5689.         viff_colormap=(unsigned char *)
  5690.           malloc(image->colors*3*sizeof(unsigned char));
  5691.         if (viff_colormap == (unsigned char *) NULL)
  5692.           {
  5693.             Warning("Unable to allocate memory",(char *) NULL);
  5694.             return(False);
  5695.           }
  5696.         q=viff_colormap;
  5697.         for (i=0; i < image->colors; i++)
  5698.           *q++=image->colormap[i].red;
  5699.         for (i=0; i < image->colors; i++)
  5700.           *q++=image->colormap[i].green;
  5701.         for (i=0; i < image->colors; i++)
  5702.           *q++=image->colormap[i].blue;
  5703.         (void) fwrite((char *) viff_colormap,1,(int) image->colors*3,
  5704.           image->file);
  5705.         (void) free((char *) viff_colormap);
  5706.         /*
  5707.           Convert PseudoClass packet to VIFF colormapped pixels.
  5708.         */
  5709.         q=viff_pixels;
  5710.         for (i=0; i < image->packets; i++)
  5711.         {
  5712.           for (j=0; j <= (int) p->length; j++)
  5713.             *q++=p->index;
  5714.           p++;
  5715.         }
  5716.       }
  5717.     else
  5718.       if (image->colors == 2)
  5719.         {
  5720.           register unsigned char
  5721.             bit,
  5722.             byte;
  5723.  
  5724.           register int
  5725.             x;
  5726.  
  5727.           /*
  5728.             Convert PseudoClass image to a VIFF monochrome image.
  5729.           */
  5730.           x=0;
  5731.           bit=0;
  5732.           byte=0;
  5733.           for (i=0; i < image->packets; i++)
  5734.           {
  5735.             for (j=0; j <= (int) p->length; j++)
  5736.             {
  5737.               byte>>=1;
  5738.               if (p->index == 1)
  5739.                 byte|=0x80;
  5740.               bit++;
  5741.               if (bit == 8)
  5742.                 {
  5743.                   *q++=byte;
  5744.                   bit=0;
  5745.                   byte=0;
  5746.                 }
  5747.               x++;
  5748.               if (x == image->columns)
  5749.                 {
  5750.                   /*
  5751.                     Advance to the next scanline.
  5752.                   */
  5753.                   if (bit != 0)
  5754.                     *q++=byte >> (8-bit);
  5755.                   bit=0;
  5756.                   byte=0;
  5757.                   x=0;
  5758.                }
  5759.             }
  5760.             p++;
  5761.           }
  5762.         }
  5763.       else
  5764.         {
  5765.           /*
  5766.             Convert PseudoClass packet to VIFF grayscale pixel.
  5767.           */
  5768.           for (i=0; i < image->packets; i++)
  5769.           {
  5770.             for (j=0; j <= (int) p->length; j++)
  5771.               *q++=p->red;
  5772.             p++;
  5773.           }
  5774.         }
  5775.   (void) fwrite((char *) viff_pixels,1,(int) packets,image->file);
  5776.   (void) free((char *) viff_pixels);
  5777.   CloseImage(image);
  5778.   return(True);
  5779. }
  5780.  
  5781. /*
  5782. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  5783. %                                                                             %
  5784. %                                                                             %
  5785. %                                                                             %
  5786. %   W r i t e X I m a g e                                                     %
  5787. %                                                                             %
  5788. %                                                                             %
  5789. %                                                                             %
  5790. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  5791. %
  5792. %  Function WriteXImage writes an image to an X server.
  5793. %
  5794. %  The format of the WriteXImage routine is:
  5795. %
  5796. %      status=WriteXImage(image,server_name)
  5797. %
  5798. %  A description of each parameter follows.
  5799. %
  5800. %    o status: Function WriteXImage return True if the image is displayed on
  5801. %      the X server.  False is returned is there is a memory shortage or if
  5802. %      the image file fails to write.
  5803. %
  5804. %    o image:  A pointer to a Image structure.
  5805. %
  5806. %    o server_name:  A pointer to a character string representing the
  5807. %      X server to display the image.
  5808. %
  5809. %
  5810. */
  5811. static unsigned int WriteXImage(image,server_name)
  5812. Image
  5813.   *image;
  5814.  
  5815. char
  5816.   *server_name;
  5817. {
  5818.   Atom
  5819.     delete_property,
  5820.     protocols_property;
  5821.  
  5822.   char
  5823.     *resource_value;
  5824.  
  5825.   Display
  5826.     *display;
  5827.  
  5828.   register char
  5829.     *p;
  5830.  
  5831.   unsigned int
  5832.     status;
  5833.  
  5834.   XResourceInfo
  5835.     resource_info;
  5836.  
  5837.   XrmDatabase
  5838.     resource_database,
  5839.     server_database;
  5840.  
  5841.   XEvent
  5842.     event;
  5843.  
  5844.   XPixelInfo
  5845.     pixel_info;
  5846.  
  5847.   XStandardColormap
  5848.     *map_info;
  5849.  
  5850.   XVisualInfo
  5851.     *visual_info;
  5852.  
  5853.   XWindowInfo
  5854.     window_info;
  5855.  
  5856.   /*
  5857.     Open X server connection.
  5858.   */
  5859.   display=XOpenDisplay(server_name);
  5860.   if (display == (Display *) NULL)
  5861.     {
  5862.       Warning("Unable to connect to X server",XDisplayName(server_name));
  5863.       return(False);
  5864.     }
  5865.   /*
  5866.     Set our forgiving error handler.
  5867.   */
  5868.   XSetErrorHandler(XError);
  5869.   /*
  5870.     Get user defaults from X resource database.
  5871.   */
  5872.   XrmInitialize();
  5873.   XGetDefault(display,client_name,"dummy");
  5874.   resource_database=XrmGetDatabase(display);
  5875.   resource_value=XResourceManagerString(display);
  5876.   if (resource_value == (char *) NULL)
  5877.     resource_value="";
  5878.   server_database=XrmGetStringDatabase(resource_value);
  5879.   XrmMergeDatabases(server_database,&resource_database);
  5880.   XGetResourceInfo(resource_database,client_name,&resource_info);
  5881.   /*
  5882.     Allocate standard colormap.
  5883.   */
  5884.   map_info=XAllocStandardColormap();
  5885.   if (map_info == (XStandardColormap *) NULL)
  5886.     Warning("Unable to create standard colormap","Memory allocation failed");
  5887.   else
  5888.     {
  5889.       /*
  5890.         Initialize visual info.
  5891.       */
  5892.       visual_info=XBestVisualInfo(display,map_info,&resource_info);
  5893.       if (visual_info == (XVisualInfo *) NULL)
  5894.         Warning("Unable to get visual",resource_info.visual_type);
  5895.       map_info->colormap=(Colormap) NULL;
  5896.       pixel_info.pixels=(unsigned long *) NULL;
  5897.     }
  5898.   /*
  5899.     Initialize atoms.
  5900.   */
  5901.   protocols_property=XInternAtom(display,"WM_PROTOCOLS",False);
  5902.   delete_property=XInternAtom(display,"WM_DELETE_WINDOW",False);
  5903.   if ((protocols_property == (Atom) NULL) || (delete_property == (Atom) NULL))
  5904.     Warning("Unable to create property",(char *) NULL);
  5905.   if ((map_info == (XStandardColormap *) NULL) ||
  5906.       (visual_info == (XVisualInfo *) NULL) ||
  5907.       (protocols_property == (Atom) NULL) || (delete_property == (Atom) NULL))
  5908.     {
  5909.       XFreeResources(display,visual_info,map_info,(XPixelInfo *) NULL,
  5910.         (XFontStruct *) NULL,&resource_info,(XWindowInfo *) NULL);
  5911.       DestroyImage(image);
  5912.       return(False);
  5913.     }
  5914.   /*
  5915.     Initialize Standard Colormap.
  5916.   */
  5917.   XMakeStandardColormap(display,visual_info,&resource_info,image,map_info,
  5918.     &pixel_info);
  5919.   pixel_info.annotate_context=(GC) NULL;
  5920.   pixel_info.highlight_context=(GC) NULL;
  5921.   pixel_info.widget_context=(GC) NULL;
  5922.   /*
  5923.     Initialize window info structure.
  5924.   */
  5925.   window_info.id=(Window) NULL;
  5926.   XGetWindowInfo(display,visual_info,map_info,&pixel_info,(XFontStruct *) NULL,
  5927.     &resource_info,&window_info);
  5928.   p=image->filename+strlen(image->filename)-1;
  5929.   while ((p > image->filename) && (*(p-1) != '/'))
  5930.     p--;
  5931.   window_info.name=p;
  5932.   window_info.width=image->columns;
  5933.   window_info.height=image->rows;
  5934.   window_info.attributes.event_mask=ButtonPressMask | ExposureMask;
  5935.   XMakeWindow(display,XRootWindow(display,visual_info->screen),(char **) NULL,0,
  5936.     (XClassHint *) NULL,(XWMHints *) NULL,delete_property,&window_info);
  5937.   /*
  5938.     Initialize graphic context.
  5939.   */
  5940.   window_info.annotate_context=
  5941.     XCreateGC(display,window_info.id,0,(XGCValues *) NULL);
  5942.   if (window_info.annotate_context == (GC) NULL)
  5943.     Warning("Unable to create property",(char *) NULL);
  5944.   /*
  5945.     Initialize X image.
  5946.   */
  5947.   status=XMakeImage(display,&resource_info,&window_info,image,image->columns,
  5948.     image->rows);
  5949.   if (status == False)
  5950.     Warning("Unable to make X image",(char *) NULL);
  5951.   if ((status == False) || (window_info.annotate_context == (GC) NULL))
  5952.     {
  5953.       XFreeResources(display,visual_info,map_info,&pixel_info,
  5954.         (XFontStruct *) NULL,&resource_info,&window_info);
  5955.       return(False);
  5956.     }
  5957.   /*
  5958.     Display image and wait for button press to exit.
  5959.   */
  5960.   XMapWindow(display,window_info.id);
  5961.   for ( ; ; )
  5962.   {
  5963.     XNextEvent(display,&event);
  5964.     if (event.type == ButtonPress)
  5965.       break;
  5966.     if (event.type == ClientMessage)
  5967.       if (event.xclient.message_type == protocols_property)
  5968.         if (*event.xclient.data.l == delete_property)
  5969.           if (event.xclient.window == window_info.id)
  5970.             break;
  5971.     if (event.type == Expose)
  5972.       XRefreshWindow(display,&window_info,&event);
  5973.   }
  5974.   XWithdrawWindow(display,window_info.id,window_info.screen);
  5975.   /*
  5976.     Free X resources.
  5977.   */
  5978.   XFreeResources(display,visual_info,map_info,&pixel_info,(XFontStruct *) NULL,
  5979.     &resource_info,&window_info);
  5980.   return(True);
  5981. }
  5982.  
  5983. /*
  5984. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  5985. %                                                                             %
  5986. %                                                                             %
  5987. %                                                                             %
  5988. %   W r i t e X B M I m a g e                                                 %
  5989. %                                                                             %
  5990. %                                                                             %
  5991. %                                                                             %
  5992. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  5993. %
  5994. %  Procedure WriteXBMImage writes an image to a file in the X bitmap format.
  5995. %
  5996. %  The format of the WriteXBMImage routine is:
  5997. %
  5998. %      status=WriteXBMImage(image)
  5999. %
  6000. %  A description of each parameter follows.
  6001. %
  6002. %    o status: Function WriteXBMImage return True if the image is written.
  6003. %      False is returned is there is a memory shortage or if the image file
  6004. %      fails to write.
  6005. %
  6006. %    o image:  A pointer to a Image structure.
  6007. %
  6008. %
  6009. */
  6010. static unsigned int WriteXBMImage(image)
  6011. Image
  6012.   *image;
  6013. {
  6014.   char
  6015.     name[MaxTextLength];
  6016.  
  6017.   register int
  6018.     i,
  6019.     j,
  6020.     x;
  6021.  
  6022.   register char
  6023.     *q;
  6024.  
  6025.   register RunlengthPacket
  6026.     *p;
  6027.  
  6028.   register unsigned char
  6029.     bit,
  6030.     byte;
  6031.  
  6032.   unsigned int
  6033.     count;
  6034.  
  6035.   /*
  6036.     Open output image file.
  6037.   */
  6038.   OpenImage(image,"w");
  6039.   if (image->file == (FILE *) NULL)
  6040.     {
  6041.       Warning("Unable to open file",image->filename);
  6042.       return(False);
  6043.     }
  6044.   /*
  6045.     Write X bitmap header.
  6046.   */
  6047.   (void) strcpy(name,image->filename);
  6048.   q=name;
  6049.   while ((*q != '.') && (*q != '\0'))
  6050.     q++;
  6051.   if (*q == '.')
  6052.     *q='\0';
  6053.   (void) fprintf(image->file,"#define %s_width %u\n",name,image->columns);
  6054.   (void) fprintf(image->file,"#define %s_height %u\n",name,image->rows);
  6055.   (void) fprintf(image->file,"static char %s_bits[] = {\n",name);
  6056.   (void) fprintf(image->file," ");
  6057.   /*
  6058.     Convert MIFF to X bitmap pixels.
  6059.   */
  6060.   QuantizeImage(image,2,8,False,GRAYColorspace,True);
  6061.   SyncImage(image);
  6062.   bit=0;
  6063.   byte=0;
  6064.   count=0;
  6065.   x=0;
  6066.   p=image->pixels;
  6067.   (void) fprintf(image->file," ");
  6068.   for (i=0; i < image->packets; i++)
  6069.   {
  6070.     for (j=0; j <= ((int) p->length); j++)
  6071.     {
  6072.       byte>>=1;
  6073.       if (p->index == 0)
  6074.         byte|=0x80;
  6075.       bit++;
  6076.       if (bit == 8)
  6077.         {
  6078.           /*
  6079.             Write a bitmap byte to the image file.
  6080.           */
  6081.           (void) fprintf(image->file,"0x%02x, ",byte & 0xff);
  6082.           count++;
  6083.           if (count == 12)
  6084.             {
  6085.               (void) fprintf(image->file,"\n  ");
  6086.               count=0;
  6087.             };
  6088.           bit=0;
  6089.           byte=0;
  6090.         }
  6091.       x++;
  6092.       if (x == image->columns)
  6093.         {
  6094.           if (bit != 0)
  6095.             {
  6096.               /*
  6097.                 Write a bitmap byte to the image file.
  6098.               */
  6099.               byte>>=(8-bit);
  6100.               (void) fprintf(image->file,"0x%02x, ",byte & 0xff);
  6101.               count++;
  6102.               if (count == 12)
  6103.                 {
  6104.                   (void) fprintf(image->file,"\n  ");
  6105.                   count=0;
  6106.                 };
  6107.               bit=0;
  6108.               byte=0;
  6109.             };
  6110.           x=0;
  6111.         }
  6112.     }
  6113.     p++;
  6114.   }
  6115.   (void) fprintf(image->file,"};\n");
  6116.   CloseImage(image);
  6117.   return(True);
  6118. }
  6119.  
  6120. /*
  6121. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  6122. %                                                                             %
  6123. %                                                                             %
  6124. %                                                                             %
  6125. %   W r i t e X C I m a g e                                                   %
  6126. %                                                                             %
  6127. %                                                                             %
  6128. %                                                                             %
  6129. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  6130. %
  6131. %  Function WriteXCImage writes an image in the X constant image format.
  6132. %
  6133. %  The format of the WriteXCImage routine is:
  6134. %
  6135. %      status=WriteXCImage(image)
  6136. %
  6137. %  A description of each parameter follows.
  6138. %
  6139. %    o status: Function WriteXCImage return True if the image is written.
  6140. %      False is returned is there is a memory shortage or if the image file
  6141. %      fails to write.
  6142. %
  6143. %    o image:  A pointer to a Image structure.
  6144. %
  6145. %
  6146. */
  6147. static unsigned int WriteXCImage(image)
  6148. Image
  6149.   *image;
  6150. {
  6151.   unsigned int
  6152.     status;
  6153.  
  6154.   Warning("Cannot write XC images",image->filename);
  6155.   status=WriteMIFFImage(image);
  6156.   return(status);
  6157. }
  6158.  
  6159. /*
  6160. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  6161. %                                                                             %
  6162. %                                                                             %
  6163. %                                                                             %
  6164. %   W r i t e X P M I m a g e                                                 %
  6165. %                                                                             %
  6166. %                                                                             %
  6167. %                                                                             %
  6168. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  6169. %
  6170. %  Procedure WriteXPMImage writes an image to a file in the X pixmap format.
  6171. %
  6172. %  The format of the WriteXPMImage routine is:
  6173. %
  6174. %      status=WriteXPMImage(image,server_name)
  6175. %
  6176. %  A description of each parameter follows.
  6177. %
  6178. %    o status: Function WriteXPMImage return True if the image is written.
  6179. %      False is returned is there is a memory shortage or if the image file
  6180. %      fails to write.
  6181. %
  6182. %    o image:  A pointer to a Image structure.
  6183. %
  6184. %    o server_name:  A pointer to a character string representing the
  6185. %      X server to display the image.
  6186. %
  6187. %
  6188. */
  6189. #ifdef HasXPM
  6190. #include "xpm.h"
  6191. static unsigned int WriteXPMImage(image,server_name)
  6192. Image
  6193.   *image;
  6194.  
  6195. char
  6196.   *server_name;
  6197. {
  6198.   char
  6199.     *resource_value,
  6200.     *xpm_buffer;
  6201.  
  6202.   Display
  6203.     *display;
  6204.  
  6205.   register char
  6206.     *p;
  6207.  
  6208.   unsigned int
  6209.     status;
  6210.  
  6211.   XResourceInfo
  6212.     resource_info;
  6213.  
  6214.   XrmDatabase
  6215.     resource_database,
  6216.     server_database;
  6217.  
  6218.   XPixelInfo
  6219.     pixel_info;
  6220.  
  6221.   XpmAttributes
  6222.     xpm_attributes;
  6223.  
  6224.   XStandardColormap
  6225.     *map_info;
  6226.  
  6227.   XVisualInfo
  6228.     *visual_info;
  6229.  
  6230.   XWindowInfo
  6231.     window_info;
  6232.  
  6233.   /*
  6234.     Open output image file.
  6235.   */
  6236.   OpenImage(image,"w");
  6237.   if (image->file == (FILE *) NULL)
  6238.     {
  6239.       Warning("Unable to open file",image->filename);
  6240.       return(False);
  6241.     }
  6242.   if ((image->class == DirectClass) || (image->colors > 256))
  6243.     {
  6244.       /*
  6245.         Demote DirectClass to PseudoClass.
  6246.       */
  6247.       QuantizeImage(image,256,8,True,RGBColorspace,True);
  6248.       SyncImage(image);
  6249.     }
  6250.   /*
  6251.     Open X server connection.
  6252.   */
  6253.   display=XOpenDisplay(server_name);
  6254.   if (display == (Display *) NULL)
  6255.     {
  6256.       Warning("Unable to connect to X server",XDisplayName(server_name));
  6257.       return(False);
  6258.     }
  6259.   /*
  6260.     Set our forgiving error handler.
  6261.   */
  6262.   XSetErrorHandler(XError);
  6263.   /*
  6264.     Get user defaults from X resource database.
  6265.   */
  6266.   XrmInitialize();
  6267.   XGetDefault(display,client_name,"dummy");
  6268.   resource_database=XrmGetDatabase(display);
  6269.   resource_value=XResourceManagerString(display);
  6270.   if (resource_value == (char *) NULL)
  6271.     resource_value="";
  6272.   server_database=XrmGetStringDatabase(resource_value);
  6273.   XrmMergeDatabases(server_database,&resource_database);
  6274.   XGetResourceInfo(resource_database,client_name,&resource_info);
  6275.   resource_info.colormap=PrivateColormap;
  6276.   /*
  6277.     Allocate standard colormap.
  6278.   */
  6279.   map_info=XAllocStandardColormap();
  6280.   if (map_info == (XStandardColormap *) NULL)
  6281.     Warning("Unable to create standard colormap","Memory allocation failed");
  6282.   else
  6283.     {
  6284.       /*
  6285.         Initialize visual info.
  6286.       */
  6287.       visual_info=XBestVisualInfo(display,map_info,&resource_info);
  6288.       if (visual_info == (XVisualInfo *) NULL)
  6289.         Warning("Unable to get visual",resource_info.visual_type);
  6290.       map_info->colormap=(Colormap) NULL;
  6291.       pixel_info.pixels=(unsigned long *) NULL;
  6292.     }
  6293.   /*
  6294.     Initialize atoms.
  6295.   */
  6296.   if ((map_info == (XStandardColormap *) NULL) ||
  6297.       (visual_info == (XVisualInfo *) NULL))
  6298.     {
  6299.       XFreeResources(display,visual_info,map_info,(XPixelInfo *) NULL,
  6300.         (XFontStruct *) NULL,&resource_info,(XWindowInfo *) NULL);
  6301.       DestroyImage(image);
  6302.       return(False);
  6303.     }
  6304.   /*
  6305.     Initialize Standard Colormap.
  6306.   */
  6307.   XMakeStandardColormap(display,visual_info,&resource_info,image,map_info,
  6308.     &pixel_info);
  6309.   pixel_info.annotate_context=(GC) NULL;
  6310.   pixel_info.highlight_context=(GC) NULL;
  6311.   pixel_info.widget_context=(GC) NULL;
  6312.   /*
  6313.     Initialize window info structure.
  6314.   */
  6315.   window_info.id=(Window) NULL;
  6316.   XGetWindowInfo(display,visual_info,map_info,&pixel_info,(XFontStruct *) NULL,
  6317.     &resource_info,&window_info);
  6318.   p=image->filename+strlen(image->filename)-1;
  6319.   while ((p > image->filename) && (*(p-1) != '/'))
  6320.     p--;
  6321.   window_info.name=p;
  6322.   window_info.width=image->columns;
  6323.   window_info.height=image->rows;
  6324.   XMakeWindow(display,XRootWindow(display,visual_info->screen),(char **) NULL,0,
  6325.     (XClassHint *) NULL,(XWMHints *) NULL,(Atom) NULL,&window_info);
  6326.   /*
  6327.     Initialize X image.
  6328.   */
  6329.   status=XMakeImage(display,&resource_info,&window_info,image,image->columns,
  6330.     image->rows);
  6331.   if (status == False)
  6332.     {
  6333.       Warning("Unable to make X image",(char *) NULL);
  6334.       XFreeResources(display,visual_info,map_info,&pixel_info,
  6335.         (XFontStruct *) NULL,&resource_info,&window_info);
  6336.       return(False);
  6337.     }
  6338.   /*
  6339.     Intialize XPM attributes.
  6340.   */
  6341.   xpm_attributes.valuemask=
  6342.     XpmColormap | XpmDepth | XpmRgbFilename | XpmSize | XpmVisual;
  6343.   xpm_attributes.visual=visual_info->visual;
  6344.   xpm_attributes.depth=visual_info->depth;
  6345.   xpm_attributes.colormap=map_info->colormap;
  6346.   xpm_attributes.rgb_fname=RGBColorDatabase;
  6347.   xpm_attributes.width=image->columns;
  6348.   xpm_attributes.height=image->rows;
  6349.   status=XpmCreateBufferFromImage(display,&xpm_buffer,window_info.ximage,
  6350.     (XImage *) NULL,&xpm_attributes);
  6351.   /*
  6352.     Free X resources.
  6353.   */
  6354.   XpmFreeAttributes(&xpm_attributes);
  6355.   XFreeResources(display,visual_info,map_info,&pixel_info,(XFontStruct *) NULL,
  6356.     &resource_info,&window_info);
  6357.   if (status != XpmSuccess)
  6358.     {
  6359.       Warning("Unable to write image",(char *) NULL);
  6360.       return(False);
  6361.     }
  6362.   /*
  6363.     Write XPM image.
  6364.   */
  6365.   status=fputs(xpm_buffer,image->file);
  6366.   (void) free((char *) xpm_buffer);
  6367.   CloseImage(image);
  6368.   return(status != EOF);
  6369. }
  6370. #else
  6371. static unsigned int WriteXPMImage(image,server_name)
  6372. Image
  6373.   *image;
  6374.  
  6375. char
  6376.   *server_name;
  6377. {
  6378.   unsigned int
  6379.     status;
  6380.  
  6381.   Warning("XPM library is not available",image->filename);
  6382.   status=WriteMIFFImage(image);
  6383.   return(status);
  6384. }
  6385. #endif
  6386.  
  6387. /*
  6388. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  6389. %                                                                             %
  6390. %                                                                             %
  6391. %                                                                             %
  6392. %   W r i t e Y U V I m a g e                                                 %
  6393. %                                                                             %
  6394. %                                                                             %
  6395. %                                                                             %
  6396. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  6397. %
  6398. %  Function WriteYUVImage writes an image to a file in the digital YUV
  6399. %  (CCIR 601 1:1:1) format.
  6400. %
  6401. %  The format of the WriteYUVImage routine is:
  6402. %
  6403. %      status=WriteYUVImage(image,interlace)
  6404. %
  6405. %  A description of each parameter follows.
  6406. %
  6407. %    o status: Function WriteYUVImage return True if the image is written.
  6408. %      False is returned is there is a memory shortage or if the image file
  6409. %      fails to write.
  6410. %
  6411. %    o image:  A pointer to a Image structure.
  6412. %
  6413. %    o interlace:  An unsigned integer that specifies the interlacing
  6414. %      scheme.
  6415. %
  6416. %
  6417. */
  6418. static unsigned int WriteYUVImage(image,interlace)
  6419. Image
  6420.   *image;
  6421.  
  6422. unsigned int
  6423.   interlace;
  6424. {
  6425.   register int
  6426.     i,
  6427.     j;
  6428.  
  6429.   register RunlengthPacket
  6430.     *p;
  6431.  
  6432.   register unsigned char
  6433.     *q;
  6434.  
  6435.   unsigned char
  6436.     *yuv_pixels;
  6437.  
  6438.   /*
  6439.     Open output image file.
  6440.   */
  6441.   OpenImage(image,"w");
  6442.   if (image->file == (FILE *) NULL)
  6443.     {
  6444.       Warning("Unable to open file",image->filename);
  6445.       return(False);
  6446.     }
  6447.   /*
  6448.     Convert MIFF to YUV raster pixels.
  6449.   */
  6450.   yuv_pixels=(unsigned char *)
  6451.     malloc(3*image->columns*image->rows*sizeof(unsigned char));
  6452.   if (yuv_pixels == (unsigned char *) NULL)
  6453.     {
  6454.       Warning("Unable to allocate memory",(char *) NULL);
  6455.       return(False);
  6456.     }
  6457.   RGBTransformImage(image,YCbCrColorspace);
  6458.   q=yuv_pixels;
  6459.   switch (interlace)
  6460.   {
  6461.     case NoneInterlace:
  6462.     default:
  6463.     {
  6464.       /*
  6465.         No interlacing:  YUVYUVYUVYUVYUVYUV...
  6466.       */
  6467.       p=image->pixels;
  6468.       for (i=0; i < image->packets; i++)
  6469.       {
  6470.         for (j=0; j <= ((int) p->length); j++)
  6471.         {
  6472.           *q++=p->red;
  6473.           *q++=p->green;
  6474.           *q++=p->blue;
  6475.         }
  6476.         p++;
  6477.       }
  6478.       break;
  6479.     }
  6480.     case LineInterlace:
  6481.     {
  6482.       register int
  6483.         x,
  6484.         y;
  6485.  
  6486.       /*
  6487.         Line interlacing:  YYY...UUU...VVV...YYY...UUU...VVV...
  6488.       */
  6489.       if (!UncompressImage(image))
  6490.         return(False);
  6491.       for (y=0; y < image->rows; y++)
  6492.       {
  6493.         p=image->pixels+(y*image->columns);
  6494.         for (x=0; x < image->columns; x++)
  6495.         {
  6496.           *q++=p->red;
  6497.           p++;
  6498.         }
  6499.         p=image->pixels+(y*image->columns);
  6500.         for (x=0; x < image->columns; x++)
  6501.         {
  6502.           *q++=p->green;
  6503.           p++;
  6504.         }
  6505.         p=image->pixels+(y*image->columns);
  6506.         for (x=0; x < image->columns; x++)
  6507.         {
  6508.           *q++=p->blue;
  6509.           p++;
  6510.         }
  6511.       }
  6512.       break;
  6513.     }
  6514.     case PlaneInterlace:
  6515.     {
  6516.       /*
  6517.         Plane interlacing:  YYYYYY...UUUUUU...VVVVVV...
  6518.       */
  6519.       p=image->pixels;
  6520.       for (i=0; i < image->packets; i++)
  6521.       {
  6522.         for (j=0; j <= ((int) p->length); j++)
  6523.           *q++=p->red;
  6524.         p++;
  6525.       }
  6526.       p=image->pixels;
  6527.       for (i=0; i < image->packets; i++)
  6528.       {
  6529.         for (j=0; j <= ((int) p->length); j++)
  6530.           *q++=p->green;
  6531.         p++;
  6532.       }
  6533.       p=image->pixels;
  6534.       for (i=0; i < image->packets; i++)
  6535.       {
  6536.         for (j=0; j <= ((int) p->length); j++)
  6537.           *q++=p->blue;
  6538.         p++;
  6539.       }
  6540.       break;
  6541.     }
  6542.   }
  6543.   (void) fwrite((char *) yuv_pixels,3,(int) (image->columns*image->rows),
  6544.     image->file);
  6545.   (void) free((char *) yuv_pixels);
  6546.   TransformRGBImage(image,YCbCrColorspace);
  6547.   CloseImage(image);
  6548.   return(True);
  6549. }
  6550.  
  6551. /*
  6552. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  6553. %                                                                             %
  6554. %                                                                             %
  6555. %                                                                             %
  6556. %   W r i t e Y U V 3 I m a g e                                               %
  6557. %                                                                             %
  6558. %                                                                             %
  6559. %                                                                             %
  6560. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  6561. %
  6562. %  Function WriteYUV3Image writes an image to a file in the digital YUV
  6563. %  (CCIR 601 2:1:1) format.
  6564. %
  6565. %  The format of the WriteYUV3Image routine is:
  6566. %
  6567. %      status=WriteYUV3Image(image)
  6568. %
  6569. %  A description of each parameter follows.
  6570. %
  6571. %    o status: Function WriteYUV3Image return True if the image is written.
  6572. %      False is returned is there is a memory shortage or if the image file
  6573. %      fails to write.
  6574. %
  6575. %    o image:  A pointer to a Image structure.
  6576. %
  6577. %
  6578. */
  6579. static unsigned int WriteYUV3Image(image)
  6580. Image
  6581.   *image;
  6582. {
  6583.   char
  6584.     filename[MaxTextLength];
  6585.  
  6586.   Image
  6587.     *scaled_image;
  6588.  
  6589.   register int
  6590.     i;
  6591.  
  6592.   register RunlengthPacket
  6593.     *p;
  6594.  
  6595.   register unsigned char
  6596.     *q;
  6597.  
  6598.   unsigned char
  6599.     *yuv_pixels;
  6600.  
  6601.   if (!UncompressImage(image))
  6602.     return(False);
  6603.   /*
  6604.     Open output image file.
  6605.   */
  6606.   (void) strcpy(filename,image->filename);
  6607.   if (strcmp(image->filename,"-") != 0)
  6608.     (void) strcat(image->filename,".Y");
  6609.   OpenImage(image,"w");
  6610.   if (image->file == (FILE *) NULL)
  6611.     {
  6612.       Warning("Unable to open file",image->filename);
  6613.       return(False);
  6614.     }
  6615.   /*
  6616.     Write Y channel.
  6617.   */
  6618.   yuv_pixels=(unsigned char *)
  6619.     malloc(image->columns*image->rows*sizeof(unsigned char));
  6620.   if (yuv_pixels == (unsigned char *) NULL)
  6621.     {
  6622.       Warning("Unable to allocate memory",(char *) NULL);
  6623.       return(False);
  6624.     }
  6625.   RGBTransformImage(image,YCbCrColorspace);
  6626.   p=image->pixels;
  6627.   q=yuv_pixels;
  6628.   for (i=0; i < (image->rows*image->columns); i++)
  6629.   {
  6630.     *q=p->red;
  6631.     p++;
  6632.     q++;
  6633.   }
  6634.   (void) fwrite((char *) yuv_pixels,1,(int) (image->columns*image->rows),
  6635.     image->file);
  6636.   CloseImage(image);
  6637.   /*
  6638.     Scale image.
  6639.   */
  6640.   image->orphan=True;
  6641.   scaled_image=ScaleImage(image,image->columns >> 1,image->rows >> 1);
  6642.   image->orphan=False;
  6643.   if (scaled_image == (Image *) NULL)
  6644.     {
  6645.       Warning("Unable to scale image",image->filename);
  6646.       return(False);
  6647.     }
  6648.   /*
  6649.     Write U channel.
  6650.   */
  6651.   (void) strcpy(scaled_image->filename,filename);
  6652.   if (strcmp(scaled_image->filename,"-") != 0)
  6653.     (void) strcat(scaled_image->filename,".U");
  6654.   OpenImage(scaled_image,"w");
  6655.   if (scaled_image->file == (FILE *) NULL)
  6656.     {
  6657.       Warning("Unable to open file",scaled_image->filename);
  6658.       DestroyImage(scaled_image);
  6659.       return(False);
  6660.     }
  6661.   p=scaled_image->pixels;
  6662.   q=yuv_pixels;
  6663.   for (i=0; i < (scaled_image->rows*scaled_image->columns); i++)
  6664.   {
  6665.     *q=p->green;
  6666.     p++;
  6667.     q++;
  6668.   }
  6669.   (void) fwrite((char *) yuv_pixels,1,(int)
  6670.     (scaled_image->columns*scaled_image->rows),scaled_image->file);
  6671.   CloseImage(scaled_image);
  6672.   /*
  6673.     Write V channel.
  6674.   */
  6675.   (void) strcpy(scaled_image->filename,filename);
  6676.   if (strcmp(scaled_image->filename,"-") != 0)
  6677.     (void) strcat(scaled_image->filename,".V");
  6678.   OpenImage(scaled_image,"w");
  6679.   if (scaled_image->file == (FILE *) NULL)
  6680.     {
  6681.       Warning("Unable to open file",scaled_image->filename);
  6682.       DestroyImage(scaled_image);
  6683.       return(False);
  6684.     }
  6685.   p=scaled_image->pixels;
  6686.   q=yuv_pixels;
  6687.   for (i=0; i < (scaled_image->rows*scaled_image->columns); i++)
  6688.   {
  6689.     *q=p->blue;
  6690.     p++;
  6691.     q++;
  6692.   }
  6693.   (void) fwrite((char *) yuv_pixels,1,(int)
  6694.     (scaled_image->columns*scaled_image->rows),scaled_image->file);
  6695.   CloseImage(scaled_image);
  6696.   DestroyImage(scaled_image);
  6697.   (void) free((char *) yuv_pixels);
  6698.   TransformRGBImage(image,YCbCrColorspace);
  6699.   (void) sprintf(image->filename,filename);
  6700.   return(True);
  6701. }
  6702.  
  6703. /*
  6704. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  6705. %                                                                             %
  6706. %                                                                             %
  6707. %                                                                             %
  6708. %   W r i t e X W D I m a g e                                                 %
  6709. %                                                                             %
  6710. %                                                                             %
  6711. %                                                                             %
  6712. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  6713. %
  6714. %  Function WriteXWDImage writes an image to a file in X window dump
  6715. %  rasterfile format.
  6716. %
  6717. %  The format of the WriteXWDImage routine is:
  6718. %
  6719. %      status=WriteXWDImage(image)
  6720. %
  6721. %  A description of each parameter follows.
  6722. %
  6723. %    o status: Function WriteXWDImage return True if the image is written.
  6724. %      False is returned is there is a memory shortage or if the image file
  6725. %      fails to write.
  6726. %
  6727. %    o image:  A pointer to a Image structure.
  6728. %
  6729. %
  6730. */
  6731. static unsigned int WriteXWDImage(image)
  6732. Image
  6733.   *image;
  6734. {
  6735.   int
  6736.     x;
  6737.  
  6738.   register int
  6739.     i,
  6740.     j;
  6741.  
  6742.   register RunlengthPacket
  6743.     *p;
  6744.  
  6745.   register unsigned char
  6746.     *q;
  6747.  
  6748.   unsigned char
  6749.     *xwd_pixels;
  6750.  
  6751.   unsigned int
  6752.     scanline_pad;
  6753.  
  6754.   unsigned long
  6755.     packets;
  6756.  
  6757.   XWDFileHeader
  6758.     xwd_header;
  6759.  
  6760.   /*
  6761.     Open output image file.
  6762.   */
  6763.   OpenImage(image,"w");
  6764.   if (image->file == (FILE *) NULL)
  6765.     {
  6766.       Warning("Unable to open file",image->filename);
  6767.       return(False);
  6768.     }
  6769.   if (image->class == DirectClass)
  6770.     if (NumberColors(image,(FILE *) NULL) <= 256)
  6771.       {
  6772.         /*
  6773.           Demote DirectClass to PseudoClass.
  6774.         */
  6775.         QuantizeImage(image,256,8,False,RGBColorspace,True);
  6776.         SyncImage(image);
  6777.       }
  6778.   /*
  6779.     Initialize XWD file header.
  6780.   */
  6781.   xwd_header.header_size=100+strlen(image->filename)+1;
  6782.   xwd_header.file_version=(unsigned long) XWD_FILE_VERSION;
  6783.   xwd_header.pixmap_format=(unsigned long) ZPixmap;
  6784.   xwd_header.pixmap_depth=(unsigned long)
  6785.     (image->class == DirectClass ? 24 : 8);
  6786.   xwd_header.pixmap_width=(unsigned long) image->columns;
  6787.   xwd_header.pixmap_height=(unsigned long) image->rows;
  6788.   xwd_header.xoffset=(unsigned long) 0;
  6789.   xwd_header.byte_order=(unsigned long) MSBFirst;
  6790.   xwd_header.bitmap_unit=(unsigned long) (image->class == DirectClass ? 32 : 8);
  6791.   xwd_header.bitmap_bit_order=(unsigned long) MSBFirst;
  6792.   xwd_header.bitmap_pad=(unsigned long) (image->class == DirectClass ? 32 : 8);
  6793.   xwd_header.bits_per_pixel=(unsigned long)
  6794.     (image->class == DirectClass ? 24 : 8);
  6795.   xwd_header.bytes_per_line=(unsigned long) ((((xwd_header.bits_per_pixel*
  6796.     xwd_header.pixmap_width)+((xwd_header.bitmap_pad)-1))/
  6797.     (xwd_header.bitmap_pad))*((xwd_header.bitmap_pad) >> 3));
  6798.   xwd_header.visual_class=(unsigned long)
  6799.     (image->class == DirectClass ? DirectColor : PseudoColor);
  6800.   xwd_header.red_mask=(unsigned long)
  6801.     (image->class == DirectClass ? 0xff0000 : 0);
  6802.   xwd_header.green_mask=(unsigned long)
  6803.     (image->class == DirectClass ? 0xff00 : 0);
  6804.   xwd_header.blue_mask=(unsigned long) (image->class == DirectClass ? 0xff : 0);
  6805.   xwd_header.bits_per_rgb=(unsigned long)
  6806.     (image->class == DirectClass ? 24 : 8);
  6807.   xwd_header.colormap_entries=(unsigned long)
  6808.     (image->class == DirectClass ? 256 : image->colors);
  6809.   xwd_header.ncolors=(image->class == DirectClass ? 0 : image->colors);
  6810.   xwd_header.window_width=(unsigned long) image->columns;
  6811.   xwd_header.window_height=(unsigned long) image->rows;
  6812.   xwd_header.window_x=0;
  6813.   xwd_header.window_y=0;
  6814.   xwd_header.window_bdrwidth=(unsigned long) 0;
  6815.   /*
  6816.     Write XWD header.
  6817.   */
  6818.   MSBFirstWriteLong(xwd_header.header_size,image->file);
  6819.   MSBFirstWriteLong(xwd_header.file_version,image->file);
  6820.   MSBFirstWriteLong(xwd_header.pixmap_format,image->file);
  6821.   MSBFirstWriteLong(xwd_header.pixmap_depth,image->file);
  6822.   MSBFirstWriteLong(xwd_header.pixmap_width,image->file);
  6823.   MSBFirstWriteLong(xwd_header.pixmap_height,image->file);
  6824.   MSBFirstWriteLong(xwd_header.xoffset,image->file);
  6825.   MSBFirstWriteLong(xwd_header.byte_order,image->file);
  6826.   MSBFirstWriteLong(xwd_header.bitmap_unit,image->file);
  6827.   MSBFirstWriteLong(xwd_header.bitmap_bit_order,image->file);
  6828.   MSBFirstWriteLong(xwd_header.bitmap_pad,image->file);
  6829.   MSBFirstWriteLong(xwd_header.bits_per_pixel,image->file);
  6830.   MSBFirstWriteLong(xwd_header.bytes_per_line,image->file);
  6831.   MSBFirstWriteLong(xwd_header.visual_class,image->file);
  6832.   MSBFirstWriteLong(xwd_header.red_mask,image->file);
  6833.   MSBFirstWriteLong(xwd_header.green_mask,image->file);
  6834.   MSBFirstWriteLong(xwd_header.blue_mask,image->file);
  6835.   MSBFirstWriteLong(xwd_header.bits_per_rgb,image->file);
  6836.   MSBFirstWriteLong(xwd_header.colormap_entries,image->file);
  6837.   MSBFirstWriteLong(xwd_header.ncolors,image->file);
  6838.   MSBFirstWriteLong(xwd_header.window_width,image->file);
  6839.   MSBFirstWriteLong(xwd_header.window_height,image->file);
  6840.   MSBFirstWriteLong(xwd_header.window_x,image->file);
  6841.   MSBFirstWriteLong(xwd_header.window_y,image->file);
  6842.   MSBFirstWriteLong(xwd_header.window_bdrwidth,image->file);
  6843.   (void) fwrite((char *) image->filename,1,strlen(image->filename)+1,
  6844.     image->file);
  6845.   if (image->class == PseudoClass)
  6846.     {
  6847.       unsigned long
  6848.         lsb_first;
  6849.  
  6850.       XColor
  6851.         *colors;
  6852.  
  6853.       /*
  6854.         Dump colormap to file.
  6855.       */
  6856.       colors=(XColor *) malloc(image->colors*sizeof(XColor));
  6857.       if (colors == (XColor *) NULL)
  6858.         {
  6859.           Warning("Unable to allocate memory",(char *) NULL);
  6860.           return(False);
  6861.         }
  6862.       lsb_first=1;
  6863.       for (i=0; i < image->colors; i++)
  6864.       {
  6865.         colors[i].pixel=i;
  6866.         colors[i].red=image->colormap[i].red << 8;
  6867.         colors[i].green=image->colormap[i].green << 8;
  6868.         colors[i].blue=image->colormap[i].blue << 8;
  6869.         colors[i].flags=DoRed | DoGreen | DoBlue;
  6870.         colors[i].pad=0;
  6871.         if (*(char *) &lsb_first)
  6872.           {
  6873.             MSBFirstOrderLong((char *) &colors[i].pixel,sizeof(long));
  6874.             MSBFirstOrderShort((char *) &colors[i].red,3*sizeof(short));
  6875.           }
  6876.       }
  6877.       (void) fwrite((char *) colors,sizeof(XColor),(int) image->colors,
  6878.         image->file);
  6879.       (void) free((char *) colors);
  6880.     }
  6881.   /*
  6882.     Convert MIFF to XWD raster pixels.
  6883.   */
  6884.   packets=xwd_header.bytes_per_line*xwd_header.pixmap_height;
  6885.   xwd_pixels=(unsigned char *)
  6886.     malloc((unsigned int) packets*sizeof(unsigned char));
  6887.   if (xwd_pixels == (unsigned char *) NULL)
  6888.     {
  6889.       Warning("Unable to allocate memory",(char *) NULL);
  6890.       return(False);
  6891.     }
  6892.   scanline_pad=(unsigned int) (xwd_header.bytes_per_line-
  6893.     ((xwd_header.pixmap_width*xwd_header.bits_per_pixel) >> 3));
  6894.   x=0;
  6895.   p=image->pixels;
  6896.   q=xwd_pixels;
  6897.   for (i=0; i < image->packets; i++)
  6898.   {
  6899.     for (j=0; j <= ((int) p->length); j++)
  6900.     {
  6901.       if (image->class == PseudoClass)
  6902.         *q++=p->index;
  6903.       else
  6904.         {
  6905.           *q++=p->red;
  6906.           *q++=p->green;
  6907.           *q++=p->blue;
  6908.         }
  6909.       x++;
  6910.       if (x == image->columns)
  6911.         {
  6912.           q+=scanline_pad;
  6913.           x=0;
  6914.         }
  6915.     }
  6916.     p++;
  6917.   }
  6918.   /*
  6919.     Dump pixels to file.
  6920.   */
  6921.   (void) fwrite((char *) xwd_pixels,1,(int) packets,image->file);
  6922.   (void) free((char *) xwd_pixels);
  6923.   CloseImage(image);
  6924.   return(True);
  6925. }
  6926.  
  6927. /*
  6928. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  6929. %                                                                             %
  6930. %                                                                             %
  6931. %                                                                             %
  6932. %   W r i t e I m a g e                                                       %
  6933. %                                                                             %
  6934. %                                                                             %
  6935. %                                                                             %
  6936. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  6937. %
  6938. %  Function WriteImage writes an image to a file.  You can specify a
  6939. %  particular image format by prefixing the file with the image type and a
  6940. %  colon (i.e. ps:image) or specify the image type as the filename suffix
  6941. %  (i.e. image.ps).
  6942. %
  6943. %  The format of the WriteImage routine is:
  6944. %
  6945. %      status=WriteImage(image_info,image)
  6946. %
  6947. %  A description of each parameter follows:
  6948. %
  6949. %    o status: Function WriteImage return True if the image is written.
  6950. %      False is returned is there is a memory shortage or if the image file
  6951. %      fails to write.
  6952. %
  6953. %    o image_info: Specifies a pointer to an ImageInfo structure.
  6954. %
  6955. %    o image: A pointer to a Image structure.
  6956. %
  6957. %
  6958. */
  6959. unsigned int WriteImage(image_info,image)
  6960. ImageInfo
  6961.   *image_info;
  6962.  
  6963. Image
  6964.   *image;
  6965. {
  6966.   unsigned int
  6967.     status;
  6968.  
  6969.   /*
  6970.     Call appropriate image writer based on image type.
  6971.   */
  6972.   (void) strcpy(image_info->filename,image->filename);
  6973.   (void) strcpy(image_info->magick,image->magick);
  6974.   SetImageMagick(image_info);
  6975.   (void) strcpy(image->filename,image_info->filename);
  6976.   (void) strcpy(image->magick,image_info->magick);
  6977.   switch (*image_info->magick)
  6978.   {
  6979.     case 'A':
  6980.     {
  6981.       if (strcmp(image_info->magick,"ALPHA") == 0)
  6982.         status=WriteALPHAImage(image);
  6983.       else
  6984.         status=WriteAVSImage(image);
  6985.       break;
  6986.     }
  6987.     case 'B':
  6988.     {
  6989.       status=WriteBMPImage(image);
  6990.       break;
  6991.     }
  6992.     case 'C':
  6993.     {
  6994.       status=WriteCMYKImage(image,image_info->interlace,image_info->undercolor);
  6995.       break;
  6996.     }
  6997.     case 'E':
  6998.     {
  6999.       status=WritePSImage(image,image_info->page,image_info->density);
  7000.       break;
  7001.     }
  7002.     case 'F':
  7003.     {
  7004.       if (strcmp(image_info->magick,"FAX") == 0)
  7005.         status=WriteFAXImage(image);
  7006.       else
  7007.         status=WriteFITSImage(image);
  7008.       break;
  7009.     }
  7010.     case 'G':
  7011.     {
  7012.       if (strcmp(image_info->magick,"GIF") == 0)
  7013.         status=WriteGIFImage(image);
  7014.       else
  7015.         if (strcmp(image_info->magick,"GIF87") == 0)
  7016.           status=WriteGIFImage(image);
  7017.         else
  7018.           if (strcmp(image_info->magick,"GRAY") == 0)
  7019.             status=WriteGRAYImage(image);
  7020.           else
  7021.             status=WriteFAXImage(image);
  7022.       break;
  7023.     }
  7024.     case 'H':
  7025.     {
  7026.       status=WriteHISTOGRAMImage(image);
  7027.       break;
  7028.     }
  7029.     case 'I':
  7030.     {
  7031.       status=WriteIRISImage(image);
  7032.       break;
  7033.     }
  7034.     case 'J':
  7035.     {
  7036.       status=WriteJPEGImage(image,image_info->quality);
  7037.       break;
  7038.     }
  7039.     case 'M':
  7040.     {
  7041.       if (strcmp(image_info->magick,"MAP") == 0)
  7042.         status=WriteMAPImage(image);
  7043.       else
  7044.         if (strcmp(image_info->magick,"MIFF") == 0)
  7045.           status=WriteMIFFImage(image);
  7046.         else
  7047.           status=WriteMTVImage(image);
  7048.       break;
  7049.     }
  7050.     case 'P':
  7051.     {
  7052.       if (strcmp(image_info->magick,"PCD") == 0)
  7053.         status=WritePCDImage(image);
  7054.       else
  7055.         if (strcmp(image_info->magick,"PCX") == 0)
  7056.           status=WritePCXImage(image);
  7057.         else
  7058.           if (strcmp(image_info->magick,"PICT") == 0)
  7059.             status=WritePICTImage(image);
  7060.           else
  7061.             if (strcmp(image_info->magick,"PM") == 0)
  7062.               status=WriteXPMImage(image,image_info->server_name);
  7063.             else
  7064.               if (strcmp(image_info->magick,"PS") == 0)
  7065.                 status=WritePSImage(image,image_info->page,image_info->density);
  7066.               else
  7067.                 if (strcmp(image_info->magick,"PS2") == 0)
  7068.                   status=
  7069.                     WritePS2Image(image,image_info->page,image_info->density);
  7070.                 else
  7071.                   status=WritePNMImage(image);
  7072.       break;
  7073.     }
  7074.     case 'R':
  7075.     {
  7076.       if (strcmp(image_info->magick,"RAS") == 0)
  7077.         status=WriteSUNImage(image);
  7078.       else
  7079.         if (strcmp(image_info->magick,"RGB") == 0)
  7080.           status=WriteRGBImage(image,image_info->interlace);
  7081.         else
  7082.           status=WriteRLEImage(image);
  7083.       break;
  7084.     }
  7085.     case 'S':
  7086.     {
  7087.       status=WriteSUNImage(image);
  7088.       break;
  7089.     }
  7090.     case 'T':
  7091.     {
  7092.       if (strcmp(image_info->magick,"TGA") == 0)
  7093.         status=WriteTARGAImage(image);
  7094.       else
  7095.         if ((strcmp(image_info->magick,"TIF") == 0) ||
  7096.             (strcmp(image_info->magick,"TIFF") == 0))
  7097.           status=WriteTIFFImage(image,image_info->verbose);
  7098.         else
  7099.           status=WriteTEXTImage(image);
  7100.       break;
  7101.     }
  7102.     case 'V':
  7103.     {
  7104.       if (strcmp(image_info->magick,"VICAR") == 0)
  7105.         status=WriteVICARImage(image);
  7106.       else
  7107.         status=WriteVIFFImage(image);
  7108.       break;
  7109.     }
  7110.     case 'X':
  7111.     {
  7112.       if (strcmp(image_info->magick,"X") == 0)
  7113.         status=WriteXImage(image,image_info->server_name);
  7114.       else
  7115.         if (strcmp(image_info->magick,"XBM") == 0)
  7116.           status=WriteXBMImage(image);
  7117.         else
  7118.           if (strcmp(image_info->magick,"XC") == 0)
  7119.             status=WriteXCImage(image);
  7120.           else
  7121.             if (strcmp(image_info->magick,"XPM") == 0)
  7122.               status=WriteXPMImage(image,image_info->server_name);
  7123.             else
  7124.               if (strcmp(image_info->magick,"XV") == 0)
  7125.                 status=WriteVIFFImage(image);
  7126.               else
  7127.                 status=WriteXWDImage(image);
  7128.       break;
  7129.     }
  7130.     case 'Y':
  7131.     {
  7132.       if (strcmp(image_info->magick,"YUV") == 0)
  7133.         status=WriteYUVImage(image,image_info->interlace);
  7134.       else
  7135.         status=WriteYUV3Image(image);
  7136.       break;
  7137.     }
  7138.     default:
  7139.       status=WriteMIFFImage(image);
  7140.   }
  7141.   if (image->status)
  7142.     {
  7143.       Warning("An error has occurred writing to file",image->filename);
  7144.       return(False);
  7145.     }
  7146.   return(status);
  7147. }
  7148.