home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
rtsi.com
/
2014.01.www.rtsi.com.tar
/
www.rtsi.com
/
OS9
/
MM1
/
CMDS
/
pcxview_mm1.lzh
/
PCXVIEW
/
pcxdecode.c
< prev
next >
Wrap
C/C++ Source or Header
|
1997-04-18
|
8KB
|
280 lines
#include <stdio.h>
#define PCX_MAGIC 0x0a
#define PCX_256_COLORS 0x0c
#define MAXCOLORS 256
#define MAXPLANES 4
extern errno, iflag, hflag;
extern short ncolors;
extern unsigned char colormap[256][3];
char *vers[] = {"2.5", "?", "2.8 with palette", "2.8 without palette", "?", "3.0"};
struct {
char Manufacturer;
char Version;
char Encoding;
char BitsPerPixel;
short Xmin, Ymin, Xmax, Ymax;
short HorizontalRes, VerticalRes;
char Colormap[16][3];
char Reserved;
char Planes;
short BytesPerLine;
short PaletteInfo;
char Filler[58];
} head;
FILE *ifp;
int Version, i, y;
short Xmin, Ymin, Xmax, Ymax;
int Width, Height, Planes, BitsPerPixel;
short BytesPerLine;
unsigned char *pcximage, *pcxplanes, *pcxpixels, *pixels;
pcx_read(ifname)
char *ifname;
{
short HorizontalRes, VerticalRes, PaletteInfo;
if ( iflag )
ifp = stdin;
else
ifp = fopen(ifname, "r");
if (ifp == NULL)
exit(_errmsg(errno, "cannot open %s\n", ifname));
/* read the PCX header */
if ( fread(&head, sizeof(head), 1, ifp) == 0 )
exit(_errmsg(errno, "cannot read header of %s\n", ifname));
if (head.Manufacturer != PCX_MAGIC)
exit(_errmsg(errno, "%s is not a PCX file\n", ifname));
Version = head.Version; /* get version # */
if (head.Encoding != 1) /* check for PCX run length encoding */
exit(_errmsg(errno, "%s has unknown encoding scheme\n", ifname));
BitsPerPixel = head.BitsPerPixel;
Xmin = swab(head.Xmin);
Ymin = swab(head.Ymin);
Xmax = swab(head.Xmax);
Ymax = swab(head.Ymax);
Width = (Xmax - Xmin) + 1;
Height = (Ymax - Ymin) + 1;
/* get the 16-color color map */
ncolors = 16;
memcpy(colormap, head.Colormap, 16*3);
if (BitsPerPixel == 1
&& colormap[0][0] == 0 && colormap[0][1] == 0 && colormap[0][2] == 0
&& colormap[1][0] == 0 && colormap[1][1] == 0 && colormap[1][2] == 0)
colormap[1][0] = colormap[1][1] = colormap[1][2] = 255;
Planes = head.Planes; /* # of color planes */
BytesPerLine = swab(head.BytesPerLine); /* # of bytes per line */
HorizontalRes = swab(head.HorizontalRes);
VerticalRes = swab(head.VerticalRes);
PaletteInfo = swab(head.PaletteInfo);
if (hflag) {
fprintf(stderr, "\nFile: %s\n", ifname);
fprintf(stderr, "Version: %d (%s)\n", Version, vers[Version]);
fprintf(stderr, "Encoding: %d (RLE)\n", head.Encoding);
fprintf(stderr, "BitsPerPixel: %d\n", BitsPerPixel);
fprintf(stderr, "Xmin x Ymin = %d x %d\n", Xmin, Ymin);
fprintf(stderr, "Xmax x Ymax = %d x %d\n", Xmax, Ymax);
fprintf(stderr, "Width x Height = %d x %d\n", Width, Height);
fprintf(stderr, "HorizontalRes x VerticalRes = %d x %d\n",
HorizontalRes, VerticalRes);
fprintf(stderr, "Planes: %d\n", head.Planes);
fprintf(stderr, "BytesPerLine: %d\n", BytesPerLine);
fprintf(stderr, "PaletteInfo: %d %s\n", PaletteInfo,
PaletteInfo == 1 ? "(color/BW)" : PaletteInfo == 2 ? "(grayscale)" : "");
fprintf(stderr, "Actual number of colors = %d\n", 1 << BitsPerPixel);
}
/* check that we can handle this image format */
switch (BitsPerPixel) {
case 1:
if (Planes > MAXPLANES)
exit(_errmsg(errno, "can't handle image with more than 4 planes\n"));
break;
case 2:
case 4:
case 8:
if (Planes == 1)
break;
default:
exit(_errmsg(errno, "can't handle %d bits per pixel image with %d planes\n",
BitsPerPixel, Planes));
}
if ( hflag ) {
fclose(ifp);
return;
}
/* read the pcx format image */
pcximage = (unsigned char *) malloc(BytesPerLine * Planes * Height);
if ( pcximage == NULL )
exit(_errmsg(errno, "cannot allocate image\n"));
memset(pcximage, 0, BytesPerLine * Planes * Height);
read_pcx_image(pcximage);
/* 256 color images have their color map at the end of the file preceeded
* by a magic byte */
if (BitsPerPixel == 8) {
int c;
ncolors = 256;
do
c = getc(ifp);
while ( c != PCX_256_COLORS && c!= EOF);
if ( ferror(ifp) || feof(ifp) ) {
fprintf(stderr, "warning: error reading color map: using grayscale\n");
for ( c = 0; c < 256; c++ )
colormap[c][0] = colormap[c][1] = colormap[c][2] = i;
} else
if ( fread(colormap, MAXCOLORS*3, 1, ifp) == 0 )
exit(_errmsg(errno, "cannot read appended color map\n"));
}
pixels = (unsigned char *) malloc(Width * Height);
if (pixels == NULL)
exit(_errmsg(errno, "cannot allocate array\n"));
pcxpixels = pixels;
/* convert the image */
for (y = 0; y < Height; y++) {
pcxplanes = pcximage + (y * BytesPerLine * Planes);
if (Planes == 1)
pcx_unpack_pixels(pcxpixels, pcxplanes);
else
pcx_planes_to_pixels(pcxpixels, pcxplanes);
pcxpixels += Width;
}
free(pcximage);
fclose(ifp);
}
read_pcx_image(pcximage) /* -> pcximage */
register unsigned char *pcximage;
{
register int c, nbytes, count;
nbytes = BytesPerLine * Planes * Height;
while (nbytes > 0) {
c = getc(ifp);
if (c == EOF)
exit(_errmsg(errno, "unexpected end of file\n"));
if ((c & 0xc0) != 0xc0) {
*pcximage++ = c;
--nbytes;
continue;
}
count = c & 0x3f;
c = getc(ifp);
if (c == EOF)
exit(_errmsg(errno, "unexpected end of file\n"));
if (count > nbytes)
exit(_errmsg(errno,
"repeat count spans end of image, count = %d, nbytes = %d\n",
count, nbytes));
nbytes -= count;
while (--count >= 0)
*pcximage++ = c;
}
}
/*
* convert multi-plane format into 1 pixel per byte
*/
pcx_planes_to_pixels(pixels, bitplanes) /* pcximage -> pixels */
unsigned char *pixels;
register unsigned char *bitplanes;
{
int i, npixels;
register unsigned char *p;
short bytes = BytesPerLine;
register unsigned char bits, pixbit, mask;
register short j;
if (Planes > MAXPLANES)
exit(_errmsg(errno, "can't handle more than 4 planes\n"));
if (BitsPerPixel != 1)
exit(_errmsg(errno, "can't handle more than 1 bit per pixel\n"));
/* clear the pixel buffer */
npixels = (bytes * 8) / BitsPerPixel;
p = pixels;
while (--npixels >= 0)
*p++ = 0;
/* do the format conversion */
for (i = 0; i < Planes; i++) {
p = pixels;
pixbit = (1 << i);
j = bytes;
while ( --j >= 0 ) {
bits = *bitplanes++;
for (mask = 0x80; mask != 0; mask >>= 1, p++) {
if (bits & mask)
*p |= (pixbit << 4);
mask >>= 1;
if (bits & mask)
*p |= pixbit;
}
}
}
}
/*
* convert packed pixel format into 1 pixel per byte
*/
pcx_unpack_pixels(pixels, bitplanes) /* pcximage -> pixels */
register unsigned char *pixels;
register unsigned char *bitplanes;
{
register unsigned char bits;
register short bytes = BytesPerLine;
switch ( BitsPerPixel ) {
case 8:
case 4:
while (--bytes >= 0)
*pixels++ = *bitplanes++;
break;
case 2:
while (--bytes >= 0) {
bits = *bitplanes++;
*pixels++ = ((bits & 0xc0) >> 2) | (bits & 0x30);
*pixels++ = ((bits & 0x30) << 2) | (bits & 0x03);
}
break;
case 1:
while (--bytes >= 0) {
bits = *bitplanes++;
*pixels++ = ((bits & 0x80) >> 3) | ((bits & 0x40) >> 6);
*pixels++ = ((bits & 0x20) >> 1) | ((bits & 0x10) >> 4);
*pixels++ = ((bits & 0x08) << 1) | ((bits & 0x04) >> 2);
*pixels++ = ((bits & 0x02) << 3) | (bits & 0x01);
}
}
}