home *** CD-ROM | disk | FTP | other *** search
- /** myReadPict.c ************************************************************
- *
- * Read an ILBM raster image file. 23-Jan-86.
- *
- * Modified version of ReadPict.c
- * by Jerry Morrison, Steve Shaw, and Steve Hayes, Electronic Arts.
- * This software is in the public domain.
- *
- * Modified by C. Scheppner 11/86
- * Handles CAMG chunks for HAM, etc.
- * Calls user defined routine getBitMap(ilbmFramePtr) when it
- * reaches the BODY.
- * getBitMap() can open a screen of the correct size using
- * information this rtn places in the ilbmFrame, and returns
- * a pointer to a BitMap structure. The BitMap structure
- * tells myReadPicture where it should load the bit planes.
- *
- * Modified by C. Scheppner 12/86
- * Loads in CCRT or CRNG chunks (converts CCRT to CRNG)
- *
- *
- * Modified by Gregg Tavares 1/89
- * Does Things I want it to do.
- * 1) Loads Infinite CyclesRanges
- * 2) Options to load GRAB chuncks
- * 3) Options to load parts of a pic
- * 4) Options to alloc mem for pic or use caller supplied memory
- * 5) Will load into a bitmap or a rastport
- ****************************************************************************/
-
- #define LOCAL static
-
- #include <exec/memory.h>
- #include <intuition/intuition.h>
- #include <libraries/dos.h>
- #include <libraries/dosextens.h>
- #include <iff/ilbm.h>
- #include <iff/readpict.h> /* cs */
- #include "picture.h"
-
- /* Define size of a temporary buffer used in unscrambling the ILBM rows.*/
- #define bufSz 512
-
- /*------------ ILBM reader -----------------------------------------------*/
- /* ILBMFrame is our "client frame" for reading FORMs ILBM in an IFF file.
- * We allocate one of these on the stack for every LIST or FORM encountered
- * in the file and use it to hold BMHD & CMAP properties. We also allocate
- * an initial one for the whole file.
- * We allocate a new GroupContext (and initialize it by OpenRIFF or
- * OpenRGroup) for every group (FORM, CAT, LIST, or PROP) encountered. It's
- * just a context for reading (nested) chunks.
- *
- * If we were to scan the entire example file outlined below:
- * reading proc(s) new new
- *
- * --whole file-- myReadPicture+ReadIFF GroupContext ILBMFrame
- * CAT ReadICat GroupContext
- * LIST GetLiILBM+ReadIList GroupContext ILBMFrame
- * PROP ILBM GetPrILBM GroupContext
- * CMAP GetCMAP
- * BMHD GetBMHD
- * FORM ILBM GetFoILBM GroupContext ILBMFrame
- * BODY GetBODY
- * FORM ILBM GetFoILBM GroupContext ILBMFrame
- * BODY GetBODY
- * FORM ILBM GetFoILBM GroupContext ILBMFrame
- */
-
- /* NOTE: For a small version of this program, set Fancy to 0.
- * That'll compile a program that reads a single FORM ILBM in a file, which
- * is what DeluxePaint produces. It'll skip all LISTs and PROPs in the input
- * file. It will, however, look inside a CAT for a FORM ILBM.
- * That's suitable for 90% of the uses.
- *
- * For a fancier version that handles LISTs and PROPs, set Fancy to 1.
- * That'll compile a program that dives into a LIST, if present, to read
- * the first FORM ILBM. E.g. a DeluxePrint library of images is a LIST of
- * FORMs ILBM.
- *
- * For an even fancier version, set Fancy to 2. That'll compile a program
- * that dives into non-ILBM FORMs, if present, looking for a nested FORM ILBM.
- * E.g. a DeluxeVideo C.S. animated object file is a FORM ANBM containing a
- * FORM ILBM for each image frame. */
- #define Fancy 2
-
- /* Global access to client-provided pointers.*/
- LOCAL ILBMFrame *giFrame = NULL; /* "client frame".*/
-
-
- CycleRange **LastCycleRange (cr)
- CycleRange **cr;
- {
- while (*cr)
- cr = &(CycleRange *)(*cr)->NextRange;
-
- return cr;
- }
-
- IFFP handleCAMG(context,frame)
- GroupContext *context;
- ILBMFrame *frame;
- {
- IFFP iffp = IFF_OKAY;
- CamgChunk camgTemp;
-
- PicValidModes(frame->pic) = TRUE;
- iffp = GetCAMG(context, &camgTemp);
- PicViewModes(frame->pic) = camgTemp.ViewModes;
- return(iffp);
- }
-
- IFFP handleCRNG(context,frame)
- GroupContext *context;
- ILBMFrame *frame;
- {
- IFFP iffp = IFF_OKAY;
- CycleRange **cr;
- CrngChunk crngTemp;
-
- if (frame->ni->Flags & NI_GETCYCLES) {
- /* Point to last range */
- cr = LastCycleRange (&PicCycleRanges(frame->pic));
-
- /* Allocate New Range */
- if(!( *cr = (CycleRange *)(*frame->allocmem)(sizeof (CycleRange), MEMF_CLEAR))) {
- return (CLIENT_ERROR);
- }
-
- /* Get CRNG Chunk from File */
- iffp = GetCRNG(context,&crngTemp);
-
- /* Copy relevant information */
- (*cr)->rate = crngTemp.rate;
- (*cr)->active = crngTemp.active;
- (*cr)->low = crngTemp.low;
- (*cr)->high = crngTemp.high;
-
- } else {
-
- /* Get CRNG Chunk from File */
- iffp = GetCRNG(context,&crngTemp);
-
- }
- return(iffp);
- }
-
-
- IFFP handleCCRT(context,frame)
- GroupContext *context;
- ILBMFrame *frame;
- {
- CycleRange **cr;
- CcrtChunk ccrtTemp;
- IFFP iffp = IFF_OKAY;
-
- if (frame->ni->Flags & NI_GETCYCLES) {
- /* Point to last range */
- cr = LastCycleRange (frame->pic);
-
- /* Allocate New Range */
- if(!( *cr = (CycleRange *)(*frame->allocmem)(sizeof (CycleRange), MEMF_CLEAR))) {
- return (CLIENT_ERROR);
- }
-
- /* Get CCRT Chunk from file */
- iffp = GetCCRT(context, &ccrtTemp);
-
- /* Copy Relevant information */
- if(ccrtTemp.direction) {
- ccrtTemp.direction = -ccrtTemp.direction;
- }
- (*cr)->active = ccrtTemp.direction & 0x03;
- (*cr)->low = ccrtTemp.start;
- (*cr)->high = ccrtTemp.end;
-
- /* Convert CCRT secs/msecs to CRNG timimg
- * 0x4000 = max CRNG rate (cycle every 1 60th sec)
- * This must be divided by # 60th's between cycles
- * seconds to 60th's is easy
- * msecs to 60th's requires division by 16667
- * this is int math so I add 8334 (half 16667) first for rounding
- */
- (*cr)->rate = 0x4000 /
- ((ccrtTemp.seconds * 60)+((ccrtTemp.microseconds+8334)/16667));
- } else {
-
- /* Get CCRT Chunk from file */
- iffp = GetCCRT(context, &ccrtTemp);
-
- }
-
- return(iffp);
- }
-
-
- /** GetFoILBM() *************************************************************
- *
- * Called via myReadPictureto handle every FORM encountered in an IFF file.
- * Reads FORMs ILBM and skips all others.
- * Inside a FORM ILBM, it stops once it reads a BODY. It complains if it
- * finds no BODY or if it has no BMHD to decode the BODY.
- *
- * Once we find a BODY chunk, we'll call user rtn getBitMap() to
- * allocate the bitmap and planes (or screen) and then read
- * the BODY into the planes.
- *
- ****************************************************************************/
- LOCAL BYTE bodyBuffer[bufSz];
- IFFP GetFoILBM(parent)
- GroupContext *parent;
- {
- /*compilerBug register*/ IFFP iffp;
- GroupContext formContext;
- ILBMFrame ilbmFrame; /* only used for non-clientFrame fields.*/
- UBYTE *buffer;
- ULONG bufsize;
- struct BitMap srcbm;
-
- /* Handle a non-ILBM FORM. */
- if (parent->subtype != ID_ILBM) {
- #if Fancy >= 2
- /* Open a non-ILBM FORM and recursively scan it for ILBMs.*/
- iffp = OpenRGroup(parent, &formContext);
- CheckIFFP();
- do {
- iffp = GetF1ChunkHdr(&formContext);
- } while (iffp >= IFF_OKAY);
- if (iffp == END_MARK) {
- iffp = IFF_OKAY; /* then continue scanning the file */
- }
- CloseRGroup(&formContext);
- return(iffp);
- #else
- return(IFF_OKAY); /* Just skip this FORM and keep scanning the file.*/
- #endif
- }
-
- ilbmFrame = *(ILBMFrame *)parent->clientFrame;
- iffp = OpenRGroup(parent, &formContext);
- CheckIFFP();
-
- do switch (iffp = GetFChunkHdr(&formContext)) {
- case ID_BMHD: {
- ilbmFrame.foundBMHD = TRUE;
- iffp = GetBMHD(&formContext, &ilbmFrame.bmHdr);
- break; }
- case ID_CAMG: { /* cs */
- iffp = handleCAMG(&formContext, &ilbmFrame);
- break; }
- case ID_CRNG: { /* cs */
- iffp = handleCRNG(&formContext, &ilbmFrame);
- break; }
- case ID_CCRT: { /* cs */
- iffp = handleCCRT(&formContext, &ilbmFrame);
- break; }
- case ID_CMAP: {
- PicColors(ilbmFrame.pic) = maxColorReg; /* room for this many */
- iffp = GetCMAP(&formContext,
- (WORD *)PicColorMap(ilbmFrame.pic),
- &PicColors(ilbmFrame.pic));
- break; }
- case ID_BODY: { /* cs */
- if (!ilbmFrame.foundBMHD) {
- iffp = BAD_FORM; /* No BMHD chunk! */
- } else {
- bufsize = RowBytes (ilbmFrame.bmHdr.w) * 3;
- if (!(buffer = (ilbmFrame.allocmem)(bufsize, NULL))) {
- iffp = CLIENT_ERROR;
- } else {
- int i;
- BOOL error = FALSE;
-
- ClearMem (&srcbm, sizeof (srcbm));
- InitBitMap (&srcbm,
- ilbmFrame.bmHdr.nPlanes,
- ilbmFrame.bmHdr.w,
- 1);
-
- for (i=0; i<ilbmFrame.bmHdr.nPlanes && !error; i++) {
- if (!(srcbm.Planes[i] = (*ilbmFrame.allocmem)(RASSIZE (ilbmFrame.bmHdr.w, 1), MEMF_CHIP))) {
- error = TRUE;
- iffp = CLIENT_ERROR;
- }
- }
-
- if (!error) {
- iffp = GetBODY( &formContext,
- &ilbmFrame,
- NULL,
- buffer,
- bufsize,
- &srcbm);
- }
-
- for (i=0; i<ilbmFrame.bmHdr.nPlanes; i++) {
- if (srcbm.Planes[i]) {
- FreeMem (srcbm.Planes[i],
- RASSIZE (ilbmFrame.bmHdr.w, 1));
- }
- }
-
- FreeMem (buffer, bufsize);
- if (iffp == IFF_OKAY) {
- iffp = IFF_DONE; /* Eureka */
- }
- *giFrame = ilbmFrame; /* copy fields to client frame */
- }
- }
- break; }
- case END_MARK: {
- iffp = BAD_FORM;
- break; }
- } while (iffp >= IFF_OKAY);
-
- /* loop if valid ID of ignored chunk or a
- * subroutine returned IFF_OKAY (no errors).*/
-
- if (iffp != IFF_DONE) return(iffp);
-
- CloseRGroup(&formContext);
- return(iffp);
- }
-
- /** Notes on extending GetFoILBM ********************************************
- *
- * To read more kinds of chunks, just add clauses to the switch statement.
- * To read more kinds of property chunks (GRAB, CAMG, etc.) add clauses to
- * the switch statement in GetPrILBM, too.
- *
- * To read a FORM type that contains a variable number of data chunks--e.g.
- * a FORM FTXT with any number of CHRS chunks--replace the ID_BODY case with
- * an ID_CHRS case that doesn't set iffp = IFF_DONE, and make the END_MARK
- * case do whatever cleanup you need.
- *
- ****************************************************************************/
-
-
- /** GetPrILBM() *************************************************************
- *
- * Called via myReadPicture to handle every PROP encountered in an IFF file.
- * Reads PROPs ILBM and skips all others.
- *
- ****************************************************************************/
- #if Fancy
- IFFP GetPrILBM(parent)
- GroupContext *parent;
- {
- /*compilerBug register*/ IFFP iffp;
- GroupContext propContext;
- ILBMFrame *ilbmFrame = (ILBMFrame *)parent->clientFrame;
-
- if (parent->subtype != ID_ILBM)
- return(IFF_OKAY); /* just continue scaning the file */
-
- iffp = OpenRGroup(parent, &propContext);
- CheckIFFP();
-
- do switch (iffp = GetPChunkHdr(&propContext)) {
- case ID_BMHD: {
- ilbmFrame->foundBMHD = TRUE;
- iffp = GetBMHD(&propContext, &ilbmFrame->bmHdr);
- break; }
- case ID_CAMG: { /* cs */
- iffp = handleCAMG(&propContext, ilbmFrame);
- break; }
- case ID_CRNG: { /* cs */
- iffp = handleCRNG(&propContext, ilbmFrame);
- break; }
- case ID_CCRT: { /* cs */
- iffp = handleCCRT(&propContext, ilbmFrame);
- break; }
- case ID_CMAP: {
- PicColors(ilbmFrame->pic) = maxColorReg; /* room for this many */
- iffp = GetCMAP(&propContext,
- (WORD *)PicColorMap(ilbmFrame->pic),
- &PicColors(ilbmFrame->pic));
- break; }
- } while (iffp >= IFF_OKAY);
- /* loop if valid ID of ignored chunk or a
- * subroutine returned IFF_OKAY (no errors).*/
-
- CloseRGroup(&propContext);
- return(iffp == END_MARK ? IFF_OKAY : iffp);
- }
- #endif
-
- /** GetLiILBM() *************************************************************
- *
- * Called via myReadPicture to handle every LIST encountered in an IFF file.
- *
- ****************************************************************************/
- #if Fancy
- IFFP GetLiILBM(parent)
- GroupContext *parent;
- {
- ILBMFrame newFrame; /* allocate a new Frame */
-
- newFrame = *(ILBMFrame *)parent->clientFrame; /* copy parent frame */
-
- return( ReadIList(parent, (ClientFrame *)&newFrame) );
- }
- #endif
-
- /** myReadPicture() ********************************************************/
- IFFP myReadPicture(file,iFrame)
- LONG file;
- ILBMFrame *iFrame; /* Top level "client frame".*/
- {
- IFFP iffp = IFF_OKAY;
-
- #if Fancy
- iFrame->clientFrame.getList = GetLiILBM;
- iFrame->clientFrame.getProp = GetPrILBM;
- #else
- iFrame->clientFrame.getList = SkipGroup;
- iFrame->clientFrame.getProp = SkipGroup;
- #endif
-
- iFrame->clientFrame.getForm = GetFoILBM;
- iFrame->clientFrame.getCat = ReadICat ;
-
- /* Initialize the top-level client frame's property settings to the
- * program-wide defaults. This example just records that we haven't read
- * any BMHD property or CMAP color registers yet. For the color map, that
- * means the default is to leave the machine's color registers alone.
- * If you want to read a property like GRAB, init it here to (0, 0). */
-
- iFrame->foundBMHD = FALSE;
- PicColors(iFrame->pic) = 0;
- PicValidModes(iFrame->pic) = FALSE; /* cs */
- giFrame = iFrame;
-
- /* Store a pointer to the client's frame in a global variable so that
- * GetFoILBM can update client's frame when done. Why do we have so
- * many frames & frame pointers floating around causing confusion?
- * Because IFF supports PROPs which apply to all FORMs in a LIST,
- * unless a given FORM overrides some property.
- * When you write code to read several FORMs,
- * it is ssential to maintain a frame at each level of the syntax
- * so that the properties for the LIST don't get overwritten by any
- * properties specified by individual FORMs.
- * We decided it was best to put that complexity into this one-FORM example,
- * so that those who need it later will have a useful starting place.
- */
-
- iffp = ReadIFF(file, (ClientFrame *)iFrame);
- return(iffp);
- }
-
-