aboutsummaryrefslogtreecommitdiff
path: root/ILBMW.C
blob: c5ec37b77ccf9c567625c6591335cef158e2d7e6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
/*----------------------------------------------------------------------*/
/* ILBMW.C  Support routines for writing ILBM files.           11/06/85 */
/* (IFF is Interchange Format File.)     				*/
/*									*/
/* By Jerry Morrison and Steve Shaw, Electronic Arts.			*/
/* This software is in the public domain.				*/
/*----------------------------------------------------------------------*/
#include "iff\packer.h"
#include "iff\ilbm.h"

/*---------- InitBMHdr -------------------------------------------------*/
IFFP InitBMHdr(bmHdr0, bitmap, masking, compression, transparentColor,
	    pageWidth, pageHeight)
        BitMapHeader *bmHdr0;  struct BitMap *bitmap;
        int masking, compression, transparentColor, pageWidth, pageHeight;
        /*  Masking, Compression, UWORD,            WORD,      WORD  */
    {
    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);
   }