Re: Unisys difax

I have fixed pcxtoppm and written a pcxtopbm utility.  The sources (which are 
short) follow.


Did someone mention that they had "fixed" pbm utilities to convert the .pcx 
difax files from Unisys correctly to Postscript?  Larry's post  brings the question up 
because we just started with our own 30 day test  yesterday and can not get the package 
to convert it correctly.  Thanks in  advance for any advice.

Paul Ruscher



/*
* pcxtopbm.c - Converts from a PC Paintbrush PCX file to a PBM file.
*
* Copyright (c) 1990 by Michael Davidson
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose and without fee is hereby granted,
* provided that the above copyright notice appear in all copies and that
* both that copyright notice and this permission notice appear in
* supporting documentation.
*
* This file is provided AS IS with no warranties of any kind.  The author
* shall have no liability with respect to the infringement of copyrights,
* trade secrets or any patents by this file or any part thereof.  In no
* event will the author be liable for any lost revenue or profits or
* other special, indirect and consequential damages.
*
*/

#include        <stdio.h>
#include        "pbm.h"

#define PCX_MAGIC       0x0a            /* PCX magic number             */
#define PCX_HDR_SIZE    128             /* size of PCX header           */
#define PCX_256_COLORS  0x0c            /* magic number for 256 colors  */

#define MAXCOLORS       256
#define MAXPLANES       4
#define PCX_MAXVAL      255

static void read_pcx_image ARGS(( FILE *fp, unsigned char *buf, int 
BytesPerLine, int Planes, int Height ));
static void pcx_planes_to_pixels ARGS(( unsigned char *pixels, unsigned char 
*bitplanes, int bytesperline, int planes, int bitsperpixel ));
static void pcx_unpack_pixels ARGS(( unsigned char *pixels, unsigned char 
*bitplanes, int bytesperline, int planes, int bitsperpixel ));
static int GetByte ARGS(( FILE *fp ));
static int GetWord ARGS(( FILE *fp ));

void
main(argc, argv)
   int          argc;
   char *argv[];
{
   register int i;
   FILE         *ifp;
   char         *ifname;
   int                  Version;
   int                  Xmin, Ymin, Xmax, Ymax;
   int                  Width, Height;
   register int x, y;
   int                  Planes;
   int                  BitsPerPixel;
   int                  BytesPerLine;
   unsigned char        Red[MAXCOLORS], Green[MAXCOLORS], Blue[MAXCOLORS];
   unsigned char        *pcximage;
   unsigned char        *pcxplanes;
   bit                  *pcxpixels;

   pbm_init( &argc, argv );

   switch (argc)
   {
         case 1:
             ifname     = "standard input";
             ifp        = stdin;
             break;
         case 2:
             ifname     = argv[1];
             ifp        = pm_openr(ifname);
             break;
         default:
             pm_usage("[pcxfile]");
             break;
   }

   /*
    * read the PCX header
    */
   if (GetByte(ifp) != PCX_MAGIC)
         pm_error("%s is not a PCX file", ifname );

   Version      = GetByte(ifp);  /* get version #                       */

   if (GetByte(ifp) != 1)        /* check for PCX run length encoding   */
         pm_error("%s has unknown encoding scheme", ifname );

   BitsPerPixel= GetByte(ifp);
   Xmin = GetWord(ifp);
   Ymin = GetWord(ifp);
   Xmax = GetWord(ifp);
   Ymax = GetWord(ifp);

   Width        = (Xmax - Xmin) + 1;
   Height       = (Ymax - Ymin) + 1;

   (void) GetWord(ifp);         /* ignore horizontal resolution */
   (void) GetWord(ifp);         /* ignore vertical resolution   */

   /*
    * get the 16-color color map
    */
   for (i = 0; i < 16; i++)
   {
         Red[i]    = GetByte(ifp);
         Green[i]  = GetByte(ifp);
         Blue[i]   = GetByte(ifp);
   }

   (void) GetByte(ifp);         /* skip reserved byte    */
   Planes       = GetByte(ifp);         /* # of color planes     */
   BytesPerLine= GetWord(ifp);          /* # of bytes per line   */
   (void) GetWord(ifp);         /* ignore palette info   */

   /*
    * check that we can handle this image format
    */
   if (Planes != 1 || BitsPerPixel != 1)
        pm_error("can't handle %d bits per pixel image with %d planes",
                 BitsPerPixel,Planes);

   /*
    * read the pcx format image (read 70 so far)
    */
   for ( i = 0; i < PCX_HDR_SIZE-70; i++) (void) GetByte(ifp);
   pcximage     = (unsigned char *)pm_allocrow(BytesPerLine * Planes, Height);
   read_pcx_image(ifp, pcximage, BytesPerLine, Planes, Height);
   pbm_writepbminit( stdout, Width, Height, 0);
   pcxpixels    = pbm_allocrow(Width);

   /*
    * convert the image
    */
   for (y = 0; y < Height; y++)
   {
         pcxplanes = pcximage + (y * BytesPerLine * Planes);

         pcx_unpack_pixels(pcxpixels, pcxplanes,
                           BytesPerLine, Planes, BitsPerPixel);
         pbm_writepbmrow( stdout, pcxpixels, Width, 0);
   }

   pm_close(ifp);
   pm_close(stdout);

   exit(0);
}

