This is xvsunras.c in view mode; [Download] [Up]
/*
* 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"
/* info on sun rasterfiles taken from rasterfile(5) man page */
#define RAS_MAGIC 0x59a66a95
struct rasterfile {
int ras_magic;
int ras_width;
int ras_height;
int ras_depth;
int ras_length;
int ras_type;
int ras_maptype;
int ras_maplength;
};
#define RT_OLD 0 /* Raw pixrect image in 68000 byte order */
#define RT_STANDARD 1 /* Raw pixrect image in 68000 byte order */
#define RT_BYTE_ENCODED 2 /* Run-length compression of bytes */
#define RT_FORMAT_RGB 3 /* XRGB or RGB instead of XBGR or BGR */
#define RMT_RAW 2
#define RMT_NONE 0
#define RMT_EQUAL_RGB 1
#define RAS_RLE 0x80
#ifdef __STDC__
static int sunRasError(char *, char *);
static int rle_read(byte *, int, int, FILE *, int);
static void SunRas1to8(byte *, byte *, int);
static void SunRas8to1(byte *, byte *, int, int);
static int read_sun_long(long *, FILE *);
static int write_sun_long(long, FILE *);
static void fixBGR(unsigned char *, int, int);
#else
static int sunRasError();
static int rle_read();
static void SunRas1to8();
static void SunRas8to1();
static int read_sun_long(), write_sun_long();
static void fixBGR();
#endif
/*******************************************/
int LoadSunRas(fname, pinfo)
char *fname;
PICINFO *pinfo;
{
FILE *fp;
int linesize,lsize,csize,isize,i,w,h,d;
byte *image, *line, *pic8;
struct rasterfile sunheader;
char *bname;
bname = BaseName(fname);
/* read in the Sun Rasterfile picture */
fp=fopen(fname,"r");
if (!fp) return( sunRasError(bname, "unable to open file") );
read_sun_long (&sunheader.ras_magic , fp);
read_sun_long (&sunheader.ras_width , fp);
read_sun_long (&sunheader.ras_height , fp);
read_sun_long (&sunheader.ras_depth , fp);
read_sun_long (&sunheader.ras_length , fp);
read_sun_long (&sunheader.ras_type , fp);
read_sun_long (&sunheader.ras_maptype , fp);
read_sun_long (&sunheader.ras_maplength, fp);
if (sunheader.ras_magic != RAS_MAGIC) {
fclose(fp);
return( sunRasError(bname, "not a Sun rasterfile") );
}
/* 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");
fclose(fp);
return 0;
}
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);
fclose(fp);
return 0;
}
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);
fclose(fp);
return 0;
}
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 % 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);
}
/* read in the colormap, if any */
if (sunheader.ras_maptype == RMT_EQUAL_RGB && csize) {
fread (pinfo->r, 1, sunheader.ras_maplength/3, fp);
fread (pinfo->g, 1, sunheader.ras_maplength/3, fp);
fread (pinfo->b, 1, sunheader.ras_maplength/3, 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) {
pinfo->r[0] = pinfo->g[0] = pinfo->b[0] = 0;
pinfo->r[1] = pinfo->g[1] = pinfo->b[1] = 255;
}
else if (sunheader.ras_depth == 8) {
for (i = 0; i < 256; i++)
pinfo->r[i] = pinfo->g[i] = pinfo->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;
}
else {
if (fread (line, 1, linesize, fp) != linesize) {
free(image); free(line); fclose(fp);
return (sunRasError (bname, "file read error"));
}
}
switch (d) {
case 1: SunRas1to8 (image + w * i, line, w); break;
case 8: xvbcopy(line, image + w * i, w); break;
case 24: xvbcopy(line, image + w * i * 3, 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 */
}
}
}
}
free(line);
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);
pinfo->type = PIC24;
}
else pinfo->type = PIC8;
pinfo->pic = image;
pinfo->w = w;
pinfo->h = h;
pinfo->frmType = F_SUNRAS;
pinfo->colType = (d==1) ? F_BWDITHER : F_FULLCOLOR;
sprintf(pinfo->fullInfo, "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(pinfo->shrtInfo, "%dx%d Sun Rasterfile.",w,h);
pinfo->comment = (char *) NULL;
fclose(fp);
return 1;
}
/*****************************/
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(fname, st)
char *fname, *st;
{
SetISTR(ISTR_WARNING,"%s: %s", fname, st);
return 0;
}
/************************************************/
static void SunRas1to8 (dest, src, len)
byte *dest, *src;
int len;
{
int i, b;
int c = 0;
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, flip)
byte *dest, *src;
int len, flip;
{
int i, b;
int c;
for (c = b = i = 0; i < len; i++) {
c <<= 1;
c |= (*src++ ? 1 : 0);
if (b++ == 7) {
if (flip) c = ~c;
*dest++ = (byte) (c & 0xff);
b = c = 0;
}
}
if (b) {
if (flip) c = ~c;
*dest = (byte) ((c<<(8-b)) & 0xff);
}
}
/*******************************************/
int WriteSunRas(fp,pic,ptype,w,h,rmap,gmap,bmap,numcols,colorstyle,userle)
FILE *fp;
byte *pic;
int ptype,w,h;
byte *rmap, *gmap, *bmap;
int numcols, colorstyle, userle;
{
/* writes a sun rasterfile to the already open stream
writes either 24-bit, 8-bit or 1-bit
currently will not write rle files
if PIC24 and F_GREYSCALE, writes an 8-bit grayscale image
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, flipbw;
byte *line, *graypic, graymap[256], *sp, *dp;
graypic = NULL;
/* special case: if PIC24 and writing GREYSCALE, write 8-bit file */
if (ptype == PIC24 && colorstyle == F_GREYSCALE) {
graypic = (byte *) malloc(w*h);
if (!graypic) FatalError("unable to malloc in WriteSunRas()");
for (i=0,sp=pic,dp=graypic; i<w*h; i++,sp+=3,dp++) {
*dp = MONO(sp[0],sp[1],sp[2]);
}
for (i=0; i<256; i++) graymap[i] = i;
rmap = gmap = bmap = graymap;
numcols = 256;
ptype = PIC8;
pic = graypic;
}
if (ptype==PIC24) { d = 24; linesize = w * 3; }
else if (colorstyle != F_BWDITHER) { d = 8; linesize = w; }
else {
d = 1;
linesize = w;
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");
if (graypic) free(graypic);
return (1);
}
if (DEBUG)
fprintf (stderr,
"WriteSunRas: d %d, linesize %d numcols %d\n",
d, linesize, numcols);
if (d==1) {
/* set flipbw if color#0 is black */
flipbw = (MONO(rmap[0],gmap[0],bmap[0]) < MONO(rmap[1],gmap[1],bmap[1]));
}
/* 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 || d==24) ? RMT_NONE : RMT_EQUAL_RGB;
sunheader.ras_maplength = (d==1 || d==24) ? 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 == 8)
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 == 24) {
byte *lptr, *pix;
for (i=0,lptr=line,pix=pic+y*w*3; i<w; i++,pix+=3) {
*lptr++ = pix[2]; /* write date out in BGR order */
*lptr++ = pix[1];
*lptr++ = pix[0];
}
}
else if (d == 8)
xvbcopy(pic + y * w, line, w);
else /* d == 1 */
SunRas8to1 (line, pic + y * w, w, flipbw);
if (fwrite (line, sizeof (byte), linesize, fp) != linesize) {
SetISTR(ISTR_WARNING, "Write failed during save!\n");
if (graypic) free(graypic);
free(line);
return (2);
}
}
free (line);
if (graypic) free(graypic);
return (0);
}
/* reads a 4-byte int in Sun byteorder
returns 0 for success, EOF for failure */
static int read_sun_long (l, fp)
long *l;
FILE *fp;
{
int c0, c1, c2, c3;
c0 = fgetc(fp);
c1 = fgetc(fp);
c2 = fgetc(fp);
c3 = fgetc(fp);
*l = (((u_long) c0 & 0xff) << 24) |
(((u_long) c1 & 0xff) << 16) |
(((u_long) c2 & 0xff) << 8) |
(((u_long) c3 & 0xff));
if (ferror(fp)) return EOF;
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 */
}
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.