home *** CD-ROM | disk | FTP | other *** search
/ Graphics 16,000 / graphics-16000.iso / amiga / fractal / mandlsqr / source / playanim / prelodnm.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-01-05  |  11.6 KB  |  423 lines

  1. /** PreLoadAnim.c ***********************************************************
  2.  *
  3.  * Load an ILBM raster image file into memory structures
  4.  * This is a modified version of ReadPict.c dated 23-Jan-86.
  5.  *
  6.  * Modified by Gary Bonham, SPARTA, Inc.  15 Aug 1986
  7.  * Modified by Olaf `Olsen' Barthel, 16-Sep-1991
  8.  *
  9.  ***************************************************************************/
  10.  
  11. #include <intuition/intuition.h>
  12. #include <libraries/dosextens.h>
  13. #include <exec/memory.h>
  14.  
  15. #include "ilbm.h"
  16. #include "readpict.h"
  17. #include "preloadanim.h"
  18.  
  19. /* This example's max number of planes in a bitmap. Could use MaxAmDepth. */
  20.  
  21. #define EXDepth 5
  22. #define maxColorReg (1 << EXDepth)
  23.  
  24. #define GetANHD(context,anHdr) IFFReadBytes(context,(BYTE *)anHdr,sizeof(AnimationHeader))
  25.  
  26. STATIC IFFP         GetCMAP(GroupContext *ilbmContext,WORD *colorMap,UBYTE *pNColorRegs);
  27. STATIC IFFP         GetPrILBM(GroupContext *parent);
  28. STATIC IFFP         GetLiILBM(GroupContext *parent);
  29. STATIC IFFP         GetFoANIM(GroupContext *parent);
  30. STATIC IFFP __regargs     PreLoadAnimation(BPTR file,ILBMFrame *iFrame);
  31. VOID             ClosePreLoadIFF(VOID);
  32. BYTE             OpenPreLoadIFF(BPTR file);
  33.  
  34. extern struct Screen    *Screen;
  35. struct IFFfile        *IFFfileList;
  36.  
  37. /*------------ ILBM reader -----------------------------------------------*/
  38. /* ILBMFrame is our "client frame" for reading FORMs ILBM in an IFF file.
  39.  * We allocate one of these on the stack for every LIST or FORM encountered
  40.  * in the file and use it to hold BMHD & CMAP properties. We also allocate
  41.  * an initial one for the whole file.
  42.  * We allocate a new GroupContext (and initialize it by OpenRIFF or
  43.  * OpenRGroup) for every group (FORM, CAT, LIST, or PROP) encountered. It's
  44.  * just a context for reading (nested) chunks.
  45.  *
  46.  * If we were to scan the entire example file outlined below:
  47.  *    reading          proc(s)                new               new
  48.  *
  49.  * --whole file--   ReadPicture+ReadIFF   GroupContext        ILBMFrame
  50.  * CAT              ReadICat                GroupContext
  51.  *   LIST           GetLiILBM+ReadIList       GroupContext        ILBMFrame
  52.  *     PROP ILBM    GetPrILBM                   GroupContext
  53.  *       CMAP       GetCMAP
  54.  *       BMHD       GetBMHD
  55.  *     FORM ILBM    GetFoILBM                   GroupContext        ILBMFrame
  56.  *       BODY       GetBODY
  57.  *     FORM ILBM    GetFoILBM                   GroupContext        ILBMFrame
  58.  *       BODY       GetBODY
  59.  *   FORM ILBM      GetFoILBM                 GroupContext        ILBMFrame
  60.  */
  61.  
  62. /* ---------- GetCMAP ------------------------------------------------*/
  63. /* pNColorRegs is passed in as a pointer to the number of ColorRegisters
  64.  * caller has space to hold.  GetCMAP sets to the number actually read.*/
  65.  
  66. STATIC IFFP
  67. GetCMAP(GroupContext *ilbmContext,WORD *colorMap,UBYTE *pNColorRegs)
  68. {
  69.     ColorRegister    colorReg;
  70.     LONG        nColorRegs;
  71.     IFFP        iffp;
  72.  
  73.     nColorRegs = ilbmContext -> ckHdr . ckSize / sizeof(ColorRegister);
  74.  
  75.     if(*pNColorRegs < nColorRegs)
  76.         nColorRegs = *pNColorRegs;
  77.  
  78.     *pNColorRegs = nColorRegs;    /* Set to the number actually there.*/
  79.  
  80.     while(nColorRegs--)
  81.     {
  82.         iffp = IFFReadBytes(ilbmContext,(BYTE *)&colorReg,sizeof(ColorRegister));
  83.  
  84.         CheckIFFP();
  85.  
  86.         *colorMap++ = ((UWORD)(colorReg . red >> 4 ) << 8 ) | ((UWORD)(colorReg . green & 0x0F0)) | ((UWORD)(colorReg . blue >> 4));
  87.     }
  88.  
  89.     return(IFF_OKAY);
  90. }
  91.  
  92. /** GetPrILBM() *************************************************************
  93.  *
  94.  * Called via ReadPicture to handle every PROP encountered in an IFF file.
  95.  * Reads PROPs ILBM and skips all others.
  96.  *
  97.  ****************************************************************************/
  98.  
  99. STATIC IFFP
  100. GetPrILBM(GroupContext *parent)
  101. {
  102.     IFFP         iffp;
  103.     GroupContext     propContext;
  104.     ILBMFrame    *ilbmFrame = (ILBMFrame *)parent -> clientFrame;
  105.  
  106.     if(parent -> subtype != ID_ILBM)
  107.         return(IFF_OKAY);    /* just continue scanning the file */
  108.  
  109.     iffp = OpenRGroup(parent,&propContext);
  110.  
  111.     CheckIFFP();
  112.  
  113.     do
  114.     {
  115.         switch(iffp = GetPChunkHdr(&propContext))
  116.         {
  117.             case ID_BMHD:
  118.             {
  119.                 ilbmFrame -> foundBMHD = TRUE;
  120.  
  121.                 iffp = GetBMHD(&propContext,&ilbmFrame -> bmHdr);
  122.                 break;
  123.             }
  124.  
  125.             case ID_CMAP:
  126.             {
  127.                 ilbmFrame -> nColorRegs = maxColorReg;
  128.  
  129.                 iffp = GetCMAP(&propContext,(WORD *)&ilbmFrame -> colorMap,&ilbmFrame -> nColorRegs);
  130.                 break;
  131.             }
  132.         }
  133.     }
  134.     while(iffp >= IFF_OKAY);    /* loop if valid ID of ignored chunk or a
  135.                      * subroutine returned IFF_OKAY (no errors).
  136.                      */
  137.  
  138.     CloseRGroup(&propContext);
  139.  
  140.     return(iffp == END_MARK ? IFF_OKAY : iffp);
  141. }
  142.  
  143. /** GetLiILBM() *************************************************************
  144.  *
  145.  * Called via ReadPicture to handle every LIST encountered in an IFF file.
  146.  *
  147.  ****************************************************************************/
  148.  
  149. STATIC IFFP
  150. GetLiILBM(GroupContext *parent)
  151. {
  152.     ILBMFrame newFrame;    /* allocate a new Frame */
  153.  
  154.     newFrame = *(ILBMFrame *)parent -> clientFrame;    /* copy parent frame */
  155.  
  156.     return(ReadIList(parent,(ClientFrame *)&newFrame));
  157. }
  158.  
  159. /** GetFoANIM() *************************************************************
  160.  *
  161.  * Called via ReadPicture to handle every FORM encountered in an IFF file.
  162.  * Reads FORMs ILBM and skips all others.
  163.  * Inside a FORM ILBM, it stops once it reads a BODY. It complains if it
  164.  * finds no BODY or if it has no BMHD to decode the BODY.
  165.  *
  166.  * Once we find a BODY chunk, we'll allocate the BitMap and read the image.
  167.  *
  168.  ****************************************************************************/
  169.  
  170. STATIC IFFP
  171. GetFoANIM(GroupContext *parent)
  172. {
  173.     IFFP        iffp;
  174.     GroupContext    formContext;
  175.     ILBMFrame    ilbmFrame;    /* only used for non-clientFrame fields.*/
  176.  
  177.     /* Handle a non-ILBM FORM. */
  178.  
  179.     if(parent -> subtype != ID_ILBM)
  180.     {
  181.         /* Open a non-ILBM FORM and recursively scan it for ILBMs.*/
  182.  
  183.         iffp = OpenRGroup(parent,&formContext);
  184.  
  185.         CheckIFFP();
  186.  
  187.         do
  188.         {
  189.             iffp = GetF1ChunkHdr(&formContext);
  190.  
  191.             if(iffp == IFF_DONE)
  192.                 iffp = IFF_OKAY;
  193.         }
  194.         while(iffp >= IFF_OKAY);
  195.  
  196.         if(iffp == END_MARK)
  197.             iffp = IFF_DONE;    /* then continue scanning the file */
  198.  
  199.         CloseRGroup(&formContext);
  200.         return(iffp);
  201.     }
  202.  
  203.     ilbmFrame = *(ILBMFrame *)parent -> clientFrame;
  204.  
  205.     iffp = OpenRGroup(parent,&formContext);
  206.  
  207.     CheckIFFP();
  208.  
  209.     if(!IFFfileList -> lastframe)
  210.     {
  211.         IFFfileList -> lastframe    = (struct FrameHD *)AllocMem(sizeof(struct FrameHD),MEMF_PUBLIC|MEMF_CLEAR);
  212.         IFFfileList -> firstframe    = IFFfileList -> lastframe;
  213.     }
  214.     else
  215.     {
  216.         if(IFFfileList -> lastframe -> next = (struct FrameHD *)AllocMem(sizeof(struct FrameHD),MEMF_PUBLIC|MEMF_CLEAR))
  217.             IFFfileList -> lastframe -> next -> prev = IFFfileList -> lastframe;
  218.  
  219.         IFFfileList -> lastframe    = IFFfileList -> lastframe -> next;
  220.     }
  221.  
  222.     if(!IFFfileList -> lastframe)
  223.         return(END_MARK);
  224.  
  225.     do
  226.     {
  227.         switch(iffp = GetFChunkHdr(&formContext))
  228.         {
  229.             case ID_ANHD:
  230.             {
  231.                 ilbmFrame . foundBMHD = TRUE;
  232.  
  233.                 if(!(IFFfileList -> lastframe -> anhd = (AnimationHeader *)AllocMem(sizeof(AnimationHeader),MEMF_PUBLIC|MEMF_CLEAR)))
  234.                 {
  235.                     iffp = DOS_ERROR;
  236.                     break;
  237.                 }
  238.  
  239.                 iffp = GetANHD(&formContext,IFFfileList -> lastframe -> anhd);
  240.                 break;
  241.             }
  242.  
  243.             case ID_BMHD:
  244.             {
  245.                 ilbmFrame . foundBMHD = TRUE;
  246.  
  247.                 if(!(IFFfileList -> lastframe -> bmhd = (BitMapHeader *)AllocMem(sizeof(BitMapHeader),MEMF_PUBLIC|MEMF_CLEAR)))
  248.                 {
  249.                     iffp = DOS_ERROR;
  250.  
  251.                     break;
  252.                 }
  253.                 else
  254.                 {
  255.                     iffp = GetBMHD(&formContext,IFFfileList -> lastframe -> bmhd);
  256.  
  257.                     if(IFFfileList -> lastframe -> bmhd -> pageHeight < IFFfileList -> lastframe -> bmhd -> h)
  258.                         IFFfileList -> lastframe -> bmhd -> pageHeight = IFFfileList -> lastframe -> bmhd -> h;
  259.  
  260.                     if(IFFfileList -> lastframe -> bmhd -> pageWidth < IFFfileList -> lastframe -> bmhd -> w)
  261.                         IFFfileList -> lastframe -> bmhd -> pageWidth = IFFfileList -> lastframe -> bmhd -> w;
  262.  
  263.                     if(IFFfileList -> lastframe -> bmhd -> pageHeight != Screen -> Height || IFFfileList -> lastframe -> bmhd -> pageWidth != Screen -> Width || IFFfileList -> lastframe -> bmhd -> nPlanes != Screen -> RastPort . BitMap -> Depth)
  264.                         iffp = DOS_ERROR;
  265.  
  266.                     break;
  267.                 }
  268.             }
  269.  
  270.             case ID_CAMG:
  271.             {
  272.                 ilbmFrame . foundCAMG = TRUE;
  273.  
  274.                 if(!(IFFfileList -> lastframe -> camg = (CamgChunk *)AllocMem(sizeof(CamgChunk),MEMF_PUBLIC|MEMF_CLEAR)))
  275.                 {
  276.                     iffp = DOS_ERROR;
  277.  
  278.                     break;
  279.                 }
  280.                 else
  281.                 {
  282.                     iffp = GetCAMG(&formContext,IFFfileList -> lastframe -> camg);
  283.                     break;
  284.                 }
  285.             }
  286.  
  287.             case ID_CMAP:
  288.             {
  289.                 IFFfileList -> lastframe -> nColorRegs = maxColorReg;    /* we have room for this many */
  290.  
  291.                 iffp = GetCMAP(&formContext,&IFFfileList -> lastframe -> cmap[0],&IFFfileList -> lastframe -> nColorRegs);
  292.                 break;
  293.             }
  294.  
  295.             case ID_DLTA:    /* at this point just read in delta chunk */
  296.             case ID_BODY:
  297.             {
  298.                 if(!ilbmFrame . foundBMHD)
  299.                     return(BAD_FORM);    /* No BMHD chunk! */
  300.  
  301.                 if(IFFfileList -> lastframe -> bodylength = formContext . ckHdr . ckSize)
  302.                 {
  303.                     if(!(IFFfileList -> lastframe -> body = (ULONG *)AllocMem(IFFfileList -> lastframe -> bodylength,MEMF_PUBLIC|MEMF_CLEAR)))
  304.                     {
  305.                         iffp = END_MARK;
  306.  
  307.                         break;
  308.                     }
  309.  
  310.                     IFFReadBytes(&formContext,(BYTE *)IFFfileList -> lastframe -> body,IFFfileList -> lastframe -> bodylength);
  311.                 }
  312.  
  313.                 break;
  314.             }
  315.  
  316.             case END_MARK:    /* No BODY chunk! */
  317.             {
  318.                 iffp = IFF_DONE;
  319.                 break;
  320.             }
  321.         }
  322.     }
  323.     while(iffp >= IFF_OKAY);    /* loop if valid ID of ignored chunk or a
  324.                      * subroutine returned IFF_OKAY (no errors).
  325.                      */
  326.  
  327.     if(iffp != IFF_DONE)
  328.         return(iffp);
  329.  
  330.     /* If we get this far, there were no errors. */
  331.  
  332.     CloseRGroup(&formContext);
  333.  
  334.     return(iffp);
  335. }
  336.  
  337. STATIC IFFP __regargs
  338. PreLoadAnimation(BPTR file,ILBMFrame *iFrame)
  339. {
  340.     iFrame -> clientFrame . getList    = GetLiILBM;
  341.     iFrame -> clientFrame . getProp    = GetPrILBM;
  342.     iFrame -> clientFrame . getForm    = GetFoANIM;
  343.     iFrame -> clientFrame . getCat    = ReadICat ;
  344.  
  345.     /* Initialize the top-level client frame's property settings to the
  346.      * program-wide defaults. This example just records that we haven't read
  347.      * any BMHD property or CMAP color registers yet. For the color map, that
  348.      * means the default is to leave the machine's color registers alone.
  349.      * If you want to read a property like GRAB, init it here to (0, 0).
  350.      */
  351.  
  352.     iFrame -> foundBMHD    = FALSE;
  353.     iFrame -> nColorRegs    = 0;
  354.  
  355.     /* Store a pointer to the client's frame in a global variable so that
  356.      * GetFoILBM can update client's frame when done.  Why do we have so
  357.      * many frames & frame pointers floating around causing confusion?
  358.      * Because IFF supports PROPs which apply to all FORMs in a LIST,
  359.      * unless a given FORM overrides some property.
  360.      * When you write code to read several FORMs,
  361.      * it is ssential to maintain a frame at each level of the syntax
  362.      * so that the properties for the LIST don't get overwritten by any
  363.      * properties specified by individual FORMs.
  364.      * We decided it was best to put that complexity into this one-FORM example,
  365.      * so that those who need it later will have a useful starting place.
  366.      */
  367.  
  368.     if(IFFfileList = (struct IFFfile *)AllocMem(sizeof(struct IFFfile),MEMF_PUBLIC|MEMF_CLEAR))
  369.         return(ReadIFF(file,(ClientFrame *)iFrame));
  370.     else
  371.         return(DOS_ERROR);
  372. }
  373.  
  374. VOID
  375. ClosePreLoadIFF()
  376. {
  377.     if(IFFfileList)
  378.     {
  379.         struct FrameHD *currentframe,*nextframe;
  380.  
  381.         currentframe = IFFfileList -> firstframe;
  382.  
  383.         while(currentframe)
  384.         {
  385.             if(currentframe -> bmhd)
  386.                 FreeMem(currentframe -> bmhd,sizeof(BitMapHeader));
  387.  
  388.             if(currentframe -> anhd)
  389.                 FreeMem(currentframe -> anhd,sizeof(AnimationHeader));
  390.             if(currentframe -> camg)
  391.                 FreeMem(currentframe -> camg,sizeof(CamgChunk));
  392.  
  393.             if(currentframe -> body && currentframe -> bodylength)
  394.                 FreeMem(currentframe -> body,currentframe -> bodylength);
  395.  
  396.             nextframe = currentframe -> next;
  397.  
  398.             FreeMem(currentframe,sizeof(struct FrameHD));
  399.  
  400.             currentframe = nextframe;
  401.         }
  402.  
  403.         FreeMem(IFFfileList,sizeof(struct IFFfile));
  404.  
  405.         IFFfileList = NULL;
  406.     }
  407. }
  408.  
  409. BYTE
  410. OpenPreLoadIFF(BPTR file)
  411. {
  412.     ILBMFrame iframe;
  413.  
  414.     if(PreLoadAnimation(file,&iframe) != IFF_DONE)
  415.     {
  416.         ClosePreLoadIFF();
  417.  
  418.         return(FALSE);
  419.     }
  420.     else
  421.         return(TRUE);
  422. }
  423.