/*----------------------------------------------------------------------* * ILBMW.C Support routines for writing ILBM files. 1/23/86 * (IFF is Interchange Format File.) * * revised for VideoStage animation IFF files by Gary Bonham, * Sparta Inc., 15 Aug 86. * * By Jerry Morrison and Steve Shaw, Electronic Arts. * This software is in the public domain. * * This version for the Commodore-Amiga computer. *----------------------------------------------------------------------*/ #include "functions.h" #include "packer.h" #include "ilbm.h" #include "stdio.h" #define MAX(a,b) ((a)>(b)?(a):(b)) #define MIN(a,b) ((a)<(b)?(a):(b)) extern int Pop; UBYTE BMmask; /*---------- InitBMHdr -------------------------------------------------*/ IFFP InitBMHdr(bmHdr0, bitmap, masking, compression, transparentColor, pageWidth, pageHeight) BitMapHeader *bmHdr0; struct BitMap *bitmap; WORD masking; /* Masking */ WORD compression; /* Compression */ WORD transparentColor; /* UWORD */ WORD pageWidth, pageHeight; { register BitMapHeader *bmHdr = bmHdr0; register WORD rowBytes = bitmap->BytesPerRow; long maxx,minx,maxy,miny,ip,ib,ir; bmHdr->w = rowBytes << 3; bmHdr->h = bitmap->Rows; bmHdr->x = bmHdr->y = 0; /* Default position is (0,0).*/ bmHdr->nPlanes = bitmap->Depth; bmHdr->masking = masking; bmHdr->compression = compression; bmHdr->pad1 = 0; bmHdr->transparentColor = transparentColor; bmHdr->xAspect = bmHdr->yAspect = 1; bmHdr->pageWidth = pageWidth; bmHdr->pageHeight = pageHeight; BMmask = 0xFF; if (Pop) { maxx = 0; minx = 10000; maxy = 0; miny = 10000; BMmask = 0; for (ip=0;ipDepth;ip++) { for (ir=0;irRows;ir++) { for (ib=0;ibPlanes[ip]+ib+ir*rowBytes)) { BMmask |= 1<Rows - 1; } rowBytes = maxx - minx + 1; if (rowBytes & 1) { rowBytes++; if (minx & 1) minx--; else maxx++; } bmHdr->x = minx << 3; bmHdr->y = miny; bmHdr->w = rowBytes << 3; bmHdr->h = maxy - miny + 1; } if (pageWidth < 400) { if (pageHeight < 300) { bmHdr->xAspect = x320x200Aspect; bmHdr->yAspect = y320x200Aspect; } else { bmHdr->xAspect = x320x400Aspect; bmHdr->yAspect = y320x400Aspect; } } else { if (pageHeight < 300) { bmHdr->xAspect = x640x200Aspect; bmHdr->yAspect = y640x200Aspect; } else { bmHdr->xAspect = x640x400Aspect; bmHdr->yAspect = y640x400Aspect; } } return( IS_ODD(rowBytes) ? CLIENT_ERROR : IFF_OKAY ); } /*---------- PutCMAP ---------------------------------------------------*/ IFFP PutCMAP(context, colorMap, depth) GroupContext *context; WORD *colorMap; UBYTE depth; { register LONG nColorRegs; IFFP iffp; ColorRegister colorReg; if (depth > 5) depth = 5; nColorRegs = 1 << depth; iffp = PutCkHdr(context, ID_CMAP , (long)(nColorRegs * sizeofColorRegister)); CheckIFFP(); for ( ; nColorRegs; --nColorRegs) { colorReg.red = ( *colorMap >> 4 ) & 0xf0; colorReg.green = ( *colorMap ) & 0xf0; colorReg.blue = ( *colorMap << 4 ) & 0xf0; iffp = IFFWriteBytes(context, (BYTE *)&colorReg , (long)sizeofColorRegister); CheckIFFP(); ++colorMap; } iffp = PutCkEnd(context); return(iffp); } /*---------- PutBODY ---------------------------------------------------*/ /* NOTE: This implementation could be a LOT faster if it used more of the * supplied buffer. It would make far fewer calls to IFFWriteBytes (and * therefore to DOS Write). */ IFFP PutBODY(context, bitmap, mask, bmHdr, buffer, bufsize) GroupContext *context; struct BitMap *bitmap; BYTE *mask; BitMapHeader *bmHdr; BYTE *buffer; LONG bufsize; { IFFP iffp; LONG rowBytes = bitmap->BytesPerRow; long dstDepth = bmHdr->nPlanes; Compression compression = bmHdr->compression; long planeCnt; /* number of bit planes including mask */ long deltabyte; register long iPlane, iRow; register LONG packedRowBytes; BYTE *buf; BYTE *planes[MaxAmDepth + 1]; /* array of ptrs to planes & mask */ deltabyte = (bmHdr->pageWidth>>3) - (bmHdr->w>>3); if ( bufsize < MaxPackedSize(rowBytes) || /* Must buffer a comprsd row*/ compression > cmpByteRun1 || /* bad arg */ bitmap->Depth < dstDepth || /* inconsistent */ dstDepth > MaxAmDepth ) /* too many for this routine*/ return(CLIENT_ERROR); planeCnt = dstDepth + (mask == NULL ? 0 : 1); /* Copy the ptrs to bit & mask planes into local array "planes" */ for (iPlane = 0; iPlane < dstDepth; iPlane++) if ((Pop == 0) || ((BMmask>>iPlane)&1)) planes[iPlane] = (BYTE *)bitmap->Planes[iPlane] + bmHdr->y * rowBytes + (bmHdr->x>>3); else planes[iPlane] = NULL; #if 0 printf("plane %ld: %ld %ld\n",iPlane,planes[iPlane],bitmap->Planes[iPlane]); #endif if (mask != NULL) planes[dstDepth] = mask; /* Write out a BODY chunk header */ iffp = PutCkHdr(context, ID_BODY, (long)szNotYetKnown); CheckIFFP(); /* Write out the BODY contents */ for (iRow = bmHdr->h; iRow > 0; iRow--) { for (iPlane = 0; iPlane < planeCnt; iPlane++) { if (planes[iPlane]) { /* Write next row.*/ if (compression == cmpNone) { iffp = IFFWriteBytes(context, planes[iPlane], (long)rowBytes); planes[iPlane] += rowBytes; } /* Compress and write next row.*/ else { buf = buffer; packedRowBytes = PackRow(&planes[iPlane], &buf , (long)(bmHdr->w>>3)); iffp = IFFWriteBytes(context, buffer, (long)packedRowBytes); planes[iPlane] += deltabyte; } } CheckIFFP(); } } /* Finish the chunk */ iffp = PutCkEnd(context); return(iffp); }