home *** CD-ROM | disk | FTP | other *** search
/ Amiga ISO Collection / AmigaUtilCD2.iso / Programming / Misc / TRSICAT.LZX / CATS_CD2_TRSI / Reference_Library / Devices / modules / ilbmw.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-21  |  6.3 KB  |  205 lines

  1. /*----------------------------------------------------------------------*
  2.  * ILBMW.C  Support routines for writing ILBM files using IFFParse.
  3.  * (IFF is Interchange Format File.)
  4.  *
  5.  * Based on code by Jerry Morrison and Steve Shaw, Electronic Arts.
  6.  * This software is in the public domain.
  7.  *
  8.  * This version for the Commodore-Amiga computer.
  9.  *----------------------------------------------------------------------*/
  10.  
  11. #include "iffp/ilbm.h"
  12. #include "iffp/packer.h"
  13.  
  14. #include <graphics/gfxbase.h>
  15.  
  16. extern struct Library *GfxBase;
  17.  
  18. /*---------- initbmhd -------------------------------------------------*/
  19. long initbmhd(BitMapHeader *bmhd, struct BitMap *bitmap,
  20.           WORD masking, WORD compression, WORD transparentColor,
  21.           WORD width, WORD height, WORD pageWidth, WORD pageHeight,
  22.           ULONG modeid)
  23.     {
  24.     extern struct Library *GfxBase;
  25.     struct DisplayInfo DI;
  26.  
  27.     WORD rowBytes = bitmap->BytesPerRow;
  28.  
  29.     D(bug("In InitBMHD\n"));
  30.  
  31.     bmhd->w = width;
  32.     bmhd->h = height;
  33.     bmhd->x = bmhd->y = 0;    /* Default position is (0,0).*/
  34.     bmhd->nPlanes = bitmap->Depth;
  35.     bmhd->masking = masking;
  36.     bmhd->compression = compression;
  37.     bmhd->reserved1 = 0;
  38.     bmhd->transparentColor = transparentColor;
  39.     bmhd->pageWidth = pageWidth;
  40.     bmhd->pageHeight = pageHeight;
  41.  
  42.     bmhd->xAspect = 0;    /* So we can tell when we've got it */
  43.     if(GfxBase->lib_Version >=36)
  44.     {
  45.        if(GetDisplayInfoData(NULL, (UBYTE *)&DI,
  46.         sizeof(struct DisplayInfo), DTAG_DISP, modeid))
  47.         {
  48.             bmhd->xAspect =  DI.Resolution.x;
  49.             bmhd->yAspect =  DI.Resolution.y;
  50.         }
  51.     }
  52.  
  53.     /* If running under 1.3 or GetDisplayInfoData failed, use old method
  54.      * of guessing aspect ratio
  55.      */
  56.     if(! bmhd->xAspect)
  57.     {
  58.         bmhd->xAspect =  44;
  59.         bmhd->yAspect =
  60.         ((struct GfxBase *)GfxBase)->DisplayFlags & PAL ? 44 : 52;
  61.         if(modeid & HIRES)    bmhd->xAspect = bmhd->xAspect >> 1;
  62.         if(modeid & LACE)    bmhd->yAspect = bmhd->yAspect >> 1;
  63.     }
  64.  
  65.     return( IS_ODD(rowBytes) ? CLIENT_ERROR : IFF_OKAY );
  66.     }
  67.  
  68. /*---------- putcmap ---------------------------------------------------*/
  69. /* This function will accept a table of color values in one of the
  70.  * following forms:
  71.  *  if bitspergun=4,  colortable is words, each with nibbles 0RGB
  72.  *  if bitspergun=8,  colortable is bytes of RGBRGB etc. (like a CMAP)
  73.  *  if bitspergun=32, colortable is ULONGS of RGBRGB etc.
  74.  *     (only the high eight bits of each gun will be written to CMAP)
  75.  */
  76. long putcmap(struct IFFHandle *iff, APTR colortable,
  77.          UWORD ncolors, UWORD bitspergun)   
  78.    {
  79.    long error, offs;
  80.    WORD  *tabw;
  81.    UBYTE *tab8;
  82.    ColorRegister cmapReg;
  83.  
  84.    D(bug("In PutCMAP\n"));
  85.  
  86.    if((!iff)||(!colortable))    return(CLIENT_ERROR);
  87.  
  88.    /* size of CMAP is 3 bytes * ncolors */
  89.    if(error = PushChunk(iff, NULL, ID_CMAP, ncolors * sizeofColorRegister))
  90.     return(error);
  91.  
  92.    D(bug("Pushed ID_CMAP, error = %ld\n",error));
  93.  
  94.    if(bitspergun == 4)
  95.     {
  96.        /* Store each 4-bit value n as nn */
  97.     tabw = (UWORD *)colortable; 
  98.        for( ;  ncolors;  --ncolors )
  99.         {
  100.               cmapReg.red    = ( *tabw >> 4 ) & 0xf0;
  101.               cmapReg.red   |= (cmapReg.red >> 4);
  102.  
  103.               cmapReg.green  = ( *tabw      ) & 0xf0;
  104.               cmapReg.green |= (cmapReg.green >> 4);
  105.  
  106.               cmapReg.blue   = ( *tabw << 4 ) & 0xf0;
  107.               cmapReg.blue  |= (cmapReg.blue >> 4);
  108.  
  109.               if((WriteChunkBytes(iff, (BYTE *)&cmapReg, sizeofColorRegister))
  110.                 != sizeofColorRegister)
  111.                         return(IFFERR_WRITE);
  112.               ++tabw;
  113.               }
  114.     }
  115.    else if((bitspergun == 8)||(bitspergun == 32))
  116.     {
  117.     tab8 = (UBYTE *)colortable;
  118.     offs = (bitspergun == 8) ? 1 : 4;
  119.        for( ;  ncolors;  --ncolors )
  120.         {
  121.         cmapReg.red   = *tab8;
  122.         tab8 += offs;
  123.         cmapReg.green = *tab8;
  124.         tab8 += offs;
  125.         cmapReg.blue  = *tab8;
  126.         tab8 += offs;
  127.               if((WriteChunkBytes(iff, (BYTE *)&cmapReg, sizeofColorRegister))
  128.                 != sizeofColorRegister)
  129.                         return(IFFERR_WRITE);
  130.         }
  131.     }
  132.    else (error = CLIENT_ERROR)
  133.  
  134.    D(bug("Wrote registers, error = %ld\n",error));
  135.  
  136.    error = PopChunk(iff);
  137.    return(error);
  138.    }
  139.  
  140. /*---------- putbody ---------------------------------------------------*/
  141. /* NOTE: This implementation could be a LOT faster if it used more of the
  142.  * supplied buffer. It would make far fewer calls to IFFWriteBytes (and
  143.  * therefore to DOS Write). */
  144. long putbody(struct IFFHandle *iff, struct BitMap *bitmap, BYTE *mask,
  145.          BitMapHeader *bmhd, BYTE *buffer, LONG bufsize)
  146.    {         
  147.    long error;
  148.    LONG rowBytes = bitmap->BytesPerRow;
  149.    int dstDepth = bmhd->nPlanes;
  150.    UBYTE compression = bmhd->compression;
  151.    int planeCnt;        /* number of bit planes including mask */
  152.    register int iPlane, iRow;
  153.    register LONG packedRowBytes;
  154.    BYTE *buf;
  155.    BYTE *planes[MAXSAVEDEPTH + 1]; /* array of ptrs to planes & mask */
  156.  
  157.    D(bug("In PutBODY\n"));
  158.  
  159.    if ( bufsize < MaxPackedSize(rowBytes)  ||    /* Must buffer a comprsd row*/
  160.         compression > cmpByteRun1  ||        /* bad arg */
  161.     bitmap->Rows != bmhd->h   ||        /* inconsistent */
  162.     rowBytes != RowBytes(bmhd->w)  ||    /* inconsistent*/
  163.     bitmap->Depth < dstDepth   ||        /* inconsistent */
  164.     dstDepth > MAXSAVEDEPTH )        /* too many for this routine*/
  165.       return(CLIENT_ERROR);
  166.  
  167.    planeCnt = dstDepth + (mask == NULL ? 0 : 1);
  168.  
  169.    /* Copy the ptrs to bit & mask planes into local array "planes" */
  170.    for (iPlane = 0; iPlane < dstDepth; iPlane++)
  171.       planes[iPlane] = (BYTE *)bitmap->Planes[iPlane];
  172.    if (mask != NULL)
  173.       planes[dstDepth] = mask;
  174.  
  175.    /* Write out a BODY chunk header */
  176.    if(error = PushChunk(iff, NULL, ID_BODY, IFFSIZE_UNKNOWN)) return(error);
  177.  
  178.    /* Write out the BODY contents */
  179.    for (iRow = bmhd->h; iRow > 0; iRow--)  {
  180.       for (iPlane = 0; iPlane < planeCnt; iPlane++)  {
  181.  
  182.          /* Write next row.*/
  183.          if (compression == cmpNone) {
  184.         if(WriteChunkBytes(iff,planes[iPlane],rowBytes) != rowBytes)
  185.         error = IFFERR_WRITE;
  186.             planes[iPlane] += rowBytes;
  187.             }
  188.  
  189.          /* Compress and write next row.*/
  190.          else {
  191.             buf = buffer;
  192.             packedRowBytes = packrow(&planes[iPlane], &buf, rowBytes);
  193.         if(WriteChunkBytes(iff,buffer,packedRowBytes) != packedRowBytes)
  194.         error = IFFERR_WRITE;
  195.             }
  196.  
  197.          if(error)    return(error);
  198.          }
  199.       }
  200.  
  201.    /* Finish the chunk */
  202.    error = PopChunk(iff);
  203.    return(error);
  204.    }
  205.