home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 311.lha / Wipedemo_v4.0 / Wipepict.c < prev   
C/C++ Source or Header  |  1980-12-10  |  10KB  |  395 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. /*this is an all too common state of software development.  Get rid
  39.   of this define as soon as it runs*/
  40. /*#define DEBUG*/
  41.  
  42. /*this is the normal state of software development.  Seriously undefine
  43.   this to make it shut up about errors and reduce code size half way
  44.   through beta testing... */
  45. /*#define PARANOID*/
  46.  
  47.  
  48. static struct ILBM_info *read_ilbm(), *read_body();
  49.  
  50. /* OK this code is almost re-entrant.  Pass this guy from above to
  51.    make it really re-entrant.  (Why do you need a reentrant ILBM
  52.    reader though??  Maybe for Dale ... ) */
  53. static struct ILBM_info root_info;  /*static so get initialized to zero*/
  54.  
  55.  
  56. #ifdef PARANOID
  57. /* a little paranoid routine that say's where we got before EOF */
  58. static void
  59. iff_truncated(where)
  60. int where;
  61. {
  62. printf("ILBM truncated %d\n", where);
  63. free_planes(&root_info.bitmap);
  64. }
  65. #endif PARANOID
  66.  
  67.  
  68. struct ILBM_info *
  69. read_iff(name, just_colors)
  70. char *name;
  71. short just_colors;
  72. {
  73. struct ILBM_info *info = &root_info;
  74. FILE *file;
  75. struct form_chunk chunk;
  76.  
  77. if ((file = fopen(name, "r") ) == 0)
  78.    {
  79. #ifdef PARANOID
  80.    printf("couldn't Open %s to read\n", name);
  81. #endif PARANOID
  82.    return(NULL);
  83.    }
  84.  
  85. if ( fread(&chunk, sizeof(struct form_chunk), 1, file) != 1)
  86.    {
  87. #ifdef PARANOID
  88.    iff_truncated(0);
  89. #endif PARANOID
  90.    fclose(file);
  91.    return(NULL);
  92.    }
  93.  
  94. if (chunk.fc_type.b4_type != FORM)
  95.    {
  96. #ifdef PARANOID
  97.    printf("not a FORM - %s\n", name);
  98. #endif PARANOID
  99.    fclose(file);
  100.    return(NULL);
  101.    }
  102.  
  103. if (chunk.fc_subtype.b4_type != ILBM)
  104.    {
  105. #ifdef PARANOID
  106.    printf("FORM not an ILBM - %s\n", name);
  107. #endif PARANOID
  108.    fclose(file);
  109.    return(NULL);
  110.    }
  111.  
  112. #ifdef DEBUG
  113. printf("FORM %ld ILBM\n", chunk.fc_length);
  114. #endif DEBUG
  115.  
  116. info = read_ilbm(file, info, chunk.fc_length - sizeof(chunk), just_colors);
  117. fclose(file);
  118. return(info);
  119. }
  120.  
  121. static
  122. struct ILBM_info *
  123. read_ilbm(file, info, length, just_colors)
  124. FILE *file;
  125. struct ILBM_info *info;
  126. long length;
  127. short just_colors;
  128. {
  129. struct iff_chunk chunk;
  130. int i,cringes = 0;
  131. long read_in = 0;
  132. int got_header = FALSE;  /*to make sure gots the header first*/
  133. int got_cmap = FALSE;  /*make sure get cmap before "BODY" */
  134.  
  135. /*make sure the Planes are all NULL so can free up memory easily
  136.   on error abort */
  137. for (i=0; i<8; i++)
  138.    info->bitmap.Planes[i] = NULL;
  139. info->camg = 0L;
  140. for (i=0; i<6; i++)
  141.    info->crng[i].active = 0;
  142.  
  143. while (read_in < length)
  144.    {
  145.    if (fread(&chunk, sizeof(chunk), 1, file) != 1)
  146.       {
  147. #ifdef PARANOID
  148.       iff_truncated(1);
  149. #endif PARANOID
  150.       return(NULL);
  151.       }
  152.    switch (chunk.iff_type.b4_type)
  153.       {
  154.       case BMHD:
  155. #ifdef DEBUG
  156.          printf("\tBMHD %ld\n", chunk.iff_length);
  157. #endif DEBUG
  158.          if (fread(&info->header, sizeof(info->header), 1, file) != 1)
  159.             {
  160. #ifdef PARANOID
  161.             iff_truncated(2);
  162. #endif PARANOID
  163.             return(NULL);
  164.             }
  165.          got_header = TRUE;
  166.          break;
  167.       case CMAP:
  168. #ifdef DEBUG
  169.          printf("\tCMAP %ld\n", chunk.iff_length);
  170. #endif DEBUG
  171.          if (!got_header)
  172.             {
  173. #ifdef PARANOID
  174.             printf("CMAP befor BMHD\n");
  175. #endif PARANOID
  176.             return(NULL);
  177.             }
  178.          if (chunk.iff_length <= 3*MAXCOL )
  179.             {
  180.             if (fread(info->cmap, (int)chunk.iff_length, 1, file) != 1)
  181.                {
  182. #ifdef PARANOID
  183.                iff_truncated(3);
  184. #endif PARANOID
  185.                return(NULL);
  186.                }
  187.             }
  188.          else
  189.             {
  190. #ifdef PARANOID
  191.             printf("warning, more than %d colors in ILBM CMAP\n",
  192.                MAXCOL);
  193. #endif PARANOID
  194.             if (fread(info->cmap, 3*MAXCOL, 1, file) != 1)
  195.                {
  196. #ifdef PARANOID
  197.                iff_truncated(4);
  198. #endif PARANOID
  199.                return(NULL);
  200.                }
  201.             bit_bucket(file, chunk.iff_length - sizeof(3*MAXCOL));
  202.             }
  203.          got_cmap = TRUE;
  204.          if (just_colors)
  205.             return(info);
  206.          break;
  207.       case BODY:
  208.          if (!got_cmap)
  209.             {
  210. #ifdef PARANOID
  211.             printf("BODY before CMAP\n");
  212. #endif PARANOID
  213.             return(NULL);
  214.             }
  215. #ifdef DEBUG
  216.          printf("\tBODY %ld\n", chunk.iff_length);
  217. #endif DEBUG
  218.          return( read_body(file, info, chunk.iff_length) );
  219.  
  220.       case CAMG:
  221. #ifdef DEBUG
  222.          printf("\tCAMG %ld\n", chunk.iff_length);
  223. #endif DEBUG
  224.          if (fread(&info->camg, 4, 1, file) != 1)
  225.             {
  226. #ifdef PARANOID
  227.             iff_truncated(2);
  228. #endif PARANOID
  229.             return(NULL);
  230.             }
  231.          break;
  232.       case CRNG:
  233.          fread(&info->crng[cringes++],8,1,file);
  234.          break;
  235.       default:
  236.          bit_bucket(file, chunk.iff_length);
  237.          break;
  238.       }
  239.    read_in += chunk.iff_length + sizeof(chunk);
  240.    }
  241. #ifdef PARANOID
  242. printf("no BODY in ILBM\n");
  243. #endif PARANOID
  244. return(NULL); 
  245. }
  246.  
  247.  
  248.  
  249. static
  250. struct ILBM_info *
  251. read_body(file, info, length)
  252. FILE *file;
  253. register struct ILBM_info *info;
  254. long length;
  255. {
  256. struct ILBM_header *header;
  257. struct BitMap *bm;
  258. int i, j;
  259. int rlength;
  260. int plane_offset;
  261.  
  262. #ifdef DEBUG
  263. printf("read_body( %lx %lx %ld)\n", file, info, length);
  264. #endif DEBUG
  265.  
  266. #ifdef PARANOID
  267. /* when paranoid do a little error checking first ... fail fast! */
  268. if (info->header.nPlanes > 8)
  269.    {
  270.    printf("Whoa, woe  Dale only speaks 8 planes boy, not %d\n",
  271.       info->header.nPlanes);
  272.    return(NULL);
  273.    }
  274. #endif PARANOID
  275.  
  276. /* ok a little more error checking */
  277. if (info->header.compression != 0 && info->header.compression != 1)
  278.    {
  279. #ifdef PARANOID
  280.    printf("unrecognized compression type %d\n", info->header.compression);
  281. #endif PARANOID
  282.    return(NULL);
  283.    }
  284.  
  285. /*set up the bitmap part that doesn't involve memory allocation first -
  286.   hey this part does get done, and let's be optimistic...*/
  287. info->bitmap.BytesPerRow = line_bytes(info->header.w);
  288. info->bitmap.Rows = info->header.h;
  289. info->bitmap.Depth = info->header.nPlanes;
  290. info->bitmap.Flags = info->bitmap.pad = 0;
  291.  
  292. rlength = info->bitmap.Rows * info->bitmap.BytesPerRow;
  293.  
  294. for (i=0; i<info->header.nPlanes; i++)
  295.    {
  296.    if ((info->bitmap.Planes[i] = ralloc(rlength)) == NULL)
  297.       {
  298. #ifdef PARANOID
  299.       printf("couldn't alloc plane %d in read_body\n",i);
  300. #endif PARANOID
  301.       free_planes( &info->bitmap );
  302.       return(NULL);
  303.       }
  304.    }
  305. plane_offset = 0;
  306. for (i=0; i<info->bitmap.Rows; i++)
  307.    {
  308.    /* this test should be in the inner loop for shortest code,
  309.       in the outer loop for greatest speed, so sue me I compromised */
  310.    if (info->header.compression == 0)
  311.       {
  312.       for (j = 0; j < info->bitmap.Depth; j++)
  313.          {
  314.          if ( fread(info->bitmap.Planes[j] + plane_offset,
  315.             info->bitmap.BytesPerRow, 1, file) != 1)
  316.             {
  317. #ifdef PARANOID
  318.             iff_truncated(6);
  319. #endif PARANOID
  320.             free_planes( &info->bitmap);
  321.             return(NULL);
  322.             }
  323.          }
  324.       }
  325.    else
  326.       {
  327.       register char *dest, value;
  328.       register int so_far, count;  /*how much have unpacked so far*/
  329.  
  330.       for (j = 0; j < info->bitmap.Depth; j++)
  331.          {
  332.          so_far = info->bitmap.BytesPerRow;
  333.          dest = (char *)info->bitmap.Planes[j] + plane_offset;
  334.          while (so_far > 0)
  335.             {
  336.             if ( (value = getc(file)) == 128)
  337.                {
  338. #ifdef DEBUG
  339.                printf("NOP\n");
  340. #endif DEBUG
  341.                }
  342.             else if (value > 0)
  343.                {
  344.                count = (int)value + 1;
  345.                so_far -= count;
  346.                if ( fread(dest, count, 1, file) != 1)
  347.                   {
  348. #ifdef PARANOID
  349.                   iff_truncated(7);
  350. #endif PARANOID
  351.                   free_planes( &info->bitmap);
  352.                   return(NULL);
  353.                   }
  354.                dest += count;
  355.                }
  356.             else 
  357.                {
  358.                count = (int)-value + 1;
  359.                so_far -= count;
  360.                value = getc(file);
  361.                while (--count >= 0)  /*this is fastest loop in C */
  362.                   *dest++ = value;
  363.                }
  364.             }
  365.          if (so_far != 0)
  366.             {
  367. #ifdef PARANOID
  368.             printf("compression quite screwed up, aborting %d\n", so_far);
  369. #endif PARANOID
  370.             free_planes( &info->bitmap);
  371.             return(NULL);
  372.             }
  373.          }
  374.       }
  375.    plane_offset += info->bitmap.BytesPerRow;
  376.    }
  377. return(info);
  378. }
  379.  
  380.  
  381. void
  382. free_planes(bmap)
  383. register struct BitMap *bmap;
  384. {
  385. PLANEPTR plane;
  386. long length;
  387. short i;
  388.  
  389. length = ((long) bmap->BytesPerRow) * bmap->Rows;
  390.  
  391. for (i=0; i<8; i++)
  392.    if ( (plane = bmap->Planes[i]) != NULL)
  393.       rfree(plane, length);
  394. }
  395.