home *** CD-ROM | disk | FTP | other *** search
/ The CDPD Public Domain Collection for CDTV 3 / CDPDIII.bin / pd / commodities / superdark / iff / jiff.c next >
C/C++ Source or Header  |  1992-11-07  |  8KB  |  376 lines

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