/* * ifficon.c V1.5 * * IFF brush handling * * (c) 1991 by Stefan Becker * */ #include "ToolManager.h" /* Our own DiskObject definition */ struct IFFDObj { struct DiskObject id_dobj; struct Image id_img; ULONG id_size; /* size of image */ }; /* Bitmap header (BMHD) structure */ struct BitMapHeader { UWORD w,h; /* Width, height in pixels */ WORD x,y; UBYTE nplanes; /* Number of planes */ UBYTE Masking; /* Masking */ UBYTE Compression; /* Compression algorithm */ UBYTE pad1; UWORD TransparentColor; UBYTE XAspect,YAspect; WORD PageWidth, PageHeight; }; #define MSK_HASMASK 1 #define COMP_NO 0 #define COMP_BYTERUN1 1 #define BPR(w) ((((w)+15)>>4)<<1) /* Bytes per row formula */ /* IFF ID's */ #define ID_ILBM MAKE_ID('I','L','B','M') #define ID_BMHD MAKE_ID('B','M','H','D') #define ID_BODY MAKE_ID('B','O','D','Y') /* miscellaneous */ struct Library *IFFParseBase; /* Read BODY chunk into memory and convert it to an image */ static BOOL ReadBODY(struct IFFHandle *iff, struct BitMapHeader *bmhd, UBYTE *dest, ULONG bpr, ULONG planeoff) { register UBYTE *sp,*dp; register ULONG row; UBYTE *src; ULONG planes=bmhd->nplanes; ULONG size=CurrentChunk(iff)->cn_Size; BOOL ncomp=bmhd->Compression==COMP_NO; BOOL mask=bmhd->Masking==MSK_HASMASK; BOOL rc=TRUE; /* Get memory for BODY chunk contents */ if (!(sp=src=malloc(size))) goto rbe1; /* Read in the complete BODY chunk */ if (ReadChunkBytes(iff,src,size)!=size) goto rbe2; for (row=0; rowh; row++) /* Read data row by row */ { register ULONG pl,rem; register char k; for (pl=0; pl=0) { /* Literal copy */ if ((rem-=++k)<0) goto rbe2; /* Error in de-compression? */ while (k--) *dp++=*sp++; /* Copy the following k+1 bytes */ } else if (k!=-128) /* Code -128 == No Operation */ { /* Byte run encoded */ register UBYTE byte; k=-k; if ((rem-=++k)<0) goto rbe2; /* Error in de-compression? */ byte=*sp++; /* Get byte */ while (k--) *dp++=byte; /* Copy this byte -k+1 times */ } } } } if (mask) /* Skip mask plane */ if (ncomp) sp+=bpr; /* No compression */ else { /* Byte Run compression */ rem=bpr; while (rem) /* Row not completed */ { k=*sp++; /* Read compression code */ if (k>=0) { /* Literal copy */ if ((rem-=++k)<0) goto rbe2; /* Error in de-compression? */ sp+=k; /* Skip the following k+1 bytes */ } else if (k!=-128) /* Code -128 == No Operation */ { /* Byte run encoded */ k=-k; if ((rem-=++k)<0) goto rbe2; /* Error in de-compression? */ sp++; /* Skip this byte */ } } } } /* All OK */ rc=FALSE; rbe2: free(src); rbe1: return(rc); } /* Load an IFF brush and create a DiskObject */ struct DiskObject *LoadIFFIcon(char *name) { register struct IFFHandle *iff; register struct IFFDObj *id=NULL; struct ContextNode *cn; struct StoredProperty *sp; struct BitMapHeader *bmhd; ULONG bpr,planeoff; BOOL error=TRUE; /* Open IFF parsing library */ if (!(IFFParseBase=OpenLibrary("iffparse.library",0))) goto lie1; /* Get memory for DiskObject and clear it */ if (!(id=calloc(sizeof(struct IFFDObj),1))) goto lie2; id->id_dobj.do_Version=WB_DISKVERSION; id->id_dobj.do_Gadget.GadgetRender=&id->id_img; id->id_dobj.do_Gadget.UserData=(APTR) WB_DISKREVISION; /* Alloc IFF handle */ if (!(iff=AllocIFF())) goto lie3; /* Open IFF file and init IFF handle */ if (!(iff->iff_Stream=Open(name,MODE_OLDFILE))) goto lie4; InitIFFasDOS(iff); /* Declare ILBM property & stop chunks. Open IFF context */ if (PropChunk(iff,ID_ILBM,ID_BMHD)) goto lie5; if (StopChunk(iff,ID_ILBM,ID_BODY)) goto lie5; if (StopOnExit(iff,ID_ILBM,ID_FORM)) goto lie5; if (OpenIFF(iff,IFFF_READ)) goto lie5; /* Start parsing */ if (ParseIFF(iff,IFFPARSE_STEP)) goto lie6; /* Check for FORM ILBM chunk */ if (!(cn=CurrentChunk(iff))) goto lie6; if ((cn->cn_ID!=ID_FORM) || (cn->cn_Type!=ID_ILBM)) goto lie6; /* Continue parsing until BODY chunk is found */ if (ParseIFF(iff,IFFPARSE_SCAN)) goto lie6; /* BMHD chunk found? */ if (!(sp=FindProp(iff,ID_ILBM,ID_BMHD))) goto lie6; bmhd=(struct BitMapHeader *) sp->sp_Data; /* Check compression type */ if ((bmhd->Compression!=COMP_NO) && (bmhd->Compression!=COMP_BYTERUN1)) goto lie6; /* Retrieve BMHD chunk values */ id->id_dobj.do_Gadget.Width=bmhd->w; id->id_dobj.do_Gadget.Height=bmhd->h+1; id->id_dobj.do_Gadget.Flags=GFLG_GADGHCOMP; id->id_img.Width=bmhd->w; id->id_img.Height=bmhd->h; id->id_img.Depth=bmhd->nplanes; id->id_img.PlanePick=(1<nplanes)-1; /* Allocate chip memory for image data */ bpr=BPR(bmhd->w); /* Bytes per row */ planeoff=bpr*bmhd->h; /* Bytes per plane */ id->id_size=planeoff*bmhd->nplanes; /* Bytes for image */ if (!(id->id_img.ImageData=AllocMem(id->id_size, MEMF_PUBLIC|MEMF_CHIP|MEMF_CLEAR))) goto lie6; /* Read ImageData */ error=ReadBODY(iff,bmhd,(UBYTE *) id->id_img.ImageData,bpr,planeoff); if (error) FreeMem(id->id_img.ImageData,id->id_size); lie6: CloseIFF(iff); lie5: Close(iff->iff_Stream); lie4: FreeIFF(iff); lie3: if (error) { free(id); id=NULL; } lie2: CloseLibrary(IFFParseBase); lie1: return(id); } /* Free an IFF icon */ void FreeIFFIcon(struct DiskObject *dobj) { register struct IFFDObj *id=dobj; FreeMem(id->id_img.ImageData,id->id_size); free(id); }