static void
read_pcx_image(fp, buf, BytesPerLine, Planes, Height)
   FILE *fp;
   unsigned char   *buf;
   int          BytesPerLine;
   int          Planes;
   int          Height;
{
   int          c;
   int          nbytes;
   int          count;

   nbytes       = BytesPerLine * Planes * Height;

   while (nbytes > 0)
   {
         c    = GetByte(fp);
         if ((c & 0xc0) != 0xc0)
         {
             *buf++    = c;
             --nbytes;
             continue;
         }

         count    = c & 0x3f;
         c    = GetByte(fp);
         if (count > nbytes)
             pm_error("repeat count spans end of image, count = %d, nbytes = 
%d", count, nbytes);

         nbytes    -= count;
         while (--count >= 0)
             *buf++ = c;
   }
}

/*
* convert packed pixel format into 1 pixel per byte
*/
static void
pcx_unpack_pixels(pixels, bitplanes, bytesperline, planes, bitsperpixel)
bit             *pixels;
unsigned char   *bitplanes;
int             bytesperline;
int             planes;
int             bitsperpixel;
{
   register int bits;

   while (--bytesperline >= 0)
   {
        bits    = *bitplanes++;
        *pixels++       = ((bits & 0x80) == 0);
        *pixels++       = ((bits & 0x40) == 0);
        *pixels++       = ((bits & 0x20) == 0);
        *pixels++       = ((bits & 0x10) == 0);
        *pixels++       = ((bits & 0x08) == 0);
        *pixels++       = ((bits & 0x04) == 0);
        *pixels++       = ((bits & 0x02) == 0);
        *pixels++       = ((bits & 0x01) == 0);
   }
}

static int
GetByte(fp)
FILE    *fp;
{
   int    c;

   if ((c = getc(fp)) == EOF)
         pm_error("unexpected end of file" );
   return c;
}

static int
GetWord(fp)
FILE    *fp;
{
   int    c;

   c  = GetByte(fp);
   c |= (GetByte(fp) << 8);
   return c;
}

- -------------------------------------------------------------------------
/*
* pcxtoppm.c - Converts from a PC Paintbrush PCX file to a PPM file.
*
* Copyright (c) 1990 by Michael Davidson
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose and without fee is hereby granted,
* provided that the above copyright notice appear in all copies and that
* both that copyright notice and this permission notice appear in
* supporting documentation.
*
* This file is provided AS IS with no warranties of any kind.  The author
* shall have no liability with respect to the infringement of copyrights,
* trade secrets or any patents by this file or any part thereof.  In no
* event will the author be liable for any lost revenue or profits or
* other special, indirect and consequential damages.
*
*/

#include        <stdio.h>
#include        "ppm.h"

#define PCX_MAGIC       0x0a            /* PCX magic number             */
#define PCX_HDR_SIZE    128             /* size of PCX header           */
#define PCX_256_COLORS  0x0c            /* magic number for 256 colors  */

#define MAXCOLORS       256
#define MAXPLANES       4
#define PCX_MAXVAL      255

static void read_pcx_image ARGS(( FILE *fp, unsigned char *buf, int 
BytesPerLine, int Planes, int Height ));
static void pcx_planes_to_pixels ARGS(( unsigned char *pixels, unsigned char 
*bitplanes, int bytesperline, int planes, int bitsperpixel ));
static void pcx_unpack_pixels ARGS(( unsigned char *pixels, unsigned char 
*bitplanes, int bytesperline, int planes, int bitsperpixel ));
static int GetByte ARGS(( FILE *fp ));
static int GetWord ARGS(( FILE *fp ));

void
main(argc, argv)
   int          argc;
   char *argv[];
{
   register int i;
   FILE         *ifp;
   char         *ifname;
   int                  Version;
   int                  Xmin, Ymin, Xmax, Ymax;
   int                  Width, Height;
   register int x, y;
   int                  Planes;
   int                  BitsPerPixel;
   int                  BytesPerLine;
   unsigned char        Red[MAXCOLORS], Green[MAXCOLORS], Blue[MAXCOLORS];
   unsigned char        *pcximage;
   unsigned char        *pcxplanes;
   unsigned char        *pcxpixels;
   pixel                **pixels;

   ppm_init( &argc, argv );

   switch (argc)
   {
         case 1:
             ifname     = "standard input";
             ifp        = stdin;
             break;
         case 2:
             ifname     = argv[1];
             ifp        = pm_openr(ifname);
             break;
         default:
             pm_usage("[pcxfile]");
             break;
   }

   /*
    * read the PCX header
    */
   if (GetByte(ifp) != PCX_MAGIC)
         pm_error("%s is not a PCX file", ifname );

   Version      = GetByte(ifp);  /* get version #                       */

   if (GetByte(ifp) != 1)        /* check for PCX run length encoding   */
         pm_error("%s has unknown encoding scheme", ifname );

   BitsPerPixel= GetByte(ifp);
   Xmin = GetWord(ifp);
   Ymin = GetWord(ifp);
   Xmax = GetWord(ifp);
   Ymax = GetWord(ifp);

   Width        = (Xmax - Xmin) + 1;
   Height       = (Ymax - Ymin) + 1;

   (void) GetWord(ifp);         /* ignore horizontal resolution */
   (void) GetWord(ifp);         /* ignore vertical resolution   */

   /*
    * get the 16-color color map
    */
   for (i = 0; i < 16; i++)
   {
         Red[i]    = GetByte(ifp);
         Green[i]  = GetByte(ifp);
         Blue[i]   = GetByte(ifp);
   }

   (void) GetByte(ifp);         /* skip reserved byte    */
   Planes       = GetByte(ifp);         /* # of color planes     */
   BytesPerLine= GetWord(ifp);          /* # of bytes per line   */
   (void) GetWord(ifp);         /* ignore palette info   */

   /*
    * check that we can handle this image format
    */
   switch (BitsPerPixel)
   {
        case 1:
            if (Planes > 4)
                pm_error("can't handle image with more than 4 planes");
            if (Planes == 1) {
                Red[0] = 0;
                Green[0] = 0;
                Blue[0] = 0;
                Red[1] = 255;
                Green[1] = 255;
                Blue[1] = 255;
            }
            break;

        case 2:
        case 4:
        case 8:
            if (Planes == 1)
                break;
        default:
            pm_error("can't handle %d bits per pixel image with %d planes",
                        BitsPerPixel,Planes);
   }


   /*
    * read the pcx format image (read 70 so far)
    */
   for ( i = 0; i < PCX_HDR_SIZE-70; i++) (void) GetByte(ifp);
   pcximage     = (unsigned char *)pm_allocrow(BytesPerLine * Planes, Height);
   read_pcx_image(ifp, pcximage, BytesPerLine, Planes, Height);

   /*
    * 256 color images have their color map at the end of the file
    * preceeded by a magic byte
    */
   if (BitsPerPixel == 8)
   {
        if (GetByte(ifp) != PCX_256_COLORS)
            pm_error("bad color map signature" );

        for (i = 0; i < MAXCOLORS; i++)
        {
            Red[i]      = GetByte(ifp);
            Green[i]    = GetByte(ifp);
            Blue[i]     = GetByte(ifp);
        }
   }

   pixels       = ppm_allocarray(Width, Height);
   pcxpixels    = (unsigned char *)pm_allocrow(Width+7, 1);

   /*
    * convert the image
    */
   for (y = 0; y < Height; y++)
   {
         pcxplanes = pcximage + (y * BytesPerLine * Planes);

         if (Planes == 1)
         {
             pcx_unpack_pixels(pcxpixels, pcxplanes,
                 BytesPerLine, Planes, BitsPerPixel);
         }
         else
         {
             pcx_planes_to_pixels(pcxpixels, pcxplanes,
                 BytesPerLine, Planes, BitsPerPixel);
         }

         for (x = 0; x < Width; x++)
         {
             i = pcxpixels[x];
             PPM_ASSIGN(pixels[y][x], Red[i], Green[i], Blue[i]);
         }
   }

   pm_close(ifp);

   ppm_writeppm(stdout, pixels, Width, Height, (pixval) 255, 0 );

   pm_close(stdout);

   exit(0);
}

static void
read_pcx_image(fp, buf, BytesPerLine, Planes, Height)
   FILE *fp;
   unsigned char   *buf;
   int          BytesPerLine;
   int          Planes;
   int          Height;
{
   int          c;
   int          nbytes;
   int          count;

   nbytes       = BytesPerLine * Planes * Height;

   while (nbytes > 0)
   {
         c    = GetByte(fp);
         if ((c & 0xc0) != 0xc0)
         {
             *buf++    = c;
             --nbytes;
             continue;
         }

         count    = c & 0x3f;
         c    = GetByte(fp);
         if (count > nbytes)
             pm_error("repeat count spans end of image, count = %d, nbytes = 
%d", count, nbytes);

         nbytes    -= count;
         while (--count >= 0)
             *buf++ = c;
   }
}

/*
* convert multi-plane format into 1 pixel per byte
*/
static void
pcx_planes_to_pixels(pixels, bitplanes, bytesperline, planes, bitsperpixel)
unsigned char   *pixels;
unsigned char   *bitplanes;
int             bytesperline;
int             planes;
int             bitsperpixel;
{
   int   i, j;
   int   npixels;
   unsigned char    *p;

   if (planes > 4)
         pm_error("can't handle more than 4 planes" );
   if (bitsperpixel != 1)
         pm_error("can't handle more than 1 bit per pixel" );

   /*
    * clear the pixel buffer
    */
   npixels = (bytesperline * 8) / bitsperpixel;
   p    = pixels;
   while (--npixels >= 0)
         *p++ = 0;

   /*
    * do the format conversion
    */
   for (i = 0; i < planes; i++)
   {
         int pixbit, bits, mask;

         p    = pixels;
         pixbit    = (1 << i);
         for (j = 0; j < bytesperline; j++)
         {
             bits = *bitplanes++;
             for (mask = 0x80; mask != 0; mask >>= 1, p++)
                 if (bits & mask)
                     *p |= pixbit;
         }
    }
}

/*
* convert packed pixel format into 1 pixel per byte
*/
static void
pcx_unpack_pixels(pixels, bitplanes, bytesperline, planes, bitsperpixel)
unsigned char   *pixels;
unsigned char   *bitplanes;
int             bytesperline;
int             planes;
int             bitsperpixel;
{
   register int bits;

   if (planes != 1)
         pm_error("can't handle packed pixels with more than 1 plane" );
   if (bitsperpixel == 8)
   {
        while (--bytesperline >= 0)
            *pixels++ = *bitplanes++;
   }
   else if (bitsperpixel == 4)
   {
        while (--bytesperline >= 0)
        {
            bits        = *bitplanes++;
            *pixels++   = (bits >> 4) & 0x0f;
            *pixels++   = (bits     ) & 0x0f;
        }
   }
   else if (bitsperpixel == 2)
   {
        while (--bytesperline >= 0)
        {
            bits        = *bitplanes++;
            *pixels++   = (bits >> 6) & 0x03;
            *pixels++   = (bits >> 4) & 0x03;
            *pixels++   = (bits >> 2) & 0x03;
            *pixels++   = (bits     ) & 0x03;
        }
   }
   else if (bitsperpixel == 1)
   {
        while (--bytesperline >= 0)
        {
            bits        = *bitplanes++;
            *pixels++   = ((bits & 0x80) != 0);
            *pixels++   = ((bits & 0x40) != 0);
            *pixels++   = ((bits & 0x20) != 0);
            *pixels++   = ((bits & 0x10) != 0);
            *pixels++   = ((bits & 0x08) != 0);
            *pixels++   = ((bits & 0x04) != 0);
            *pixels++   = ((bits & 0x02) != 0);
            *pixels++   = ((bits & 0x01) != 0);
        }
   }
}

static int
GetByte(fp)
FILE    *fp;
{
   int    c;

   if ((c = getc(fp)) == EOF)
         pm_error("unexpected end of file" );

   return c;
}

static int
GetWord(fp)
FILE    *fp;
{
   int    c;

   c  = GetByte(fp);
   c |= (GetByte(fp) << 8);
   return c;
}