home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 1 / 1321 / sun2ps.c < prev   
Encoding:
C/C++ Source or Header  |  1990-12-28  |  24.3 KB  |  804 lines

  1. /*
  2. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  3. %                                                                             %
  4. %                                                                             %
  5. %                                                                             %
  6. %                  SSSSS  U   U  N   N  22222  PPPP   SSSSS                   %
  7. %                  SS     U   U  NN  N      2  P   P  S                       %
  8. %                   SSS   U   U  N N N   222   PPPP    SSS                    %
  9. %                     SS  U   U  N  NN  2      P          S                   %
  10. %                  SSSSS   UUU   N   N  22222  P      SSSSS                   %
  11. %                                                                             %
  12. %                                                                             %
  13. %                  Import SUN image to a postscript format.                   %
  14. %                                                                             %
  15. %                                                                             %
  16. %                                                                             %
  17. %                           Software Design                                   %
  18. %                             John Cristy                                     %
  19. %                            January  1990                                    %
  20. %                                                                             %
  21. %                                                                             %
  22. %  Copyright 1990 E. I. Dupont de Nemours & Company                           %
  23. %                                                                             %
  24. %  Permission to use, copy, modify, distribute, and sell this software and    %
  25. %  its documentation for any purpose is hereby granted without fee,           %
  26. %  provided that the above copyright notice appear in all copies and that     %
  27. %  both that copyright notice and this permission notice appear in            %
  28. %  supporting documentation, and that the name of E. I. Dupont de Nemours     %
  29. %  & Company not be used in advertising or publicity pertaining to            %
  30. %  distribution of the software without specific, written prior               %
  31. %  permission.  E. I. Dupont de Nemours & Company makes no representations    %
  32. %  about the suitability of this software for any purpose.  It is provided    %
  33. %  "as is" without express or implied warranty.                               %
  34. %                                                                             %
  35. %  E. I. Dupont de Nemours & Company disclaims all warranties with regard     %
  36. %  to this software, including all implied warranties of merchantability      %
  37. %  and fitness, in no event shall E. I. Dupont de Nemours & Company be        %
  38. %  liable for any special, indirect or consequential damages or any           %
  39. %  damages whatsoever resulting from loss of use, data or profits, whether    %
  40. %  in an action of contract, negligence or other tortious action, arising     %
  41. %  out of or in connection with the use or performance of this software.      %
  42. %                                                                             %
  43. %                                                                             %
  44. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  45. %
  46. %  The Sun2ps program reads a sun image and converts it to postscript format.
  47. %  The image can then be printed on a postscript compatible printer in either
  48. %  color or grayscale.
  49. %
  50. %  The Sun2ps program command syntax is:
  51. %
  52. %  Usage: sun2ps [options ...] file
  53. %
  54. %  Where options include:
  55. %    +grayscale     print image as gray scale colors
  56. %
  57. %  Specify 'file' as '-' for standard output.
  58. %
  59. %  Change '+' to '-' in any option above to reverse its effect.
  60. %  For example, -borders means do not include image borders).
  61. %
  62. %
  63. */
  64.  
  65. #include <string.h>
  66. #include "display.h"
  67.  
  68. /*
  69. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  70. %                                                                             %
  71. %                                                                             %
  72. %                                                                             %
  73. %   C o m p r e s s I m a g e                                                 %
  74. %                                                                             %
  75. %                                                                             %
  76. %                                                                             %
  77. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  78. %
  79. %  Function CompressImage compresses an image into runlength-encoded packets.
  80. %
  81. %  The format of the CompressImage routine is:
  82. %
  83. %      CompressImage(image)
  84. %
  85. %  A description of each parameter follows:
  86. %
  87. %    o image:  The address of a structure of type Image.
  88. %
  89. %
  90. */
  91. unsigned int CompressImage(image)
  92. Image
  93.   *image;
  94. {
  95.   Image
  96.     compressed_image;
  97.  
  98.   register int
  99.     i;
  100.  
  101.   register RunlengthPacket
  102.     *p;
  103.  
  104.   unsigned int
  105.     InitializeChannel(),
  106.     WritePacket();
  107.  
  108.   compressed_image.pixels=(RunlengthPacket *)
  109.     malloc(image->packets*sizeof(RunlengthPacket));
  110.   if (compressed_image.pixels == (RunlengthPacket *) NULL)
  111.     {
  112.       (void) fprintf(stderr,"Can't compress image, not enough memory.\n");
  113.       return(False);
  114.     }
  115.   compressed_image.channel=InitializeChannel(compressed_image.pixels);
  116.   compressed_image.packets=0;
  117.   p=image->pixels;
  118.   for (i=0; i < image->packets; i++)
  119.   {
  120.     compressed_image.packets+=WritePacket(compressed_image.channel,p->red,
  121.       p->green,p->blue,p->index,p->length+1);
  122.     p++;
  123.   }
  124.   free((char *) image->pixels);
  125.   image->packets=compressed_image.packets;
  126.   image->pixels=compressed_image.pixels;
  127.   image->pixels=(RunlengthPacket *)
  128.     realloc((char *) image->pixels,image->packets*sizeof(RunlengthPacket));
  129.   return(True);
  130. }
  131.  
  132. /*
  133. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  134. %                                                                             %
  135. %                                                                             %
  136. %                                                                             %
  137. %   P r i n t I m a g e                                                       %
  138. %                                                                             %
  139. %                                                                             %
  140. %                                                                             %
  141. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  142. %
  143. %  Function PrintImage translates a MIFF image to postscript for printing.
  144. %
  145. %  The format of the PrintImage routine is:
  146. %
  147. %      status=PrintImage(image,grayscale)
  148. %
  149. %  A description of each parameter follows:
  150. %
  151. %    o status:  Function PrintImage return True if the image is printed.
  152. %      False is returned if the image file cannot be opened for printing.
  153. %
  154. %    o image:  The address of a structure of type Image;  returned from
  155. %      ReadImage.
  156. %
  157. %    o grayscale: An integer that specifies a grayscale image if non-zero.
  158. %
  159. %
  160. */
  161. unsigned int PrintImage(image,grayscale)
  162. Image
  163.   *image;
  164.  
  165. unsigned int
  166.   grayscale;
  167. {
  168. #define PointsPerInch 72.0
  169. #define PageBorder 0.25
  170. #define PageWidth  8.5
  171. #define PageHeight 11.0
  172.  
  173.   static char
  174.     *commands[]=
  175.     {
  176.       "%!",
  177.       "%",
  178.       "% Display a runlength-encoded grayscale or color image.",
  179.       "%",
  180.       "/buffer 512 string def",
  181.       "/byte 1 string def",
  182.       "/color_packet 3 string def",
  183.       "/gray_packet 1 string def",
  184.       "/expanded_packet 768 string def",
  185.       " ",
  186.       "/ReadColorPacket",
  187.       "{",
  188.       "  %",
  189.       "  % read a runlength-encoded color packet (length red green blue).",
  190.       "  %",
  191.       "  currentfile byte readhexstring pop 0 get",
  192.       "  /count exch 1 add def",
  193.       "  /count count 3 mul def",
  194.       "  currentfile color_packet readhexstring pop",
  195.       "  0 3 count 1 sub",
  196.       "  {",
  197.       "    expanded_packet exch color_packet putinterval",
  198.       "  } for pop",
  199.       "  expanded_packet 0 count getinterval",
  200.       "} def",
  201.       " ",
  202.       "/DisplayColorImage",
  203.       "{",
  204.       "  %",
  205.       "  % display a runlength-encoded color image.",
  206.       "  %",
  207.       "  columns rows 8",
  208.       "  [",
  209.       "    columns 0 0",
  210.       "    rows neg 0 rows",
  211.       "  ]",
  212.       "  { ReadColorPacket } false 3 colorimage",
  213.       "} def",
  214.       " ",
  215.       "/ReadGrayPacket",
  216.       "{",
  217.       "  %",
  218.       "  % read a runlength-encoded grayscale packet (length gray).",
  219.       "  %",
  220.       "  currentfile byte readhexstring pop 0 get",
  221.       "  /count exch 1 add def",
  222.       "  currentfile gray_packet readhexstring pop",
  223.       "  0 1 count 1 sub",
  224.       "  {",
  225.       "    expanded_packet exch gray_packet putinterval",
  226.       "  } for pop",
  227.       "  expanded_packet 0 count getinterval",
  228.       "} def",
  229.       " ",
  230.       "/DisplayGrayImage",
  231.       "{",
  232.       "  %",
  233.       "  % display a runlength-encoded grayscale image.",
  234.       "  %",
  235.       "  columns rows 8",
  236.       "  [",
  237.       "    columns 0 0",
  238.       "    rows neg 0 rows",
  239.       "  ]",
  240.       "  { ReadGrayPacket } image",
  241.       "} def",
  242.       " ",
  243.       "/DisplayImage",
  244.       "{",
  245.       "  %",
  246.       "  % display a runlength-encoded grayscale or color image.",
  247.       "  %",
  248.       "  initgraphics",
  249.       "  gsave",
  250.       "  currentfile buffer readline pop",
  251.       "  token { /degrees exch def } { } ifelse",
  252.       "  degrees rotate",
  253.       "  currentfile buffer readline pop",
  254.       "  token { /x exch def } { } ifelse",
  255.       "  token { /y exch def } { } ifelse",
  256.       "  x y translate",
  257.       "  currentfile buffer readline pop",
  258.       "  token { /x exch def } { } ifelse",
  259.       "  token { /y exch def } { } ifelse",
  260.       "  x y scale",
  261.       "  currentfile buffer readline pop",
  262.       "  currentfile buffer readline pop",
  263.       "  token { /columns exch def } { } ifelse",
  264.       "  token { /rows exch def } { } ifelse",
  265.       "  currentfile buffer readline pop",
  266.       "  token { /grayscale exch def } { } ifelse",
  267.       "  grayscale 0 gt { DisplayGrayImage } { DisplayColorImage } ifelse",
  268.       "  grestore",
  269.       "  showpage",
  270.       "} def",
  271.       " ",
  272.       "%",
  273.       "% DisplayImage parameters:",
  274.       "%   degrees rotation.",
  275.       "%   x & y translation.",
  276.       "%   x & y scale.",
  277.       "%   image name.",
  278.       "%   image columns & rows.",
  279.       "%   grayscale.",
  280.       "%   hex grayscale or color runlength-encoded packets.",
  281.       "% ",
  282.       "DisplayImage",
  283.       NULL
  284.     };
  285.  
  286.   char
  287.     **q;
  288.  
  289.   double
  290.     delta_x,
  291.     delta_y,
  292.     image_height,
  293.     image_width,
  294.     max,
  295.     min,
  296.     rotate,
  297.     scale,
  298.     scale_x,
  299.     scale_y,
  300.     translate_x,
  301.     translate_y;
  302.  
  303.   register RunlengthPacket
  304.     *p;
  305.  
  306.   register int
  307.     i,
  308.     j;
  309.  
  310.   register unsigned char
  311.     blue,
  312.     gray,
  313.     green,
  314.     red;
  315.  
  316.   /*
  317.     Open output image file.
  318.   */
  319.   if (*image->filename == '-')
  320.     image->file=stdout;
  321.   else
  322.     image->file=fopen(image->filename,"w");
  323.   if (image->file == (FILE *) NULL)
  324.     {
  325.       (void) fprintf(stderr,"Can't open %s for printing\n",image->filename);
  326.       return(False);
  327.     }
  328.   /*
  329.     Compute image rotation.
  330.   */
  331.   if (((double) image->columns/(double) image->rows) > 1.0)
  332.     rotate=(-90.0);
  333.   else
  334.     rotate=0.0;
  335.   /*
  336.     Compute image scaling.
  337.   */
  338.   image_width=(double) image->columns/PointsPerInch;
  339.   image_height=(double) image->rows/PointsPerInch;
  340.   /*
  341.     Check max page sizes
  342.   */
  343.   max=image_width > image_height ? image_width : image_height;
  344.   if (max > (PageHeight-(2.0*PageBorder)))
  345.     {
  346.       scale=(PageHeight-(2.0*PageBorder))/max;
  347.       image_height*=scale;
  348.       image_width*=scale;
  349.     }
  350.   min=image_width > image_height ? image_height : image_width;
  351.   if (min > (PageWidth-(2.0*PageBorder)))
  352.     {
  353.       scale=(PageWidth-(2.0*PageBorder))/min;
  354.       image_width*=scale;
  355.       image_height*=scale;
  356.     }
  357.   scale_x=image_width*PointsPerInch;
  358.   scale_y=image_height*PointsPerInch;
  359.   translate_x=0.0;
  360.   translate_y=0.0;
  361.   if (rotate == 0.0)
  362.     {
  363.       delta_x=PageWidth-(image_width+(2.0*PageBorder));
  364.       delta_y=PageHeight-(image_height+(2.0*PageBorder));
  365.       if (delta_x >= 0.0)
  366.         translate_x=((delta_x/2.0+PageBorder)* PointsPerInch);
  367.       else
  368.         translate_x=PageBorder*PointsPerInch;
  369.       if (delta_y >= 0.0)
  370.         translate_y=((delta_y/2.0+PageBorder)* PointsPerInch);
  371.       else
  372.         translate_y=PageBorder*PointsPerInch;
  373.     }
  374.   else
  375.     {
  376.       delta_x=PageHeight-(image_width+(2.0*PageBorder));
  377.       delta_y=PageWidth-(image_height+(2.0*PageBorder));
  378.       if (delta_x >= 0.0)
  379.         translate_x=((delta_x/2.0+PageBorder-PageHeight)*PointsPerInch);
  380.       else
  381.         translate_x=(PageBorder-PageHeight)*PointsPerInch;
  382.       if (delta_y >= 0.0)
  383.         translate_y=((delta_y/2.0+PageBorder)*PointsPerInch);
  384.       else
  385.         translate_y=PageBorder*PointsPerInch;
  386.     }
  387.   /*
  388.     Output postscript commands.
  389.   */
  390.   for (q=commands; *q; q++)
  391.     (void) fprintf(image->file,"%s\n",*q);
  392.   /*
  393.     Output image data.
  394.   */
  395.   (void) fprintf(image->file,"%f\n%f %f\n%f %f\n%s\n%d %d\n%d\n",rotate,
  396.     translate_x,translate_y,scale_x,scale_y,image->filename,image->columns,
  397.     image->rows,grayscale);
  398.   p=image->pixels;
  399.   j=0;
  400.   for (i=0; i < image->packets; i++)
  401.   {
  402.     j++;
  403.     if (grayscale)
  404.       {
  405.         gray=Intensity(*p);
  406.         (void) fprintf(image->file,"%02x%02x ",p->length,gray);
  407.         if ((j % 6) == 0)
  408.           (void) fprintf(image->file,"\n");
  409.       }
  410.     else
  411.       {
  412.         red=p->red;
  413.         green=p->green;
  414.         blue=p->blue;
  415.         (void) fprintf(image->file,"%02x%02x%02x%02x ",p->length,red,green,
  416.           blue);
  417.         if ((j % 3) == 0)
  418.           (void) fprintf(image->file,"\n");
  419.       }
  420.     p++;
  421.   }
  422.   (void) fprintf(image->file,"\n\n");
  423.   if (image->file != stdin)
  424.     (void) fclose(image->file);
  425.   return(True);
  426. }
  427.  
  428. /*
  429. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  430. %                                                                             %
  431. %                                                                             %
  432. %                                                                             %
  433. %  S u n R e a d I m a g e                                                    %
  434. %                                                                             %
  435. %                                                                             %
  436. %                                                                             %
  437. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  438. %
  439. %  Procedure SunReadImage reads a Sun raster image from a file on disk.
  440. %
  441. %  The format of the SunReadImage routine is:
  442. %
  443. %      SunReadImage(image);
  444. %
  445. %  A description of each parameter follows.
  446. %
  447. %   o  image:  Specifies a pointer to an Image structure.
  448. %
  449. %
  450. %
  451. */
  452. void SunReadImage(image)
  453. Image
  454.   *image;
  455. {
  456.   typedef struct _Rasterfile
  457.   {
  458.     int
  459.       magic,
  460.       width,
  461.       height,
  462.       depth,
  463.       length,
  464.       type,
  465.       maptype,
  466.       maplength;
  467.   } Rasterfile;
  468.  
  469.   Rasterfile
  470.     sun_header;
  471.  
  472.   register int
  473.     bit,
  474.     i,
  475.     x,
  476.     y;
  477.  
  478.   register RunlengthPacket
  479.     *q;
  480.  
  481.   register unsigned char
  482.     *p;
  483.  
  484.   unsigned char
  485.     *sun_pixels;
  486.  
  487.   /*
  488.     Open image file.
  489.   */
  490.   if (*image->filename == '-')
  491.     image->file=stdin;
  492.   else
  493.     if (strcmp(image->filename+strlen(image->filename)-2,".Z"))
  494.       image->file=fopen(image->filename,"r");
  495.     else
  496.       {
  497.         char
  498.           command[256];
  499.  
  500.         /*
  501.           Image file is compressed-- uncompress it.
  502.         */
  503.         (void) sprintf(command,"uncompress -c %s",image->filename);
  504.         image->file=popen(command,"r");
  505.       }
  506.   if (image->file == (FILE *) NULL)
  507.     {
  508.       (void) fprintf(stderr,
  509.         "Can't continue, Sun raster image does not exist.\n");
  510.       exit(1);
  511.     }
  512.   (void) fread((char *) &sun_header,1,sizeof(Rasterfile),image->file);
  513.   if (sun_header.magic != 0x59a66a95)
  514.     {
  515.       (void) fprintf(stderr,"Can't continue, %s is not a Sun raster image.\n",
  516.         image->filename);
  517.       exit(1);
  518.     }
  519.   if (sun_header.type != 1)
  520.     {
  521.       (void) fprintf(stderr,
  522.         "Can't continue, image is not in standard format.\n");
  523.       exit(1);
  524.     }
  525.   if (sun_header.maplength > 0)
  526.     {
  527.       unsigned char
  528.         *sun_colormap;
  529.  
  530.       /*
  531.         Read Sun raster colormap.
  532.       */
  533.       image->colors=sun_header.maplength/3;
  534.       image->colormap=(ColorPacket *)
  535.         malloc(image->colors*sizeof(ColorPacket));
  536.       sun_colormap=(unsigned char *)
  537.         malloc(image->colors*sizeof(unsigned char));
  538.       if ((image->colormap == (ColorPacket *) NULL) ||
  539.           (sun_colormap == (unsigned char *) NULL))
  540.         {
  541.           (void) fprintf(stderr,"Can't continue, not enough memory.\n");
  542.           exit(1);
  543.         }
  544.       (void) fread((char *) sun_colormap,1,(int) image->colors,image->file);
  545.       for (i=0; i < image->colors; i++)
  546.         image->colormap[i].red=sun_colormap[i];
  547.       (void) fread((char *) sun_colormap,1,(int) image->colors,image->file);
  548.       for (i=0; i < image->colors; i++)
  549.         image->colormap[i].green=sun_colormap[i];
  550.       (void) fread((char *) sun_colormap,1,(int) image->colors,image->file);
  551.       for (i=0; i < image->colors; i++)
  552.         image->colormap[i].blue=sun_colormap[i];
  553.       (void) free((char *) sun_colormap);
  554.     }
  555.   else
  556.     if (sun_header.depth < 24)
  557.       {
  558.         /*
  559.           Create linear color ramp.
  560.         */
  561.         image->colors=1 << sun_header.depth;
  562.         image->colormap=(ColorPacket *)
  563.           malloc(image->colors*sizeof(ColorPacket));
  564.         if (image->colormap == (ColorPacket *) NULL)
  565.           {
  566.             (void) fprintf(stderr,"Can't continue, not enough memory.\n");
  567.             exit(1);
  568.           }
  569.         for (i=0; i < image->colors; i++)
  570.         {
  571.           image->colormap[i].red=(255*i)/(image->colors-1);
  572.           image->colormap[i].green=(255*i)/(image->colors-1);
  573.           image->colormap[i].blue=(255*i)/(image->colors-1);
  574.         }
  575.       }
  576.   sun_pixels=(unsigned char *)
  577.     malloc((unsigned int) sun_header.length*sizeof(unsigned char));
  578.   if (sun_pixels == (unsigned char *) NULL)
  579.     {
  580.       (void) fprintf(stderr,"Can't continue, not enough memory.\n");
  581.       exit(1);
  582.     }
  583.   (void) fread((char *) sun_pixels,1,sun_header.length,image->file);
  584.   /*
  585.     Create image.
  586.   */
  587.   image->comments=(char *) malloc((unsigned int) (strlen(image->filename)+256));
  588.   if (image->comments == (char *) NULL)
  589.     {
  590.       (void) fprintf(stderr,
  591.         "Can't import Sun raster image, not enough memory.\n");
  592.       exit(1);
  593.     }
  594.   (void) strcpy(image->comments,"  Imported from Sun raster image: ");
  595.   (void) strcat(image->comments,image->filename);
  596.   image->class=(sun_header.depth < 24 ? PseudoClass : DirectClass);
  597.   image->compression=RunlengthEncodedCompression;
  598.   image->scene=0;
  599.   image->columns=sun_header.width;
  600.   image->rows=sun_header.height;
  601.   image->packets=image->columns*image->rows;
  602.   image->pixels=(RunlengthPacket *)
  603.     malloc(image->packets*sizeof(RunlengthPacket));
  604.   if (image->pixels == (RunlengthPacket *) NULL)
  605.     {
  606.       (void) fprintf(stderr,"Can't continue, not enough memory.\n");
  607.       exit(1);
  608.     }
  609.   /*
  610.     Convert Sun raster image to runlength-encoded packets.
  611.   */
  612.   p=sun_pixels;
  613.   q=image->pixels;
  614.   if (sun_header.depth == 1)
  615.     for (y=0; y < image->rows; y++)
  616.     {
  617.       /*
  618.         Convert bitmap scanline to runlength-encoded color packets.
  619.       */
  620.       for (x=0; x < (image->columns >> 3); x++)
  621.       {
  622.         for (bit=7; bit >= 0; bit--)
  623.         {
  624.           q->index=((*p) & (0x01 << bit) ? 0x00 : 0x01);
  625.           q->red=image->colormap[q->index].red;
  626.           q->green=image->colormap[q->index].green;
  627.           q->blue=image->colormap[q->index].blue;
  628.           q->length=0;
  629.           q++;
  630.         }
  631.         p++;
  632.       }
  633.       if (image->columns % 8)
  634.         {
  635.           for (bit=7; bit >= (8-(image->columns % 8)); bit--)
  636.           {
  637.             q->index=((*p) & (0x01 << bit) ? 0x00 : 0x01);
  638.             q->red=image->colormap[q->index].red;
  639.             q->green=image->colormap[q->index].green;
  640.             q->blue=image->colormap[q->index].blue;
  641.             q->length=0;
  642.             q++;
  643.           }
  644.           p++;
  645.         }
  646.     }
  647.   else
  648.     if (image->class == PseudoClass)
  649.       for (y=0; y < image->rows; y++)
  650.       {
  651.         /*
  652.           Convert PseudoColor scanline to runlength-encoded color packets.
  653.         */
  654.         for (x=0; x < image->columns; x++)
  655.         {
  656.           q->index=(*p++);
  657.           q->red=image->colormap[q->index].red;
  658.           q->green=image->colormap[q->index].green;
  659.           q->blue=image->colormap[q->index].blue;
  660.           q->length=0;
  661.           q++;
  662.         }
  663.         if (image->columns % 2)
  664.           p++;
  665.       }
  666.     else
  667.       for (y=0; y < image->rows; y++)
  668.       {
  669.         /*
  670.           Convert DirectColor scanline to runlength-encoded color packets.
  671.         */
  672.         for (x=0; x < image->columns; x++)
  673.         {
  674.           q->red=(*p++);
  675.           q->green=(*p++);
  676.           q->blue=(*p++);
  677.           q->index=0;
  678.           q->length=0;
  679.           q++;
  680.         }
  681.         if (image->columns % 2)
  682.           p++;
  683.       }
  684.   (void) free((char *) sun_pixels);
  685. }
  686.  
  687. /*
  688. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  689. %                                                                             %
  690. %                                                                             %
  691. %                                                                             %
  692. %   U s a g e                                                                 %
  693. %                                                                             %
  694. %                                                                             %
  695. %                                                                             %
  696. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  697. %
  698. %  Procedure Usage displays the program usage;
  699. %
  700. %  The format of the Usage routine is:
  701. %
  702. %      Usage(program_name,message)
  703. %
  704. %  A description of each parameter follows:
  705. %
  706. %    program_name:  Specifies the name of this program.
  707. %
  708. %    message:  Specifies a specific message to display to the user.
  709. %
  710. */
  711. void Usage(program_name,message)
  712. char
  713.   *message,
  714.   *program_name;
  715. {
  716.   char
  717.     **p;
  718.  
  719.   static char
  720.     *options[]=
  721.     {
  722.       "+grayscale     print image as grayscale",
  723.       NULL
  724.     };
  725.   if (message)
  726.     (void) fprintf(stderr,"Can't continue, %s\n\n",message);
  727.   (void) fprintf(stderr,"Usage: %s [options ...] file\n",program_name);
  728.   (void) fprintf(stderr,"\nWhere options include:\n");
  729.   for (p=options; *p; *p++)
  730.     (void) fprintf(stderr,"  %s\n",*p);
  731.   (void) fprintf(stderr,
  732.       "\nSpecify 'file' as '-' for standard output.\n");
  733.   (void) fprintf(stderr,
  734.       "\nChange '+' to '-' in any option above to reverse its effect.\n");
  735.   (void) fprintf(stderr,
  736.     "For example, -grayscale means print the image in color.\n");
  737.   exit(1);
  738. }
  739.  
  740. /*
  741. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  742. %                                                                             %
  743. %                                                                             %
  744. %                                                                             %
  745. %    M a i n                                                                  %
  746. %                                                                             %
  747. %                                                                             %
  748. %                                                                             %
  749. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  750. %
  751. %
  752. */
  753. main(argc,argv)
  754. int
  755.   argc;
  756.  
  757. char
  758.   *argv[];
  759. {
  760.   char
  761.     *option,
  762.     *program_name;
  763.  
  764.   Image
  765.     image;
  766.  
  767.   int
  768.     i;
  769.  
  770.   unsigned int
  771.     grayscale;
  772.  
  773.   program_name=argv[0];
  774.   grayscale=False;
  775.   for (i=1; i < argc-1; i++)
  776.   {
  777.     option=argv[i];
  778.     if ((strlen(option) > 1) && ((*option == '-') || (*option == '+')))
  779.       switch(*(option+1))
  780.       {
  781.         case 'g':
  782.         {
  783.           grayscale=(*option == '+');
  784.           break;
  785.         }
  786.         case 'h':
  787.         {
  788.           Usage(program_name,(char *) NULL);
  789.           break;
  790.         }
  791.         default:
  792.           Usage(program_name,(char *) NULL);
  793.       }
  794.   }
  795.   if (argc == 1)
  796.     Usage(program_name,(char *) NULL);
  797.   (void) strcpy(image.filename,argv[argc-1]);
  798.   SunReadImage(&image);
  799.   (void) CompressImage(&image);
  800.   (void) strcpy(image.filename,"-");
  801.   (void) fprintf(stderr,"%s %dx%d\n",image.filename,image.columns,image.rows);
  802.   (void) PrintImage(&image,grayscale);
  803. }
  804.