home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 8 / FreshFishVol8-CD1.bin / new / gfx / misc / getilbm / getilbm.c < prev    next >
C/C++ Source or Header  |  1994-11-11  |  32KB  |  882 lines

  1. //===========================================================================
  2. // GETILBM.C  --  for AmigaDOS 2.0/3.0 (and maybe 1.3 with iffparse.library)
  3. // Rev: 30 September 1994, Alex Matulich  matulich_alex@SEAA.NAVSEA.NAVY.MIL
  4. //
  5. // For SAS C/C++ 6.xx.  Compile with IGNORE=51 to disable warnings for
  6. // C++ comments (I got addicted to those C++ comments...)
  7. //
  8. // This module is for loading IFF ILBM pictures.  The *only* functions you
  9. // need to call are loadilbmScreen() and freeilbmScreen(), or if you are
  10. // just loading into bitmaps, call loadilbmBitMap() and freeBitMap().
  11. //
  12. // The iffparse.library must be opened prior to calling these routines.
  13. // SAS C 6.xx does this automatically for you.
  14. //
  15. // This module was adapted from the confusing plethora of functions in the
  16. // Amiga Developer's package for AmigaDOS 3.1.  All adaptations and excerpts
  17. // are indicated in the comments.
  18. //===========================================================================
  19.  
  20.  
  21. //---------------------------------------------------------------------------
  22. // To make the demo ILBM file reader, compile with only the symbol DEMO
  23. // defined.  Example:  sc optimize optsize def=DEMO link getilbm.c
  24. //
  25. // You might have your own versions of getBitMap() and freeBitMap() external
  26. // to this module (I do, for example, in my video buffering module).  If so,
  27. // then make sure the following two #defines are commented out.  If you wish
  28. // to use the getBitMap() and freeBitMap() functions contained in this
  29. // module, then uncomment the following two #defines.
  30.  
  31. // #define USE_GETBM    // comment out if you already have a getBitMap()
  32. // #define USE_FREEBM   // comment out if you already have a freeBitMap()
  33.  
  34. // These functions, if external, should be compatible with the prototypes
  35. // in getilbm_proto.h.
  36. //
  37. // Defining TIMECHECK enables calls to a user-supplied external function
  38. // check_for_switch() while the IFF file is loading.  The purpose of this
  39. // function is to allow the program to do time-critical things while a
  40. // large ILBM file is loading.  Sort of a pseudo-multitasking technique.
  41.  
  42. // #define TIMECHECK    // only if you need a check_for_switch() function
  43.  
  44. // Often it is more useful to simply load an IFF file into a bitmap, rather
  45. // than create a whole screen for it.  If you want to do just this, and you
  46. // never need to load an IFF file into a screen, then uncomment this line:
  47.  
  48. // #define NOILBMSCREEN  // only compile loadilbmBitMap() and associates
  49.  
  50. // This will cause the functions loadilbmScreen() and associated functions
  51. // and declarations to be skipped during compililation.
  52. //
  53. // Conversely, if you don't need loadilbmBitMap(), but only loadilbmScreen(),
  54. // then uncomment this line:
  55. //
  56. // #define ILBMSCREENONLY  // only compile loadilbmScreen() and associates
  57. //
  58. // The existence of getBitMap() and freeBitMap() are still controlled by
  59. // USE_GETBM and USE_FREEBM.
  60. // Do not define both NOILBMSCREEN and ILBMSCREENONLY at the same time.
  61. // Do not define either of them if you need *both* loadilbmScreen() and
  62. // loadilbmBitMap().
  63. //---------------------------------------------------------------------------
  64.  
  65. #ifdef NOTIMECHECK  // for compatibility with previous versions
  66.    #undef TIMECHECK
  67. #endif
  68.  
  69. #ifdef DEMO         // re-set definitions if compiling the demo
  70.    #ifdef USE_GETBM
  71.       #undef USE_GETBM          // demo doesn't need getBitMap()
  72.    #endif
  73.    #ifdef USE_FREEBM
  74.       #undef USE_FREEBM         // demo doesn't need freeBitMap()
  75.    #endif
  76.    #ifdef TIMECHECK
  77.       #undef TIMECHECK          // demo doesn't need check_for_switch()
  78.    #endif
  79.    #ifdef NOILBMSCREEN
  80.       #undef NOILBMSCREEN       // demo doesn't need loadilbmBitmap()
  81.    #endif
  82.    #ifndef ILBMSCREENONLY
  83.       #define ILBMSCREENONLY    // demo DOES need loadilbmScreen()
  84.    #endif
  85. #endif
  86.  
  87. #include <exec/memory.h>
  88. #include <exec/libraries.h>
  89. #include <graphics/gfx.h>
  90. #include <libraries/dos.h>
  91. #include <libraries/iffparse.h>
  92.  
  93. #include <proto/exec.h>
  94. #include <proto/graphics.h>
  95. #include <proto/dos.h>
  96. #include <proto/iffparse.h>
  97.  
  98. #ifndef NOILBMSCREEN
  99. #define USE_BUILTIN_MATH 1  // to use built-in min() and max() in string.h
  100. #include <string.h>
  101. #include <graphics/display.h>
  102. #include <intuition/intuition.h>
  103. #include <proto/intuition.h>
  104. #endif  // !NOILBMSCREEN
  105.  
  106. #include <stdlib.h>
  107.  
  108. #include "getilbm_proto.h"   // prototypes for user-callable functions
  109.  
  110. extern struct Library *IFFParseBase;
  111.  
  112.  
  113. // definitions from iffp/iff.h
  114.  
  115. #define ChunkMoreBytes(cn) (cn->cn_Size - cn->cn_Scan)
  116.  
  117. struct Chunk {
  118.    struct Chunk *ch_Next;
  119.    long ch_Type, ch_ID, ch_Size;
  120.    void *ch_Data;
  121.    };
  122.  
  123.  
  124. // definitions from iffp/ilbm.h
  125.  
  126. #define ID_ILBM  MAKE_ID('I','L','B','M')
  127. #define ID_BMHD  MAKE_ID('B','M','H','D')
  128. #define ID_CMAP  MAKE_ID('C','M','A','P')
  129. #define ID_BODY  MAKE_ID('B','O','D','Y')
  130. #define ID_CAMG  MAKE_ID('C','A','M','G')
  131.  
  132. // sizeof(a 3-byte structure) returns 16 due to word alignment, so we use:
  133. #define sizeofColorRegister 3
  134.  
  135. #define MAXAMDEPTH      8  // used for OS<V37, screen.c maxdisplaydepth(ID)
  136. #define MAXAMCOLORREG  32  // should use ViewPort->ColorMap.Count instead
  137.  
  138. #define RowBytes(w)        ((((w) + 15) >> 4) << 1)
  139. #define RowBits(w)         ((((w) + 15) >> 4) << 4)
  140.  
  141. #define mskNone      0  // masking techniques
  142. #define mskHasMask   1
  143. #define cmpNone      0  // compression techniques
  144. #define cmpByteRun1  1
  145.  
  146. typedef struct {
  147.    UWORD w, h;                  // raster width and height
  148.    WORD x, y;                   // pixel position for this image
  149.    UBYTE nPlanes, masking,      // # source bitplanes, masking (?)
  150.          compression, flags;    // compression, Commodore-defined flags
  151.    UWORD transparentColor;      // transparent color number (sort of)
  152.    UBYTE xAspect, yAspect;      // pixel aspect ratio width/height
  153.    WORD pageWidth, pageHeight;  // source page size in pixels
  154.    } BitMapHeader;
  155.  
  156. typedef struct { UBYTE red, green, blue; } ColorRegister;
  157. typedef struct { ULONG ViewModes; } CamgChunk;
  158.  
  159. #define BMHDB_CMAPOK 7
  160. #define BMHDF_CMAPOK (1 << BMHDB_CMAPOK)
  161.  
  162.  
  163. // from iffp/packer.h
  164. #define MaxPackedSize(rowsize) ((rowsize)+(((rowsize)+127)>>7))
  165.  
  166.  
  167. //---------------------------------------------------------------------------
  168. // Skip following five declarations if you don't need loadilbmScreen().
  169.  
  170. #ifndef NOILBMSCREEN
  171.  
  172. static UWORD __far ins_pens[] = { 0xffff }; // minimal pen definitions
  173.  
  174. long li_errcode;                      // error code returned by OpenScreen()
  175.  
  176. // You will want to expand the following tag list if you decide to
  177. // substitute OpenScreenTagList() for OpenScreen() in loadilbmScreen().
  178. // OpenScreen() works with all video modes, and is used here for
  179. // compatibility with AmigaDOS 1.3, just in case such an OS happens to
  180. // have a compatible iffparse.library.
  181.  
  182. static struct TagItem __far ins_ext[] = {
  183.    SA_DisplayID, 0L,                  // tag needed for display mode
  184.    SA_DClip, 0L,                      // needed for screen centering
  185.    SA_AutoScroll, TRUE,               // not really needed, but who cares?
  186.    SA_Pens, (ULONG)ins_pens,          // minimal tags needed for 2.0
  187.    SA_ErrorCode, (ULONG)&li_errcode,  // examine li_errcode for error codes
  188.    TAG_DONE
  189.    };
  190.  
  191. // Instead of opening a screen with functions specific to AmigaDOS 2.0,
  192. // we define an ExtNewScreen structure for use with OpenScreen() to
  193. // maintain compatibility with earlier OS versions.  The ins_ext[] taglist
  194. // above provides the enhancements necessary for OS 2.0 or greater.
  195.  
  196. static struct ExtNewScreen __far ins = {
  197.    0, 0, ~0, ~0,                      // left, top, width & height
  198.    2, 0, 1,                           // depth, DetailPen, BlockPen
  199.    0,                                 // ViewModes
  200.    CUSTOMSCREEN | SCREENQUIET | SCREENBEHIND | NS_EXTENDED,
  201.    NULL,                              // font
  202.    NULL, NULL, NULL,                  // title, gadgets, bitmap
  203.    ins_ext                            // tag extensions
  204.    };
  205.    
  206. static struct NewWindow __far inw = {
  207.    0, 0, ~0, ~0,                      // left, top, width, height
  208.    0, 1,                              // DetailPen, BlockPen
  209.    IDCMP_RAWKEY | IDCMP_VANILLAKEY,   // IDCMP flags (whatever you like)
  210.    SIMPLE_REFRESH | BORDERLESS | BACKDROP |