home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
rtsi.com
/
2014.01.www.rtsi.com.tar
/
www.rtsi.com
/
OS9
/
OSK
/
NETWORK
/
netpbm_src.lzh
/
NETPBM
/
PPM
/
pcxtoppm.c.orig
< prev
next >
Wrap
Text File
|
1996-11-18
|
8KB
|
357 lines
/*
* 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 ));
int
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");
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
*/
fseek(ifp, (long)PCX_HDR_SIZE, 0);
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;
}