/*----------------------------------------------------------------------* * ILBMW.C Support routines for writing ILBM files. 1/23/86 * (IFF is Interchange Format File.) * * By Jerry Morrison and Steve Shaw, Electronic Arts. * This software is in the public domain. * * This version for the Commodore-Amiga computer. *----------------------------------------------------------------------*/ #include "packer.h" #include "ilbm.h" /*---------- 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; 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; if (pageWidth = 320) switch (pageHeight) { case 200: {bmHdr->xAspect = x320x200Aspect; bmHdr->yAspect = y320x200Aspect; break;} case 400: {bmHdr->xAspect = x320x400Aspect; bmHdr->yAspect = y320x400Aspect; break;} } else if (pageWidth = 640) switch (pageHeight) { case 200: {bmHdr->xAspect = x640x200Aspect; bmHdr->yAspect = y640x200Aspect; break;} case 400: {bmHdr->xAspect = x640x400Aspect; bmHdr->yAspect = y640x400Aspect; break;} } 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 > MaxAmDepth) depth = MaxAmDepth; nColorRegs = 1 << depth; iffp = PutCkHdr(context, ID_CMAP, 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, 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; int dstDepth = bmHdr->nPlanes; Compression compression = bmHdr->compression; int planeCnt; /* number of bit planes including mask */ register int iPlane, iRow; register LONG packedRowBytes; BYTE *buf; BYTE *planes[MaxAmDepth + 1]; /* array of ptrs to planes & mask */ if ( bufsize < MaxPackedSize(rowBytes) || /* Must buffer a comprsd row*/ compression > cmpByteRun1 || /* bad arg */ bitmap->Rows != bmHdr->h || /* inconsistent */ rowBytes != RowBytes(bmHdr->w) || /* inconsistent*/ 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++) planes[iPlane] = (BYTE *)bitmap->Planes[iPlane]; if (mask != NULL) planes[dstDepth] = mask; /* Write out a BODY chunk header */ iffp = PutCkHdr(context, ID_BODY, szNotYetKnown); CheckIFFP(); /* Write out the BODY contents */ for (iRow = bmHdr->h; iRow > 0; iRow--) { for (iPlane = 0; iPlane < planeCnt; iPlane++) { /* Write next row.*/ if (compression == cmpNone) { iffp = IFFWriteBytes(context, planes[iPlane], rowBytes); planes[iPlane] += rowBytes; } /* Compress and write next row.*/ else { buf = buffer; packedRowBytes = PackRow(&planes[iPlane], &buf, rowBytes); iffp = IFFWriteBytes(context, buffer, packedRowBytes); } CheckIFFP(); } } /* Finish the chunk */ iffp = PutCkEnd(context); return(iffp); }