home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fractal Frenzy 1
/
WalnutCreekFractalFrenzy-1.iso
/
pc
/
viewers
/
x11
/
xv221.tz
/
xv221
/
xv-2.21
/
xvrle.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-04-06
|
9KB
|
348 lines
/*
* xvrle.c - load routine for rle (Utah Raster Toolkit) format pictures
*
* LoadRLE(fname, numcols) - loads an RLE file
*/
/*
* Copyright 1989, 1990, 1991, 1992 by John Bradley and
* The University of Pennsylvania
*
* Permission to use, copy, and distribute for non-commercial purposes,
* is hereby granted without fee, providing that the above copyright
* notice appear in all copies and that both the copyright notice and this
* permission notice appear in supporting documentation.
*
* The software may be modified for your own purposes, but modified versions
* may not be distributed.
*
* This software is provided "as is" without any expressed or implied warranty.
*
* The author may be contacted via:
* US Mail: John Bradley
* GRASP Lab, Room 301C
* 3401 Walnut St.
* Philadelphia, PA 19104
*
* Phone: (215) 898-8813
* EMail: bradley@cis.upenn.edu
*/
#include "xv.h"
/* Definitions needed to parse RLE format */
/* snarfed from rle_code.h, part of the Utah Raster Toolkit */
#define LONG_OP 0x40
#define RSkipLinesOp 1
#define RSetColorOp 2
#define RSkipPixelsOp 3
#define RByteDataOp 5
#define RRunDataOp 6
#define REOFOp 7
#define H_CLEARFIRST 0x1 /* clear framebuffer flag */
#define H_NO_BACKGROUND 0x2 /* if set, no bg color supplied */
#define H_ALPHA 0x4 /* if set, alpha channel (-1) present */
#define H_COMMENT 0x8 /* if set, comments present */
#define GETINT(fp) (c=getc(fp), c1=getc(fp), (c1<<8) + c )
static void read_rle();
static int RLEerr();
/*******************************************/
int LoadRLE(fname,nc)
char *fname;
int nc;
/*******************************************/
{
FILE *fp;
int c, c1, i, j, k;
byte bgcol[256];
byte maps[3][256];
int xpos, ypos, w, h, flags, ncolors, pixelbits, ncmap, cmaplen;
int cmtlen;
byte *img;
long filesize;
/* open the stream */
fp=fopen(fname,"r");
if (!fp) return 1;
/* figure out the file size */
fseek(fp, 0L, 2);
filesize = ftell(fp);
fseek(fp, 0L, 0);
/* read the magic number */
c = getc(fp); c1 = getc(fp);
if ((c != 0x52) || (c1 != 0xcc))
return(RLEerr("unrecognized magic number"));
xpos = GETINT(fp); /* read rest of header info */
ypos = GETINT(fp);
w = GETINT(fp);
h = GETINT(fp);
flags = getc(fp);
ncolors = getc(fp);
pixelbits = getc(fp);
ncmap = getc(fp);
c = getc(fp);
cmaplen = (1L << c);
if (DEBUG) {
fprintf(stderr,"RLE: %dx%d image at %d,%d\n", w, h, xpos, ypos);
fprintf(stderr,"flags: 0x%02x (%s%s%s%s)\n",
flags,
(flags & H_CLEARFIRST) ? "CLEARFIRST " : "",
(flags & H_NO_BACKGROUND) ? "NO_BG " : "",
(flags & H_ALPHA) ? "ALPHA " : "",
(flags & H_COMMENT) ? "COMMENT" : "");
fprintf(stderr, "%d bands, %d pixelbits, %d cmap bands, %d cmap entries\n",
ncolors, pixelbits, ncmap, cmaplen);
}
if (DEBUG) fprintf(stderr, "background value: ");
for (i=0; i<ncolors; i++) {
bgcol[i] = getc(fp);
if (DEBUG) fprintf(stderr, "0x%02x ", bgcol[i]);
}
if (DEBUG) fprintf(stderr,"\n");
if ((ncolors % 2) == 0) getc(fp); /* get on a word boundary */
/* read colormap(s) */
for (i=0; i<ncmap; i++) {
for (j = 0; j<cmaplen; j++) {
k = GETINT(fp);
if (i<3) maps[i][j] = k>>8;
}
}
if (DEBUG) {
if (ncmap) {
fprintf(stderr, "Colormap:\n");
for (i=0; i<cmaplen; i++) {
fprintf(stderr,"(");
for (j=0; (j<ncmap && j<3); j++) {
fprintf(stderr, "%02x ", maps[j][i]);
}
fprintf(stderr,") ");
}
fprintf(stderr,"\n\n");
}
else fprintf(stderr,"No colormap\n");
}
/* read (skip over, actually) the comments, if any */
if (flags & H_COMMENT) {
cmtlen = GETINT(fp);
if (cmtlen) {
if (DEBUG) fprintf(stderr,"Comment: (%d bytes) '", cmtlen);
for (i=0; i<cmtlen; i++) {
c = getc(fp);
if (DEBUG) fprintf(stderr,"%c",c);
}
if (cmtlen % 2) getc(fp); /* get on a word boundary */
if (DEBUG) fprintf(stderr,"'\n\n");
}
}
if (ferror(fp))
return RLEerr("EOF reached while reading RLE header.\n");
/*
* Acceptable cases:
* ncolors = 1, 3, or >3 (extra planes ignored)
* pixelbits = 8
* ncmap = 0 (interpreted as TrueColor/TrueGray)
* 1 (TrueColor/TrueGray with a gamma curve)
* 3 | ncolors (TrueColor with three gamma curves)
*/
if (ncolors == 0 || ncolors == 2)
return RLEerr("Unsupported number of channels in RLE file.\n");
if (pixelbits != 8)
return RLEerr("Only 8-bit pixels supported in RLE files.\n");
if (ncmap==0 || ncmap==1 || (ncmap == 3 && ncolors >=3)) { /* ok */ }
else return RLEerr("Invalid # of colormap channels in RLE file.\n");
if (w<1 || h<1)
return RLEerr("Bogus size in RLE header.\n");
/* allocate image memory */
if (ncolors == 1) img = (byte *) calloc(w * h, 1);
else img = (byte *) calloc(w * h * 3, 1);
if (!img) return RLEerr("LoadRLE(): Unable to allocate image data.\n");
/* set background, if necessary */
if ((flags & H_CLEARFIRST) && ((~flags) & H_NO_BACKGROUND)) {
byte *ip;
if (ncolors == 1) {
for (i=0, ip=img; i<w*h; i++, ip++) *ip = bgcol[0];
}
else {
for (i=0, ip=img; i<w*h; i++)
for (j=0; j<3; j++, ip++) *ip = bgcol[j];
}
}
read_rle(fp, img, w, h, ncolors, ncmap);
/* apply colormap transformation to image */
if (ncmap) {
byte *ip;
int imagelen, cmask;
imagelen = (ncolors==1) ? w*h : w*h*3;
cmask = (cmaplen-1);
if (ncmap == 1) {
for (i=0, ip=img; i<imagelen; i++, ip++) *ip = maps[0][*ip & cmask];
}
else if (ncmap == 3) {
for (i=0, ip=img; i<w*h; i++) {
*ip = maps[0][*ip & cmask]; ip++;
*ip = maps[1][*ip & cmask]; ip++;
*ip = maps[2][*ip & cmask]; ip++;
}
}
}
/* finally, convert into XV internal format */
if (ncolors == 1) { /* grayscale */
pic = img; pWIDE = w; pHIGH = h;
SetISTR(ISTR_FORMAT, "Greyscale RLE. (%ld bytes)", filesize);
sprintf(formatStr, "%dx%d RLE.",w, h);
SetDirRButt(F_COLORS, F_GREYSCALE);
for (i=0; i<256; i++) r[i] = g[i] = b[i] = i; /* gray cmap */
}
else { /* true color */
SetISTR(ISTR_FORMAT, "Color RLE. (%ld bytes)", filesize);
sprintf(formatStr, "%dx%d RLE.",w, h);
SetDirRButt(F_COLORS, F_FULLCOLOR);
i = Conv24to8(img, w, h, nc);
free(img);
return i;
}
return 0;
}
/*******************************************/
static void read_rle(fp, img, w, h, ncolors, ncmap)
FILE *fp;
byte *img;
int w, h, ncolors, ncmap;
{
int posx, posy, plane, bperpix, i, pixval, skipcalls;
int opcode, operand, done, c, c1;
byte *ip;
posx = posy = plane = done = skipcalls = 0;
if (ncolors == 1) bperpix = 1;
else bperpix = 3;
while (!done && (opcode=getc(fp)) != EOF) {
switch (opcode & 0x3f) {
case RSkipLinesOp:
if (opcode & LONG_OP) { getc(fp); operand = GETINT(fp); }
else operand = getc(fp);
posx = 0;
posy += operand;
skipcalls++;
if ((skipcalls & 0x7f)==0) WaitCursor();
break;
case RSetColorOp:
operand = getc(fp);
plane = operand;
posx = 0;
break;
case RSkipPixelsOp:
if (opcode & LONG_OP) { getc(fp); operand = GETINT(fp); }
else operand = getc(fp);
posx += operand;
break;
case RByteDataOp:
if (opcode & LONG_OP) { getc(fp); operand = GETINT(fp); }
else operand = getc(fp);
ip = img + ((h-posy-1) * w*bperpix) + posx*bperpix + plane;
operand++;
for (i=0; i<operand; i++, ip+=bperpix) {
c = getc(fp);
if (plane<ncolors && posy<h && (posx+i < w)) *ip = c;
}
if (operand & 1) getc(fp); /* word boundary */
posx += operand;
break;
case RRunDataOp:
if (opcode & LONG_OP) { getc(fp); operand = GETINT(fp); }
else operand = getc(fp);
pixval = getc(fp); getc(fp);
operand++;
ip = img + ((h-posy-1) * w*bperpix) + posx*bperpix + plane;
for (i=0; i<operand; i++, ip+=bperpix) {
if (plane<ncolors && posy<h && (posx+i < w)) *ip = pixval;
}
/* if (operand & 1) getc(fp); /* word boundary */
posx += operand;
break;
case REOFOp:
done = 1;
break;
}
}
}
/*******************************************/
static int RLEerr(st)
char *st;
{
SetISTR(ISTR_WARNING,st);
return 1;
}