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

  1. /* ilbmr.c --- ILBM loading routines for use with iffparse */
  2.  
  3. /*----------------------------------------------------------------------*
  4.  * ILBMR.C  Support routines for reading ILBM files.
  5.  * (IFF is Interchange Format File.)
  6.  *
  7.  * Based on code by Jerry Morrison and Steve Shaw, Electronic Arts.
  8.  * This software is in the public domain.
  9.  * Modified for iffparse.library 05/90
  10.  * This version for the Commodore-Amiga computer.
  11.  *----------------------------------------------------------------------*/
  12.  
  13. #include "iffp/ilbm.h"
  14. #include "iffp/packer.h"
  15. #include "iffp/ilbmapp.h"
  16.  
  17. #define movmem CopyMem
  18.  
  19. #define MaxSrcPlanes (25)
  20.  
  21. extern struct Library *GfxBase;
  22.  
  23. /*---------- loadbody ---------------------------------------------------*/
  24.  
  25. LONG loadbody(iff, bitmap, bmhd)
  26. struct IFFHandle *iff;
  27. struct BitMap *bitmap;
  28. BitMapHeader *bmhd;
  29.     {
  30.     BYTE *buffer;
  31.     ULONG bufsize;
  32.     LONG error = 1;
  33.  
  34.     D(bug("In loadbody\n"));
  35.  
  36.     if(!(currentchunkis(iff,ID_ILBM,ID_BODY)))
  37.         {
  38.         message("ILBM has no BODY\n");    /* Maybe it's a palette */
  39.         return(IFF_OKAY);
  40.         }
  41.  
  42.     if((bitmap)&&(bmhd))
  43.         {
  44.         D(bug("Have bitmap and bmhd\n"));
  45.  
  46.         bufsize = MaxPackedSize(RowBytes(bmhd->w)) << 4;
  47.             if(!(buffer = AllocMem(bufsize,0L)))
  48.         {
  49.         D(bug("Buffer alloc of %ld failed\n",bufsize));
  50.         return(IFFERR_NOMEM);
  51.         }
  52.         error = loadbody2(iff, bitmap, NULL, bmhd, buffer, bufsize);
  53.         D(bug("Returned from getbody, error = %ld\n",error));
  54.         }
  55.     FreeMem(buffer,bufsize);
  56.     return(error);
  57.     }
  58.  
  59.  
  60. /* like the old GetBODY */
  61. LONG loadbody2(iff, bitmap, mask, bmhd, buffer, bufsize)
  62. struct IFFHandle *iff;
  63. struct BitMap *bitmap;
  64. BYTE *mask;
  65. BitMapHeader *bmhd;
  66. BYTE *buffer;
  67. ULONG bufsize;
  68.    {
  69.    UBYTE srcPlaneCnt = bmhd->nPlanes;   /* Haven't counted for mask plane yet*/
  70.    WORD srcRowBytes = RowBytes(bmhd->w);
  71.    WORD destRowBytes = bitmap->BytesPerRow;
  72.    LONG bufRowBytes = MaxPackedSize(srcRowBytes);
  73.    int nRows = bmhd->h;
  74.    WORD compression = bmhd->compression;
  75.    register int iPlane, iRow, nEmpty;
  76.    register WORD nFilled;
  77.    BYTE *buf, *nullDest, *nullBuf, **pDest;
  78.    BYTE *planes[MaxSrcPlanes]; /* array of ptrs to planes & mask */
  79.    struct ContextNode *cn;
  80.  
  81.    D(bug("srcRowBytes = %ld\n",srcRowBytes));
  82.  
  83.    cn = CurrentChunk(iff);
  84.  
  85.    if (compression > cmpByteRun1)
  86.       return(CLIENT_ERROR);
  87.  
  88.    D(bug("loadbody2: compression=%ld srcBytes=%ld bitmapBytes=%ld\n",
  89.         compression, srcRowBytes, bitmap->BytesPerRow));
  90.    D(bug("loadbody2: bufsize=%ld bufRowBytes=%ld, srcPlaneCnt=%ld\n",
  91.             bufsize, bufRowBytes, srcPlaneCnt));
  92.  
  93.    /* Complain if client asked for a conversion GetBODY doesn't handle.*/
  94.    if ( srcRowBytes  >  bitmap->BytesPerRow  ||
  95.          bufsize < bufRowBytes * 2  ||
  96.          srcPlaneCnt > MaxSrcPlanes )
  97.       return(CLIENT_ERROR);
  98.  
  99.    D(bug("loadbody2: past conversion checks\n"));
  100.  
  101.    if (nRows > bitmap->Rows)   nRows = bitmap->Rows;
  102.  
  103.    D(bug("loadbody2: srcRowBytes=%ld, srcRows=%ld, srcDepth=%ld, destDepth=%ld\n",
  104.         srcRowBytes, nRows, bmhd->nPlanes, bitmap->Depth));
  105.    
  106.    /* Initialize array "planes" with bitmap ptrs; NULL in empty slots.*/
  107.    for (iPlane = 0; iPlane < bitmap->Depth; iPlane++)
  108.       planes[iPlane] = (BYTE *)bitmap->Planes[iPlane];
  109.    for ( ;  iPlane < MaxSrcPlanes;  iPlane++)
  110.       planes[iPlane] = NULL;
  111.  
  112.    /* Copy any mask plane ptr into corresponding "planes" slot.*/
  113.    if (bmhd->masking == mskHasMask)
  114.     {
  115.           if (mask != NULL)
  116.              planes[srcPlaneCnt] = mask;  /* If there are more srcPlanes than
  117.                * dstPlanes, there will be NULL plane-pointers before this.*/
  118.           else
  119.              planes[srcPlaneCnt] = NULL;  /* In case more dstPlanes than src.*/
  120.           srcPlaneCnt += 1;  /* Include mask plane in count.*/
  121.           }
  122.  
  123.    /* Setup a sink for dummy destination of rows from unwanted planes.*/
  124.    nullDest = buffer;
  125.    buffer  += srcRowBytes;
  126.    bufsize -= srcRowBytes;
  127.  
  128.    /* Read the BODY contents into client's bitmap.
  129.     * De-interleave planes and decompress rows.
  130.     * MODIFIES: Last iteration modifies bufsize.*/
  131.  
  132.    buf = buffer + bufsize;  /* Buffer is currently empty.*/
  133.    for (iRow = nRows; iRow > 0; iRow--)
  134.     {
  135.           for (iPlane = 0; iPlane < srcPlaneCnt; iPlane++)
  136.         {
  137.          pDest = &planes[iPlane];
  138.  
  139.             /* Establish a sink for any unwanted plane.*/
  140.             if (*pDest == NULL)
  141.         {
  142.             nullBuf = nullDest;
  143.                 pDest   = &nullBuf;
  144.                 }
  145.  
  146.             /* Read in at least enough bytes to uncompress next row.*/
  147.             nEmpty  = buf - buffer;      /* size of empty part of buffer.*/
  148.             nFilled = bufsize - nEmpty;      /* this part has data.*/
  149.         if (nFilled < bufRowBytes)
  150.         {
  151.             /* Need to read more.*/
  152.  
  153.             /* Move the existing data to the front of the buffer.*/
  154.             /* Now covers range buffer[0]..buffer[nFilled-1].*/
  155.                 movmem(buf, buffer, nFilled);  /* Could be moving 0 bytes.*/
  156.  
  157.                 if(nEmpty > ChunkMoreBytes(cn))
  158.             {
  159.                        /* There aren't enough bytes left to fill the buffer.*/
  160.                        nEmpty = ChunkMoreBytes(cn);
  161.                        bufsize = nFilled + nEmpty;  /* heh-heh */
  162.                        }
  163.  
  164.             /* Append new data to the existing data.*/
  165.                 if(ReadChunkBytes(iff, &buffer[nFilled], nEmpty) < nEmpty)
  166.             return(CLIENT_ERROR);
  167.  
  168.                 buf     = buffer;
  169.             nFilled = bufsize;
  170.             nEmpty  = 0;
  171.             }
  172.  
  173.          /* Copy uncompressed row to destination plane.*/
  174.             if(compression == cmpNone)
  175.         {
  176.                 if(nFilled < srcRowBytes)  return(IFFERR_MANGLED);
  177.             movmem(buf, *pDest, srcRowBytes);
  178.             buf    += srcRowBytes;
  179.                 *pDest += destRowBytes;
  180.                 }
  181.         else
  182.         {
  183.              /* Decompress row to destination plane.*/
  184.                 if ( unpackrow(&buf, pDest, nFilled,  srcRowBytes) )
  185.                     /*  pSource, pDest, srcBytes, dstBytes  */
  186.                        return(IFFERR_MANGLED);
  187.             else *pDest += (destRowBytes - srcRowBytes);
  188.         }
  189.         }
  190.     }
  191.    return(IFF_OKAY);
  192.    }
  193.  
  194.  
  195. /* ----------- getcolors ------------- */
  196.  
  197. /* getcolors - allocates a ilbm->colortable for at least MAXAMCOLORREG
  198.  *      and loads CMAP colors into it, setting ilbm->ncolors to number
  199.  *      of colors actually loaded.
  200.  */ 
  201. LONG getcolors(struct ILBMInfo *ilbm)
  202.     {
  203.     struct IFFHandle    *iff;
  204.     int error = 1;
  205.  
  206.     if(!(iff=ilbm->ParseInfo.iff))    return(CLIENT_ERROR);
  207.  
  208.     if(!(error = alloccolortable(ilbm)))
  209.        error = loadcmap(iff, ilbm->colortable, &ilbm->ncolors);
  210.     if(error) freecolors(ilbm);
  211.     D(bug("getcolors: error = %ld\n",error));
  212.     return(error);
  213.     }
  214.  
  215.  
  216. /* alloccolortable - allocates ilbm->colortable and sets ilbm->ncolors
  217.  *    to the number of colors we have room for in the table.
  218.  */ 
  219.  
  220. LONG alloccolortable(struct ILBMInfo *ilbm)
  221.     {
  222.     struct IFFHandle    *iff;
  223.     struct    StoredProperty    *sp;
  224.  
  225.     LONG    error = CLIENT_ERROR;
  226.     ULONG    ctabsize;
  227.     USHORT    ncolors;
  228.  
  229.     if(!(iff=ilbm->ParseInfo.iff))    return(CLIENT_ERROR);
  230.  
  231.     if(sp = FindProp (iff, ID_ILBM, ID_CMAP))
  232.         {
  233.         /*
  234.          * Compute the size table we need
  235.          */
  236.         ncolors = sp->sp_Size / 3;        /* how many in CMAP */
  237.         ncolors = MAX(ncolors, MAXAMCOLORREG);
  238.  
  239.         ctabsize = ncolors * sizeof(Color4);
  240.         if(ilbm->colortable = 
  241.            (Color4 *)AllocMem(ctabsize,MEMF_CLEAR|MEMF_PUBLIC))
  242.             {
  243.             ilbm->ncolors = ncolors;
  244.             ilbm->ctabsize = ctabsize;
  245.             error = 0L;
  246.             }
  247.         else error = IFFERR_NOMEM;
  248.         }
  249.     D(bug("alloccolortable for %ld colors: error = %ld\n",ncolors,error));
  250.     return(error);
  251.     }
  252.  
  253.  
  254. void freecolors(struct ILBMInfo *ilbm)
  255.     {
  256.     if(ilbm->colortable)
  257.         {
  258.         FreeMem(ilbm->colortable, ilbm->ctabsize);
  259.         }
  260.     ilbm->colortable = NULL;
  261.     ilbm->ctabsize = 0;
  262.     }
  263.  
  264.  
  265.  
  266. /* Passed IFFHandle, pointer to colortable array, and pointer to
  267.  * a USHORT containing number of colors caller has space to hold,
  268.  * loads the colors and sets pNcolors to the number actually read.
  269.  *
  270.  * NOTE !!! - Old GetCMAP passed a pointer to a UBYTE for pNcolors
  271.  *            This one is passed a pointer to a USHORT
  272.  */
  273. LONG loadcmap(struct IFFHandle *iff, WORD *colortable,USHORT *pNcolors)
  274.     {
  275.     register struct StoredProperty    *sp;
  276.     register LONG            idx;
  277.     register ULONG            ncolors;
  278.     register UBYTE            *rgb;
  279.     LONG                r, g, b;
  280.  
  281.     if(!(colortable))
  282.         {
  283.         message("No colortable allocated\n");
  284.         return(1);
  285.         }
  286.  
  287.     if(!(sp = FindProp (iff, ID_ILBM, ID_CMAP)))    return(1);
  288.  
  289.     rgb = sp->sp_Data;
  290.     ncolors = sp->sp_Size / sizeofColorRegister;
  291.     if(*pNcolors < ncolors)    ncolors = *pNcolors;
  292.     *pNcolors = ncolors;
  293.  
  294.     idx = 0;
  295.         while (ncolors--) 
  296.                 {
  297.                 r = (*rgb++ & 0xF0) << 4;
  298.                 g = *rgb++ & 0xF0;
  299.                 b = *rgb++ >> 4;
  300.                 colortable[idx] = r | g | b;
  301.                 idx++;
  302.                 }
  303.         return(0);
  304.         }
  305.  
  306. /*
  307.  * Returns CAMG or computed mode for storage in ilbm->camg
  308.  *
  309.  * ilbm->Bmhd structure must be initialized prior to this call.
  310.  */
  311. ULONG getcamg(struct ILBMInfo *ilbm)
  312.     {
  313.     struct IFFHandle *iff;
  314.     struct StoredProperty *sp;
  315.     UWORD  wide,high,deep;
  316.     ULONG modeid = 0L;
  317.  
  318.         if(!(iff=ilbm->ParseInfo.iff))    return(0L);
  319.  
  320.     wide = ilbm->Bmhd.pageWidth;
  321.     high = ilbm->Bmhd.pageHeight;
  322.     deep = ilbm->Bmhd.nPlanes;
  323.  
  324.     D(bug("Getting CAMG for w=%ld h=%ld d=%ld ILBM\n",wide,high,deep));
  325.  
  326.         /*
  327.          * Grab CAMG's idea of the viewmodes.
  328.          */
  329.         if (sp = FindProp (iff, ID_ILBM, ID_CAMG))
  330.                 {
  331.                 modeid = (* (ULONG *) sp->sp_Data);
  332.  
  333.                 /* knock bad bits out of old-style 16-bit viewmode CAMGs
  334.                  */
  335.                 if((!(modeid & MONITOR_ID_MASK))||
  336.           ((modeid & EXTENDED_MODE)&&(!(modeid & 0xFFFF0000))))
  337.                    modeid &= 
  338.             (~(EXTENDED_MODE|SPRITES|GENLOCK_AUDIO|GENLOCK_VIDEO|VP_HIDE));
  339.  
  340.                 /* check for bogus CAMG like DPaintII brushes
  341.                  * with junk in upper word and extended bit
  342.                  * not set in lower word.
  343.                  */
  344.                 if((modeid & 0xFFFF0000)&&(!(modeid & 0x00001000))) sp=NULL;
  345.                 }
  346.  
  347.         if(!sp) {
  348.                 /*
  349.                  * No CAMG (or bad CAMG) present; use computed modes.
  350.                  */
  351.                 if (wide >= 640)        modeid = HIRES;
  352.                 if (high >= 400)        modeid |= LACE;
  353.                 if (deep == 6)
  354.                         {
  355.                         modeid |= ilbm->EHB ? EXTRA_HALFBRITE : HAM;
  356.                         }
  357.         D(bug("No CAMG found - using mode $%08lx\n",modeid));
  358.                 }
  359.  
  360.     D(bug("getcamg: modeid = $%08lx\n",modeid));
  361.     return(modeid);
  362.     }
  363.