home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
unix
/
volume19
/
fbm
/
part05
/
flsun.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-06-08
|
9KB
|
340 lines
/*****************************************************************
* flsun.c: FBM Library 0.94 (Beta test) 20-May-89 Michael Mauldin
*
* Copyright (C) 1989 by Michael Mauldin. Permission is granted to
* use this file in whole or in part provided that you do not sell it
* for profit and that this copyright notice is retained unchanged.
*
* flsun.c:
*
* CONTENTS
* read_sun (image, rfile, mstr, mlen)
* write_sun (image, wfile)
*
* EDITLOG
* LastEditDate = Sat May 20 19:08:32 1989 - Michael Mauldin
* LastFileName = /usr2/mlm/src/misc/fbm/flsun.c
*
* HISTORY
* 20-May-89 Michael Mauldin (mlm) at Carnegie Mellon University
* Fixed problem with odd length rows on reading
*
* 07-Mar-89 Michael Mauldin (mlm) at Carnegie Mellon University
* Beta release (version 0.9) mlm@cs.cmu.edu
*
* 12-Nov-88 Michael Mauldin (mlm) at Carnegie-Mellon University
* Created.
*****************************************************************/
# include <stdio.h>
# include <math.h>
# include <ctype.h>
# include "fbm.h"
typedef struct rasterfile {
long ras_magic;
long ras_width;
long ras_height;
long ras_depth;
long ras_length;
long ras_type;
long ras_maptype;
long ras_maplength;
} RASHDR;
# define RT_STANDARD 1
# define RMT_NONE 0
# define RMT_EQUAL_RGB 1
# define RMT_RAW 2
# define RED 0
# define GRN 1
# define BLU 2
/****************************************************************
* write_sun (image, wfile)
****************************************************************/
#ifndef lint
static char *fbmid =
"$FBM flsun.c <0.9> 07-Mar-89 (C) 1989 by Michael Mauldin$";
#endif
write_sun (image, wfile)
FBM *image;
FILE *wfile;
{ RASHDR rhdr;
register int i, j, byte;
register unsigned char *bmp, *rp, *gp, *bp;
int width, height, plnlen, clrlen, rowlen, depth, bits;
if (image->hdr.planes != 1 && image->hdr.planes != 3)
{ fprintf (stderr,
"Error, write_sun can only handle images with depth 1 or 3\n");
return (0);
}
if (image->hdr.physbits != 8)
{ fprintf (stderr,
"Error, write_sun can only handle 8 physical bits per pixel\n");
return (0);
}
if (image->hdr.physbits == 1 && (image->hdr.rowlen % 16) != 0)
{ fprintf (stderr,
"Error, 1 bit deep files must have rowlen (%d) divisible by 16");
return (0);
}
if (image->hdr.physbits == 8 && image->hdr.bits == 1)
bits = 1;
else
bits = image->hdr.physbits > 1 ? 8 : 1;
# ifdef DEBUG
fprintf (stderr, "write_sun: [%dx%d] rowlen %d, planes %d, bits %d, physbits %d, using %d\n",
image->hdr.cols,
image->hdr.rows,
image->hdr.rowlen,
image->hdr.planes,
image->hdr.bits,
image->hdr.physbits,
bits);
# endif
width = image->hdr.cols;
height = image->hdr.rows;
rowlen = image->hdr.rowlen;
plnlen = image->hdr.plnlen;
clrlen = image->hdr.clrlen;
depth = bits * image->hdr.planes;
/* Initialize Sun raster header */
rhdr.ras_magic = SUN_MAGIC;
rhdr.ras_width = width;
rhdr.ras_height = height;
rhdr.ras_depth = depth;
rhdr.ras_length = plnlen * bits / 8;
rhdr.ras_type = RT_STANDARD;
rhdr.ras_maptype = depth > 8 ? RMT_RAW : clrlen ? RMT_EQUAL_RGB : RMT_NONE;
rhdr.ras_maplength = clrlen;
/* Write rasterfile header - note: use Sun byte order */
put_long (rhdr.ras_magic, wfile, BIG);
put_long (rhdr.ras_width, wfile, BIG);
put_long (rhdr.ras_height, wfile, BIG);
put_long (rhdr.ras_depth, wfile, BIG);
put_long (rhdr.ras_length, wfile, BIG);
put_long (rhdr.ras_type, wfile, BIG);
put_long (rhdr.ras_maptype, wfile, BIG);
put_long (rhdr.ras_maplength, wfile, BIG);
/* Dump colormap if need be */
if (clrlen > 0)
{ fwrite (image->cm, 1, clrlen, wfile); }
/* Write bytes */
switch (depth)
{ case 24: rp = &image->bm[0];
gp = rp + plnlen;
bp = gp + plnlen;
for (i=0; i<plnlen; i++)
{ fputc (*rp++, wfile);
fputc (*gp++, wfile);
fputc (*bp++, wfile);
}
break;
case 8: fwrite (image->bm, 1, plnlen, wfile);
break;
case 1:
# ifdef DEBUG
fprintf (stderr, "Writing Sun 1bit file [%dx%d] rowlen %d\n",
width, height, rowlen);
# endif
for (j=0; j<height; j++)
{ bmp = &(image->bm[j*rowlen]);
byte = 0;
for (i=0; i<rowlen; i++)
{ byte = (byte << 1) | (*bmp++ ? 0 : 1);
if ((i & 7) == 7)
{ fputc (byte, wfile); byte = 0; }
}
}
break;
default: fprintf (stderr,
"Error, write_sun given invalid depth %d bits\n",
depth);
return (0);
}
return (1);
}
/****************************************************************
* read_sun (image, rfile)
****************************************************************/
read_sun (image, rfile, mstr, mlen)
FBM *image;
FILE *rfile;
char *mstr;
int mlen;
{ RASHDR rhdr;
int width, height, plnlen, rowlen, clrlen, res, depth;
register int i, j, byte;
register unsigned char *bmp, *rp, *gp, *bp;
int m1, m2, m3, m4;
m1 = NEXTMCH(rfile,mstr,mlen) & 0xff;
m2 = NEXTMCH(rfile,mstr,mlen) & 0xff;
m3 = NEXTMCH(rfile,mstr,mlen) & 0xff;
m4 = NEXTMCH(rfile,mstr,mlen) & 0xff;
rhdr.ras_magic = (m1 << 24) | (m2 << 16) | (m3 << 8)| (m4);
/* Write rasterfile header - note: use Sun byte order */
if (rhdr.ras_magic != SUN_MAGIC)
{ fprintf (stderr, "Error, not a Sun raster file (bad magic %08x)\n",
rhdr.ras_magic);
return (0);
}
rhdr.ras_width = get_long (rfile, BIG);
rhdr.ras_height = get_long (rfile, BIG);
rhdr.ras_depth = get_long (rfile, BIG);
rhdr.ras_length = get_long (rfile, BIG);
rhdr.ras_type = get_long (rfile, BIG);
rhdr.ras_maptype = get_long (rfile, BIG);
rhdr.ras_maplength = get_long (rfile, BIG);
/* Check for nonstandard rasterfile formats */
if (rhdr.ras_type != RT_STANDARD)
{ fprintf (stderr, "Error: rasterfile is not a Sun RT_STANDARD file\n");
return (0);
}
if (rhdr.ras_maplength > 0 && rhdr.ras_maptype != RMT_EQUAL_RGB)
{ fprintf (stderr, "Error: color rasterfile is not RMT_EQUAL_RGB\n");
return (0);
}
if (rhdr.ras_maplength == 0 &&
rhdr.ras_maptype != RMT_NONE &&
rhdr.ras_maptype != RMT_RAW)
{ fprintf (stderr, "Error: black and white rasterfile is not RMT_NONE\n");
return (0);
}
if (rhdr.ras_depth != 24 && rhdr.ras_depth != 8 && rhdr.ras_depth != 1)
{ fprintf (stderr, "Error, bits per pixel (%d) must be 1, 8 or 24\n",
rhdr.ras_depth);
return (0);
}
/* Initialize and allocate input image */
width = rhdr.ras_width;
height = rhdr.ras_height;
depth = rhdr.ras_depth;
clrlen = rhdr.ras_maplength;
if (depth == 1)
{ rowlen = 16 * ((width + 15) / 16);
plnlen = rowlen * height;
}
else
{ rowlen = width;
if (rowlen & 1) rowlen++;
plnlen = width * height;
}
/* Check for consitency between colormap and depth */
if (depth > 8 && clrlen > 0)
{ fprintf (stderr,
"Error, input has colormap of length %d, but %d bits per pixel\n",
clrlen, depth);
return (0);
}
/* Initialize image header */
image->hdr.cols = width;
image->hdr.rows = height;
image->hdr.planes = (depth == 24) ? 3 : 1;
image->hdr.bits = (depth == 24) ? 8 : depth;
image->hdr.physbits = 8;
image->hdr.rowlen = rowlen;
image->hdr.plnlen = plnlen;
image->hdr.clrlen = clrlen;
image->hdr.aspect = 1.0;
image->hdr.title[0] = '\0';
image->hdr.credits[0] = '\0';
/* Allocate space */
alloc_fbm (image);
/* Read colormap if need be */
if (clrlen > 0 && (res = fread (image->cm, 1, clrlen, rfile)) != clrlen)
{ fprintf (stderr, "Error: couldn't read colormap, read %d of %d bytes\n",
res, clrlen);
return (0);
}
/* Read bytes */
switch (depth)
{ case 24: rp = &image->bm[0];
gp = rp + plnlen;
bp = gp + plnlen;
for (i=0; i<plnlen && !feof (rfile); i++)
{ *rp++ = fgetc (rfile);
*gp++ = fgetc (rfile);
*bp++ = fgetc (rfile);
}
if (i<plnlen)
{ fprintf (stderr, "Error: %s %d of %d pixels (%d bytes)\n",
"EOF on bitmap after",
i, plnlen, plnlen * image->hdr.planes);
return (0);
}
break;
case 8: if ((res = fread (image->bm, 1, plnlen, rfile)) != plnlen)
{ fprintf (stderr,
"Error: EOF on bitmap after %d of %d bytes\n",
res, plnlen);
return (0);
}
break;
case 1: for (j=0; j<height; j++)
{ bmp = &(image->bm[j * rowlen]);
for (i=0; i<rowlen; i++)
{ if ((i&7) == 0)
{ if ((byte = fgetc (rfile)) == EOF)
{ fprintf (stderr,
"Error: EOF on bitmap after %d of %d bytes\n",
j*rowlen + i, height*rowlen);
return (0);
}
}
*bmp++ = (byte & 0x80) ? BLACK : WHITE;
byte <<= 1;
}
}
break;
default: fprintf (stderr, "Invalid depth %d bits\n", depth);
return (0);
}
return (1);
}