home *** CD-ROM | disk | FTP | other *** search
/ Amiga Elysian Archive / AmigaElysianArchive.iso / anim / players / mpeg_src.lha / amiga / lib / ilbmw.c < prev    next >
C/C++ Source or Header  |  1992-12-20  |  7KB  |  228 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.  * mod 06-Apr-92 - Add JM change for separate source and dest modulo
  11.  *----------------------------------------------------------------------*/
  12. #define INTUI_V36_NAMES_ONLY
  13.  
  14. #include <exec/types.h>
  15. #include <exec/memory.h>
  16. #include <exec/libraries.h>
  17. #include <intuition/intuition.h>
  18. #include <intuition/classes.h>
  19. #include <graphics/gfxbase.h>
  20. #include <graphics/gfxmacros.h>
  21. #include <graphics/modeid.h>
  22. #include <graphics/scale.h>
  23. #include <graphics/graphint.h>
  24. #include <dos/dos.h>
  25. #include <dos/exall.h>
  26.  
  27. #include "iffp/ilbm.h"
  28. #include "iffp/packer.h"
  29.  
  30. #include <graphics/gfxbase.h>
  31.  
  32. extern struct Library *GfxBase;
  33.  
  34. /*---------- initbmhd -------------------------------------------------*/
  35. long initbmhd(BitMapHeader *bmhd, struct BitMap *bitmap,
  36.           WORD masking, WORD compression, WORD transparentColor,
  37.           WORD width, WORD height, WORD pageWidth, WORD pageHeight,
  38.           ULONG modeid)
  39.     {
  40.     extern struct Library *GfxBase;
  41.     struct DisplayInfo DI;
  42.  
  43.     WORD rowBytes = bitmap->BytesPerRow;
  44.  
  45.     D(bug("In InitBMHD\n"));
  46.  
  47.     bmhd->w = width;
  48.     bmhd->h = height;
  49.     bmhd->x = bmhd->y = 0;    /* Default position is (0,0).*/
  50.     bmhd->nPlanes = bitmap->Depth;
  51.     bmhd->masking = masking;
  52.     bmhd->compression = compression;
  53.     bmhd->reserved1 = 0;
  54.     bmhd->transparentColor = transparentColor;
  55.     bmhd->pageWidth = pageWidth;
  56.     bmhd->pageHeight = pageHeight;
  57.  
  58.     bmhd->xAspect = 0;    /* So we can tell when we've got it */
  59.     if(GfxBase->lib_Version >=36)
  60.     {
  61.        if(GetDisplayInfoData(NULL, (UBYTE *)&DI,
  62.         sizeof(struct DisplayInfo), DTAG_DISP, modeid))
  63.         {
  64.             bmhd->xAspect =  DI.Resolution.x;
  65.             bmhd->yAspect =  DI.Resolution.y;
  66.         }
  67.     }
  68.  
  69.     /* If running under 1.3 or GetDisplayInfoData failed, use old method
  70.      * of guessing aspect ratio
  71.      */
  72.     if(! bmhd->xAspect)
  73.     {
  74.         bmhd->xAspect =  44;
  75.         bmhd->yAspect =
  76.         ((struct GfxBase *)GfxBase)->DisplayFlags & PAL ? 44 : 52;
  77.         if(modeid & HIRES)    bmhd->xAspect = bmhd->xAspect >> 1;
  78.         if(modeid & LACE)    bmhd->yAspect = bmhd->yAspect >> 1;
  79.     }
  80.  
  81.     return( IS_ODD(rowBytes) ? CLIENT_ERROR : IFF_OKAY );
  82.     }
  83.  
  84. /*---------- putcmap ---------------------------------------------------*/
  85. /* This function will accept a table of color values in one of the
  86.  * following forms:
  87.  *  if bitspergun=4,  colortable is words, each with nibbles 0RGB
  88.  *  if bitspergun=8,  colortable is bytes of RGBRGB etc. (like a CMAP)
  89.  *  if bitspergun=32, colortable is ULONGS of RGBRGB etc.
  90.  *     (only the high eight bits of each gun will be written to CMAP)
  91.  */
  92. long putcmap(struct IFFHandle *iff, APTR colortable,
  93.          UWORD ncolors, UWORD bitspergun)
  94.    {
  95.    long error, offs;
  96.    WORD  *tabw;
  97.    UBYTE *tab8;
  98.    ColorRegister cmapReg;
  99.  
  100.    D(bug("In PutCMAP\n"));
  101.  
  102.    if((!iff)||(!colortable))    return(CLIENT_ERROR);
  103.  
  104.    /* size of CMAP is 3 bytes * ncolors */
  105.    if(error = PushChunk(iff, NULL, ID_CMAP, ncolors * sizeofColorRegister))
  106.     return(error);
  107.  
  108.    D(bug("Pushed ID_CMAP, error = %ld\n",error));
  109.  
  110.    if(bitspergun == 4)
  111.     {
  112.        /* Store each 4-bit value n as nn */
  113.     tabw = (UWORD *)colortable;
  114.        for( ;  ncolors;  --ncolors )
  115.         {
  116.               cmapReg.red    = ( *tabw >> 4 ) & 0xf0;
  117.               cmapReg.red   |= (cmapReg.red >> 4);
  118.  
  119.               cmapReg.green  = ( *tabw      ) & 0xf0;
  120.               cmapReg.green |= (cmapReg.green >> 4);
  121.  
  122.               cmapReg.blue   = ( *tabw << 4 ) & 0xf0;
  123.               cmapReg.blue  |= (cmapReg.blue >> 4);
  124.  
  125.               if((WriteChunkBytes(iff, (BYTE *)&cmapReg, sizeofColorRegister))
  126.                 != sizeofColorRegister)
  127.                         return(IFFERR_WRITE);
  128.               ++tabw;
  129.               }
  130.     }
  131.    else if((bitspergun == 8)||(bitspergun == 32))
  132.     {
  133.     tab8 = (UBYTE *)colortable;
  134.     offs = (bitspergun == 8) ? 1 : 4;
  135.        for( ;  ncolors;  --ncolors )
  136.         {
  137.         cmapReg.red   = *tab8;
  138.         tab8 += offs;
  139.         cmapReg.green = *tab8;
  140.         tab8 += offs;
  141.         cmapReg.blue  = *tab8;
  142.         tab8 += offs;
  143.               if((WriteChunkBytes(iff, (BYTE *)&cmapReg, sizeofColorRegister))
  144.                 != sizeofColorRegister)
  145.                         return(IFFERR_WRITE);
  146.         }
  147.     }
  148.    else (error = CLIENT_ERROR);
  149.  
  150.    D(bug("Wrote registers, error = %ld\n",error));
  151.  
  152.    error = PopChunk(iff);
  153.    return(error);
  154.    }
  155.  
  156. /*---------- putbody ---------------------------------------------------*/
  157. /* NOTE: This implementation could be a LOT faster if it used more of the
  158.  * supplied buffer. It would make far fewer calls to IFFWriteBytes (and
  159.  * therefore to DOS Write).
  160.  *
  161.  * Incorporates modification by Jesper Steen Moller to accept source
  162.  * rows are wider than dest rows, one for the source bitplanes
  163.  * and one for the ILBM bitmap.
  164.  */
  165. long putbody(struct IFFHandle *iff, struct BitMap *bitmap, BYTE *mask,
  166.          BitMapHeader *bmhd, BYTE *buffer, LONG bufsize)
  167.    {
  168.    long error;
  169.    LONG rowBytes = bitmap->BytesPerRow;
  170.    LONG FileRowBytes = RowBytes(bmhd->w);
  171.    int dstDepth = bmhd->nPlanes;
  172.    UBYTE compression = bmhd->compression;
  173.    int planeCnt;        /* number of bit planes including mask */
  174.    register int iPlane, iRow;
  175.    register LONG packedRowBytes;
  176.    BYTE *buf;
  177.    BYTE *planes[MAXSAVEDEPTH + 1]; /* array of ptrs to planes & mask */
  178.  
  179.    D(bug("In PutBODY, rows = %ld, rowBytes = %ld, expected %ld\n", bitmap->Rows, rowBytes, RowBytes(bmhd->w)));
  180.  
  181.    if ( bufsize < MaxPackedSize(rowBytes)  ||    /* Must buffer a comprsd row*/
  182.         compression > cmpByteRun1  ||        /* bad arg */
  183.     bitmap->Rows != bmhd->h   ||        /* inconsistent */
  184.     rowBytes < FileRowBytes  ||    /* inconsistent*/
  185.     bitmap->Depth < dstDepth   ||        /* inconsistent */
  186.     dstDepth > MAXSAVEDEPTH )        /* too many for this routine*/
  187.       return(CLIENT_ERROR);
  188.  
  189.    planeCnt = dstDepth + (mask == NULL ? 0 : 1);
  190.  
  191.    /* Copy the ptrs to bit & mask planes into local array "planes" */
  192.    for (iPlane = 0; iPlane < dstDepth; iPlane++)
  193.       planes[iPlane] = (BYTE *)bitmap->Planes[iPlane];
  194.    if (mask != NULL)
  195.       planes[dstDepth] = mask;
  196.  
  197.    /* Write out a BODY chunk header */
  198.    if(error = PushChunk(iff, NULL, ID_BODY, IFFSIZE_UNKNOWN)) return(error);
  199.  
  200.    /* Write out the BODY contents */
  201.    for (iRow = bmhd->h; iRow > 0; iRow--)  {
  202.       for (iPlane = 0; iPlane < planeCnt; iPlane++)  {
  203.  
  204.          /* Write next row.*/
  205.          if (compression == cmpNone) {
  206.         if(WriteChunkBytes(iff,planes[iPlane],FileRowBytes) != FileRowBytes)
  207.         error = IFFERR_WRITE;
  208.             planes[iPlane] += rowBytes; /* Possibly skipping unused bytes */
  209.             }
  210.  
  211.          /* Compress and write next row.*/
  212.          else {
  213.             buf = buffer;
  214.             packedRowBytes = packrow(&planes[iPlane], &buf, FileRowBytes);
  215.             planes[iPlane] += rowBytes-FileRowBytes; /* Possibly skipping unused bytes */
  216.         if(WriteChunkBytes(iff,buffer,packedRowBytes) != packedRowBytes)
  217.         error = IFFERR_WRITE;
  218.             }
  219.  
  220.          if(error)    return(error);
  221.          }
  222.       }
  223.  
  224.    /* Finish the chunk */
  225.    error = PopChunk(iff);
  226.    return(error);
  227.    }
  228.