home *** CD-ROM | disk | FTP | other *** search
/ Gold Fish 3 / goldfish_volume_3.bin / files / fish / disks / d1104.lha / Programs / Image2C / i2c.c < prev    next >
C/C++ Source or Header  |  1995-03-19  |  25KB  |  683 lines

  1. /****************************************************************************
  2.  *
  3.  *  I2C (Image2'C') 1.2
  4.  *  Copyright © 1994,1995 Udo Schuermann
  5.  *  All rights reserved
  6.  *
  7.  *  This program uses  iffparse.library  to load an ILBM from a FORM IFF
  8.  *  (in plain English, it loads an IFF picture) and produces output that
  9.  *  can be used directly as part of a  struct Image  in your 'C' source
  10.  *  code.
  11.  *
  12.  *  I make this code available as a demonstration of an exceedingly simple,
  13.  *  yet functional program that uses  iffparse.library  and does something
  14.  *  moderately useful with it.  Of some interest might be the fact that
  15.  *  the program extracts a number of additional properties from the file,
  16.  *  if they are present: ANNO, AUTH, (c), and FVER chunks are inserted in
  17.  *  the output file as comments.  Hopefully, none of these contain the end-
  18.  *  comment symbol... :-7
  19.  *
  20.  *  THIS PROGRAM MAY *NOT* BE DISTRIBUTED WITHOUT SOURCE CODE AND ALL
  21.  *  NOTICES INTACT.  YOU MAY NOT SELL THIS PROGRAM OR INCLUDE IT WITH
  22.  *  A COMMERCIAL PRODUCT WITHOUT EXPRESS WRITTEN PERMISSION FROM THE
  23.  *  AUTHOR.  IT IS PERMITTED TO DISTRIBUTE THIS PROGRAM BY ELECTRONIC
  24.  *  MEANS (USENET), OR AS PART OF FRED FISH'S CD-ROMS OR RELATED
  25.  *  COLLECTIONS.  YOU MAY USE IT FOR INSTRUCTIONAL PURPOSES, AND EVEN
  26.  *  GIVE IT TO FRIENDS, BUT DON'T YOU SELL IT OR YOUR NAME SHALL BE
  27.  *  FOREVER STAINED.
  28.  *
  29.  *  Commodore is dead.  Long live the Amiga!
  30.  *
  31.  *  Share and enjoy!  ;-)
  32.  *
  33.  *  ---------------------------------------------------------------------
  34.  *
  35.  *  This program uses the following CLI template (I am not using standard
  36.  *  code for that, but am parsing the command line on my own):
  37.  *
  38.  *  ILBMFILE/A,SYMPREFIX/A,NOINFO/S,NOPENS/S,NODATA/S,NOIMAGESTRUCT/S,
  39.  *    NORGB4/S,USEIFDEFS/S,NOCHIP/S
  40.  *
  41.  *  ILBMFILE/A        Must always be given.  This is the IFF ILBM input
  42.  *            file to be converted.  I2C supports images up to
  43.  *            8 bitplanes deep (actually, any bitplane oriented
  44.  *            ILBM)
  45.  *
  46.  *  SYMPREFIX/A        Must always be given.  The symbol prefix for this
  47.  *            image file.  This forms the prefix to all symbols
  48.  *            in the file.
  49.  *            Example:  A prefix of "myImage_" will generate
  50.  *            symbols such as "UWORD myImage_ImageData[]"
  51.  *
  52.  *  NOINFO/S        This switch will cause image information, such
  53.  *            such as height, width, depth, number of colors
  54.  *            to be omitted.  See also NOIMAGESTRUCT below!
  55.  *
  56.  *  NOPENS/S        This switch will cause pens (used by LoadRGB32()
  57.  *            for example) to be omitted.
  58.  *
  59.  *  NODATA/S        This switch will cause the actual image data to
  60.  *            be omitted.  See also NOIMAGESTRUCT below!
  61.  *
  62.  *  NOIMAGESTRUCT/S    This switch will cause a "struct Image ..." item
  63.  *            to be omitted.  This item requires the presence
  64.  *            of INFO and DATA items; if you specify that either
  65.  *            or both of those should not be included (NOINFO
  66.  *            and/or NODATA) but you do not also specify the
  67.  *            NOIMAGESTRUCT, then I2C will reverse your decision
  68.  *            on NOINFO and/or NODATA so that the Image struct
  69.  *            can be built.
  70.  *
  71.  *  ADDRGB4/S        This switch will cause register color values to
  72.  *            be added.  Such values are 12-bit only and are
  73.  *            probably of use only for older software.  It is
  74.  *            for this reason that this is the only switch that
  75.  *                needs to be specified to add something to the
  76.  *            code; i.e. if not specified you will NOT get the
  77.  *            information for this item.
  78.  *
  79.  *  USEIFDEFS/S        This switch encloses the INFO, PENS, DATA, IMG,
  80.  *            and RGB4 sections with #ifdef/#endif constructs
  81.  *            to allow you to build a source file with ALL
  82.  *            information, but decide at a later time which
  83.  *            portions the compiler should include or ignore.
  84.  *            Use of this switch enables an additional level
  85.  *            of flexibility, which you may or may not find
  86.  *            of use.
  87.  *
  88.  *            The following #define statements used BEFORE you
  89.  *            #include the source code generated by I2C will
  90.  *            tell the compiler which portions of the file to
  91.  *            use and which to ignore:
  92.  *
  93.  *            #define I2C_IMAGE_INFO        Accept image info
  94.  *            #define I2C_IMAGE_PENS        Accept RGB32 pens
  95.  *            #define I2C_IMAGE_RGB4        Accept 4-bit pens
  96.  *            #define I2C_IMAGE_DATA        Accept image data
  97.  *            #define I2C_IMAGE_IMG        Accept struct Image
  98.  *
  99.  *  NOCHIP/S        Omit the __chip attribute on structures.  This may
  100.  *            be desirable if you are going to remap image colors
  101.  *            anyway and won't be needing the original in chip
  102.  *            RAM.
  103.  *
  104.  *  If you are not clear on some of the points described above, you are
  105.  *  hereby STRONGLY advised to run the program on a test image and see what
  106.  *  the resulting output file contains.  Try this:
  107.  *
  108.  *    I2C  TestImage.IFF  MyTest_  USEIFDEFS
  109.  */
  110.  
  111.  
  112. #include <stdio.h>
  113. #include <stdlib.h>
  114. #include <string.h>
  115. #include <exec/types.h>
  116. #include <libraries/iffparse.h>
  117.  
  118. #include <proto/dos.h>
  119. #include <proto/iffparse.h>
  120.  
  121.  
  122. /* If we define __MYDATE__ from the commandline, then we'll use that instead of
  123.  * redefining it to the standard Amiga __AMIGADATE__ (which is broken in SAS/C
  124.  * 6.51 whenever both the month and the day require two digits.)
  125.  */
  126. #ifndef __MYDATE__
  127. #define __MYDATE__ __AMIGADATE__
  128. #endif
  129.  
  130. #define VERSION  "1.2"
  131. char const VER[] = "$VER: Image2'C' "VERSION" "__MYDATE__;
  132.  
  133. BOOL AddINFO = TRUE;
  134. BOOL AddPENS = TRUE;
  135. BOOL AddDATA = TRUE;
  136. BOOL AddRGB4 = FALSE;
  137. BOOL AddIMG  = TRUE;
  138. BOOL UseIFDEFs = FALSE;
  139. BOOL UseCHIP = TRUE;
  140. char *ILBMFILE = NULL;
  141. char *SYMPREFIX = NULL;
  142.  
  143. struct IFFHandle *OpenFileAsIFF( char *filename ) {
  144.  
  145.   struct IFFHandle *iff;
  146.  
  147.   if( iff = AllocIFF() ) {
  148.     if( iff->iff_Stream = (ULONG)Open(filename,MODE_OLDFILE) ) { /* open the file stream */
  149.       InitIFFasDOS( iff );                                       /* initialize this as a DOS stream */
  150.       if( OpenIFF( iff, IFFF_READ ) == 0 )                       /* now open it as an IFF */
  151.     return iff;                                              /* and return read-to-go IFF handle */
  152.       else
  153.     Close( iff->iff_Stream );                                /* not an IFF file; close file */
  154.     } else
  155.       fprintf(stderr,"File unavailable (%s)!\n",filename);
  156.     FreeIFF( iff );                                              /* free the iff handle */
  157.   } else
  158.     fprintf(stderr,"Out of memory opening (%s)!\n",filename);
  159.   return NULL;                                                   /* return failure */
  160. } /* OpenFileAsIFF() */
  161.  
  162.  
  163.  
  164. #define ID_ILBM  MAKE_ID('I','L','B','M')
  165. #define ID_BMHD  MAKE_ID('B','M','H','D')
  166. #define ID_CMAP  MAKE_ID('C','M','A','P')
  167. #define ID_BODY  MAKE_ID('B','O','D','Y')
  168. #define ID_AUTH  MAKE_ID('A','U','T','H')
  169. #define ID_CPRT  MAKE_ID('(','c',')',' ')
  170. #define ID_ANNO  MAKE_ID('A','N','N','O')
  171. #define ID_FVER  MAKE_ID('F','V','E','R')
  172.  
  173.  
  174. #define mskHasMask 1      /* the only mask that REALLY needs handling */
  175. #define ByteRun1   1      /* the only compression we understand */
  176. typedef UBYTE Masking;
  177. typedef UBYTE Compression;
  178. struct BitMapHeader {
  179.   UWORD       w, h;
  180.   WORD        x, y;
  181.   UBYTE       nPlanes;
  182.   Masking     masking;
  183.   Compression compression;
  184.   UBYTE       reserved1;
  185.   UWORD       transparentColor;
  186.   UBYTE       xAspect, yAspect;
  187.   WORD        pageWidth, pageHeight;
  188. };
  189.  
  190.  
  191.  
  192. /* The ByteToWordStream() function, along with a limited set of global variables,
  193.  * permits us to produce really lovely, and well-formatted output.
  194.  *
  195.  * OnNewLine is externally set to 1 whenever we have finished with a scanline so
  196.  * that the next time we call ByteToWordStream, we start nicely on a new line.
  197.  * If you never use OnNewLine, then all data is merely dumped one word after
  198.  * another.  NO FUNCTIONALITY IS LOST, it just won't look nice.  Your compiler
  199.  * doesn't care.  Lines are ALWAYS limited to 11 words per line.
  200.  *
  201.  * LineHeader, if not set to a "" string, is printed before a new line is output,
  202.  * so we can print the nice "/× Plane 2 ×/" items before the new plane actually
  203.  * begins, but still give this function the chance to clean up the previous line
  204.  * by adding a comma and newline to it, etc.
  205.  * If you never use LineHeader, you will simply be missing the human-readable
  206.  * markers for the bit planes.  No biggie.  Again, your compiler couldn't care
  207.  * less.
  208.  */
  209. #define WORDS_PER_LINE 11
  210. UBYTE OnNewLine = 0;
  211. char LineHeader[64] = "";
  212. void ByteToWordStream( char c ) {
  213.  
  214.   static char prev;
  215.   static UBYTE odd=0;
  216.   static UBYTE needComma=0;
  217.   static UBYTE onLine=0;
  218.  
  219.   if( odd ) {
  220.     odd = 0;
  221.     if( needComma )   /* prevents leading comma AND unnecessary trailing comma */
  222.       printf(",");
  223.     else
  224.       needComma = 1;
  225.     if( (onLine == WORDS_PER_LINE) || OnNewLine ) {
  226.       printf("\n");
  227.       onLine = 0;
  228.       OnNewLine = 0;
  229.     }
  230.     if( *LineHeader ) {
  231.       printf("%s",LineHeader);
  232.       *LineHeader = '\0';
  233.     }
  234.     if( onLine == 0 )
  235.       printf("  ");
  236.     
  237.     printf("0x%02x%02x",prev,c);
  238.     onLine++;
  239.   } else
  240.     odd = 1;
  241.   prev = c;
  242. } /* ByteToWordStream() */
  243.  
  244.  
  245. /* These are all the properties in the IFF FORM ILBM that we are interested in.
  246.  * We use a PropChunk() in conjunction with FindProp() in our main() function to
  247.  * locate these and then obtain a pointer to their data.  If a pointer is NULL,
  248.  * then no such property exists in the IFF FORM ILBM.
  249.  */
  250. struct StoredProperty *auth_prop,*cprt_prop,*anno_prop,*fver_prop;
  251.  
  252.  
  253. /* Here is our nifty routine that scans the ILBM and creates nice 'C' code!
  254.  * Here is how it works:  Most common ILBMs are stored in this way:
  255.  *
  256.  *       (Scanline 1, Plane 1)(mask)(Scanline 1, Plane 2)(mask)(Scanline 1, Plane 3)(mask)
  257.  *       (Scanline 2, Plane 1)(mask)(Scanline 2, Plane 2)(mask)(Scanline 2, Plane 3)(mask)
  258.  *       (Scanline 3, Plane 1)(mask)(Scanline 3, Plane 2)(mask)(Scanline 3, Plane 3)(mask)
  259.  *       (Scanline 4, Plane 1)(mask)(Scanline 4, Plane 2)(mask)(Scanline 4, Plane 3)(mask)
  260.  *       (Scanline 5, Plane 1)(mask)(Scanline 5, Plane 2)(mask)(Scanline 5, Plane 3)(mask)
  261.  *
  262.  * In order to extract only Plane 1 information, one scanline at a time,
  263.  * we'd have to skip information in the file, i.e. read (Scanline 1, Plane 1)
  264.  * and then skip (Scanline 1, Plane 2) and (Scanline 1, Plane 3)
  265.  *    This, in fact, is what we do.  This process is quite fast, especially
  266.  * with small images, and allows us to work without additional image buffers,
  267.  * which is something nice, too.
  268.  *    Once we have Plane 1 extracted, we start from the beginning again and
  269.  * now we skip (Scanline 1, Plane 1), process (Scanline 1, Plane 2) and again
  270.  * skip (Scanline 1, Plane 3).  We continue once again through the whole file,
  271.  * extracting all scanlines for the 2nd plane.
  272.  *    And the 3rd plane is handled the same way.  Once we have processed all
  273.  * bitplanes, we're done!
  274.  *    All this is handled with 3 nested while-loops.
  275.  */
  276. void CreateSource(struct IFFHandle *iff,
  277.           struct BitMapHeader *bmhd,
  278.           UBYTE *cmap,
  279.           struct ContextNode *body_context,
  280.           char *Filename,
  281.           char *ID ) {
  282.  
  283.   ULONG n;
  284.   UWORD ColorReg;
  285.   UBYTE *colors;
  286.   ULONG bodysize;
  287.   char *bodybuffer;
  288.   char *iffInfo;
  289.   BOOL Mask = bmhd->masking;
  290.  
  291.  
  292.   printf("/* Source created by Image2'C' "VERSION"\n"
  293.      " * Copyright \© 1994,1995 Udo Schuermann\n"
  294.      " * All rights reserved\n"
  295.      " *\n");
  296.   printf(" * · Inputfile:  \"%s\"\n",
  297.      Filename);
  298.   if( AddDATA && !UseCHIP )
  299.     printf(" * · Image data is not stored in Chip RAM\n");
  300.   if( UseIFDEFs )
  301.     printf(" * · #ifdef/#endif pairs permit selective activation of sections\n");
  302.   printf(" * · Symbol prefix = \"%s\"\n",SYMPREFIX);
  303.   printf(" *\n");
  304.  
  305.   if( fver_prop )
  306.     if( iffInfo = (UBYTE *)fver_prop->sp_Data )
  307.       printf(" * Version:   %s=n",iffInfo);
  308.   if( auth_prop )
  309.     if( iffInfo = (UBYTE *)auth_prop->sp_Data )
  310.       printf(" * Author:    %s\n",iffInfo);
  311.   if( cprt_prop )
  312.     if( iffInfo = (UBYTE *)cprt_prop->sp_Data )
  313.       printf(" * Copyright: %s\n",iffInfo);
  314.   if( anno_prop )
  315.     if( iffInfo = (UBYTE *)anno_prop->sp_Data )
  316.       printf(" * %s\n",iffInfo);
  317.  
  318.   printf(" */\n\n");
  319.  
  320.  
  321.   if( AddIMG ) {
  322.     AddINFO = TRUE;  /* we MUST have this part */
  323.     AddDATA = TRUE;  /* same with this one! */
  324.     if( UseIFDEFs ) {
  325.       printf("#ifdef I2C_IMAGE_IMG\n");
  326.       printf("/* make sure we have all components for the (struct Image) stuff */\n");
  327.       printf("#ifndef I2C_IMAGE_INFO\n");
  328.       printf("#define I2C_IMAGE_INFO\n");
  329.       printf("#endif\n");
  330.       printf("#ifndef I2C_IMAGE_DATA\n");
  331.       printf("#define I2C_IMAGE_DATA\n");
  332.       printf("#endif\n");
  333.       printf("#endif\n\n");
  334.     }
  335.   }
  336.  
  337.  
  338.   if( AddINFO ) {
  339.     if( UseIFDEFs )
  340.       printf("#ifdef I2C_IMAGE_INFO\n");
  341.     printf("/* Image information */\n");
  342.     printf("#define %sImageWide   %d    /* pixels */\n",ID,bmhd->w);
  343.     printf("#define %sImageHigh   %d    /* lines */\n",ID,bmhd->h);
  344.     printf("#define %sImageDeep   %d    /* bit planes */\n",ID,bmhd->nPlanes);
  345.     printf("#define %sImageColors %ld    /* planes^2 */\n",ID,1L<<bmhd->nPlanes);
  346.     if( UseIFDEFs )
  347.       printf("#endif\n");
  348.   }
  349.  
  350.   
  351.   if( AddPENS ) {
  352.     if( UseIFDEFs )
  353.       printf("\n#ifdef I2C_IMAGE_PENS");
  354.     printf("\n/* Register color table (32 bit RGB register values)\n"
  355.        " * Leading these is a WORD with total count and a word\n"
  356.        " * with the first color to be obtained.  We'll start\n"
  357.        " * with the first color there (0)\n"
  358.        " */\n");
  359.     printf("ULONG %sColorPENS[] = {\n",ID);
  360.     n = 1L<<bmhd->nPlanes;
  361.     printf("  (%dL<<16)+0,\n",n);
  362.     colors = cmap;
  363.     while( n-- ) {
  364.       printf("  0x%02x%02x%02x%02x, 0x%02x%02x%02x%02x, 0x%02x%02x%02x%02x",
  365.          *colors,*colors,*colors,*colors,
  366.          *(colors+1),*(colors+1),*(colors+1),*(colors+1),
  367.          *(colors+2),*(colors+2),*(colors+2),*(colors+2));
  368.       colors += 3;
  369.       printf(",\n");
  370.     } /* while */
  371.     printf("  0\n");  /* is this one really necessary? */
  372.     printf("}; /* %sColorPENS[] */\n",ID);
  373.     if( UseIFDEFs )
  374.       printf("#endif\n");
  375.   }
  376.  
  377.  
  378.   if( AddRGB4 ) {
  379.     if( UseIFDEFs )
  380.       printf("\n#ifdef I2C_IMAGE_RGB4");
  381.     printf("\n/* Register color table (4-bit RGB register values):\n"
  382.        " * One packed register value for each `ImageColors`\n"
  383.        " * This table is compatible with the LoadRGB4() function\n"
  384.        " * BUT IS ACCURATE ONLY TO 4 BITS (I.E. A 12-BIT PALETTE)\n"
  385.        " */\n");
  386.     printf("UWORD %sColorRGB4[] = {\n",ID);
  387.     n = 1L<<bmhd->nPlanes;
  388.     colors = cmap;
  389.     while( n-- ) {
  390.       ColorReg = (((UWORD)(*colors) & 0x00f0) << 4) | ((UWORD)(*(colors+1))) & 0x00f0 | (((UWORD)(*(colors+2))) &0x00f0) >> 4;
  391.       printf("  0x%03x",ColorReg);
  392.       colors += 3;
  393.       if( n )
  394.     printf(",\n");
  395.       else
  396.     printf("\n");
  397.     } /* while */
  398.     printf("}; /* %sColorRGB4[] */\n",ID);
  399.     if( UseIFDEFs )
  400.       printf("#endif\n");
  401.   }
  402.  
  403.  
  404.   if( AddDATA )
  405.     if( bodybuffer = malloc(bodysize=body_context->cn_Size) ) {
  406.       if( (bodysize = ReadChunkBytes( iff, bodybuffer, body_context->cn_Size )) == body_context->cn_Size ) {
  407.     char *p;
  408.     UBYTE n;
  409.     UWORD Wide = ((bmhd->w + 15) >> 4) * 2;          /* actual width of a scanline in bytes */
  410.     UWORD Plane;                                     /* Bitplane being output to the 'C' file */
  411.     UWORD curPlane;                                  /* Bitplane being scanned out of the IFF file */
  412.     UWORD curLine;                                   /* Scanline being scanned out of the IFF file */
  413.     UWORD curWide;                                   /* What's been output from the scanline */
  414.     
  415.     if( UseIFDEFs )
  416.       printf("\n#ifdef I2C_IMAGE_DATA");
  417.     printf("\n/* Image data,%s one scanline at a time */\n",((bmhd->nPlanes > 1)?" plane-by-plane, and":""));
  418.     printf("UWORD %s%sImageData[] = {\n",(UseCHIP?"__chip ":""),ID);
  419.     
  420.     Plane = 1;
  421.     while( Plane <= bmhd->nPlanes ) {
  422.       
  423.       if( bmhd->nPlanes > 1 )
  424.         sprintf(LineHeader,"    /* Plane %d */\n",Plane);
  425.       
  426.       p = bodybuffer;                                /* point at the beginning of the buffer */
  427.       curPlane = 1;
  428.       curLine = bmhd->h;
  429.       while( curLine ) {
  430.         
  431.         if( bmhd->compression == 1 ) {
  432.           curWide = Wide;
  433.           while( curWide ) {
  434.         n = *p++;                                  /* get a character from the buffer */
  435.         if( (n >= 0) && (n <= 0x7f) ) {            /* this is a 'copy next n bytes literally' code? */
  436.           n++;
  437.           curWide -= n;
  438.           if( Plane == curPlane ) {
  439.             while( n-- )
  440.               ByteToWordStream(*p++);
  441.           } else
  442.             p += n;
  443.         } else
  444.           if( n != -128 ) {                        /* this is a 'duplicate next byte n times' code? */
  445.             char c = *p++;
  446.             n = 1 - n;
  447.             curWide -= n;
  448.             if( Plane == curPlane ) {
  449.               while( n-- )
  450.             ByteToWordStream(c);
  451.             }
  452.           }
  453.           } /* while */    
  454.           
  455.           /* if we have a standard mask, we'll just skip and ignore it.  Tough luck, mate! */
  456.           if( Mask == mskHasMask ) {
  457.         curWide = Wide;
  458.         while( curWide ) {
  459.           n = *p++;                                  /* get a character from the buffer */
  460.           if( (n >= 0) && (n <= 0x7f) ) {            /* this is a 'copy next n bytes literally' code? */
  461.             n++;
  462.             curWide -= n;
  463.             while( n-- )
  464.               p++;
  465.           } else
  466.             if( n != -128 ) {                        /* this is a 'duplicate next byte n times' code? */
  467.               p++;
  468.               n = 1 - n;
  469.               curWide -= n;
  470.             }
  471.         } /* while */    
  472.           }
  473.         } else {
  474.           /* UNCOMPRESSED; the same code structure would work as we used above, but we've
  475.            * optimized this a bit to avoid excessive checking of (Plane==curPlane)...
  476.            */
  477.           curWide = Wide;
  478.           if( Plane == curPlane ) {
  479.         while( curWide-- )
  480.           ByteToWordStream(*p++);
  481.           } else
  482.         p += curWide;
  483.           
  484.           /* if we have a standard mask, we'll just skip and ignore it.  Tough luck, mate! */
  485.           if( Mask == mskHasMask )
  486.         p += curWide;
  487.         }
  488.         
  489.         if( curPlane == bmhd->nPlanes ) {            /* reached last plane info for this scanline? */
  490.           curPlane = 1;
  491.           curLine--;
  492.           OnNewLine = 1;
  493.         } else
  494.           curPlane++;
  495.         
  496.       } /* while */
  497.       Plane++;
  498.       
  499.     } /* while */
  500.     printf("\n}; /* %sImageData[] */\n",ID);
  501.     if( UseIFDEFs )
  502.       printf("#endif\n");
  503.     
  504.     if( AddIMG ) {
  505.       if( UseIFDEFs )
  506.         printf("\n#ifdef I2C_IMAGE_IMG");
  507.       printf("\nstruct Image %sImage = {0,0,%sImageWide,%sImageHigh,%sImageDeep,%sImageData,0x%02x,0,NULL};\n",
  508.          ID,ID,ID,ID,ID,(1<<bmhd->nPlanes)-1);
  509.       if( UseIFDEFs )
  510.         printf("#endif\n");
  511.     }
  512.       } else
  513.     fprintf(stderr,"Read only %ld bytes instead of %ld from BODY chunk of file (%s)\n",bodysize,body_context->cn_Size,ILBMFILE);
  514.       free( bodybuffer );
  515.     } else
  516.       fprintf(stderr,"No memory to load %ld bytes from BODY chunk of file (%s)\n",body_context->cn_Size,ILBMFILE);
  517.  
  518. } /* CreateSource() */
  519.  
  520.  
  521. #ifdef DEBUG
  522. #define MASKING(n)  (n==0?"None":(n==1?"Mask":(n==2?"Transparent":(n==3?"Lasso":"<unknown>"))))
  523. #define COMPRESS(n) (n==0?"None":(n==1?"ByteRun1":"<unknown>"))
  524. #endif
  525.  
  526. int main( int argc, char *argv[] ) {
  527.  
  528.   struct IFFHandle *IFF;
  529.   struct StoredProperty *bmhd_prop,*cmap_prop;
  530.   struct ContextNode *body_context;
  531.   int argn;
  532.   BOOL badargs = FALSE;
  533.  
  534.   for( argn=1; argn<argc; argn++ ) {
  535.     if( strnicmp("ILBMFILE",argv[argn],8) == 0 ) {
  536.       if( argv[argn][8] == '=' )
  537.     ILBMFILE = &argv[argn][9];
  538.       else {
  539.     argn++;
  540.     if( argn < argc )
  541.       ILBMFILE = argv[argn];
  542.     else {
  543.       fprintf(stderr,"No argument for ILBMFILE key\n");
  544.       badargs = TRUE;
  545.     }
  546.       }
  547.     } else
  548.     if( strnicmp("SYMPREFIX",argv[argn],9) == 0 ) {
  549.       if( argv[argn][9] == '=' )
  550.     SYMPREFIX = &argv[argn][10];
  551.       else {
  552.     argn++;
  553.     if( argn < argc )
  554.       SYMPREFIX = argv[argn];
  555.     else {
  556.       fprintf(stderr,"No argument for SYMPREFIX key\n");
  557.       badargs = TRUE;
  558.     }
  559.       }
  560.     } else
  561.     if( stricmp("NOINFO",argv[argn]) == 0 ) {
  562.       AddINFO = FALSE;
  563.     } else
  564.     if( stricmp("NOPENS",argv[argn]) == 0 ) {
  565.       AddPENS = FALSE;
  566.     } else
  567.     if( stricmp("NODATA",argv[argn]) == 0 ) {
  568.       AddDATA = FALSE;
  569.     } else
  570.     if( stricmp("NOIMAGESTRUCT",argv[argn]) == 0 ) {
  571.       AddIMG = FALSE;
  572.     } else
  573.     if( stricmp("NOIMG",argv[argn]) == 0 ) {
  574.       AddIMG = FALSE;
  575.     } else
  576.     if( stricmp("ADDRGB4",argv[argn]) == 0 ) {
  577.       AddRGB4 = TRUE;
  578.     } else
  579.     if( stricmp("USEIFDEFS",argv[argn]) == 0 ) {
  580.       UseIFDEFs = TRUE;
  581.     } else
  582.     if( stricmp("NOCHIP",argv[argn]) == 0 ) {
  583.       UseCHIP = FALSE;
  584.     } else {
  585.       if( ILBMFILE )
  586.     if( SYMPREFIX ) {
  587.       fprintf(stderr,"Too many arguments; don't know what do to with \"%s\"\n",argv[argn]);
  588.       badargs = TRUE;
  589.     } else
  590.       SYMPREFIX = argv[argn];
  591.       else
  592.     ILBMFILE = argv[argn];
  593.     }
  594.   }
  595.   if( (ILBMFILE == NULL) || (SYMPREFIX == NULL) || badargs ) {
  596.     if( badargs )
  597.       fprintf(stderr,"\n");
  598.     fprintf(stderr,"Image2'C' "VERSION"\n"
  599.         "Copyright © 1994,1995 Udo Schuermann\n"
  600.         "All rights reserved\n\n"
  601.         "Template:  ILBMFILE/A,SYMPREFIX/A,NOINFO/S,NOPENS/S,NODATA/S,NOIMG=NOIMAGESTRUCT/S,ADDRGB4/S,USEIFDEFS/S,NOCHIP/S\n"
  602.         "   ILBMFILE/A        An IFF ILBM (picture) file\n"
  603.         "   SYMPREFIX/A        Prefix for symbols (may be \"\")\n"
  604.         "   NOINFO/S        Suppress image size/depth information\n"
  605.         "   NOPENS/S        Suppress RGB32 pens\n"
  606.         "   NODATA/S        Suppress image data\n"
  607.         "   NOIMG=NOIMAGESTRUCT/S    Suppress \"struct Image...\"\n"
  608.         "   ADDRGB4/S        Add old 4-bit RGB color table\n"
  609.         "   USEIFDEFS/S        Enclose sections with #ifdef/#endif pairs\n"
  610.         "   NOCHIP/S        Omit the __chip attribute on structs\n");
  611.     exit(10);
  612.   }
  613.  
  614.   if( IFF = OpenFileAsIFF( ILBMFILE ) ) {                         /* open file for IFF parsing */
  615.     struct BitMapHeader   *bmhd;
  616.     UBYTE                 *cmap;
  617.     int                   error;
  618.  
  619.     PropChunk( IFF, ID_ILBM, ID_AUTH );                          /* collect AUTH (if any) */
  620.     PropChunk( IFF, ID_ILBM, ID_CPRT );                          /* collect (c)  (if any) */
  621.     PropChunk( IFF, ID_ILBM, ID_ANNO );                          /* collect ANNO (if any) */
  622.     PropChunk( IFF, ID_ILBM, ID_FVER );                          /* collect FVER (if any) */
  623.  
  624.     if( error = PropChunk( IFF, ID_ILBM, ID_BMHD ) )             /* collect BMHD */
  625.       fprintf(stderr,"Error %ld with PropChunk(ILBM,BMHD) in file (%s)\n",error,ILBMFILE);
  626.  
  627.     if( error = PropChunk( IFF, ID_ILBM, ID_CMAP ) )             /* collect CMAP */
  628.       fprintf(stderr,"Error %ld with PropChunk(ILBM,CMAP) in file (%s)\n",error,ILBMFILE);
  629.  
  630.     if( error = StopChunk( IFF, ID_ILBM, ID_BODY ) )             /* stop when we reach BODY */
  631.       fprintf(stderr,"Error %ld with StopChunk(ILBM,BODY) in file (%s)\n",error,ILBMFILE);
  632.  
  633.     if( ParseIFF( IFF, IFFPARSE_SCAN ) == 0 ) {                  /* Let's BOOGIE!!! (we stop at BODY) */
  634.       auth_prop = FindProp( IFF, ID_ILBM, ID_AUTH );             /* get pointer to AUTH, if any */
  635.       cprt_prop = FindProp( IFF, ID_ILBM, ID_CPRT );
  636.       anno_prop = FindProp( IFF, ID_ILBM, ID_ANNO );
  637.       fver_prop = FindProp( IFF, ID_ILBM, ID_FVER );
  638.       if( bmhd_prop = FindProp( IFF, ID_ILBM, ID_BMHD ) ) {      /* get pointer to BMHD; required! */
  639.     bmhd = (struct BitMapHeader *)bmhd_prop->sp_Data;
  640.     if( cmap_prop = FindProp( IFF, ID_ILBM, ID_CMAP ) ) {    /* get pointer to CMAP; required! */
  641.       cmap = (UBYTE *)cmap_prop->sp_Data;
  642.       if( body_context = CurrentChunk( IFF ) ) {             /* where we stopped is the BODY chunk */
  643. #ifdef DEBUG
  644.         fprintf(stderr,"BMHD.width       = %4d\n",bmhd->w);
  645.         fprintf(stderr,"BMHD.height      = %4d\n",bmhd->h);
  646.         fprintf(stderr,"BMHD.depth       = %4d\n",bmhd->nPlanes);
  647.         fprintf(stderr,"BMHD.masking     = %s\n",MASKING(bmhd->masking));
  648.         fprintf(stderr,"BMHD.compression = %s\n",COMPRESS(bmhd->compression));
  649.         fprintf(stderr,"BMHD.transpColor = %4d\n",bmhd->transparentColor);
  650.         fprintf(stderr,"BMHD.Aspect (x:y)= %d:%d\n",bmhd->xAspect,bmhd->yAspect);
  651.         fprintf(stderr,"\n");
  652.         
  653.         fprintf(stderr,"CMAP.SIZE        = %ld\n",cmap_prop->sp_Size);
  654.         fprintf(stderr,"\n");
  655.         
  656.         fprintf(stderr,"BODY.SIZE        = %ld\n",body_context->cn_Size);
  657. #endif
  658.         /* make sure we can handle the masking and compression that is used */
  659.         if(((bmhd->compression == 0) || (bmhd->compression == 1)) &&
  660.            ((bmhd->masking == 0) || (bmhd->masking == 1) || (bmhd->masking == 2) ||
  661.         (bmhd->masking == 3)))
  662.           CreateSource( IFF, bmhd, cmap, body_context, ILBMFILE, SYMPREFIX );
  663.         else {
  664.           /* error messages as to why we can't process this file */
  665.           printf("Sorry, I do not know how to handle images (%s) with compression code %d!\n",
  666.              ILBMFILE,bmhd->compression);
  667.         }
  668.       } else
  669.         fprintf(stderr,"Missing BODY chunk in file (%s)\n",ILBMFILE);
  670.     } else
  671.       fprintf(stderr,"Missing CMAP chunk in file (%s)\n",ILBMFILE);
  672.       } else
  673.     fprintf(stderr,"Missing BMHD chunk in file (%s)\n",ILBMFILE);
  674.     } else
  675.       fprintf(stderr,"File (%s) seems to contain no images\n",ILBMFILE);
  676.  
  677.     CloseIFF( IFF );                                             /* close iff parsing */
  678.     Close( IFF->iff_Stream );                                    /* close file stream */
  679.     FreeIFF( IFF );                                              /* free associated internal structures */
  680.   } else
  681.     fprintf(stderr,"File (%s) unavailable or not a FORM IFF\n",ILBMFILE);
  682. } /* main() */
  683.