home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 403.lha / VediSrc / readpict.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-08-06  |  11.6 KB  |  312 lines

  1. /** ReadPict.c *******************************************************
  2.  *
  3.  * Read an ILBM raster image file.               23-Jan-86.
  4.  *
  5.  * By Jerry Morrison, Steve Shaw, and Steve Hayes, Electronic Arts.
  6.  * This software is in the public domain.
  7.  *
  8.  * USE THIS AS AN EXAMPLE PROGRAM FOR AN IFF READER.
  9.  *
  10.  * The IFF reader portion is essentially a recursive-descent parser.
  11.  *
  12.  *********************************************************************
  13.  *
  14.  * Modified to accept a BEAM chunk in an ILBM FORM. Search for lines
  15.  *
  16.  * containing 'dp' to find the difference from the original EA files
  17.  *
  18.  * Date: 20-Feb-89       Registered Developer: ECI004 - Diego Perini
  19.  *
  20.  ********************************************************************/
  21.  
  22. #define LOCAL   static
  23.  
  24. #include "iff/intuall.h"
  25. #include "libraries/dos.h"
  26. #include "libraries/dosextens.h"
  27. #include "iff/ilbm.h"
  28. #include "iff/readpict.h"
  29.  
  30. UWORD BeamPalette[592][32]; /* dp */
  31.  
  32. #define MIN(a,b) ((a)<(b)?(a):(b))
  33.  
  34. /* Define the size of a temporary buffer used in unscrambling the ILBM rows.*/
  35. #define bufSz 32768L /* dp */
  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.  *       BMHD       GetBMHD
  54.  *       CMAP       GetCMAP
  55.  *       BEAM       GetBEAM
  56.  *     FORM ILBM    GetFoILBM             GroupContext        ILBMFrame
  57.  *       BODY       GetBODY
  58.  *     FORM ILBM    GetFoILBM             GroupContext        ILBMFrame
  59.  *       BODY       GetBODY
  60.  *   FORM ILBM      GetFoILBM             GroupContext        ILBMFrame
  61.  */
  62.  
  63. /* NOTE: For a small version of this program, set Fancy to 0.
  64.  * That'll compile a program that reads a single FORM ILBM in a file, which
  65.  * is what DeluxePaint produces. It'll skip all LISTs and PROPs in the input
  66.  * file. It will, however, look inside a CAT for a FORM ILBM.
  67.  * That's suitable for 90% of the uses.
  68.  *
  69.  * For a fancier version that handles LISTs and PROPs, set Fancy to 1.
  70.  * That'll compile a program that dives into a LIST, if present, to read
  71.  * the first FORM ILBM. E.g. a DeluxePrint library of images is a LIST of
  72.  * FORMs ILBM.
  73.  *
  74.  * For an even fancier version, set Fancy to 2. That'll compile a program
  75.  * that dives into non-ILBM FORMs, if present, looking for a nested FORM ILBM.
  76.  * E.g. a DeluxeVideo C.S. animated object file is a FORM ANBM containing a
  77.  * FORM ILBM for each image frame. */
  78. #define Fancy  2 /* dp */
  79.  
  80. /* Global access to client-provided pointers.*/
  81. LOCAL ILBMFrame *giFrame = NULL;   /* "client frame".*/
  82.  
  83. /** GetFoILBM() *************************************************************
  84.  *
  85.  * Called via ReadPicture to handle every FORM encountered in an IFF file.
  86.  * Reads FORMs ILBM and skips all others.
  87.  * Inside a FORM ILBM, it stops once it reads a BODY. It complains if it
  88.  * finds no BODY or if it has no BMHD to decode the BODY.
  89.  *
  90.  * Once we find a BODY chunk, we'll allocate the BitMap and read the image.
  91.  *
  92.  ****************************************************************************/
  93. LOCAL BYTE bodyBuffer[bufSz];
  94. IFFP GetFoILBM(parent)  GroupContext *parent;  {
  95.    /*compilerBug register*/ IFFP iffp;
  96.    GroupContext formContext;
  97.    ILBMFrame ilbmFrame;      /* only used for non-clientFrame fields.*/
  98.    struct BitMap *destBitMap; /* dp */
  99.  
  100.     /* Handle a non-ILBM FORM. */
  101.     if (parent->subtype != ID_ILBM) {
  102. #if Fancy >= 2
  103.         /* Open a non-ILBM FORM and recursively scan it for ILBMs.*/
  104.         iffp = OpenRGroup(parent, &formContext);
  105.         CheckIFFP();
  106.         do {
  107.             iffp = GetF1ChunkHdr(&formContext);
  108.             } while (iffp >= IFF_OKAY);
  109.         if (iffp == END_MARK)
  110.             iffp = IFF_OKAY;   /* then continue scanning the file */
  111.         CloseRGroup(&formContext);
  112.         return(iffp);
  113. #else
  114.         return(IFF_OKAY); /* Just skip this FORM and keep scanning the file.*/
  115. #endif
  116.         }
  117.  
  118.    ilbmFrame = *(ILBMFrame *)parent->clientFrame;
  119.    iffp = OpenRGroup(parent, &formContext);
  120.    CheckIFFP();
  121.  
  122.    do switch (iffp = GetFChunkHdr(&formContext)) {
  123.       case ID_BMHD: {
  124.          ilbmFrame.foundBMHD = TRUE;
  125.          iffp = GetBMHD(&formContext, &ilbmFrame.bmHdr);
  126.          break; }
  127.       case ID_CMAP: {
  128.          ilbmFrame.nColorRegs = maxColorReg;  /* we have room for this many */
  129.          iffp = GetCMAP(&formContext,
  130.                 (WORD *)&ilbmFrame.colorMap[0], &ilbmFrame.nColorRegs);
  131.          break; }
  132.       case ID_BEAM: { /* dp */
  133.          ilbmFrame.foundBEAM = TRUE;
  134.          iffp = GetBEAM(&formContext,
  135.                 (UWORD *)&BeamPalette[0], ilbmFrame.bmHdr.h);
  136.          break; }
  137.       case ID_CAMG: { /* dp */
  138.          ilbmFrame.foundCAMG = TRUE;
  139.          iffp = GetCAMG(&formContext, &ilbmFrame.camgChunk);
  140.          break; }
  141.       case ID_CRNG: { /* dp */
  142.          iffp = GetCRNG(&formContext,
  143.              &ilbmFrame.crngChunk[ilbmFrame.crngCount++]);
  144.          break; }
  145.       case ID_CCRT: { /* dp */
  146.          iffp = GetCCRT(&formContext,
  147.              &ilbmFrame.ccrtChunk[ilbmFrame.ccrtCount++]);
  148.          break; }
  149.       case ID_BODY: { /* dp */
  150.          if (!ilbmFrame.foundBMHD)
  151.             iffp = BAD_FORM;   /* No BMHD chunk! */
  152.          else
  153.             if (destBitMap = (struct BitMap *)getBitMap(&ilbmFrame))
  154.                {
  155.                iffp = GetBODY( &formContext,
  156.                                destBitMap,
  157.                                (BYTE *)NULL,
  158.                                &ilbmFrame.bmHdr,
  159.                                (BYTE *)bodyBuffer,
  160.                                (LONG)bufSz);
  161.                if (iffp == IFF_OKAY) iffp = IFF_DONE;   /* Eureka */
  162.                *giFrame = ilbmFrame;  /* Copy fields to client's frame.*/
  163.                }
  164.             else
  165.                iffp = CLIENT_ERROR;   /* not enough RAM for the bitmap */
  166.          break; }
  167.       case END_MARK: {
  168.          iffp = BAD_FORM;   /* No BODY chunk! */
  169.          break; }
  170.       } while (iffp >= IFF_OKAY);
  171.         /* loop if valid ID of ignored chunk or a
  172.          * subroutine returned IFF_OKAY (no errors).*/
  173.  
  174.    if (iffp != IFF_DONE)  return(iffp);
  175.  
  176.    /* If we get this far, there were no errors. */
  177.    CloseRGroup(&formContext);
  178.    return(iffp);
  179.    }
  180.  
  181. /** Notes on extending GetFoILBM ********************************************
  182.  *
  183.  * To read more kinds of chunks, just add clauses to the switch statement.
  184.  * To read more kinds of property chunks (GRAB, CAMG, etc.) add clauses to
  185.  * the switch statement in GetPrILBM, too.
  186.  *
  187.  * To read a FORM type that contains a variable number of data chunks--e.g.
  188.  * a FORM FTXT with any number of CHRS chunks--replace the ID_BODY case with
  189.  * an ID_CHRS case that doesn't set iffp = IFF_DONE, and make the END_MARK
  190.  * case do whatever cleanup you need.
  191.  *
  192.  ****************************************************************************/
  193.  
  194. /** GetPrILBM() *************************************************************
  195.  *
  196.  * Called via ReadPicture to handle every PROP encountered in an IFF file.
  197.  * Reads PROPs ILBM and skips all others.
  198.  *
  199.  ****************************************************************************/
  200. #if Fancy
  201. IFFP GetPrILBM(parent)  GroupContext *parent;  {
  202.    /*compilerBug register*/ IFFP iffp;
  203.    GroupContext propContext;
  204.    ILBMFrame *ilbmFrame = (ILBMFrame *)parent->clientFrame;
  205.  
  206.    if (parent->subtype != ID_ILBM)
  207.       return(IFF_OKAY);   /* just continue scaning the file */
  208.  
  209.    iffp = OpenRGroup(parent, &propContext);
  210.    CheckIFFP();
  211.  
  212.    do switch (iffp = GetPChunkHdr(&propContext)) {
  213.       case ID_BMHD: {
  214.          ilbmFrame->foundBMHD = TRUE;
  215.          iffp = GetBMHD(&propContext, &ilbmFrame->bmHdr);
  216.          break; }
  217.       case ID_CMAP: {
  218.          ilbmFrame->nColorRegs = maxColorReg; /* we have room for this many */
  219.          iffp = GetCMAP(&propContext,
  220.                 (WORD *)&ilbmFrame->colorMap[0], &ilbmFrame->nColorRegs);
  221.          break; }
  222.       case ID_BEAM: { /* dp */
  223.          ilbmFrame->foundBEAM = TRUE;
  224.          iffp = GetBEAM(&propContext,
  225.                 (UWORD *)&BeamPalette[0], ilbmFrame->bmHdr.h);
  226.          break; }
  227.       case ID_CAMG: { /* dp */
  228.          ilbmFrame->foundCAMG = TRUE;
  229.          iffp = GetCAMG(&propContext, &ilbmFrame->camgChunk);
  230.          break; }
  231.       case ID_CRNG: { /* dp */
  232.          iffp = GetCRNG(&propContext,
  233.              &ilbmFrame->crngChunk[ilbmFrame->crngCount++]);
  234.          break; }
  235.       case ID_CCRT: { /* dp */
  236.          iffp = GetCCRT(&propContext,
  237.              &ilbmFrame->ccrtChunk[ilbmFrame->ccrtCount++]);
  238.          break; }
  239.       } while (iffp >= IFF_OKAY);
  240.         /* loop if valid ID of ignored chunk or a
  241.          * subroutine returned IFF_OKAY (no errors).*/
  242.  
  243.    CloseRGroup(&propContext);
  244.    return(iffp == END_MARK ? IFF_OKAY : iffp);
  245.    }
  246. #endif
  247.  
  248. /** GetLiILBM() *************************************************************
  249.  *
  250.  * Called via ReadPicture to handle every LIST encountered in an IFF file.
  251.  *
  252.  ****************************************************************************/
  253. #if Fancy
  254. IFFP GetLiILBM(parent)  GroupContext *parent;  {
  255.     ILBMFrame newFrame;   /* allocate a new Frame */
  256.  
  257.     newFrame = *(ILBMFrame *)parent->clientFrame;  /* copy parent frame */
  258.  
  259.     return( ReadIList(parent, (ClientFrame *)&newFrame) );
  260.     }
  261. #endif
  262.  
  263. /** ReadPicture() **********************************************************/
  264. IFFP ReadPicture(file, iFrame)
  265.    LONG file;
  266.    ILBMFrame *iFrame;   /* Top level "client frame".*/
  267.    {
  268.    IFFP iffp = IFF_OKAY;
  269.  
  270. #if Fancy
  271.    iFrame->clientFrame.getList = GetLiILBM;
  272.    iFrame->clientFrame.getProp = GetPrILBM;
  273. #else
  274.    iFrame->clientFrame.getList = SkipGroup;
  275.    iFrame->clientFrame.getProp = SkipGroup;
  276. #endif
  277.    iFrame->clientFrame.getForm = GetFoILBM;
  278.    iFrame->clientFrame.getCat  = ReadICat ;
  279.  
  280.    /* Initialize the top-level client frame's property settings to the
  281.     * program-wide defaults. This example just records that we haven't read
  282.     * any BMHD property or CMAP color registers yet. For the color map, that
  283.     * means the default is to leave the machine's color registers alone.
  284.     * If you want to read a property like GRAB, init it here to (0, 0). */
  285.  
  286.    iFrame->foundBMHD  = FALSE;
  287.    iFrame->nColorRegs = 0;
  288.    iFrame->foundBEAM  = FALSE;
  289.    iFrame->foundCAMG  = FALSE;
  290.    iFrame->crngCount  = 0;
  291.    iFrame->ccrtCount  = 0;
  292.  
  293.    giFrame = iFrame;
  294.  
  295.   /* Store a pointer to the client's frame in a global variable so that
  296.    * GetFoILBM can update client's frame when done.  Why do we have so
  297.    * many frames & frame pointers floating around causing confusion?
  298.    * Because IFF supports PROPs which apply to all FORMs in a LIST,
  299.    * unless a given FORM overrides some property.  
  300.    * When you write code to read several FORMs,
  301.    * it is essential to maintain a frame at each level of the syntax
  302.    * so that the properties for the LIST don't get overwritten by any
  303.    * properties specified by individual FORMs.
  304.    * We decided it was best to put that complexity into this one-FORM example,
  305.    * so that those who need it later will have a useful starting place.
  306.    */
  307.  
  308.    iffp = ReadIFF(file, (ClientFrame *)iFrame);
  309.    return(iffp);
  310.    }
  311.  
  312.