home *** CD-ROM | disk | FTP | other *** search
- /*
- * 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 "xvimage.h"
- #include "xvsunras.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);
- }
-
- sprintf(formatStr, "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);
-
- /* 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 (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;
- {
- printf("LoadSunRas() - %s\n",st);
- 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) {
- printf("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 (d > 1)
- memcpy (line, pic + y * w, w);
- else
- SunRas8to1 (line, pic + y * w, w);
-
- if (fwrite (line, sizeof (byte), linesize, fp) != linesize) {
- printf("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 */
- }
- }
-
-