home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 2 / FFMCD02.bin / new / gfx / edit / tsmorph / ilbmr.c < prev    next >
C/C++ Source or Header  |  1993-12-21  |  11KB  |  385 lines

  1. //    $Author: M_J_Paddock $
  2. //    $Date: 1992/08/08 01:05:50 $
  3. //    $Revision: 1.4 $
  4.  
  5. /* ilbmr.c --- ILBM loading routines for use with iffparse */
  6.  
  7. /*----------------------------------------------------------------------*
  8.  * ILBMR.C  Support routines for reading ILBM files.
  9.  * (IFF is Interchange Format File.)
  10.  *
  11.  * Based on code by Jerry Morrison and Steve Shaw, Electronic Arts.
  12.  * This software is in the public domain.
  13.  * Modified for iffparse.library 05/90
  14.  * This version for the Commodore-Amiga computer.
  15.  *
  16.  * 37.9 04/92
  17.  *----------------------------------------------------------------------*/
  18.  
  19. // Minor changes to error handling and other stuff MJP
  20.  
  21. #define INTUI_V36_NAMES_ONLY
  22.  
  23. #include "iffp/ilbm.h"
  24. #include "iffp/packer.h"
  25. #include "iffp/ilbmapp.h"
  26.  
  27. #define movmem CopyMem
  28.  
  29. #define MaxSrcPlanes (25)
  30.  
  31. extern struct Library *GfxBase;
  32.  
  33. /*---------- loadbody ---------------------------------------------------*/
  34.  
  35. LONG loadbody(iff, bitmap, bmhd)
  36. struct IFFHandle *iff;
  37. struct BitMap *bitmap;
  38. BitMapHeader *bmhd;
  39.     {
  40.     BYTE *buffer;
  41.     ULONG bufsize;
  42.     LONG error = 1;
  43.  
  44.     D(bug("In loadbody\n"));
  45.  
  46.     if(!(currentchunkis(iff,ID_ILBM,ID_BODY)))
  47.         {
  48.         message(SI(MSG_IFFP_NOBODY),NULL,4);    /* Maybe it's a palette */        // MJP 4 = HE_IFFBODY
  49.         return(IFF_OKAY);
  50.         }
  51.  
  52.     if((bitmap)&&(bmhd))
  53.         {
  54.         D(bug("Have bitmap and bmhd\n"));
  55.  
  56.         bufsize = MaxPackedSize(RowBytes(bmhd->w)) << 4;
  57.             if(!(buffer = AllocMem(bufsize,0L)))
  58.         {
  59.         D(bug("Buffer alloc of %ld failed\n",bufsize));
  60.         return(IFFERR_NOMEM);
  61.         }
  62.         error = loadbody2(iff, bitmap, NULL, bmhd, buffer, bufsize);
  63.         D(bug("Returned from getbody, error = %ld\n",error));
  64.         }
  65.     FreeMem(buffer,bufsize);
  66.     return(error);
  67.     }
  68.  
  69.  
  70. /* like the old GetBODY */
  71. LONG loadbody2(iff, bitmap, mask, bmhd, buffer, bufsize)
  72. struct IFFHandle *iff;
  73. struct BitMap *bitmap;
  74. BYTE *mask;
  75. BitMapHeader *bmhd;
  76. BYTE *buffer;
  77. ULONG bufsize;
  78.    {
  79.    UBYTE srcPlaneCnt = bmhd->nPlanes;   /* Haven't counted for mask plane yet*/
  80.    WORD srcRowBytes = RowBytes(bmhd->w);
  81.    WORD destRowBytes = bitmap->BytesPerRow;
  82.    LONG bufRowBytes = MaxPackedSize(srcRowBytes);
  83.    int nRows = bmhd->h;
  84.    WORD compression = bmhd->compression;
  85.    register int iPlane, iRow, nEmpty;
  86.    register WORD nFilled;
  87.    BYTE *buf, *nullDest, *nullBuf, **pDest;
  88.    BYTE *planes[MaxSrcPlanes]; /* array of ptrs to planes & mask */
  89.    struct ContextNode *cn;
  90.  
  91.    D(bug("srcRowBytes = %ld\n",srcRowBytes));
  92.  
  93.    cn = CurrentChunk(iff);
  94.  
  95.    if (compression > cmpByteRun1)
  96.       return(CLIENT_ERROR);
  97.  
  98.    D(bug("loadbody2: compression=%ld srcBytes=%ld bitmapBytes=%ld\n",
  99.         compression, srcRowBytes, bitmap->BytesPerRow));
  100.    D(bug("loadbody2: bufsize=%ld bufRowBytes=%ld, srcPlaneCnt=%ld\n",
  101.             bufsize, bufRowBytes, srcPlaneCnt));
  102.  
  103.    /* Complain if client asked for a conversion GetBODY doesn't handle.*/
  104.    if ( srcRowBytes  >  bitmap->BytesPerRow  ||
  105.          bufsize < bufRowBytes * 2  ||
  106.          srcPlaneCnt > MaxSrcPlanes )
  107.       return(CLIENT_ERROR);
  108.  
  109.    D(bug("loadbody2: past conversion checks\n"));
  110.  
  111.    if (nRows > bitmap->Rows)   nRows = bitmap->Rows;
  112.  
  113.    D(bug("loadbody2: srcRowBytes=%ld, srcRows=%ld, srcDepth=%ld, destDepth=%ld\n",
  114.         srcRowBytes, nRows, bmhd->nPlanes, bitmap->Depth));
  115.    
  116.    /* Initialize array "planes" with bitmap ptrs; NULL in empty slots.*/
  117.    for (iPlane = 0; iPlane < bitmap->Depth; iPlane++)
  118.       planes[iPlane] = (BYTE *)bitmap->Planes[iPlane];
  119.    for ( ;  iPlane < MaxSrcPlanes;  iPlane++)
  120.       planes[iPlane] = NULL;
  121.  
  122.    /* Copy any mask plane ptr into corresponding "planes" slot.*/
  123.    if (bmhd->masking == mskHasMask)
  124.     {
  125.           if (mask != NULL)
  126.              planes[srcPlaneCnt] = mask;  /* If there are more srcPlanes than
  127.                * dstPlanes, there will be NULL plane-pointers before this.*/
  128.           else
  129.              planes[srcPlaneCnt] = NULL;  /* In case more dstPlanes than src.*/
  130.           srcPlaneCnt += 1;  /* Include mask plane in count.*/
  131.           }
  132.  
  133.    /* Setup a sink for dummy destination of rows from unwanted planes.*/
  134.    nullDest = buffer;
  135.    buffer  += srcRowBytes;
  136.    bufsize -= srcRowBytes;
  137.  
  138.    /* Read the BODY contents into client's bitmap.
  139.     * De-interleave planes and decompress rows.
  140.     * MODIFIES: Last iteration modifies bufsize.*/
  141.  
  142.    buf = buffer + bufsize;  /* Buffer is currently empty.*/
  143.    for (iRow = nRows; iRow > 0; iRow--)
  144.     {
  145.           for (iPlane = 0; iPlane < srcPlaneCnt; iPlane++)
  146.         {
  147.          pDest = &planes[iPlane];
  148.  
  149.             /* Establish a sink for any unwanted plane.*/
  150.             if (*pDest == NULL)
  151.         {
  152.             nullBuf = nullDest;
  153.                 pDest   = &nullBuf;
  154.                 }
  155.  
  156.             /* Read in at least enough bytes to uncompress next row.*/
  157.             nEmpty  = buf - buffer;      /* size of empty part of buffer.*/
  158.             nFilled = bufsize - nEmpty;      /* this part has data.*/
  159.         if (nFilled < bufRowBytes)
  160.         {
  161.             /* Need to read more.*/
  162.  
  163.             /* Move the existing data to the front of the buffer.*/
  164.             /* Now covers range buffer[0]..buffer[nFilled-1].*/
  165.                 movmem(buf, buffer, nFilled);  /* Could be moving 0 bytes.*/
  166.  
  167.                 if(nEmpty > ChunkMoreBytes(cn))
  168.             {
  169.                        /* There aren't enough bytes left to fill the buffer.*/
  170.                        nEmpty = ChunkMoreBytes(cn);
  171.                        bufsize = nFilled + nEmpty;  /* heh-heh */
  172.                        }
  173.  
  174.             /* Append new data to the existing data.*/
  175.                 if(ReadChunkBytes(iff, &buffer[nFilled], nEmpty) < nEmpty)
  176.             return(CLIENT_ERROR);
  177.  
  178.                 buf     = buffer;
  179.             nFilled = bufsize;
  180.             nEmpty  = 0;
  181.             }
  182.  
  183.          /* Copy uncompressed row to destination plane.*/
  184.             if(compression == cmpNone)
  185.         {
  186.                 if(nFilled < srcRowBytes)  return(IFFERR_MANGLED);
  187.             movmem(buf, *pDest, srcRowBytes);
  188.             buf    += srcRowBytes;
  189.                 *pDest += destRowBytes;
  190.                 }
  191.         else
  192.         {
  193.              /* Decompress row to destination plane.*/
  194.                 if ( unpackrow(&buf, pDest, nFilled,  srcRowBytes) )
  195.                     /*  pSource, pDest, srcBytes, dstBytes  */
  196.                        return(IFFERR_MANGLED);
  197.             else *pDest += (destRowBytes - srcRowBytes);
  198.         }
  199.         }
  200.     }
  201.    return(IFF_OKAY);
  202.    }
  203.  
  204.  
  205. /* ----------- getcolors ------------- */
  206.  
  207. /* getcolors - allocates a ilbm->colortable for at least 32 registers
  208.  *      and loads CMAP colors into it, setting ilbm->ncolors to number
  209.  *      of colors actually loaded.
  210.  */ 
  211. LONG getcolors(struct ILBMInfo *ilbm)
  212.     {
  213.     struct IFFHandle    *iff;
  214.     int error = 1;
  215.  
  216.     if(!(iff=ilbm->ParseInfo.iff))    return(CLIENT_ERROR);
  217.  
  218.     if(!(error = alloccolortable(ilbm)))
  219.        error = loadcmap(iff, ilbm->colortable, &ilbm->ncolors,ilbm);
  220.     if(error) freecolors(ilbm);
  221.     D(bug("getcolors: error = %ld\n",error));
  222.     return(error);
  223.     }
  224.  
  225. /* alloccolortable - allocates ilbm->colortable and sets ilbm->ncolors
  226.  *    to the number of colors we have room for in the table.
  227.  */ 
  228.  
  229. LONG alloccolortable(struct ILBMInfo *ilbm)
  230.     {
  231.     struct IFFHandle    *iff;
  232.     struct    StoredProperty    *sp;
  233.  
  234.     LONG    error = CLIENT_ERROR;
  235.     ULONG    ctabsize;
  236.     USHORT    ncolors;
  237.  
  238.     if(!(iff=ilbm->ParseInfo.iff))    return(CLIENT_ERROR);
  239.  
  240.     if(sp = FindProp (iff, ID_ILBM, ID_CMAP))
  241.         {
  242.         /*
  243.          * Compute the size table we need
  244.          */
  245.         ncolors = sp->sp_Size / 3;        /* how many in CMAP */
  246. //        ncolors = MAX(ncolors, 32);    MJP - may be more than 32 colours
  247.  
  248.         ctabsize = ncolors * sizeof(Color4);
  249.         if ((ilbm->colortable = 
  250.            (Color4 *)AllocMem(ctabsize,MEMF_CLEAR|MEMF_PUBLIC)) &&    // MJP
  251.            (ilbm->RGB = AllocMem(ncolors*4,MEMF_CLEAR|MEMF_PUBLIC))) // RGB colors
  252.             {
  253.             ilbm->ncolors = ncolors;
  254.             ilbm->ctabsize = ctabsize;
  255.             error = 0L;
  256.             }
  257.         else {
  258.              error = IFFERR_NOMEM;
  259.             if (ilbm->colortable) {
  260.                 FreeMem(ilbm->colortable,ctabsize);
  261.                 ilbm->colortable = NULL;
  262.             }
  263.         }
  264.     }
  265.     D(bug("alloccolortable for %ld colors: error = %ld\n",ncolors,error));
  266.     return(error);
  267.     }
  268.  
  269.  
  270. void freecolors(struct ILBMInfo *ilbm)
  271.     {
  272.     if(ilbm->colortable)
  273.         {
  274.         FreeMem(ilbm->colortable, ilbm->ctabsize);
  275.         }
  276.     if (ilbm->RGB) {
  277.         FreeMem(ilbm->RGB,ilbm->ncolors*4);
  278.     }
  279.     ilbm->RGB = NULL;
  280.     ilbm->colortable = NULL;
  281.     ilbm->ctabsize = 0;
  282.     }
  283.  
  284.  
  285.  
  286. /* Passed IFFHandle, pointer to colortable array, and pointer to
  287.  * a USHORT containing nu