NOTE: The difax
mailing list is no longer active. The list archives are made available for historical reasons.
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; }
difax
archives: