This is pcxtoppm.c in view mode; [Download] [Up]
/* * 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; }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.