This is xvpcx.c in view mode; [Download] [Up]
/*
* xvpcx.c - load routine for PCX format pictures
*
* LoadPCX(fname, pinfo) - loads a PCX file
*/
/* Copyright Notice
* ================
* Copyright 1989, 1990, 1991, 1992, 1993 by John Bradley
*
* Permission to use, copy, and distribute XV in its entirety, for
* non-commercial purposes, is hereby granted without fee, provided that
* this license information and copyright notice appear in all copies.
*
* Note that distributing XV 'bundled' in with ANY product is considered
* to be a 'commercial purpose'.
*
* Also note that any copies of XV that are distributed MUST be built
* and/or configured to be in their 'unregistered copy' mode, so that it
* is made obvious to the user that XV is shareware, and that they should
* consider donating, or at least reading this License Info.
*
* The software may be modified for your own purposes, but modified
* versions may NOT be distributed without prior consent of the author.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the author be held liable for any damages
* arising from the use of this software.
*
* If you would like to do something with XV that this copyright
* prohibits (such as distributing it with a commercial product,
* using portions of the source in some other program, etc.), please
* contact the author (preferably via email). Arrangements can
* probably be worked out.
*
* XV is shareware for PERSONAL USE only. You may use XV for your own
* amusement, and if you find it nifty, useful, generally cool, or of
* some value to you, your non-deductable donation would be greatly
* appreciated. $25 is the suggested donation, though, of course,
* larger donations are quite welcome. Folks who donate $25 or more
* can receive a Real Nice bound copy of the XV manual for no extra
* charge.
*
* Commercial, government, and institutional users MUST register their
* copies of XV, for the exceedingly REASONABLE price of just $25 per
* workstation/X terminal. Site licenses are available for those who
* wish to run XV on a large number of machines. Contact the author
* for more details.
*
* The author may be contacted via:
* US Mail: John Bradley
* 1053 Floyd Terrace
* Bryn Mawr, PA 19010
*
* Phone: (215) 898-8813
* EMail: bradley@cis.upenn.edu
*/
/*
* the following code has been derived from code written by
* Eckhard Rueggeberg (Eckhard.Rueggeberg@ts.go.dlr.de)
*/
#include "xv.h"
/* offsets into PCX header */
#define PCX_ID 0
#define PCX_VER 1
#define PCX_ENC 2
#define PCX_BPP 3
#define PCX_XMINL 4
#define PCX_XMINH 5
#define PCX_YMINL 6
#define PCX_YMINH 7
#define PCX_XMAXL 8
#define PCX_XMAXH 9
#define PCX_YMAXL 10
#define PCX_YMAXH 11
/* hres (12,13) and vres (14,15) not used */
#define PCX_CMAP 16 /* start of 16*3 colormap data */
#define PCX_PLANES 65
#define PCX_BPRL 66
#define PCX_BPRH 67
#define PCX_MAPSTART 0x0c /* Start of appended colormap */
#ifdef __STDC__
static int pcxLoadImage(char *, FILE *, byte *, byte *, int, int);
static void pcxLoadRaster(FILE *, byte *, int, byte *, int, int);
static int pcxError(char *, char *);
#else
static int pcxLoadImage(), pcxError();
static void pcxLoadRaster();
#endif
/*******************************************/
int LoadPCX(fname, pinfo)
char *fname;
PICINFO *pinfo;
/*******************************************/
{
FILE *fp;
long filesize;
char *bname, *errstr;
byte hdr[128], *image;
int i, colors, gray;
pinfo->type = PIC8;
pinfo->pic = (byte *) NULL;
pinfo->comment = (char *) NULL;
bname = BaseName(fname);
/* open the stream */
fp=fopen(fname,"r");
if (!fp) return (pcxError(bname, "unable to open file"));
/* figure out the file size */
fseek(fp, 0L, 2);
filesize = ftell(fp);
fseek(fp, 0L, 0);
/* read the PCX header */
fread(hdr, 128, 1, fp);
if (ferror(fp)) {
fclose(fp);
return pcxError(bname, "EOF reached in PCX header.\n");
}
if (hdr[PCX_ID] != 0x0a || hdr[PCX_VER] > 5) {
fclose(fp);
return pcxError(bname,"unrecognized magic number");
}
pinfo->w = (hdr[PCX_XMAXL] + ((int) hdr[PCX_XMAXH]<<8))
- (hdr[PCX_XMINL] + ((int) hdr[PCX_XMINH]<<8));
pinfo->h = (hdr[PCX_YMAXL] + ((int) hdr[PCX_YMAXH]<<8))
- (hdr[PCX_YMINL] + ((int) hdr[PCX_YMINH]<<8));
pinfo->w++; pinfo->h++;
colors = 1 << (hdr[PCX_BPP] * hdr[PCX_PLANES]);
if (DEBUG) {
fprintf(stderr,"PCX: %dx%d image, version=%d, encoding=%d\n",
pinfo->w, pinfo->h, hdr[PCX_VER], hdr[PCX_ENC]);
fprintf(stderr," BitsPerPixel=%d, planes=%d, BytePerRow=%d, colors=%d\n",
hdr[PCX_BPP], hdr[PCX_PLANES],
hdr[PCX_BPRL] + ((int) hdr[PCX_BPRH]<<8),
colors);
}
if (colors>256) {
fclose(fp);
return pcxError(bname,"No more than 256 colors allowed in PCX file.");
}
if (hdr[PCX_ENC] != 1) {
fclose(fp);
return pcxError(bname,"Unsupported PCX encoding format.");
}
/* note: overallocation to make life easier... */
image = (byte *) malloc((pinfo->h + 1) * pinfo->w + 16);
if (!image) FatalError("Can't alloc 'image' in LoadPCX()");
xvbzero((char *) image, (pinfo->h+1) * pinfo->w + 16); /* must clear img */
if (!pcxLoadImage(bname, fp, image, hdr, pinfo->w, pinfo->h)) {
free(image);
fclose(fp);
return 0;
}
if (ferror(fp)) /* just a warning */
pcxError(bname, "PCX file appears to be truncated.");
if (colors>16) { /* handle trailing colormap */
while (1) {
i=getc(fp);
if (i==PCX_MAPSTART || i==EOF) break;
}
for (i=0; i<colors; i++) {
pinfo->r[i] = getc(fp);
pinfo->g[i] = getc(fp);
pinfo->b[i] = getc(fp);
}
if (ferror(fp)) {
pcxError(bname,"Error reading PCX colormap. Using grayscale.");
for (i=0; i<256; i++) pinfo->r[i] = pinfo->g[i] = pinfo->b[i] = i;
}
}
else if (colors<=16) { /* internal colormap */
for (i=0; i<colors; i++) {
pinfo->r[i] = hdr[PCX_CMAP + i*3];
pinfo->g[i] = hdr[PCX_CMAP + i*3 + 1];
pinfo->b[i] = hdr[PCX_CMAP + i*3 + 2];
}
}
if (colors == 2) { /* b&w */
if (MONO(pinfo->r[0],pinfo->g[0],pinfo->b[0]) ==
MONO(pinfo->r[1],pinfo->g[1],pinfo->b[1])) { /* create cmap */
pinfo->r[0] = pinfo->g[0] = pinfo->b[0] = 255;
pinfo->r[1] = pinfo->g[1] = pinfo->b[1] = 0;
if (DEBUG) fprintf(stderr,"PCX: no cmap: using 0=white,1=black\n");
}
}
fclose(fp);
/* finally, convert into XV internal format */
pinfo->pic = image;
pinfo->type = PIC8;
pinfo->frmType = -1; /* no default format to save in */
/* check for grayscaleitude */
for (i=0; i<colors; i++) {
if ((pinfo->r[i] != pinfo->g[i]) || (pinfo->r[i] != pinfo->b[i])) break;
}
gray = (i==colors) ? 1 : 0;
if (colors > 2 || (colors==2 && !gray)) { /* grayscale or PseudoColor */
pinfo->colType = (gray) ? F_GREYSCALE : F_FULLCOLOR;
sprintf(pinfo->fullInfo,
"%s PCX, %d plane%s, %d bit%s per pixel. (%ld bytes)",
(gray) ? "Greyscale" : "Color",
hdr[PCX_PLANES], (hdr[PCX_PLANES]==1) ? "" : "s",
hdr[PCX_BPP], (hdr[PCX_BPP]==1) ? "" : "s",
filesize);
}
else {
pinfo->colType = F_BWDITHER;
sprintf(pinfo->fullInfo, "B&W PCX. (%ld bytes)", filesize);
}
sprintf(pinfo->shrtInfo, "%dx%d PCX.", pinfo->w, pinfo->h);
return 1;
}
/*****************************/
static int pcxLoadImage(fname, fp, image, hdr, w, h)
char *fname;
FILE *fp;
byte *image, *hdr;
int w, h;
{
switch (hdr[PCX_BPP]) {
case 1: pcxLoadRaster(fp, image, 1, hdr, w, h); break;
case 8: pcxLoadRaster(fp, image, 8, hdr, w, h); break;
default:
pcxError(fname, "Unsupported # of bits per plane.");
return (0);
}
return 1;
}
/*****************************/
static void pcxLoadRaster(fp, image, depth, hdr, w,h)
FILE *fp;
byte *image, *hdr;
int depth,w,h;
{
/* supported: 8 bits per pixel, 1 plane, or 1 bit per pixel, 1-8 planes */
int row, bcnt, bperlin, pad;
int i, j, b, cnt, mask, plane, pmask;
byte *oldimage;
bperlin = hdr[PCX_BPRL] + ((int) hdr[PCX_BPRH]<<8);
if (depth == 1) pad = (bperlin * 8) - w;
else pad = bperlin - w;
row = bcnt = 0;
plane = 0; pmask = 1; oldimage = image;
while ( (b=getc(fp)) != EOF) {
if ((b & 0xC0) == 0xC0) { /* have a rep. count */
cnt = b & 0x3F;
b = getc(fp);
if (b == EOF) { getc(fp); return; }
}
else cnt = 1;
for (i=0; i<cnt; i++) {
if (depth == 1) {
for (j=0, mask=0x80; j<8; j++) {
*image++ |= ((b & mask) ? pmask : 0);
mask = mask >> 1;
}
}
else *image++ = (byte) b;
bcnt++;
if (bcnt == bperlin) { /* end of a line reached */
bcnt = 0;
plane++;
if (plane>=hdr[PCX_PLANES]) { /* moved to next row */
plane = 0;
image -= pad;
oldimage = image;
row++;
if (row >= h) return; /* done */
}
else { /* next plane, same row */
image = oldimage;
}
pmask = 1 << plane;
}
}
}
}
/*******************************************/
static int pcxError(fname,st)
char *fname, *st;
{
SetISTR(ISTR_WARNING,"%s: %s", fname, st);
return 0;
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.