home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fractal Frenzy 1
/
WalnutCreekFractalFrenzy-1.iso
/
pc
/
viewers
/
x11
/
xv221.tz
/
xv221
/
xv-2.21
/
xvsunras.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-01-16
|
11KB
|
457 lines
/*
* xvsunras.c - load routine for 'sun rasterfile' format pictures
*
* LoadSunRas(fname, numcols) - loads a PM pic, does 24to8 code if nec.
* WriteSunRas(fp, pic, w, h, r,g,b, numcols, style)
* WriteRaw(fp, pic, w, h, r,g,b, numcols, style)
*
* This file written by Dave Heath (heath@cs.jhu.edu)
* fixBGR() added by Ken Rossman (ken@shibuya.cc.columbia.edu)
*/
#include "xv.h"
#include "sunras.h"
static int SunRasError();
static int rle_read();
static void flipl();
static void SunRas1to8();
static void SunRas8to1();
static int write_sun_long();
static void fixBGR();
/*******************************************/
int LoadSunRas(fname,nc)
char *fname;
int nc;
/*******************************************/
{
FILE *fp;
int linesize,lsize,csize,isize,flipit,i,w,h,d,rv;
byte *image, *line;
struct rasterfile sunheader;
rv = 0;
/* read in the Sun Rasterfile picture */
fp=fopen(fname,"r");
if (!fp) return( SunRasError("unable to open file") );
flipit = 0;
fread(&sunheader,sizeof(struct rasterfile),1,fp);
if (sunheader.ras_magic != RAS_MAGIC)
{
flipl( (byte *) &sunheader.ras_magic);
if (sunheader.ras_magic == RAS_MAGIC) flipit = 1;
else flipl( (byte *) &sunheader.ras_magic);
}
if (sunheader.ras_magic != RAS_MAGIC)
return( SunRasError("not a Sun rasterfile") );
if (flipit) {
flipl((byte *) &sunheader.ras_width);
flipl((byte *) &sunheader.ras_height);
flipl((byte *) &sunheader.ras_depth);
flipl((byte *) &sunheader.ras_length);
flipl((byte *) &sunheader.ras_type);
flipl((byte *) &sunheader.ras_maptype);
flipl((byte *) &sunheader.ras_maplength);
}
/* make sure that the input picture can be dealt with */
if (sunheader.ras_depth != 1 &&
sunheader.ras_depth != 8 &&
sunheader.ras_depth != 24 &&
sunheader.ras_depth != 32) {
fprintf (stderr, "Sun rasterfile image has depth %d\n",
sunheader.ras_depth);
fprintf (stderr, "Depths supported are 1, 8, 24, and 32\n");
return 1;
}
if (sunheader.ras_type != RT_OLD &&
sunheader.ras_type != RT_STANDARD &&
sunheader.ras_type != RT_BYTE_ENCODED &&
sunheader.ras_type != RT_FORMAT_RGB) {
fprintf (stderr, "Sun rasterfile of unsupported type %d\n",
sunheader.ras_type);
return 1;
}
if (sunheader.ras_maptype != RMT_RAW &&
sunheader.ras_maptype != RMT_NONE &&
sunheader.ras_maptype != RMT_EQUAL_RGB) {
fprintf (stderr, "Sun rasterfile colormap of unsupported type %d\n",
sunheader.ras_maptype);
return 1;
}
w = sunheader.ras_width;
h = sunheader.ras_height;
d = sunheader.ras_depth;
isize = sunheader.ras_length ?
sunheader.ras_length :
(w * h * d) / 8;
csize = (sunheader.ras_maptype == RMT_NONE) ? 0 : sunheader.ras_maplength;
/* compute length of the output (xv-format) image */
lsize = w * h;
if (d == 24 || d == 32) lsize = lsize * 3;
linesize = w * d;
/* if ((linesize % 48) && d == 24) linesize += (48 - (linesize % 48)); */
if (linesize % 16) linesize += (16 - (linesize % 16));
linesize /= 8;
if (DEBUG)
{
fprintf(stderr,"%s: LoadSunRas() - loading a %dx%d pic, %d planes\n",
cmd, w, h,
d);
fprintf (stderr,
"type %d, maptype %d, isize %d, csize %d, lsize %d, linesize %d\n",
sunheader.ras_type, sunheader.ras_maptype,
isize, csize, lsize, linesize);
}
SetDirRButt(F_FORMAT, F_SUNRAS);
if (d==1) SetDirRButt(F_COLORS, F_BWDITHER);
else SetDirRButt(F_COLORS, F_FULLCOLOR);
SetISTR(ISTR_FORMAT,"Sun %s rasterfile. (%d plane%s) (%d bytes)",
sunheader.ras_type == RT_BYTE_ENCODED ? "rle" : "standard",
d,
d == 1 ? "" : "s",
sizeof (struct rasterfile) + csize + isize);
sprintf(formatStr, "%dx%d Sun Rasterfile.",w,h);
/* read in the colormap, if any */
if (sunheader.ras_maptype == RMT_EQUAL_RGB && csize)
{
fread (r, sizeof (byte), sunheader.ras_maplength/3, fp);
fread (g, sizeof (byte), sunheader.ras_maplength/3, fp);
fread (b, sizeof (byte), sunheader.ras_maplength/3, fp);
/* for (i = 0; i < sunheader.ras_maplength/3; i++)
{
r[i] = getc (fp);
g[i] = getc (fp);
b[i] = getc (fp);
} */
}
else if (sunheader.ras_maptype == RMT_RAW && csize)
{
/* we don't know how to handle raw colormap, ignore */
fseek (fp, (long) csize, 1);
}
else { /* no colormap, make one up */
if (sunheader.ras_depth == 1) {
r[0] = g[0] = b[0] = 0;
r[1] = g[1] = b[1] = 255;
}
else if (sunheader.ras_depth == 8) {
for (i = 0; i < 256; i++)
r[i] = g[i] = b[i] = i;
}
}
/* allocate memory for picture and read it in */
/* note we may slightly overallocate here (if image is padded) */
image = (byte *) malloc (lsize);
line = (byte *) malloc (linesize);
if (image == NULL || line == NULL)
FatalError("Can't allocate memory for image\n");
for (i = 0; i < h; i++) {
if ((i&0x1f) == 0) WaitCursor();
if (sunheader.ras_type == RT_BYTE_ENCODED) {
if (rle_read (line, 1, linesize, fp, (i==0)) != linesize) break;
/* return (SunRasError ("rle file read error")); */
}
else {
if (fread (line, 1, linesize, fp) != linesize)
return (SunRasError ("file read error"));
}
switch (d) {
case 1: SunRas1to8 (image + w * i, line, w); break;
case 8: memcpy (image + w * i, line, w); break;
case 24: memcpy (image + w * i * 3, line, w * 3); break;
case 32: {
int k;
byte *ip, *op;
ip = line;
op = (byte *) (image + w * i * 3);
for (k = 0; k<w; k++) {
*ip++; /* skip 'alpha' */
*op++ = *ip++; /* red */
*op++ = *ip++; /* green */
*op++ = *ip++; /* blue */
}
}
}
}
if (fp != stdin) fclose (fp);
if (DEBUG) fprintf(stderr,"Sun ras: image loaded!\n");
if (d == 24 || d == 32) {
if (sunheader.ras_type != RT_FORMAT_RGB) fixBGR(image,w,h);
rv = Conv24to8 (image, w, h, nc);
free (image);
return (rv);
}
else {
pic = image;
pWIDE = w;
pHIGH = h;
return (0);
}
}
/*****************************/
static int rle_read (ptr, size, nitems, fp, init)
byte *ptr;
int size, nitems,init;
FILE *fp;
{
static int count, ch;
int readbytes, c, read;
if (init) { count = ch = 0; }
readbytes = size * nitems;
for (read = 0; read < readbytes; read++) {
if (count) {
*ptr++ = (byte) ch;
count--;
}
else {
c = getc(fp);
if (c == EOF) break;
if (c == RAS_RLE) { /* 0x80 */
count = getc(fp);
if (count == EOF) break;
if (count < 0) count &= 0xff;
if (count == 0) *ptr++ = c;
else {
if ((ch = getc(fp)) == EOF) break;
*ptr++ = ch;
}
}
else *ptr++ = c;
}
}
return (read/size);
}
/*****************************/
static int SunRasError(st)
char *st;
{
SetISTR(ISTR_WARNING,"LoadSunRas() - %s",st);
Warning();
return -1;
}
/*****************************/
static void flipl(p)
byte *p;
{
byte t;
t = p[0]; p[0]=p[3]; p[3] = t;
t = p[1]; p[1]=p[2]; p[2] = t;
}
static void SunRas1to8 (dest, src, len)
byte *dest, *src;
int len;
{
int i, b;
int c;
for (i = 0, b = -1; i < len; i++) {
if (b < 0) {
b = 7;
c = ~*src++;
}
*dest++ = ((c >> (b--)) & 1);
}
}
static void SunRas8to1 (dest, src, len)
byte *dest, *src;
int len;
{
int i, b;
int c;
for (c = b = i = 0; i < len; i++) {
c <<= 1;
c |= (*src++ ? 0 : 1);
if (b++ == 7) {
*dest++ = c;
b = c = 0;
}
}
if (b) *dest = c;
}
/*******************************************/
int WriteSunRas(fp,pic,w,h,rmap,gmap,bmap,numcols,colorstyle,userle)
FILE *fp;
byte *pic;
int w,h;
byte *rmap, *gmap, *bmap;
int numcols, colorstyle, userle;
{
/* writes a sun rasterfile to the already open stream
writes either 8-bit or 1-bit (never 24)
currently will not write rle files
biggest problem w/ rle file: should we compute
image size first (nicer) or go back and write it
in when we are done (kludgy)?
*/
struct rasterfile sunheader;
int linesize, i, color, d, y;
byte *line;
if (colorstyle != 2 && numcols > 2) d = 8;
else d = 1;
linesize = w;
if (d == 1) {
if (linesize % 8) linesize += (8 - linesize % 8);
linesize /= 8;
}
if (linesize % 2) linesize++;
line = (byte *) malloc (linesize);
if (!line) {
SetISTR(ISTR_WARNING, "Can't allocate memory for save!\n");
return (1);
}
if (DEBUG)
fprintf (stderr,
"WriteSunRas: d %d, linesize %d numcols %d\n",
d, linesize, numcols);
/* set up the header */
sunheader.ras_magic = RAS_MAGIC;
sunheader.ras_width = w;
sunheader.ras_height = h;
sunheader.ras_depth = d;
sunheader.ras_length = linesize * h;
sunheader.ras_type = RT_STANDARD;
sunheader.ras_maptype = (d == 1) ? RMT_NONE : RMT_EQUAL_RGB;
sunheader.ras_maplength = (d == 1) ? 0 : 3 * numcols;
write_sun_long (sunheader.ras_magic , fp);
write_sun_long (sunheader.ras_width , fp);
write_sun_long (sunheader.ras_height , fp);
write_sun_long (sunheader.ras_depth , fp);
write_sun_long (sunheader.ras_length , fp);
write_sun_long (sunheader.ras_type , fp);
write_sun_long (sunheader.ras_maptype , fp);
write_sun_long (sunheader.ras_maplength, fp);
/* write the colormap */
if (d > 1)
if (colorstyle == 1) /* grayscale */
for (color = 0; color < 3; color++)
for (i = 0; i < numcols; i++)
putc (MONO(rmap[i],gmap[i],bmap[i]), fp);
else {
fwrite (rmap, sizeof (byte), numcols, fp);
fwrite (gmap, sizeof (byte), numcols, fp);
fwrite (bmap, sizeof (byte), numcols, fp);
}
/* write the image */
line[linesize-1] = 0;
for (y = 0; y < h; y++) {
if ((y&0x1f) == 0) WaitCursor();
if (d > 1)
memcpy (line, pic + y * w, w);
else
SunRas8to1 (line, pic + y * w, w);
if (fwrite (line, sizeof (byte), linesize, fp) != linesize) {
SetISTR(ISTR_WARNING, "Write failed during save!\n");
free (line);
return (2);
}
}
free (line);
return (0);
}
/* write a long word in sun byte-order
returns 0 for success, EOF for failure
*/
static int write_sun_long (l, fp)
long l;
FILE *fp;
{
char c;
c = ((l >> 24) & 0xff);
if (putc (c, fp) == EOF) return (EOF);
c = ((l >> 16) & 0xff);
if (putc (c, fp) == EOF) return (EOF);
c = ((l >> 8) & 0xff);
if (putc (c, fp) == EOF) return (EOF);
c = (l & 0xff);
if (putc (c, fp) == EOF) return (EOF);
return (0);
}
/* kr3 - fix up BGR order SUN 24-bit rasters to be RGB order */
static void fixBGR(img,w,h)
unsigned char *img;
int w,h;
{
int i,npixels;
unsigned char tmp;
npixels = w*h;
for (i=0; i<npixels; i++) {
tmp = img[0]; /* swap red and blue channels */
img[0] = img[2];
img[2] = tmp;
img += 3; /* bump to next pixel */
}
}