home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include <ctype.h>
- #include "readilbm.h"
-
- #define FALSE 0
- #define TRUE 1
-
- #define RED 0
- #define GRN 1
- #define BLU 2
-
- /* color to grey conversion methods */
-
- #define AVERAGE 0
- #define LUMIN 1
- #define DIST 2
- #define REDONLY 3
- #define GREENONLY 4
- #define BLUEONLY 5
-
- #define MakeID(a,b,c,d) ( ((a)<<24) | ((b)<<16) | ((c)<<8) | (d) )
-
- #define ID_FORM MakeID('F','O','R','M')
- #define ID_ILBM MakeID('I','L','B','M')
- #define ID_BMHD MakeID('B','M','H','D')
- #define ID_CMAP MakeID('C','M','A','P')
- #define ID_CAMG MakeID('C','A','M','G')
- #define ID_BODY MakeID('B','O','D','Y')
-
- #define ROUNDUP(x) ( ((x)+1) & (~1L) )
-
-
-
- static struct CHUNK {
- unsigned long Id, Size;
- } Chunk;
-
- static unsigned char cmap[32][3];
-
- struct BMHD {
- short w,h,x,y;
- char npl,mask,compress,pad1;
- short transparentColor;
- char xAspect,yAspect;
- short pageWidth,pageHeight;
- };
-
-
- static short Color[32], /* output colors */
- Method = AVERAGE; /* color conversion */
- static short numcolors;
-
- static
- FILE *fin; /* input file */
-
- extern char *malloc();
-
- static void FRead();
- static void ReadBMHD();
- static void ReadChunk();
- static void RastOut();
- static void HamOut();
- static char GetIlbmVal();
- static void InitColorMappings();
- static short Convert();
- static void ReadDecomLine();
- static void ProcessRows();
-
- #define ABORT(str) { OutErr(str); goto ErrorExit; }
-
-
- void SetGreyModel( model )
- int model;
- {
- Method = model;
- }
-
- /*
- * main routine for reading in an iff file
- */
-
- void ReadIlbm(filename)
- char *filename;
- {
- struct BMHD bmhd;
- long ILBMid;
- unsigned char cmapFlag = FALSE,
- bmhdFlag = FALSE;
-
-
- if ((fin = fopen (filename, "r")) == NULL) {
- OutErr ("ERROR: cannot open input file");
- return;
- }
- /* read in iff file */
-
- ReadChunk ();
- if (Chunk.Id != ID_FORM)
- ABORT ("Not an IFF File");
-
- FRead (&ILBMid, 4);
- if (ILBMid != ID_ILBM)
- ABORT ("Not an ILBM File");
-
- while (1) {
- long camgdata;
-
- ReadChunk ();
-
- if (Chunk.Id == ID_BODY)
- break;
-
- if( feof( fin ) ) {
- ABORT("reached end of file without seeing body\n");
- }
-
- switch (Chunk.Id) {
- case ID_CMAP:
- FRead (cmap, Chunk.Size);
- numcolors = Chunk.Size/3;
- cmapFlag = TRUE;
- break;
- case ID_BMHD:
- ReadBMHD (&bmhd);
- bmhdFlag = TRUE;
- break;
- case ID_CAMG:
- FRead( &camgdata, sizeof(camgdata) );
- break;
- default: /* unknown identifier */
- fseek( fin, Chunk.Size, 1);
- break;
- }
- }
- if (!cmapFlag) {
- ABORT("IFF file does not contain a CMAP chunk before the BODY\n");
- }
-
- if (!bmhdFlag) {
- ABORT("IFF file does not contain a BMHD chunk before the BODY\n");
- }
-
- InitColorMappings();
- if( OpenImgPix( bmhd.w, bmhd.h, Convert(0xf, 0xf, 0xf)) ) {
- ProcessRows(&bmhd);
- }
-
- ErrorExit:
- fclose( fin);
- }
-
- static void ProcessRows(bmhd)
- struct BMHD *bmhd;
- {
- char *rastlist[6];
- char *Raster;
- int depth, i, v, pixwidth;
- int BytePerLine;
-
- depth = bmhd->npl;
- pixwidth = bmhd->w;
- BytePerLine =(pixwidth+7) / 8;
-
-
- Raster = (char *) malloc (BytePerLine * depth);
-
- if(!Raster ) {
- OutErr("ProcessRows:could not allocate Raster");
- return;
- }
-
- for( i = 0; i < depth; i++ ) {
- rastlist[i] = Raster + BytePerLine*i;
- }
-
- for( v = 0; v < bmhd->h; v++) {
- switch (bmhd->compress) {
- case 0:
- FRead (Raster, BytePerLine * depth);
- break;
- case 1:
- for( i = 0; i < depth; i++) {
- ReadDecomLine( BytePerLine, rastlist[i]);
- }
- break;
- default:
- ABORT ("Unknown Compression type in BODY");
-
- }
- if(depth == 6 ) {
- HamOut( rastlist, pixwidth, v);
- }
- else {
- RastOut( rastlist, pixwidth, v, depth);
- }
- }
-
- ErrorExit:
- if( Raster ) free(Raster);
- }
-
-
- static void ReadDecomLine(linebytes, rp)
- int linebytes;
- char *rp;
- {
- int runlen;
- char pixel;
-
- while (linebytes) {
- runlen = getc (fin);
- if (runlen > 127)
- runlen -= 256;
- if (runlen >= 0) {
- runlen++;
- FRead (rp, runlen);
- rp += runlen;
- linebytes -= runlen;
- }
- else {
- runlen = -runlen + 1;
- linebytes -= runlen;
- pixel = getc (fin);
- do
- *(rp++) = pixel;
- while (--runlen);
- }
- }
- }
-
- /*
- * Convert - convert (r,g,b) to hex greyscale.
- */
-
- static short Convert(r,g,b)
- unsigned char r,g,b;
- {
- short i,
- rd, gd, bd,
- min,
- dist,
- best;
-
- /* convert color according to 'Method' */
- switch (Method) {
- case AVERAGE: /* average r,g,b to obtain grey level */
- return ((r + g + b) / 3);
- case LUMIN: /* use NTSC luminescence as grey level */
- return ((r * 30 + g * 59 + b * 11) / 100);
- case DIST: /* use grey with minimum distance in color */
- min = 15*15 * 3;
- for( i = 0; i < numcolors; i++ ) {
- rd = r -i;
- gd = g - i;
- bd = b - i;
- dist = rd * rd + gd * gd + bd * bd;
- if( dist < min ) {
- min = dist; best = i;
- }
- }
- return( best );
- case REDONLY:
- return(r);
- case GREENONLY:
- return(g);
- case BLUEONLY:
- return(b);
-
- }
- } /* Convert */
-
- static void InitColorMappings()
- {
- int i;
-
- /* put colors in 4-bit range and Convert */
- for (i = 0; i < 32; i++) {
- cmap[i][RED] >>= 4;
- cmap[i][GRN] >>= 4;
- cmap[i][BLU] >>= 4;
- Color[i] = Convert (cmap[i][RED], cmap[i][GRN], cmap[i][BLU]);
- }
- }
-
-
- /*
- * leftmost pixel of byte is in most significant bit of byte
- */
- static char GetIlbmVal( rastlist, h, bpp )
- char *rastlist[6];
- int h, bpp;
- {
- int i;
- char value = 0;
- short mask, bytep;
-
- mask = 0x80 >> ( h & 7);
- bytep = h >> 3;
-
- for( i = bpp-1; i >= 0; i-- ) {
- value <<= 1;
- value |= (*(rastlist[i]+bytep) & mask) ? 1: 0;
- }
- return( value );
- }
-
- /*
- * HamOut - output ham image in hex.
- */
- static void HamOut(rastlist, pixwidth, v)
- char *rastlist[6];
- int pixwidth, v;
- {
- unsigned char lastred = 0,
- lastgreen = 0,
- lastblue = 0;
- int h;
- char pixval;
- for( h = 0; h <pixwidth; h++ ) {
- short shade;
-
- shade = GetIlbmVal(rastlist, h, 6);
- pixval = shade & 0x0F;
- switch (shade & 0x30) {
- case 0x00:
- lastred = cmap[pixval][RED];
- lastgreen = cmap[pixval][GRN];
- lastblue = cmap[pixval][BLU];
- shade = Color[pixval];
- break;
- case 0x10:
- lastblue = pixval;
- shade = Convert(lastred,lastgreen,lastblue);
- break;
- case 0x20:
- lastred = pixval;
- shade = Convert(lastred,lastgreen,lastblue);
- break;
- case 0x30:
- lastgreen = pixval;
- shade = Convert(lastred,lastgreen,lastblue);
- }
- SetImgPix(h, v, shade);
- }
- }
-
- /*
- * RastOut - handle normal bit mapped images
- */
- static void RastOut(rastlist, pixwidth, v, depth)
- char *rastlist[6];
- int pixwidth, v, depth;
- {
- int h, bit;
- for( h = 0; h < pixwidth; h++ ) {
- short shade;
- shade = Color[GetIlbmVal( rastlist, h, depth)];
- SetImgPix( h, v, shade);
- }
- }
-
- /*
- * ReadChunk - read in an IFF Chunk.
- */
-
- static void ReadChunk()
- {
- FRead (&Chunk, sizeof (Chunk));
-
- } /* ReadChunk */
-
- /*
- * ReadBMHD - read the BMHD structure.
- */
-
- static void ReadBMHD(bmhd)
- struct BMHD *bmhd;
- {
- FRead (bmhd, Chunk.Size);
- } /* ReadBMHD */
-
-
- /*
- * FRead - read 'len' bytes to 'pointer' while checking for an error.
- */
-
- static void FRead(pointer,len)
- char *pointer;
- int len;
- {
- if (fread (pointer, len, 1, fin) == 0) {
- char outbuff[90];
- sprintf(outbuff,"Fread Error in reading input file at %d ", ftell(fin));
- OutErr(outbuff);
- }
- } /* FRead */
-