home *** CD-ROM | disk | FTP | other *** search
- /*
- * FILE: picture.c
- * Support routines for reading IFF/ILBM files.
- *
- * Public Domain, but keep our names in it as the original authors.
- * 08-Dec-87 Rico Mariani original code (modified by JST)
- * 31-Aug-88 Jan Sven Trabandt first release version
- */
-
-
- #define I_AM_PICTURE
- #include "gimmelib/gimmefuncs.h"
- #include "gimmelib/picture.h"
- #include "gimmelib/postext.h"
- #include "gimmelib/minterm.h"
- #include <stdio.h>
-
-
- #define GET(iffile) getc( iffile )
-
- #define getId getLong
- #define getLen getLong
- #define getByte GET
- #define skip(len, file) fseek(file, (long)(len), 1)
-
- #define getBMH(bmh, file) fread(bmh, sizeof(BitMapHeader), 1, file)
-
- /* requires an existent variable 'char *errmsg' and a label 'failure_return' */
- #define fail_and_return(msg) {errmsg = msg; goto failure_return;}
-
- /* forward declarations */
- static LONG getLong();
- static WORD getWord();
- static ULONG makeBM();
-
- static char noMemMsg[] = "insufficient memory\n";
- static char badFileMsg[] = "corrupt or incomplete file\n";
-
-
- PICTURE *gimmePicture( filename, myflags )
- UBYTE *filename;
- ULONG myflags;
- {
- LONG len, id;
- PICTURE *pic = NULL;
- BYTE *p;
- void *mh = NULL;
- FILE *file = NULL;
- char *errmsg = " ";
- SHORT i;
-
- if( !(file = fopen(filename, "r")) ) {
- fail_and_return( "unable to open iff picture file for read\n" );
- }
- if( getId(file) != ID_FORM ) {
- fail_and_return( "not IFF format\n" );
- }
- getLen( file );
- if( getId(file) != ID_ILBM ) {
- fail_and_return( "not ILBM format\n" );
- }
- for( ;; ) {
- getChunk( &id, &len, file );
- if( ferror(file) || feof(file) ) {
- fail_and_return( badFileMsg );
- }
- switch( id ) {
- case ID_BMHD:
- pic = chainAllocMem( &mh, (ULONG)sizeof(PICTURE),
- MEMF_PUBLIC | MEMF_CLEAR );
- if( !pic ) {
- fail_and_return( noMemMsg );
- }
- getBMH( &pic->bmh, file );
- if( len & 1 ) {
- GET(file);
- }
- break;
- case ID_CMAP:
- if( getLut(pic, len, file) ) {
- fail_and_return( "unable to get color table\n" );
- }
- break;
- case ID_BODY:
- if( !pic ) {
- fail_and_return( "didn't find BMHD chunk\n" );
- return( NULL );
- }
- switch( pic->bmh.masking ) {
- case mskNone:
- case mskLasso:
- case mskHasTranCol:
- break;
- default:
- printf("Error, unsupported masking type\n");
- return( NULL );
- } /* switch */
-
- pic->xsize = pic->bmh.w;
- if( (pic->myflags = makeBM(pic, myflags)) == GBP_ERROR ) {
- return( NULL );
- }
- switch( pic->bmh.compression ) {
- case cmpNone:
- if( getBody(pic->bm, pic->myflags, file) ) {
- fail_and_return( "error in uncompressed body\n" );
- }
- break;
- case cmpByteRun1:
- if( getCmpBody(pic->bm, file) ) {
- fail_and_return( "error in compressed body\n" );
- }
- break;
- default:
- fail_and_return( "unknown compression form\n" );
- return( NULL );
- } /* switch */
- if( ferror(file) ) {
- fail_and_return( badFileMsg );
- }
- pic->memhead = mh;
- fclose( file );
- return( pic );
- break;
- case ID_DEST:
- case ID_SPRT:
- case ID_CAMG:
- case ID_CRNG:
- case ID_CCRT:
- default: /* unimplemented chunk type */
- skip( EVEN(len), file );
- break;
- } /* switch */
- } /* for */
- failure_return: {}
- if( Output() ) {
- Write( Output(), errmsg, (ULONG)strlen(errmsg) );
- }
- if( mh ) {
- chainFreeMem( mh );
- }
- if( file ) {
- fclose( file );
- }
- return( NULL );
- } /* gimmePicture */
-
-
- static ULONG makeBM( pic, myflags )
- register PICTURE *pic;
- ULONG myflags;
- {
- UBYTE *plane;
-
- if( !(pic->bm = AllocMem((ULONG)sizeof(struct BitMap), MEMF_PUBLIC)) ) {
- return( GBP_ERROR );
- }
- InitBitMap( pic->bm, (long) pic->bmh.nPlanes, (long) pic->bmh.w,
- (long) pic->bmh.h );
- return( gimmeBitPlanes(pic->bm, myflags) );
- } /* makeBM */
-
-
- short getRidOfPicture( picture )
- PICTURE *picture;
- {
- #ifdef GIMME_WIMPY
- if( picture ) {
- return( -1 );
- }
- #endif
- if( picture->colormap.ColorTable ) {
- FreeMem( picture->colormap.ColorTable,
- (ULONG) picture->colormap.Count * sizeof(USHORT) );
- }
- if( picture->bm ) {
- getRidOfBitPlanes( picture->bm, picture->myflags );
- FreeMem( picture->bm, (ULONG)sizeof(struct BitMap) );
- }
- chainFreeMem( picture->memhead );
- return( 0 );
- } /* getRidOfPicture */
-
-
- short positionPicture( rp, myflags, pic, minterm, x, y )
- struct RastPort *rp;
- ULONG myflags;
- PICTURE *pic;
- SHORT minterm;
- register SHORT x, y;
- {
- SHORT left, top;
- SHORT width, height;
- SHORT temp;
- struct BitMap *bm;
-
- #ifdef GIMME_WIMPY
- if( !pic || !rp ) {
- return( -1 );
- }
- #endif
- left = top = 0;
- width = pic->bmh.w;
- height = pic->bmh.h;
- bm = rp->BitMap;
- switch( myflags & GPT_XFLAGS ) {
- case GPT_XCENTRE:
- x -= width >> 1;
- break;
- case GPT_XRIGHT:
- x -= width;
- break;
- case GPT_XLEFT:
- default:
- break;
- } /* switch */
- switch( myflags & GPT_YFLAGS ) {
- case GPT_YBOTTOM:
- case GPT_YBASELINE:
- y -= height;
- break;
- case GPT_YCENTRE:
- case GPT_YCENTREBASE:
- y -= height >> 1;
- break;
- case GPT_YTOP:
- default:
- break;
- } /* switch */
- if( minterm != GIM_MINTERM_DEST ) {
- if( x < 0 ) {
- width += x;
- left -= x;
- x = 0;
- } else if( (temp = x + width - (bm->BytesPerRow << 3)) > 0 ) {
- width -= temp;
- }
- if( y < 0 ) {
- height += y;
- top -= y;
- y = 0;
- } else if( (temp = y + height - bm->Rows) > 0 ) {
- height -= temp;
- }
- if( width > 0 && height > 0 ) {
- BltBitMapRastPort( pic->bm, (long) left, (long) top, rp,
- (long) x, (long) y,
- (long) width, (long) height, (long) minterm );
- }
- }
- return( 0 );
- } /* positionPicture */
-
-
- short usePictureColors( pic, screen )
- register PICTURE *pic;
- struct Screen *screen;
- {
- #ifdef GIMME_WIMPY
- if( !pic || !screen ) {
- return( -1 );
- }
- #endif
- return( setColors(screen, pic->colormap.ColorTable,
- (SHORT) pic->colormap.Count) );
- } /* usePictureColors */
-
-
- /* read an IFF Id */
- static LONG getLong( file )
- FILE *file;
- {
- register UBYTE p[4];
-
- p[0] = GET(file);
- p[1] = GET(file);
- p[2] = GET(file);
- p[3] = GET(file);
- return( (LONG) Mk(p[0],p[1],p[2],p[3]) );
- } /* getLong */
-
-
- /* read an IFF chunk header */
- static getChunk( id, len, file )
- LONG *id, *len;
- FILE *file;
- {
- *id = getId( file );
- *len = getLen( file );
- } /* getChunk */
-
-
- /* get len bytes from the file and put them into memory */
- static memget( p, len, file )
- UBYTE *p;
- LONG len;
- FILE *file;
- {
- for( ; len > 0L; len -= 0x07fffL, p += 0x07fffL ) {
- fread( p, (int) (len & 0x07fffL), 1, file );
- } /* for */
- } /* memget */
-
-
- /* get a word */
- static WORD getWord( file )
- FILE *file;
- {
- WORD v;
-
- v = GET(file) << 8;
- return( v | GET(file) );
- } /* getWord */
-
-
- static int getCmpBody( bm, file )
- struct BitMap *bm;
- FILE *file;
- {
- register short x;
- short y, pl;
- UBYTE *plane;
- UBYTE run_len, verb_len, run_byte;
- BYTE v;
- register BYTE mybyte;
-
- verb_len = run_len = 0;
- /* note: the bit-planes should be clear already */
- for( y = 0; y < bm->Rows; ++y ) {
- for( pl = 0; pl < bm->Depth; ++pl ) {
- plane = bm->Planes[pl] + y * bm->BytesPerRow;
- for( x = 0; x < bm->BytesPerRow; ++x ) {
- if( run_len ) {
- --run_len;
- mybyte = run_byte;
- } else if( verb_len ) {
- --verb_len;
- mybyte = GET(file);
- } else if( (v = GET(file)) >= 0 ) {
- verb_len = v;
- mybyte = GET(file);
- } else {
- run_len = -v;
- mybyte = run_byte = GET(file);
- }
- plane[x] = mybyte;
- } /* for */
- } /* for */
- } /* for */
- return( 0 );
- } /* getCmpBody */
-
-
- static int getBody( bm, flags, file )
- register struct BitMap *bm;
- ULONG flags;
- FILE *file;
- {
- register short i;
-
- if( flags & GBP_CONTIGUOUS ) {
- memget( bm->Planes[0], (ULONG)(bm->Depth) * bm->Rows * bm->BytesPerRow,
- file );
- } else {
- for( i = 0; i < bm->Depth; ++i ) {
- memget( bm->Planes[i], (ULONG)(bm->Rows) * bm->BytesPerRow, file );
- } /* for */
- }
- return( 0 );
- } /* getBody */
-
-
- static int getLut( pic, len, file )
- PICTURE *pic;
- LONG len;
- FILE *file;
- {
- SHORT i, ncols;
- USHORT red, green, blue;
- USHORT *lut;
-
- pic->colormap.Flags = pic->colormap.Type = 0;
- ncols = len / 3;
- lut = (USHORT *) AllocMem( (ULONG) ncols * sizeof(USHORT), MEMF_PUBLIC );
- if( !lut ) {
- return( -1 );
- }
- for( i = 0; i < ncols; ++i ) {
- red = GET(file) >> 4;
- green = GET(file) >> 4;
- blue = GET(file) >> 4;
- lut[i] = (red << 8) | (green << 4) | blue;
- } /* for */
- if( len & 1 ) {
- GET(file);
- }
- pic->colormap.Count = ncols;
- pic->colormap.ColorTable = (APTR) lut;
- return( 0 );
- } /* getLut */
-