home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d1xx / d160 / dwip.lha / DWIP / jiff.c < prev    next >
C/C++ Source or Header  |  1988-10-02  |  9KB  |  350 lines

  1. /**********************************************************************
  2. *
  3. *            jiff.c   Jim Kent's iff - ilbm  reader
  4. *
  5. * This is the (sortof) short (sortof) simple no-frills IFF reader
  6. * to get something out of DPaint, Images, or the Animator.  It
  7. * works well with the Aztec C compiler.  It should work with Lattice
  8. * but you never know until you try it.  I haven't.
  9. *
  10. * I've included a simple main program.  This is just to make it
  11. * stand alone.  Since amiga screen initializations are massive, all
  12. * it does as is is read it into a BitMap, and then free up the BitMap.
  13. * Should crash it if it's gonna crash though.
  14. *
  15. * The main interface to this is through the routine read_iff(filename).
  16. * This returns a ILBM_info structure-pointer on success, and NULL on
  17. * failure.  It cleans up after itself on failure.
  18. *
  19. * I hope you will find this useful and easy to use.  Please forgive
  20. * my funky indentation style?  Well at least I'm consistent!
  21. *
  22. * To demonstrate what a nice guy I am even though I'm far from wild
  23. * about the IFF standard I'm placing this in the public domain.  When
  24. * you remove the DEBUG and PARANOID definitions the code is only
  25. * 1536 bytes long.
  26. *
  27. *        -Jim Kent  April 22, 1986
  28. ************************************************************************/
  29.  
  30. #include <stdio.h>
  31. #include <exec/types.h>
  32. #include <exec/memory.h>
  33. #include <graphics/gfx.h>
  34. #include <libraries/dos.h>
  35. #include "jiff.h"
  36.  
  37. /*this is the normal state of software development.  Seriously undefine
  38.   this to make it shut up about errors and reduce code size half way
  39.   through beta testing... */
  40. #define PARANOID
  41.  
  42. static struct ILBM_info *read_ilbm(), *read_body();
  43.  
  44. /* OK this code is almost re-entrant.  Pass this guy from above to
  45.    make it really re-entrant.  (Why do you need a reentrant ILBM
  46.    reader though??  Maybe for Dale ... ) */
  47. static struct ILBM_info root_info;  /*static so get initialized to zero*/
  48.  
  49.  
  50. #ifdef PARANOID
  51. /* a little paranoid routine that say's where we got before EOF */
  52. static void iff_truncated(where)
  53. int where;
  54. {
  55.     printf("ILBM truncated %d\n", where);
  56.     free_planes(&root_info.bitmap);
  57. } /* iff_truncated */
  58. #endif PARANOID
  59.  
  60. struct ILBM_info *read_iff(name, just_colors)
  61. char *name;
  62. short just_colors;
  63. {
  64.     struct ILBM_info *info = &root_info;
  65.     FILE *file;
  66.     struct form_chunk chunk;
  67.  
  68.     if ((file = fopen(name, "r") ) == 0){
  69. #ifdef PARANOID
  70.         printf("couldn't Open %s to read\n", name);
  71. #endif PARANOID
  72.         return(NULL);
  73.     }
  74.  
  75.     if ( fread(&chunk, sizeof(struct form_chunk), 1, file) != 1){
  76. #ifdef PARANOID
  77.         iff_truncated(0);
  78. #endif PARANOID
  79.         fclose(file);
  80.         return(NULL);
  81.     }
  82.  
  83.     if (chunk.fc_type.b4_type != FORM){
  84. #ifdef PARANOID
  85.         printf("not a FORM - %s\n", name);
  86. #endif PARANOID
  87.         fclose(file);
  88.         return(NULL);
  89.     }
  90.  
  91.     if (chunk.fc_subtype.b4_type != ILBM){
  92. #ifdef PARANOID
  93.         printf("FORM not an ILBM - %s\n", name);
  94. #endif PARANOID
  95.         fclose(file);
  96.         return(NULL);
  97.     }
  98.  
  99. #ifdef DEBUG
  100.     printf("FORM %ld ILBM\n", chunk.fc_length);
  101. #endif DEBUG
  102.  
  103.     info = read_ilbm(file, info, chunk.fc_length - sizeof(chunk), 
  104.         just_colors);
  105.     fclose(file);
  106. #ifdef DEBUG
  107.     printf("info = %lx\n", info);
  108. #endif DEBUG
  109.     return(info);
  110. } /* read_iff */
  111.  
  112. static struct ILBM_info *read_ilbm(file, info, length, just_colors)
  113. FILE *file;
  114. struct ILBM_info *info;
  115. long length;
  116. short just_colors;
  117. {
  118.     struct iff_chunk chunk;
  119.     int i;
  120.     long read_in = 0;
  121.     int got_header = FALSE;  /*to make sure gots the header first*/
  122.     int got_cmap = FALSE;  /*make sure get cmap before "BODY" */
  123.  
  124. /* make sure the Planes are all NULL so can free up memory easily
  125.  * on error abort */
  126.     for (i=0; i<8; i++)
  127.         info->bitmap.Planes[i] = NULL;
  128.  
  129.     while (read_in < length){
  130.         if (fread(&chunk, sizeof(chunk), 1, file) != 1){
  131. #ifdef PARANOID
  132.             iff_truncated(1);
  133. #endif PARANOID
  134.             return(NULL);
  135.         }
  136.         switch (chunk.iff_type.b4_type){
  137.  
  138.         case BMHD:
  139. #ifdef DEBUG
  140.             printf("\tBMHD %ld\n", chunk.iff_length);
  141. #endif DEBUG
  142.             if (fread(&info->header, sizeof(info->header), 1, file) != 1){
  143. #ifdef PARANOID
  144.                 iff_truncated(2);
  145. #endif PARANOID
  146.                 return(NULL);
  147.             }
  148.             got_header = TRUE;
  149.             break;
  150.  
  151.         case CMAP:
  152. #ifdef DEBUG
  153.             printf("\tCMAP %ld\n", chunk.iff_length);
  154. #endif DEBUG
  155.             if (!got_header){
  156. #ifdef PARANOID
  157.                 printf("CMAP befor BMHD\n");
  158. #endif PARANOID
  159.                 return(NULL);
  160.             }
  161.             if (chunk.iff_length <= 3*MAXCOL ){
  162.                 if (fread(info->cmap, (int)chunk.iff_length, 1, file) != 1){
  163. #ifdef PARANOID
  164.                     iff_truncated(3);
  165. #endif PARANOID
  166.                     return(NULL);
  167.                 }
  168.             }else{
  169. #ifdef PARANOID
  170.                 printf("warning, more than %d colors in ILBM CMAP\n",
  171.                     MAXCOL);
  172. #endif PARANOID
  173.                 if (fread(info->cmap, 3*MAXCOL, 1, file) != 1){
  174. #ifdef PARANOID
  175.                     iff_truncated(4);
  176. #endif PARANOID
  177.                     return(NULL);
  178.                 }
  179.                 bit_bucket(file, chunk.iff_length - sizeof(3*MAXCOL));
  180.             }
  181.             got_cmap = TRUE;
  182.             if (just_colors)
  183.                 return(info);
  184.             break;
  185.  
  186.         case BODY:
  187.             if (!got_cmap){
  188. #ifdef PARANOID
  189.                 printf("BODY before CMAP\n");
  190. #endif PARANOID
  191.                 return(NULL);
  192.             }
  193. #ifdef DEBUG
  194.             printf("\tBODY %ld\n", chunk.iff_length);
  195. #endif DEBUG
  196.             return( read_body(file, info, chunk.iff_length) );
  197.  
  198.         case GRAB:  /*ignore documented but unwanted types*/
  199.         case DEST:
  200.         case SPRT:
  201.         case CAMG:
  202.         case CRNG:
  203.         case CCRT:
  204.             bit_bucket(file, chunk.iff_length);
  205.             break;
  206.  
  207.         default:    /*squawk about unknown types if PARANOID */
  208. #ifdef PARANOID
  209.             printf("\t unk type %lx of b4_type\n", chunk.iff_type.b4_type);
  210. #endif PARANOID
  211.  
  212.         } /* switch */
  213.  
  214.         read_in += chunk.iff_length + sizeof(chunk);
  215.     } /* while */
  216. #ifdef PARANOID
  217.     printf("no BODY in ILBM\n");
  218. #endif PARANOID
  219.     return(NULL); 
  220. } /* read_ilbm */
  221.  
  222. static struct ILBM_info *read_body(file, info, length)
  223. FILE *file;
  224. register struct ILBM_info *info;
  225. long length;
  226. {
  227.     struct ILBM_header *header;
  228.     struct BitMap *bm;
  229.     int i, j;
  230.     int rlength;
  231.     int plane_offset;
  232.  
  233. #ifdef DEBUG
  234.     printf("read_body( %lx %lx %ld)\n", file, info, length);
  235. #endif DEBUG
  236.  
  237. #ifdef PARANOID
  238.     /* when paranoid do a little error checking first ... fail fast! */
  239.     if (info->header.nPlanes > 8){
  240.         printf("Whoa, woe  Dale only speaks 8 planes boy, not %d\n",
  241.             info->header.nPlanes);
  242.         return(NULL);
  243.     }
  244. #endif PARANOID
  245.  
  246.     /* ok a little more error checking */
  247.     if (info->header.compression != 0 && info->header.compression != 1){
  248. #ifdef PARANOID
  249.         printf("unrecognized compression type %d\n", 
  250.             info->header.compression);
  251. #endif PARANOID
  252.         return(NULL);
  253.     }
  254.  
  255. /*set up the bitmap part that doesn't involve memory allocation first -
  256.   hey this part does get done, and let's be optimistic...*/
  257.     info->bitmap.BytesPerRow = line_bytes(info->header.w);
  258.     info->bitmap.Rows = info->header.h;
  259.     info->bitmap.Depth = info->header.nPlanes;
  260.     info->bitmap.Flags = info->bitmap.pad = 0;
  261.  
  262.     rlength = info->bitmap.Rows * info->bitmap.BytesPerRow;
  263.  
  264.     for (i=0; i<info->header.nPlanes; i++){
  265.         if ((info->bitmap.Planes[i] = ralloc(rlength)) == NULL){
  266. #ifdef PARANOID
  267.             printf("couldn't alloc plane %d in read_body\n",i);
  268. #endif PARANOID
  269.             free_planes( &info->bitmap );
  270.             return(NULL);
  271.         }
  272.     } /* for i */
  273.  
  274.     plane_offset = 0;
  275.     for (i=0; i<info->bitmap.Rows; i++){
  276.         /* this test should be in the inner loop for shortest code,
  277.             * in the outer loop for greatest speed, so sue me I compromised.
  278.          */
  279.         if (info->header.compression == 0){
  280.             for (j = 0; j < info->bitmap.Depth; j++){
  281.                 if ( fread(info->bitmap.Planes[j] + plane_offset,
  282.                         info->bitmap.BytesPerRow, 1, file) != 1){
  283. #ifdef PARANOID
  284.                     iff_truncated(6);
  285. #endif PARANOID
  286.                     free_planes( &info->bitmap);
  287.                     return(NULL);
  288.                 }
  289.             } /* for j */
  290.         }else{
  291.             register char *dest, value;
  292.             register int so_far, count;  /*how much have unpacked so far*/
  293.  
  294.             for (j = 0; j < info->bitmap.Depth; j++){
  295.                 so_far = info->bitmap.BytesPerRow;
  296.                 dest = (char *)info->bitmap.Planes[j] + plane_offset;
  297.                 while (so_far > 0){
  298.                     if ( (value = getc(file)) == 128){
  299. #ifdef DEBUG
  300.                         printf("NOP\n");
  301. #endif DEBUG
  302.                     }else if (value > 0){
  303.                         count = (int)value + 1;
  304.                         so_far -= count;
  305.                         if ( fread(dest, count, 1, file) != 1){
  306. #ifdef PARANOID
  307.                             iff_truncated(7);
  308. #endif PARANOID
  309.                             free_planes( &info->bitmap);
  310.                             return(NULL);
  311.                         }
  312.                         dest += count;
  313.                     }else{
  314.                         count = (int)-value + 1;
  315.                         so_far -= count;
  316.                         value = getc(file);
  317.                         while (--count >= 0)  /*this is fastest loop in C */
  318.                             *dest++ = value;
  319.                     } /* if value */
  320.                 } /* while */
  321.                 if (so_far != 0){
  322. #ifdef PARANOID
  323.                     printf("compression quite screwed up, aborting %d\n", 
  324.                             so_far);
  325. #endif PARANOID
  326.                     free_planes( &info->bitmap);
  327.                     return(NULL);
  328.                 } /* if so_far */
  329.             } /* for j */
  330.         } /* if info->header.compression */
  331.         plane_offset += info->bitmap.BytesPerRow;
  332.     } /* for i */
  333.     return(info);
  334. } /* read_body */
  335.  
  336. void free_planes(bmap)
  337. register struct BitMap *bmap;
  338. {
  339.     PLANEPTR plane;
  340.     long length;
  341.     short i;
  342.  
  343.     length = bmap->BytesPerRow * bmap->Rows;
  344.  
  345.     for (i=0; i<8; i++)
  346.         if ( (plane = bmap->Planes[i]) != NULL)
  347.             rfree(plane, length);
  348. } /* free_planes */
  349.  
  350.