[alt.sources] SUNtoPS

cristy@eplrx7.uucp (John Cristy) (06/05/91)

SUN raster to Postscript... 

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%                 IIIII  M   M  PPPP    OOO   RRRR    TTTTT                   %
%                   I    MM MM  P   P  O   O  R   R     T                     %
%                   I    M M M  PPPP   O   O  RRRR      T                     %
%                   I    M   M  P      O   O  R R       T                     %
%                 IIIII  M   M  P       OOO   R  R      T                     % 
%                                                                             %
%                                                                             %
%         Import SUN raster image to Encapsulated Postscript format.          %
%                                                                             %
%                                                                             %
%                                                                             %
%                           Software Design                                   %
%                             John Cristy                                     %
%                            January  1991                                    %
%                                                                             %
%                                                                             %
%  Copyright 1991 E. I. Dupont de Nemours & Company                           %
%                                                                             %
%  Permission to use, copy, modify, distribute, and sell this software and    %
%  its documentation for any purpose is hereby granted without fee,           %
%  provided that the above Copyright notice appear in all copies and that     %
%  both that Copyright notice and this permission notice appear in            %
%  supporting documentation, and that the name of E. I. Dupont de Nemours     %
%  & Company not be used in advertising or publicity pertaining to            %
%  distribution of the software without specific, written prior               %
%  permission.  E. I. Dupont de Nemours & Company makes no representations    %
%  about the suitability of this software for any purpose.  It is provided    %
%  "as is" without express or implied warranty.                               %
%                                                                             %
%  E. I. Dupont de Nemours & Company disclaims all warranties with regard     %
%  to this software, including all implied warranties of merchantability      %
%  and fitness, in no event shall E. I. Dupont de Nemours & Company be        %
%  liable for any special, indirect or consequential damages or any           %
%  damages whatsoever resulting from loss of use, data or profits, whether    %
%  in an action of contract, negligence or other tortious action, arising     %
%  out of or in connection with the use or performance of this software.      %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% 
%  Command syntax:
%
%  import [-scene #] image.sun image.ps
%  
%  Specify 'image.sun' as '-' for standard input.  
%  Specify 'image.ps' as '-' for standard output.
%  
%
*/

/*
  Include declarations
*/
#include <stdio.h>
#include <ctype.h>
#include <math.h>
#ifdef __STDC__
#include <stdlib.h>
#else
#ifndef vms
#include <malloc.h>
#include <memory.h>

extern long
  strtol(),
  time();
#endif
#endif

/*
  Define declarations for the Display program.
*/
#define False  0
#define Intensity(color)  \
  (((color).red*77+(color).green*150+(color).blue*29) >> 8)
#define Max(x,y)  (((x) > (y)) ? (x) : (y))
#define MaxColormapSize  65535
#define MaxImageSize  (4096*4096)
#define MaxRgb  255
#define MaxRunlength  255
#define Min(x,y)  (((x) < (y)) ? (x) : (y))
#define MinInfoSize (1 << 18)
#define True  1
#define Warning(message,qualifier)  \
{  \
  (void) fprintf(stderr,"%s: %s",application_name,message);  \
  if (qualifier != (char *) NULL)  \
    (void) fprintf(stderr," (%s)",qualifier);  \
  (void) fprintf(stderr,".\n");  \
}

/*
  Image Id's
*/
#define UnknownId  0
#define ImageMagickId  1
/*
  Image classes:
*/
#define UnknownClass  0
#define DirectClass  1
#define PseudoClass  2
/*
  Image compression algorithms:
*/
#define UnknownCompression  0
#define NoCompression  1
#define RunlengthEncodedCompression  2
#define QEncodedCompression  3

/*
  Typedef declarations for the Display program.
*/
typedef struct _ColorPacket
{
  unsigned char
    red,
    green,
    blue;

  unsigned short
    index;
} ColorPacket;

typedef struct _RunlengthPacket
{
  unsigned char
    red,
    green,
    blue,
    length;

  unsigned short
    index;
} RunlengthPacket;

typedef struct _Image
{
  FILE
    *file;

  char
    filename[256];

  char
    *comments;

  unsigned int
    id,
    class,
    compression,
    columns,
    rows;

  unsigned int
    colors;

  ColorPacket
    *colormap;

  unsigned int
    packets,
    runlength;

  RunlengthPacket
    *pixels;

  unsigned int
    scene;
} Image;

/*
  Variable declarations.
*/
char
  *application_name;

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   E r r o r                                                                 %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Function Error displays an error message and then terminates the program.
%
%  The format of the Error routine is:
%
%      Error(message,qualifier)
%
%  A description of each parameter follows:
%
%    o message:  Specifies the message to display before terminating the
%      program.
%
%    o qualifier:  Specifies any qualifier to the message.
%
%
*/
void Error(message,qualifier)
char
  *message,
  *qualifier;
{
  (void) fprintf(stderr,"%s: %s",application_name,message); 
  if (qualifier != (char *) NULL)
    (void) fprintf(stderr," %s",qualifier);
  (void) fprintf(stderr,".\n");
  exit(1);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%  M S B F i r s t O r d e r                                                  %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Function MSBFirstOrder converts a least-significant byte first buffer of
%  integers to most-significant byte first.
%
%  The format of the MSBFirstOrder routine is:
%
%       MSBFirstOrder(p,length);
%
%  A description of each parameter follows.
%
%   o  p:  Specifies a pointer to a buffer of integers.
%
%   o  length:  Specifies the length of the buffer.
%
%
*/
MSBFirstOrder(p,length)
register char 
  *p;

register unsigned 
  length;
{
  register char 
    c,
    *q,
    *sp;

  q=p+length;
  while (p < q) 
  {
    sp=p+3;
    c=(*sp);
    *sp=(*p);
    *p++=c;
    sp=p+1;
    c=(*sp);
    *sp=(*p);
    *p++=c;
    p+=2;
  }
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   P r i n t I m a g e                                                       %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Function PrintImage translates a MIFF image to encapsulated Postscript for
%  printing.  If the supplied geometry is null, the image is centered on the
%  Postscript page.  Otherwise, the image is positioned as specified by the
%  geometry.
%
%  The format of the PrintImage routine is:
%
%      status=PrintImage(image)
%
%  A description of each parameter follows:
%
%    o status: Function PrintImage return True if the image is printed.
%      False is returned if the image file cannot be opened for printing.
%
%    o image: The address of a structure of type Image;  returned from
%      ReadImage.
%
%
*/
unsigned int PrintImage(image)
Image
  *image;
{
#define PageBottomMargin 92
#define PageLeftMargin 16
#define PageWidth  612
#define PageHeight 792

  static char
    *Postscript[]=
    {
      "%",
      "% Display a color image.  The image is displayed in color on",
      "% Postscript viewers or printers that support color, otherwise",
      "% it is displayed as grayscale.",
      "%",
      "/buffer 512 string def",
      "/byte 1 string def",
      "/color_packet 3 string def",
      "/compression 1 string def",
      "/gray_packet 1 string def",
      "/pixels 768 string def",
      "",
      "/DirectClassPacket",
      "{",
      "  %",
      "  % Get a DirectClass packet.",
      "  %",
      "  % Parameters: ",
      "  %   red.",
      "  %   green.",
      "  %   blue.",
      "  %   length: number of pixels minus one of this color (optional).",
      "  %",
      "  currentfile color_packet readhexstring pop pop",
      "  compression 0 gt",
      "  {",
      "    /number_pixels 3 def",
      "  }",
      "  {",
      "    currentfile byte readhexstring pop 0 get",
      "    /number_pixels exch 1 add 3 mul def",
      "  } ifelse",
      "  0 3 number_pixels 1 sub",
      "  {",
      "    pixels exch color_packet putinterval",
      "  } for",
      "  pixels 0 number_pixels getinterval",
      "} bind def",
      "",
      "/DirectClassImage",
      "{",
      "  %",
      "  % Display a DirectClass image.",
      "  %",
      "  systemdict /colorimage known",
      "  {",
      "    columns rows 8",
      "    [",
      "      columns 0 0",
      "      rows neg 0 rows",
      "    ]",
      "    { DirectClassPacket } false 3 colorimage",
      "  }",
      "  {",
      "    %",
      "    % No colorimage operator;  convert to grayscale.",
      "    %",
      "    columns rows 8",
      "    [",
      "      columns 0 0",
      "      rows neg 0 rows",
      "    ]",
      "    { GrayDirectClassPacket } image",
      "  } ifelse",
      "} bind def",
      "",
      "/GrayDirectClassPacket",
      "{",
      "  %",
      "  % Get a DirectClass packet;  convert to grayscale.",
      "  %",
      "  % Parameters: ",
      "  %   red",
      "  %   green",
      "  %   blue",
      "  %   length: number of pixels minus one of this color (optional).",
      "  %",
      "  currentfile color_packet readhexstring pop pop",
      "  color_packet 0 get 0.299 mul",
      "  color_packet 1 get 0.587 mul add",
      "  color_packet 2 get 0.114 mul add",
      "  cvi",
      "  /gray_packet exch def",
      "  compression 0 gt",
      "  {",
      "    /number_pixels 1 def",
      "  }",
      "  {",
      "    currentfile byte readhexstring pop 0 get",
      "    /number_pixels exch 1 add def",
      "  } ifelse",
      "  0 1 number_pixels 1 sub",
      "  {",
      "    pixels exch gray_packet put",
      "  } for",
      "  pixels 0 number_pixels getinterval",
      "} bind def",
      "",
      "/GrayPseudoClassPacket",
      "{",
      "  %",
      "  % Get a PseudoClass packet;  convert to grayscale.",
      "  %",
      "  % Parameters: ",
      "  %   index: index into the colormap.",
      "  %   length: number of pixels minus one of this color (optional).",
      "  %",
      "  currentfile byte readhexstring pop 0 get",
      "  /offset exch 3 mul def",
      "  /color_packet colormap offset 3 getinterval def",
      "  color_packet 0 get 0.299 mul",
      "  color_packet 1 get 0.587 mul add",
      "  color_packet 2 get 0.114 mul add",
      "  cvi",
      "  /gray_packet exch def",
      "  compression 0 gt",
      "  {",
      "    /number_pixels 1 def",
      "  }",
      "  {",
      "    currentfile byte readhexstring pop 0 get",
      "    /number_pixels exch 1 add def",
      "  } ifelse",
      "  0 1 number_pixels 1 sub",
      "  {",
      "    pixels exch gray_packet put",
      "  } for",
      "  pixels 0 number_pixels getinterval",
      "} bind def",
      "",
      "/PseudoClassPacket",
      "{",
      "  %",
      "  % Get a PseudoClass packet.",
      "  %",
      "  % Parameters: ",
      "  %   index: index into the colormap.",
      "  %   length: number of pixels minus one of this color (optional).",
      "  %",
      "  %",
      "  currentfile byte readhexstring pop 0 get",
      "  /offset exch 3 mul def",
      "  /color_packet colormap offset 3 getinterval def",
      "  compression 0 gt",
      "  {",
      "    /number_pixels 3 def",
      "  }",
      "  {",
      "    currentfile byte readhexstring pop 0 get",
      "    /number_pixels exch 1 add 3 mul def",
      "  } ifelse",
      "  0 3 number_pixels 1 sub",
      "  {",
      "    pixels exch color_packet putinterval",
      "  } for",
      "  pixels 0 number_pixels getinterval",
      "} bind def",
      "",
      "/PseudoClassImage",
      "{",
      "  %",
      "  % Display a PseudoClass image.",
      "  %",
      "  % Parameters: ",
      "  %   colors: number of colors in the colormap.",
      "  %   colormap: red, green, blue color packets.",
      "  %",
      "  currentfile buffer readline pop",
      "  token pop /colors exch def pop",
      "  /colors colors 3 mul def",
      "  /colormap colors string def",
      "  currentfile colormap readhexstring pop pop",
      "  systemdict /colorimage known",
      "  {",
      "    columns rows 8",
      "    [",
      "      columns 0 0",
      "      rows neg 0 rows",
      "    ]",
      "    { PseudoClassPacket } false 3 colorimage",
      "  }",
      "  {",
      "    %",
      "    % No colorimage operator;  convert to grayscale.",
      "    %",
      "    columns rows 8",
      "    [",
      "      columns 0 0",
      "      rows neg 0 rows",
      "    ]",
      "    { GrayPseudoClassPacket } image",
      "  } ifelse",
      "} bind def",
      "",
      "/DisplayImage",
      "{",
      "  %",
      "  % Display a DirectClass or PseudoClass image.",
      "  %",
      "  % Parameters: ",
      "  %   x & y translation.",
      "  %   x & y scale.",
      "  %   image columns & rows.",
      "  %   class: 0-DirectClass or 1-PseudoClass.",
      "  %   compression: 0-RunlengthEncodedCompression or 1-NoCompression.",
      "  %   hex color packets.",
      "  %",
      "  gsave",
      "  currentfile buffer readline pop",
      "  token pop /x exch def",
      "  token pop /y exch def pop",
      "  x y translate",
      "  currentfile buffer readline pop",
      "  token pop /x exch def",
      "  token pop /y exch def pop",
      "  x y scale",
      "  currentfile buffer readline pop",
      "  token pop /columns exch def",
      "  token pop /rows exch def pop",
      "  currentfile buffer readline pop",
      "  token pop /class exch def pop",
      "  currentfile buffer readline pop",
      "  token pop /compression exch def pop",
      "  class 0 gt { PseudoClassImage } { DirectClassImage } ifelse",
      "  grestore",
      "  showpage",
      "} bind def",
      "",
      "DisplayImage",
      NULL
    };

  char
    **q;

  int
    center,
    x,
    y;

  register RunlengthPacket
    *p;

  register int
    i,
    j;

  unsigned int
    height,
    width;

  /*
    Open output image file.
  */
  if (*image->filename == '-')
    image->file=stdout;
  else
    image->file=fopen(image->filename,"w");
  if (image->file == (FILE *) NULL)
    {
      (void) fprintf(stderr,"%s: unable to print image, cannot open %s.\n",
        application_name,image->filename);
      return(False);
    }
  width=image->columns;
  height=image->rows;
  center=True;
  if (center)
    {
      int
        delta_x,
        delta_y;

      unsigned long
        scale;

      /*
        Center image on Postscript page.
      */
      if (width > (PageWidth-(2*PageLeftMargin)))
        {
          scale=((PageWidth-(2*PageLeftMargin)) << 14)/width;
          width=(width*scale) >> 14;
          height=(height*scale) >> 14;
        }
      if (height > (PageHeight-(2*PageBottomMargin)))
        {
          scale=((PageHeight-(2*PageBottomMargin)) << 14)/height;
          width=(width*scale) >> 14;
          height=(height*scale) >> 14;
        }
      delta_x=PageWidth-(width+(2*PageLeftMargin));
      delta_y=PageHeight-(height+(2*PageBottomMargin));
      if (delta_x >= 0)
        x=delta_x/2+PageLeftMargin;
      else
        x=PageLeftMargin;
      if (delta_y >= 0)
        y=delta_y/2+PageBottomMargin;
      else
        y=PageBottomMargin;
    }
  /*
    Output encapsulated Postscript header.
  */
  (void) fprintf(image->file,"%%!PS-Adobe-2.0 EPSF-2.0\n");
  (void) fprintf(image->file,"%%%%BoundingBox: %d %d %d %d\n",x,y,x+width,
    y+height);
  (void) fprintf(image->file,"%%%%Creator: ImageMagick\n");
  (void) fprintf(image->file,"%%%%Title: %s\n",image->filename);
  (void) fprintf(image->file,"%%%%EndComments\n");
  /*
    Output encapsulated Postscript commands.
  */
  for (q=Postscript; *q; q++)
    (void) fprintf(image->file,"%s\n",*q);
  /*
    Output image data.
  */
  (void) fprintf(image->file,"%d %d\n%d %d\n%d %d\n%d\n%d\n",x,y,width,height,
    image->columns,image->rows,(image->class == PseudoClass),
    image->compression == NoCompression);
  x=0;
  p=image->pixels;
  switch (image->class)
  {
    case DirectClass:
    {
      switch (image->compression)
      {
        case RunlengthEncodedCompression:
        default:
        {
          /*
            Dump runlength-encoded DirectColor packets.
          */
          for (i=0; i < image->packets; i++)
          {
            x++;
            (void) fprintf(image->file,"%02x%02x%02x%02x",p->red,p->green,
              p->blue,p->length);
            if (x == 9)
              {
                x=0;
                (void) fprintf(image->file,"\n");
              }
            p++;
          }
          break;
        }
        case NoCompression:
        {
          /*
            Dump DirectColor packets.
          */
          for (i=0; i < image->packets; i++)
          {
            for (j=0; j <= p->length; j++)
            {
              x++;
              (void) fprintf(image->file,"%02x%02x%02x",p->red,p->green,
                p->blue);
              if (x == 12)
                {
                  x=0;
                  (void) fprintf(image->file,"\n");
                }
            }
            p++;
          }
          break;
        }
      }
      break;
    }
    case PseudoClass:
    {
      /*
        Dump number of colors, colormap, PseudoColor packets.
      */
      (void) fprintf(image->file,"%d\n",image->colors);
      for (i=0; i < image->colors; i++)
        (void) fprintf(image->file,"%02x%02x%02x\n",image->colormap[i].red,
          image->colormap[i].green,image->colormap[i].blue);
      switch (image->compression)
      {
        case RunlengthEncodedCompression:
        default:
        {
          for (i=0; i < image->packets; i++)
          {
            x++;
            (void) fprintf(image->file,"%02x%02x",p->index,p->length);
            if (x == 18)
              {
                x=0;
                (void) fprintf(image->file,"\n");
              }
            p++;
          }
          break;
        }
        case NoCompression:
        {
          for (i=0; i < image->packets; i++)
          {
            for (j=0; j <= p->length; j++)
            {
              x++;
              (void) fprintf(image->file,"%02x",p->index);
              if (x == 36)
                {
                  x=0;
                  (void) fprintf(image->file,"\n");
                }
            }
            p++;
          }
        }
        break;
      }
    }
  }
  (void) fprintf(image->file,"\n\n");
  (void) fprintf(image->file,"%%%%Trailer\n");
  if (image->file != stdin)
    (void) fclose(image->file);
  return(True);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%  R e a d D a t a                                                            %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Function ReadData reads data from the image file and returns it.  If it
%  cannot read the requested number of items, False is returned indicating
%  an error.
%
%  The format of the ReadData routine is:
%
%      status=ReadData(data,size,number_items,file)
%
%  A description of each parameter follows:
%
%    o status:  Function ReadData returns True if all the data requested
%      is obtained without error, otherwise False.
%
%    o data:  Specifies an area to place the information reuested from
%      the file.
%
%    o size:  Specifies an integer representing the length of an
%      individual item to be read from the file.
%
%    o numer_items:  Specifies an integer representing the number of items
%      to read from the file.
%
%    o file:  Specifies a file to read the data.
%
%
*/
unsigned int ReadData(data,size,number_items,file)
char
  *data;

int
  size,
  number_items;

FILE
  *file;
{
  size*=number_items;
  while (size > 0)
  {
    number_items=fread(data,1,size,file);
    if (number_items <= 0)
      return(False);
    size-=number_items;
    data+=number_items;
  }
  return(True);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%  R e a d S U N I m a g e                                                    %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Function ReadSUNImage reads an image file and returns it.  It allocates 
%  the memory necessary for the new Image structure and returns a pointer to 
%  the new image.
%
%  The format of the ReadSUNImage routine is:
%
%      image=ReadSUNImage(filename)
%
%  A description of each parameter follows:
%
%    o image:  Function ReadSUNImage returns a pointer to the image after 
%      reading.  A null image is returned if there is a a memory shortage or 
%      if the image cannot be read.
%
%    o filename:  Specifies the name of the image to read.
%
%
*/
static Image *ReadSUNImage(filename)
char
  *filename;
{
#define RMT_EQUAL_RGB  1
#define RMT_NONE  0
#define RMT_RAW  2
#define RT_STANDARD  1
#define RT_ENCODED  2
#define RT_FORMAT_RGB  3

  typedef struct _Rasterfile
  {
    int
      magic,
      width,
      height,
      depth,
      length,
      type,
      maptype,
      maplength;
  } Rasterfile;

  Image
    *image;

  Rasterfile
    sun_header;

  register int
    bit,
    i,
    x,
    y;

  register RunlengthPacket
    *q;

  register unsigned char
    *p;

  unsigned char
    blue,
    green,
    red,
    *sun_data,
    *sun_pixels;

  unsigned long 
    lsb_first;

  unsigned short
    index;

  /*
    Allocate image structure.
  */
  image=(Image *) malloc(sizeof(Image));
  if (image == (Image *) NULL)
    Error("memory allocation error",(char *) NULL);
  /*
    Initialize Image structure.
  */
  image->id=UnknownId;
  image->class=DirectClass;
  image->compression=RunlengthEncodedCompression;
  image->columns=0;
  image->rows=0;
  image->packets=0;
  image->colors=0;
  image->scene=0;
  image->colormap=(ColorPacket *) NULL;
  image->pixels=(RunlengthPacket *) NULL;
  image->comments=(char *) NULL;
  /*
    Open image file.
  */
  (void) strcpy(image->filename,filename);
  if (*image->filename == '-')
    image->file=stdin;
  else
    if (strcmp(image->filename+strlen(image->filename)-2,".Z") != 0)
      image->file=fopen(image->filename,"r");
    else
      {
        char
          command[256];

        /*
          Image file is compressed-- uncompress it.
        */
        (void) sprintf(command,"uncompress -c %s",image->filename);
        image->file=(FILE *) popen(command,"r");
      }
  if (image->file == (FILE *) NULL)
    Error("unable to open file",image->filename);
  /*
    Read raster image.
  */
  (void) ReadData((char *) &sun_header,1,sizeof(Rasterfile),image->file);
  /*
    Ensure the header byte-order is most-significant byte first.
  */
  lsb_first=1;
  if (*(char *) &lsb_first)
    MSBFirstOrder((char *) &sun_header,sizeof(sun_header));
  if (sun_header.magic != 0x59a66a95)
    Error("not a SUN raster,",image->filename);
  switch (sun_header.maptype)
  {
    case RMT_NONE:
    {
      if (sun_header.depth < 24)
        {
          /*
            Create linear color ramp.
          */
          image->colors=1 << sun_header.depth;
          image->colormap=(ColorPacket *) 
            malloc(image->colors*sizeof(ColorPacket));
          if (image->colormap == (ColorPacket *) NULL)
            Error("memory allocation error",(char *) NULL);
          for (i=0; i < image->colors; i++)
          {
            image->colormap[i].red=(255*i)/(image->colors-1);
            image->colormap[i].green=(255*i)/(image->colors-1);
            image->colormap[i].blue=(255*i)/(image->colors-1);
          }
        }
      break;
    }
    case RMT_EQUAL_RGB:
    {
      unsigned char
        *sun_colormap;

      /*
        Read Sun raster colormap.
      */
      image->colors=sun_header.maplength/3;
      image->colormap=
        (ColorPacket *) malloc(image->colors*sizeof(ColorPacket));
      sun_colormap=(unsigned char *) 
        malloc(image->colors*sizeof(unsigned char));
      if ((image->colormap == (ColorPacket *) NULL) ||
          (sun_colormap == (unsigned char *) NULL))
        Error("memory allocation error",(char *) NULL);
      (void) ReadData((char *) sun_colormap,1,(int) image->colors,image->file);
      for (i=0; i < image->colors; i++)
        image->colormap[i].red=sun_colormap[i];
      (void) ReadData((char *) sun_colormap,1,(int) image->colors,image->file);
      for (i=0; i < image->colors; i++)
        image->colormap[i].green=sun_colormap[i];
      (void) ReadData((char *) sun_colormap,1,(int) image->colors,image->file);
      for (i=0; i < image->colors; i++)
        image->colormap[i].blue=sun_colormap[i];
      (void) free((char *) sun_colormap);
      break;
    }
    case RMT_RAW:
    {
      unsigned char
        *sun_colormap;

      /*
        Read Sun raster colormap.
      */
      sun_colormap=(unsigned char *) 
        malloc((unsigned int) sun_header.maplength*sizeof(unsigned char));
      if (sun_colormap == (unsigned char *) NULL)
        Error("memory allocation error",(char *) NULL);
      (void) ReadData((char *) sun_colormap,1,sun_header.maplength,
        image->file);
      (void) free((char *) sun_colormap);
      break;
    }
    default:
    {
      Error("colormap type is not supported",image->filename);
      break;
    }
  }
  sun_data=(unsigned char *) 
    malloc((unsigned int) sun_header.length*sizeof(unsigned char));
  if (sun_data == (unsigned char *) NULL)
    Error("memory allocation error",(char *) NULL);
  (void) ReadData((char *) sun_data,1,sun_header.length,image->file);
  sun_pixels=sun_data;
  if (sun_header.type == RT_ENCODED) 
    {
      register int
        count,
        number_pixels;

      register unsigned char
        byte,
        *q;

      /*
        Read run-length encoded raster pixels.
      */
      number_pixels=(sun_header.width+(sun_header.width % 2))*
        sun_header.height*(((sun_header.depth-1) >> 3)+1);
      sun_pixels=(unsigned char *) 
        malloc((unsigned int) number_pixels*sizeof(unsigned char));
      if (sun_pixels == (unsigned char *) NULL)
        Error("memory allocation error",(char *) NULL);
      p=sun_data;
      q=sun_pixels;
      while ((q-sun_pixels) <= number_pixels)
      {
        byte=(*p++);
        if (byte != 128)
          *q++=byte;
        else
          {
            /*
              Runlength-encoded packet: <count><byte>
            */
            count=(*p++);
            if (count > 0)
              byte=(*p++);
            while (count >= 0)
            {
              *q++=byte;
              count--;
            }
         }
      }
    (void) free((char *) sun_data);
  }
  /*
    Create image.
  */
  image->comments=(char *) malloc((unsigned int) (strlen(image->filename)+256));
  if (image->comments == (char *) NULL)
    Error("memory allocation error",(char *) NULL);
  (void) sprintf(image->comments,"\n  Imported from Sun raster image:  %s\n\0",
    image->filename);
  image->class=(sun_header.depth < 24 ? PseudoClass : DirectClass);
  image->columns=sun_header.width;
  image->rows=sun_header.height;
  image->pixels=(RunlengthPacket *) 
    malloc(image->columns*image->rows*sizeof(RunlengthPacket));
  if (image->pixels == (RunlengthPacket *) NULL)
    Error("memory allocation error",(char *) NULL);
  /*
    Convert Sun raster image to runlength-encoded packets.
  */
  p=sun_pixels;
  image->packets=0;
  q=image->pixels;
  q->length=MaxRunlength;
  if (sun_header.depth == 1)
    for (y=0; y < image->rows; y++)
    {
      /*
        Convert bitmap scanline to runlength-encoded color packets.
      */
      for (x=0; x < (image->columns >> 3); x++) 
      {
        for (bit=7; bit >= 0; bit--)
        {
          index=((*p) & (0x01 << bit) ? 0x00 : 0x01);
          red=image->colormap[index].red;
          green=image->colormap[index].green;
          blue=image->colormap[index].blue;
          if ((red == q->red) && (green == q->green) && (blue == q->blue) &&
              (q->length < MaxRunlength))
            q->length++;
          else
            {
              if (image->packets > 0)
                q++;
              image->packets++;
              q->red=red;
              q->green=green;
              q->blue=blue;
              q->index=index;
              q->length=0;
            }
        }
        p++;
      }
      if ((image->columns % 8) != 0)
        {
          for (bit=7; bit >= (8-(image->columns % 8)); bit--)
          {
            index=((*p) & (0x01 << bit) ? 0x00 : 0x01);
            red=image->colormap[index].red;
            green=image->colormap[index].green;
            blue=image->colormap[index].blue;
            if ((red == q->red) && (green == q->green) && (blue == q->blue) &&
                (q->length < MaxRunlength))
              q->length++;
            else
              {
                if (image->packets > 0)
                  q++;
                image->packets++;
                q->red=red;
                q->green=green;
                q->blue=blue;
                q->index=index;
                q->length=0;
              }
          }
          p++;
        }
    }
  else
    if (image->class == PseudoClass)
      for (y=0; y < image->rows; y++)
      {
        /*
          Convert PseudoColor scanline to runlength-encoded color packets.
        */
        for (x=0; x < image->columns; x++) 
        {
          index=(*p++);
          red=image->colormap[index].red;
          green=image->colormap[index].green;
          blue=image->colormap[index].blue;
          if ((red == q->red) && (green == q->green) && (blue == q->blue) &&
              (q->length < MaxRunlength))
            q->length++;
          else
            {
              if (image->packets > 0)
                q++;
              image->packets++;
              q->red=red;
              q->green=green;
              q->blue=blue;
              q->index=index;
              q->length=0;
            }
        }
        if ((image->columns % 2) != 0)
          p++;
      }
    else
      for (y=0; y < image->rows; y++)
      {
        /*
          Convert DirectColor scanline to runlength-encoded color packets.
        */
        for (x=0; x < image->columns; x++) 
        {
          if (sun_header.type == RT_STANDARD)
            {
              blue=(*p++);
              green=(*p++);
              red=(*p++);
            }
          else
            {
              red=(*p++);
              green=(*p++);
              blue=(*p++);
            }
          if (image->colors > 0)
            {
              red=image->colormap[red].red;
              green=image->colormap[green].green;
              blue=image->colormap[blue].blue;
            }
          if ((red == q->red) && (green == q->green) && (blue == q->blue) &&
              (q->length < MaxRunlength))
              q->length++;
            else
              {
                if (image->packets > 0)
                  q++;
                image->packets++;
                q->red=red;
                q->green=green;
                q->blue=blue;
                q->index=0;
                q->length=0;
              }
        }
        if ((image->columns % 2) != 0)
          p++;
      }
  (void) free((char *) sun_pixels);
  if (image->file != stdin)
    if (strcmp(image->filename+strlen(image->filename)-2,".Z") != 0)
      (void) fclose(image->file);
    else
      (void) pclose(image->file);
  if (image->packets > ((image->columns*image->rows*3) >> 2))
    image->compression=NoCompression;
  image->pixels=(RunlengthPacket *)
    realloc((char *) image->pixels,image->packets*sizeof(RunlengthPacket));
  return(image);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   U s a g e                                                                 %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Function Usage displays the program usage;
%
%  The format of the Usage routine is:
%
%      Usage(message)
%
%  A description of each parameter follows:
%
%    message:  Specifies a specific message to display to the user.
%
*/
static void Usage(message)
char
  *message;
{
  if (message != (char *) NULL)
    (void) fprintf(stderr,"Can't continue, %s\n\n",message);
  (void) fprintf(stderr,"Usage: %s [-scene #] image.sun image.ps\n\n",
    application_name);
  (void) fprintf(stderr,"Specify 'image.sun' as '-' for standard input.\n");
  (void) fprintf(stderr,"Specify 'image.ps' as '-' for standard output.\n");
  exit(1);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%  M a i n                                                                    %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%
*/
int main(argc,argv)
int
  argc;
   
char
  *argv[];
{
  char
    filename[256];

  Image
    *image;

  int
    i;

  unsigned int
    scene;

  /*
    Initialize program variables.
  */
  application_name=argv[0];
  i=1;
  scene=0;
  if (argc < 3)
    Usage((char *) NULL);
  /*
    Read image and convert to MIFF format.
  */
  if (strncmp(argv[i],"-scene",2) == 0)
    {
      i++;
      scene=atoi(argv[i++]);
    }
  (void) strcpy(filename,argv[i++]);
  image=ReadSUNImage(filename);
  if (image == (Image *) NULL)
    exit(1);
  (void) strcpy(image->filename,argv[i++]);
  image->scene=scene;
  (void) PrintImage(image);
  (void) fprintf(stderr,"%s => %s  %dx%d\n",filename,image->filename,
    image->columns,image->rows);
  return(False);
}
--
The UUCP Mailer