home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d1xx / d185 / iff.lha / EXAMPLES / Display / myreadpict.c < prev    next >
C/C++ Source or Header  |  1988-12-13  |  13KB  |  365 lines

  1. /** myReadPict.c ************************************************************
  2.  *
  3.  * Read an ILBM raster image file.               23-Jan-86.
  4.  *
  5.  * Modified version of ReadPict.c 
  6.  *   by Jerry Morrison, Steve Shaw, and Steve Hayes, Electronic Arts.
  7.  *   This software is in the public domain.
  8.  *
  9.  * Modified by C. Scheppner  11/86
  10.  *   Handles CAMG chunks for HAM, etc.
  11.  *   Calls user defined routine getBitMap(ilbmFramePtr) when it
  12.  *      reaches the BODY.
  13.  *   getBitMap() can open a screen of the correct size using
  14.  *      information this rtn places in the ilbmFrame, and returns
  15.  *      a pointer to a BitMap structure.  The BitMap structure
  16.  *      tells myReadPicture where it should load the bit planes.
  17.  *
  18.  * Modified by C. Scheppner  12/86
  19.  *   Loads in CCRT or CRNG chunks (converts CCRT to CRNG)
  20.  * Modified 11-88 to use CCRT, CAMG defs and macros added to ilbm.h
  21.  *                 and existing CRange (not CrngChunk) def in ilbm.h
  22.  ****************************************************************************/
  23.  
  24. #define LOCAL   static
  25.  
  26. #include "intuition/intuition.h"
  27. #include "libraries/dos.h"
  28. #include "libraries/dosextens.h"
  29. #include "iff/ilbm.h"
  30. #include "myreadpict.h"    /* cs */
  31.  
  32. /* Define size of a temporary buffer used in unscrambling the ILBM rows.*/
  33. #define bufSz 512
  34.  
  35. /*------------ ILBM reader -----------------------------------------------*/
  36. /* ILBMFrame is our "client frame" for reading FORMs ILBM in an IFF file.
  37.  * We allocate one of these on the stack for every LIST or FORM encountered
  38.  * in the file and use it to hold BMHD & CMAP properties. We also allocate
  39.  * an initial one for the whole file.
  40.  * We allocate a new GroupContext (and initialize it by OpenRIFF or
  41.  * OpenRGroup) for every group (FORM, CAT, LIST, or PROP) encountered. It's
  42.  * just a context for reading (nested) chunks.
  43.  *
  44.  * If we were to scan the entire example file outlined below:
  45.  *    reading          proc(s)                new               new
  46.  *
  47.  * --whole file--   myReadPicture+ReadIFF GroupContext        ILBMFrame
  48.  * CAT              ReadICat                GroupContext
  49.  *   LIST           GetLiILBM+ReadIList       GroupContext        ILBMFrame
  50.  *     PROP ILBM    GetPrILBM                   GroupContext
  51.  *       CMAP       GetCMAP
  52.  *       BMHD       GetBMHD
  53.  *     FORM ILBM    GetFoILBM                   GroupContext        ILBMFrame
  54.  *       BODY       GetBODY
  55.  *     FORM ILBM    GetFoILBM                   GroupContext        ILBMFrame
  56.  *       BODY       GetBODY
  57.  *   FORM ILBM      GetFoILBM                 GroupContext        ILBMFrame
  58.  */
  59.  
  60. /* NOTE: For a small version of this program, set Fancy to 0.
  61.  * That'll compile a program that reads a single FORM ILBM in a file, which
  62.  * is what DeluxePaint produces. It'll skip all LISTs and PROPs in the input
  63.  * file. It will, however, look inside a CAT for a FORM ILBM.
  64.  * That's suitable for 90% of the uses.
  65.  *
  66.  * For a fancier version that handles LISTs and PROPs, set Fancy to 1.
  67.  * That'll compile a program that dives into a LIST, if present, to read
  68.  * the first FORM ILBM. E.g. a DeluxePrint library of images is a LIST of
  69.  * FORMs ILBM.
  70.  *
  71.  * For an even fancier version, set Fancy to 2. That'll compile a program
  72.  * that dives into non-ILBM FORMs, if present, looking for a nested FORM ILBM.
  73.  * E.g. a DeluxeVideo C.S. animated object file is a FORM ANBM containing a
  74.  * FORM ILBM for each image frame. */
  75. #define Fancy  0
  76.  
  77. /* Global access to client-provided pointers.*/
  78. LOCAL ILBMFrame *giFrame = NULL;   /* "client frame".*/
  79.  
  80.  
  81.  
  82. IFFP handleCAMG(context,frame)
  83. GroupContext *context;
  84. ILBMFrame    *frame;
  85.    {
  86.    IFFP iffp = IFF_OKAY;
  87.  
  88.    frame->foundCAMG = TRUE;
  89.    iffp = GetCAMG(context, &frame->camgChunk);
  90.    return(iffp);
  91.    }
  92.  
  93. IFFP handleCRNG(context,frame)
  94. GroupContext *context;
  95. ILBMFrame    *frame;
  96.    {
  97.    IFFP iffp = IFF_OKAY;
  98.  
  99.    if(frame->cycleCnt < maxCycles)
  100.       {
  101.       iffp = GetCRNG(context,&(frame->crngChunks[frame->cycleCnt]));
  102.       frame->cycleCnt++;
  103.       }
  104.    return(iffp);
  105.    }
  106.  
  107.  
  108. IFFP handleCCRT(context,frame)
  109. GroupContext *context;
  110. ILBMFrame    *frame;
  111.    {
  112.    CcrtChunk  ccrtTmp;
  113.    CRange  *ptCrng;
  114.    IFFP iffp = IFF_OKAY;
  115.  
  116.    if(frame->cycleCnt < maxCycles)
  117.       {
  118.       iffp = GetCCRT(context, &ccrtTmp);
  119.       ptCrng = &(frame->crngChunks[frame->cycleCnt]);
  120.       if(ccrtTmp.direction)  ccrtTmp.direction = -ccrtTmp.direction;
  121.       ptCrng->active = ccrtTmp.direction & 0x03;
  122.       ptCrng->low = ccrtTmp.start;
  123.       ptCrng->high = ccrtTmp.end;
  124.  
  125.       /* Convert  CCRT secs/msecs to CRNG timimg
  126.        * 0x4000 = max CRNG rate  (cycle every 1 60th sec)
  127.        * This must be divided by # 60th's between cycles
  128.        * seconds to 60th's is easy
  129.        * msecs to 60th's requires division by 16667
  130.        * this is int math so I add 8334 (half 16667) first for rounding
  131.        */
  132.       ptCrng->rate = 0x4000 /
  133.          ((ccrtTmp.seconds * 60)+((ccrtTmp.microseconds+8334)/16667));
  134.       frame->cycleCnt++;
  135.       }
  136.    return(iffp);
  137.    }
  138.  
  139.  
  140. /** GetFoILBM() *************************************************************
  141.  *
  142.  * Called via myReadPictureto handle every FORM encountered in an IFF file.
  143.  * Reads FORMs ILBM and skips all others.
  144.  * Inside a FORM ILBM, it stops once it reads a BODY. It complains if it
  145.  * finds no BODY or if it has no BMHD to decode the BODY.
  146.  *
  147.  * Once we find a BODY chunk, we'll call user rtn getBitMap() to
  148.  *    allocate the bitmap and planes (or screen) and then read
  149.  *    the BODY into the planes.
  150.  *
  151.  ****************************************************************************/
  152. LOCAL BYTE bodyBuffer[bufSz];
  153. IFFP GetFoILBM(parent)  GroupContext *parent;
  154.    {
  155.    /*compilerBug register*/ IFFP iffp;
  156.    GroupContext formContext;
  157.    ILBMFrame ilbmFrame;      /* only used for non-clientFrame fields.*/
  158.    struct BitMap *destBitMap;   /* cs */
  159.  
  160.    /* Handle a non-ILBM FORM. */
  161.    if (parent->subtype != ID_ILBM)
  162.       {
  163. #if Fancy >= 2
  164.       /* Open a non-ILBM FORM and recursively scan it for ILBMs.*/
  165.       iffp = OpenRGroup(parent, &formContext);
  166.       CheckIFFP();
  167.       do {
  168.          iffp = GetF1ChunkHdr(&formContext);
  169.          } while (iffp >= IFF_OKAY);
  170.       if (iffp == END_MARK)
  171.          {
  172.          iffp = IFF_OKAY;   /* then continue scanning the file */
  173.          }
  174.       CloseRGroup(&formContext);
  175.       return(iffp);
  176. #else
  177.       return(IFF_OKAY); /* Just skip this FORM and keep scanning the file.*/
  178. #endif
  179.       }
  180.  
  181.    ilbmFrame = *(ILBMFrame *)parent->clientFrame;
  182.    iffp = OpenRGroup(parent, &formContext);
  183.    CheckIFFP();
  184.  
  185.    do switch (iffp = GetFChunkHdr(&formContext)) {
  186.       case ID_BMHD: {
  187.          ilbmFrame.foundBMHD = TRUE;
  188.          iffp = GetBMHD(&formContext, &ilbmFrame.bmHdr);
  189.          break; }
  190.       case ID_CAMG: {       /* cs */
  191.          iffp = handleCAMG(&formContext, &ilbmFrame);
  192.          break; }
  193.       case ID_CRNG: {       /* cs */
  194.          iffp = handleCRNG(&formContext, &ilbmFrame);
  195.          break; }
  196.       case ID_CCRT: {       /* cs */
  197.          iffp = handleCCRT(&formContext, &ilbmFrame);
  198.          break; }
  199.       case ID_CMAP: {
  200.          ilbmFrame.nColorRegs = maxColorReg; /* room for this many */
  201.          iffp = GetCMAP(&formContext, (WORD *)ilbmFrame.colorMap,
  202.                            &ilbmFrame.nColorRegs);
  203.          break; }
  204.       case ID_BODY: {       /* cs */
  205.          if (!ilbmFrame.foundBMHD)
  206.             {
  207.             iffp = BAD_FORM;   /* No BMHD chunk! */
  208.             }
  209.          else
  210.             {
  211.             if(destBitMap=(struct BitMap *)getBitMap(&ilbmFrame))
  212.                {
  213.                iffp = GetBODY( &formContext,
  214.                                destBitMap,
  215.                                NULL,
  216.                                &ilbmFrame.bmHdr,
  217.                                bodyBuffer,
  218.                                bufSz);
  219.                if (iffp == IFF_OKAY) iffp = IFF_DONE;   /* Eureka */
  220.                *giFrame = ilbmFrame; /* copy fields to client frame */
  221.                }
  222.             else
  223.                {
  224.                iffp = CLIENT_ERROR;   /* not enough RAM for the bitmap */
  225.                }
  226.             }
  227.          break; }
  228.  
  229.       case END_MARK: {
  230.          iffp = BAD_FORM;
  231.          break; }
  232.  
  233.       } while (iffp >= IFF_OKAY);
  234.       /* loop if valid ID of ignored chunk or a
  235.        * subroutine returned IFF_OKAY (no errors).*/
  236.  
  237.    if (iffp != IFF_DONE)  return(iffp);
  238.  
  239.    CloseRGroup(&formContext);
  240.    return(iffp);
  241.    }
  242.  
  243. /** Notes on extending GetFoILBM ********************************************
  244.  *
  245.  * To read more kinds of chunks, just add clauses to the switch statement.
  246.  * To read more kinds of property chunks (GRAB, CAMG, etc.) add clauses to
  247.  * the switch statement in GetPrILBM, too.
  248.  *
  249.  * To read a FORM type that contains a variable number of data chunks--e.g.
  250.  * a FORM FTXT with any number of CHRS chunks--replace the ID_BODY case with
  251.  * an ID_CHRS case that doesn't set iffp = IFF_DONE, and make the END_MARK
  252.  * case do whatever cleanup you need.
  253.  *
  254.  ****************************************************************************/
  255.  
  256.  
  257. /** GetPrILBM() *************************************************************
  258.  *
  259.  * Called via myReadPicture to handle every PROP encountered in an IFF file.
  260.  * Reads PROPs ILBM and skips all others.
  261.  *
  262.  ****************************************************************************/
  263. #if Fancy
  264. IFFP GetPrILBM(parent)  GroupContext *parent;  {
  265.    /*compilerBug register*/ IFFP iffp;
  266.    GroupContext propContext;
  267.    ILBMFrame *ilbmFrame = (ILBMFrame *)parent->clientFrame;
  268.  
  269.    if (parent->subtype != ID_ILBM)
  270.       return(IFF_OKAY);   /* just continue scaning the file */
  271.  
  272.    iffp = OpenRGroup(parent, &propContext);
  273.    CheckIFFP();
  274.  
  275.    do switch (iffp = GetPChunkHdr(&propContext)) {
  276.       case ID_BMHD: {
  277.          ilbmFrame->foundBMHD = TRUE;
  278.          iffp = GetBMHD(&propContext, &ilbmFrame->bmHdr);
  279.          break; }
  280.       case ID_CAMG: {       /* cs */
  281.          iffp = handleCAMG(&propContext, ilbmFrame);
  282.          break; }
  283.       case ID_CRNG: {       /* cs */
  284.          iffp = handleCRNG(&propContext, ilbmFrame);
  285.          break; }
  286.       case ID_CCRT: {       /* cs */
  287.          iffp = handleCCRT(&propContext, ilbmFrame);
  288.          break; }
  289.       case ID_CMAP: {
  290.          ilbmFrame->nColorRegs = maxColorReg; /* room for this many */
  291.          iffp = GetCMAP(&propContext,
  292.                           (WORD *)&ilbmFrame->colorMap,
  293.                              &ilbmFrame->nColorRegs);
  294.          break; }
  295.       } while (iffp >= IFF_OKAY);
  296.         /* loop if valid ID of ignored chunk or a
  297.          * subroutine returned IFF_OKAY (no errors).*/
  298.  
  299.    CloseRGroup(&propContext);
  300.    return(iffp == END_MARK ? IFF_OKAY : iffp);
  301.    }
  302. #endif
  303.  
  304. /** GetLiILBM() *************************************************************
  305.  *
  306.  * Called via myReadPicture to handle every LIST encountered in an IFF file.
  307.  *
  308.  ****************************************************************************/
  309. #if Fancy
  310. IFFP GetLiILBM(parent)  GroupContext *parent;  {
  311.     ILBMFrame newFrame;   /* allocate a new Frame */
  312.  
  313.     newFrame = *(ILBMFrame *)parent->clientFrame;  /* copy parent frame */
  314.  
  315.     return( ReadIList(parent, (ClientFrame *)&newFrame) );
  316.     }
  317. #endif
  318.  
  319. /** myReadPicture() ********************************************************/
  320. IFFP myReadPicture(file,iFrame)
  321.    LONG file;
  322.    ILBMFrame *iFrame;   /* Top level "client frame".*/
  323.    {
  324.    IFFP iffp = IFF_OKAY;
  325.  
  326. #if Fancy
  327.    iFrame->clientFrame.getList = GetLiILBM;
  328.    iFrame->clientFrame.getProp = GetPrILBM;
  329. #else
  330.    iFrame->clientFrame.getList = SkipGroup;
  331.    iFrame->clientFrame.getProp = SkipGroup;
  332. #endif
  333.    iFrame->clientFrame.getForm = GetFoILBM;
  334.    iFrame->clientFrame.getCat  = ReadICat ;
  335.  
  336.    /* Initialize the top-level client frame's property settings to the
  337.     * program-wide defaults. This example just records that we haven't read
  338.     * any BMHD property or CMAP color registers yet. For the color map, that
  339.     * means the default is to leave the machine's color registers alone.
  340.     * If you want to read a property like GRAB, init it here to (0, 0). */
  341.  
  342.    iFrame->foundBMHD  = FALSE;
  343.    iFrame->nColorRegs = 0;
  344.    iFrame->foundCAMG  = FALSE;    /* cs */
  345.    iFrame->cycleCnt   = 0;        /* cs */
  346.    giFrame = iFrame;
  347.  
  348.   /* Store a pointer to the client's frame in a global variable so that
  349.    * GetFoILBM can update client's frame when done.  Why do we have so
  350.    * many frames & frame pointers floating around causing confusion?
  351.    * Because IFF supports PROPs which apply to all FORMs in a LIST,
  352.    * unless a given FORM overrides some property.  
  353.    * When you write code to read several FORMs,
  354.    * it is ssential to maintain a frame at each level of the syntax
  355.    * so that the properties for the LIST don't get overwritten by any
  356.    * properties specified by individual FORMs.
  357.    * We decided it was best to put that complexity into this one-FORM example,
  358.    * so that those who need it later will have a useful starting place.
  359.    */
  360.  
  361.    iffp = ReadIFF(file, (ClientFrame *)iFrame);
  362.    return(iffp);
  363.    }
  364.  
  365.