home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d1xx / d114 / wblander.lha / WBLander / Source / jiff.c < prev    next >
C/C++ Source or Header  |  1987-11-22  |  9KB  |  376 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. * The main interface to this is through the routine read_iff(filename).
  11. * This returns a ILBM_info structure-pointer on success, and NULL on
  12. * failure.  It cleans up after itself on failure.
  13. *
  14. * I hope you will find this useful and easy to use.  Please forgive
  15. * my funky indentation style?  Well at least I'm consistent!
  16. *
  17. *     [ I didn't forgive it. I changed it -- Peter ]
  18. *
  19. * To demonstrate what a nice guy I am even though I'm far from wild
  20. * about the IFF standard I'm placing this in the public domain.  When
  21. * you remove the DEBUG and PARANOID definitions the code is only
  22. * 1536 bytes long.
  23. *
  24. *        -Jim Kent  April 22, 1986
  25. *
  26. * Cleaned it up and added CAMG chunk handler. Also, fixed indentation
  27. * and removed static reference to root_info, allowing multiple images
  28. * to be loaded.
  29. *
  30. *       -Peter da Silva  September 27, 1987
  31. ************************************************************************/
  32.  
  33. #include <stdio.h>
  34. #include <exec/types.h>
  35. #include <exec/memory.h>
  36. #include <graphics/gfx.h>
  37. #include <libraries/dos.h>
  38. #include <intuition/intuition.h>
  39. #include "jiff.h"
  40.  
  41. /* #define DEBUG */
  42. #define PARANOID
  43.  
  44. #ifdef DEBUG
  45. # define D(x) x
  46. #else
  47. # define D(x)
  48. #endif
  49.  
  50. #ifdef PARANOID
  51. # define P(x) x
  52. #else
  53. # define P(x)
  54. #endif
  55.  
  56. static struct ILBM_info *read_ilbm(), *read_body();
  57.  
  58. static struct ILBM_info *root_info;
  59.  
  60. void free_image();
  61. #define CHIP (MEMF_PUBLIC|MEMF_CHIP)
  62.  
  63. #ifdef PARANOID
  64. /* a little paranoid routine that say's where we got before EOF */
  65. static void
  66. iff_truncated(info,where)
  67. struct ILBM_info *info;
  68. int where;
  69. {
  70.     printf("ILBM truncated %d\n", where);
  71.     free_image(info);
  72. }
  73. #else
  74. #define iff_truncated(i,w) free_image(i)
  75. #endif
  76.  
  77. struct ILBM_info *
  78. read_iff(name, just_colors)
  79. char *name;
  80. short just_colors;
  81. {
  82.     struct ILBM_info *info;
  83.     FILE *file;
  84.     struct form_chunk chunk;
  85.  
  86.     info = 0;
  87.  
  88.     if((file = fopen(name, "r") ) == 0)
  89.     {
  90.         P(printf("couldn't Open %s to read\n", name));
  91.         return(NULL);
  92.     }
  93.  
  94.     if( fread(&chunk, sizeof(struct form_chunk), 1, file) != 1)
  95.     {
  96.         iff_truncated(NULL, 0);
  97.         fclose(file);
  98.         return(NULL);
  99.     }
  100.  
  101.     if(chunk.fc_type.b4_type != FORM)
  102.     {
  103.         P(printf("not a FORM - %s\n", name));
  104.         fclose(file);
  105.         return(NULL);
  106.     }
  107.  
  108.     if(chunk.fc_subtype.b4_type != ILBM)
  109.     {
  110.         P(printf("FORM not an ILBM - %s\n", name));
  111.         fclose(file);
  112.         return(NULL);
  113.     }
  114.  
  115.     D(printf("FORM %ld ILBM\n", chunk.fc_length));
  116.  
  117.     root_info = AllocMem(sizeof(struct ILBM_info), MEMF_PUBLIC);
  118.     if(!root_info) {
  119.         P(printf("Can't allocate ILBM_info.\n"));
  120.         fclose(file);
  121.         return NULL;
  122.     }
  123.  
  124.     info = read_ilbm(file, root_info, chunk.fc_length - sizeof(chunk), just_colors);
  125.     if(info) {
  126.         if(info->viewmode & HAM)
  127.             info->colors = 16;
  128.         if(info->header.h > 298)
  129.             info->viewmode |= LACE;
  130.         if(info->header.w > 376)
  131.             info->viewmode |= HIRES;
  132.     }
  133.     fclose(file);
  134.     D(printf("info = %lx\n", info));
  135.     return(info);
  136. }
  137.  
  138. static
  139. struct ILBM_info *
  140. read_ilbm(file, info, length, just_colors)
  141. FILE *file;
  142. struct ILBM_info *info;
  143. long length;
  144. short just_colors;
  145. {
  146.     struct iff_chunk chunk;
  147.     int i;
  148.     long read_in = 0;
  149.     int got_header = FALSE;  /*to make sure gots the header first*/
  150.     int got_cmap = FALSE;  /*make sure get cmap before "BODY" */
  151.  
  152.     info->viewmode = 0L;
  153.  
  154.     /*make sure the Planes are all NULL so can free up memory easily
  155.       on error abort */
  156.     for (i=0; i<8; i++)
  157.         info->bitmap.Planes[i] = NULL;
  158.  
  159.     while (read_in < length)
  160.     {
  161.         if(fread(&chunk, sizeof(chunk), 1, file) != 1)
  162.         {
  163.             iff_truncated(info, 1);
  164.             return(NULL);
  165.         }
  166.         switch (chunk.iff_type.b4_type)
  167.         {
  168.             case BMHD:
  169.                 D(printf("\tBMHD %ld\n", chunk.iff_length));
  170.                 if(fread(&info->header, sizeof(info->header), 1, file) != 1)
  171.                 {
  172.                     iff_truncated(info, 2);
  173.                     return(NULL);
  174.                 }
  175.                 got_header = TRUE;
  176.                 break;
  177.             case CMAP:
  178.                 D(printf("\tCMAP %ld\n", chunk.iff_length));
  179.                 if(!got_header) {
  180.                     printf("CMAP befor BMHD\n");
  181.                     free_image(info);
  182.                     return(NULL);
  183.                 }
  184.                 if(chunk.iff_length <= 3*MAXCOL ) {
  185.                     if(fread(info->cmap, (int)chunk.iff_length, 1, file) != 1) {
  186.                         iff_truncated(info, 3);
  187.                         return(NULL);
  188.                     }
  189.                     info->colors = chunk.iff_length/3;
  190.                 } else {
  191.                     P(printf("warning, more than %d colors in ILBM CMAP\n",
  192.                         MAXCOL));
  193.                     if(fread(info->cmap, 3*MAXCOL, 1, file) != 1)
  194.                     {
  195.                         iff_truncated(info, 4);
  196.                         return(NULL);
  197.                     }
  198.                     bit_bucket(file, chunk.iff_length - 3*MAXCOL);
  199.                     info->colors = MAXCOL;
  200.                 }
  201.                 got_cmap = TRUE;
  202.                 if(just_colors)
  203.                     return(info);
  204.                 break;
  205.             case CAMG:
  206.                 D(printf("\tCAMG %ld\n", chunk.iff_length));
  207.                 if(chunk.iff_length <= sizeof(long) ) {
  208.                     if(fread(&info->viewmode, (int)chunk.iff_length, 1, file) != 1) {
  209.                         iff_truncated(info, 8);
  210.                         return(NULL);
  211.                     }
  212.                 } else {
  213.                     P(printf("warning, more than viewport mode in ILBM CMAP\n"));
  214.                     if(fread(&info->viewmode, sizeof(long), 1, file) != 1) {
  215.                         iff_truncated(info, 9);
  216.                         return(NULL);
  217.                     }
  218.                     bit_bucket(file, chunk.iff_length - sizeof(long));
  219.                 }
  220.                 break;
  221.             case BODY:
  222.                 if(!got_cmap) {
  223.                     P(printf("BODY before CMAP\n"));
  224.                     free_image(info);
  225.                     return(NULL);
  226.                 }
  227.                 D(printf("\tBODY %ld\n", chunk.iff_length));
  228.                 return( read_body(file, info, chunk.iff_length) );
  229.  
  230.             default:
  231. #ifdef PARANOID
  232.                 printf("Unknown type ");
  233.                 printf("%c", (chunk.iff_type.b4_type>>24)&0x7F);
  234.                 printf("%c", (chunk.iff_type.b4_type>>16)&0x7F);
  235.                 printf("%c", (chunk.iff_type.b4_type>>8)&0x7F);
  236.                 printf("%c", (chunk.iff_type.b4_type)&0x7F);
  237.                 printf(" of b4_type\n");
  238. #endif PARANOID
  239.             case GRAB:  /*ignore documented but unwanted types*/
  240.             case DEST:
  241.             case SPRT:
  242.             case CRNG:
  243.             case CCRT:
  244.                 bit_bucket(file, chunk.iff_length);
  245.                 break;
  246.         }
  247.         read_in += chunk.iff_length + sizeof(chunk);
  248.     }
  249.     P(printf("no BODY in ILBM\n"));
  250.     free_image(info);
  251.     return(NULL); 
  252. }
  253.  
  254. static
  255. struct ILBM_info *
  256. read_body(file, info, length)
  257. FILE *file;
  258. register struct ILBM_info *info;
  259. long length;
  260. {
  261.     struct ILBM_header *header;
  262.     struct BitMap *bm;
  263.     int i, j;
  264.     int rlength;
  265.     int plane_offset;
  266.  
  267.     D(printf("read_body( %lx %lx %ld)\n", file, info, length));
  268.  
  269. #ifdef PARANOID
  270.     /* when paranoid do a little error checking first ... fail fast! */
  271.     if(info->header.nPlanes > 8) {
  272.         printf("Whoa, woe  Dale only speaks 8 planes boy, not %d\n",
  273.             info->header.nPlanes);
  274.         free_image(info);
  275.         return(NULL);
  276.     }
  277. #endif PARANOID
  278.  
  279.     /* ok a little more error checking */
  280.     if(info->header.compression != 0 && info->header.compression != 1) {
  281.         P(printf("unrecognized compression type %d\n", info->header.compression));
  282.         free_image(info);
  283.         return(NULL);
  284.     }
  285.  
  286.     /*set up the bitmap part that doesn't involve memory allocation first -
  287.       hey this part does get done, and let's be optimistic...*/
  288.     info->bitmap.BytesPerRow = line_bytes(info->header.w);
  289.     info->bitmap.Rows = info->header.h;
  290.     info->bitmap.Depth = info->header.nPlanes;
  291.     info->bitmap.Flags = info->bitmap.pad = 0;
  292.  
  293.     rlength = info->bitmap.Rows * info->bitmap.BytesPerRow;
  294.  
  295.     for (i=0; i<info->header.nPlanes; i++) {
  296.         if((info->bitmap.Planes[i] = AllocMem(rlength, CHIP)) == NULL) {
  297.             P(printf("couldn't alloc plane %d in read_body\n",i));
  298.             free_image(info);
  299.             return(NULL);
  300.         }
  301.     }
  302.  
  303.     plane_offset = 0;
  304.     for (i=0; i<info->bitmap.Rows; i++) {
  305.         /* this test should be in the inner loop for shortest code,
  306.            in the outer loop for greatest speed, so sue me I compromised */
  307.         if(info->header.compression == 0) {
  308.             for (j = 0; j < info->bitmap.Depth; j++) {
  309.                 if(fread(info->bitmap.Planes[j] + plane_offset,
  310.                    info->bitmap.BytesPerRow, 1, file) != 1) {
  311.                     iff_truncated(info, 6);
  312.                     return(NULL);
  313.                 }
  314.             }
  315.         } else {
  316.             register char *dest, value;
  317.             register int so_far, count;  /*how much have unpacked so far*/
  318.  
  319.             for (j = 0; j < info->bitmap.Depth; j++) {
  320.                 so_far = info->bitmap.BytesPerRow;
  321.                 dest = (char *)info->bitmap.Planes[j] + plane_offset;
  322.                 while (so_far > 0) {
  323.                     if( (value = getc(file)) == 128) {
  324.                         D(printf("NOP\n"));
  325.                     } else if(value > 0) {
  326.                         count = (int)value + 1;
  327.                         so_far -= count;
  328.                         if( fread(dest, count, 1, file) != 1) {
  329.                             iff_truncated(info, 7);
  330.                             return(NULL);
  331.                         }
  332.                         dest += count;
  333.                     } else  {
  334.                         count = (int)-value + 1;
  335.                         so_far -= count;
  336.                         value = getc(file);
  337.                         while (--count >= 0)  /*this is fastest loop in C */
  338.                             *dest++ = value;
  339.                     }
  340.                 }
  341.                 if(so_far != 0) {
  342.                     P(printf("compression quite screwed up, aborting %d\n", so_far));
  343.                     free_image(info);
  344.                     return(NULL);
  345.                 }
  346.             }
  347.         }
  348.         plane_offset += info->bitmap.BytesPerRow;
  349.     }
  350.     return(info);
  351. }
  352.  
  353. void free_image(info)
  354. struct ILBM_info *info;
  355. {
  356.     if(info) {
  357.         free_planes(&info->bitmap);
  358.         FreeMem(info, sizeof(struct ILBM_info));
  359.     }
  360. }
  361.  
  362. void
  363. free_planes(bmap)
  364. register struct BitMap *bmap;
  365. {
  366.     PLANEPTR plane;
  367.     long length;
  368.     short i;
  369.  
  370.     length = bmap->BytesPerRow * bmap->Rows;
  371.  
  372.     for (i=0; i<8; i++)
  373.         if( (plane = bmap->Planes[i]) != NULL)
  374.             FreeMem(plane, length);
  375. }
  376.