home *** CD-ROM | disk | FTP | other *** search
/ Archive Magazine 1996 / ARCHIVE_96.iso / discs / shareware / share_43 / source / c / IFF < prev    next >
Text File  |  1991-08-22  |  11KB  |  296 lines

  1. /*****************************************************************************
  2. *
  3. *                                     iff.c
  4. *
  5. *   from DKBTrace (c) 1990  David Buck
  6. *
  7. *  This file implements a simple IFF format file reader.
  8. *
  9. * This software is freely distributable. The source and/or object code may be
  10. * copied or uploaded to communications services so long as this notice remains
  11. * at the top of each file.  If any changes are made to the program, you must
  12. * clearly indicate in the documentation and in the programs startup message
  13. * who it was who made the changes. The documentation should also describe what
  14. * those changes were. This software may not be included in whole or in
  15. * part into any commercial package without the express written consent of the
  16. * author.  It may, however, be included in other public domain or freely
  17. * distributed software so long as the proper credit for the software is given.
  18. *
  19. * This software is provided as is without any guarantees or warranty. Although
  20. * the author has attempted to find and correct any bugs in the software, he
  21. * is not responsible for any damage caused by the use of the software.  The
  22. * author is under no obligation to provide service, corrections, or upgrades
  23. * to this package.
  24. *
  25. * Despite all the legal stuff above, if you do find bugs, I would like to hear
  26. * about them.  Also, if you have any comments or questions, you may contact me
  27. * at the following address:
  28. *
  29. *     David Buck
  30. *     22C Sonnet Cres.
  31. *     Nepean Ontario
  32. *     Canada, K2H 8W7
  33. *
  34. *  I can also be reached on the following bulleton boards:
  35. *
  36. *     ATX              (613) 526-4141
  37. *     OMX              (613) 731-3419
  38. *     Mystic           (613) 731-0088 or (613) 731-6698
  39. *
  40. *  Fidonet:   1:163/109.9
  41. *  Internet:  David_Buck@Carleton.CA
  42. *
  43. *  IBM Port by Aaron A. Collins. Aaron may be reached on the following BBS'es:
  44. *
  45. *     Lattice BBS                      (708) 916-1200
  46. *     The Information Exchange BBS     (708) 945-5575
  47. *     Stillwaters BBS                  (708) 403-2826
  48. *
  49. *****************************************************************************/
  50.  
  51.  
  52. #include "frame.h"
  53. #include "dkbproto.h"
  54.  
  55. static IMAGE_COLOUR *iff_colour_map;
  56. static int colourmap_size;
  57. static CHUNK_HEADER Chunk_Header;
  58.  
  59. #define FORM 0x464f524dL
  60. #define ILBM 0x494c424dL
  61. #define BMHD 0x424d4844L
  62. #define CAMG 0x43414d47L
  63. #define CMAP 0x434d4150L
  64. #define BODY 0x424f4459L
  65. #define CMPNONE 0
  66.  
  67. #define HAM 0x800
  68.  
  69. void iff_error()
  70.    {
  71.    printf ("Invalid iff file\n");
  72.    exit(1);
  73.    }
  74.  
  75. int read_byte(f)
  76.    FILE *f;
  77.    {
  78.    int c;
  79.    if ((c = getc(f)) == EOF)
  80.       iff_error();
  81.    return (c);
  82.    }
  83.  
  84. int read_word(f)
  85.    FILE *f;
  86.    {
  87.    int result;
  88.  
  89.    result = read_byte(f)*256;
  90.    result += read_byte(f);
  91.    return (result);
  92.    }
  93.  
  94. long read_long(f)
  95.    FILE *f;
  96.    {
  97.    int i;
  98.    long result;
  99.  
  100.    result = 0;
  101.    for (i = 0 ; i < 4 ; i++)
  102.       result = result * 256 + read_byte(f);
  103.  
  104.    return (result);
  105.    }
  106.  
  107. void Read_Chunk_Header (f, dest)
  108.    FILE *f;
  109.    CHUNK_HEADER *dest;
  110.    {
  111.    dest->name = read_long(f);
  112.    dest->size = read_long(f);
  113.    }
  114.  
  115. void read_iff_image(Image, filename)
  116.    IMAGE *Image;
  117.    char *filename;
  118.    {
  119.    FILE *f;
  120.    unsigned char **row_bytes;
  121.    int c, i, j, k, creg, index, nBytes, nPlanes, compression,
  122.        mask, byte_index, count, viewmodes;
  123.    int Previous_Red, Previous_Green, Previous_Blue;
  124.  
  125.    if ((f = fopen(filename, "rb")) == NULL) {
  126.       printf ("Cannot open IFF file %s\n", filename);
  127.       exit(1);
  128.       }
  129.  
  130.    Previous_Red = Previous_Green = Previous_Blue = 0;
  131.  
  132.    viewmodes = 0;
  133.  
  134.    while (1) {
  135.       Read_Chunk_Header(f, &Chunk_Header);
  136.       switch ((int) Chunk_Header.name) {
  137.          case FORM:  if (read_long(f) != ILBM)
  138.                         iff_error();
  139.                      break;
  140.  
  141.          case BMHD:  Image->iwidth = read_word(f);
  142.                      Image->width = (DBL)Image->iwidth;
  143.                      Image->iheight = read_word(f);
  144.                      Image->height = (DBL)Image->iheight;
  145.  
  146.              if ((long)Image->iwidth * (long)Image->iheight > MAX_BITMAP_SIZE) {
  147.             printf("\nBitmap File TOO BIG!!\n");
  148.             fclose(f);
  149.             exit (1);
  150.             }
  151.  
  152.                      read_word(f);  /* x position ignored */
  153.                      read_word(f);  /* y position ignored */
  154.                      nPlanes = read_byte(f);
  155.                      colourmap_size = 1<<nPlanes;
  156.                      read_byte(f);   /* masking ignored */
  157.                      compression = read_byte(f);   /* masking ignored */
  158.                      read_byte(f);   /* pad */
  159.                      read_word(f);   /* Transparent colour ignored */
  160.                      read_word(f);   /* Aspect ratio ignored */
  161.                      read_word(f);   /* page width ignored */
  162.                      read_word(f);   /* page height ignored */
  163.                      break;
  164.  
  165.          case CAMG:  viewmodes = (int) read_long(f);   /* Viewmodes */
  166.                      if (viewmodes & HAM)
  167.                         colourmap_size = 16;
  168.                      break;
  169.  
  170.          case CMAP:  colourmap_size = (int) Chunk_Header.size / 3;
  171.  
  172.                      if ((iff_colour_map = (IMAGE_COLOUR *) malloc(sizeof(IMAGE_COLOUR)*colourmap_size)) == NULL) {
  173.             printf("Cannot allocate memory for iff colour map\n");
  174.             exit(1);
  175.             }
  176.  
  177.                      for (i = 0 ; i < colourmap_size ; i++) {
  178.                         iff_colour_map[i].Red = read_byte(f);
  179.                         iff_colour_map[i].Green = read_byte(f);
  180.                         iff_colour_map[i].Blue = read_byte(f);
  181.                         }
  182.                      Previous_Red = iff_colour_map[0].Red;
  183.                      Previous_Green = iff_colour_map[0].Green;
  184.                      Previous_Blue = iff_colour_map[0].Blue;
  185.                      for (i = colourmap_size*3 ; i < Chunk_Header.size ; i++)
  186.                         read_byte(f);
  187.  
  188.                      break;
  189.  
  190.          case BODY:  if ((row_bytes = (unsigned char **) malloc (4*nPlanes)) == NULL) {
  191.                         printf ("Cannot allocate memory for row bytes\n");
  192.                         exit(1);
  193.                         }
  194.  
  195.                      for (i = 0 ; i < nPlanes ; i++)
  196.                         if ((row_bytes[i] = (unsigned char *) malloc((Image->iwidth+7)/8)) == NULL) {
  197.                printf ("Cannot allocate memory for row bytes\n");
  198.                            exit(1);
  199.                         }
  200.  
  201.                      if (((Image->red = (unsigned char *) malloc(Image->iwidth*Image->iheight))==NULL) ||
  202.                          ((Image->green = (unsigned char *) malloc(Image->iwidth*Image->iheight))==NULL) ||
  203.                          ((Image->blue = (unsigned char *) malloc(Image->iwidth*Image->iheight))==NULL)) {
  204.                         printf ("Cannot allocate memory for picture\n");
  205.                         exit(1);
  206.                         }
  207.  
  208.                      for (i = 0 ; i < Image->iheight ; i++) {
  209.                         for (j = 0 ; j < nPlanes ; j++)
  210.                            if (compression == CMPNONE) {
  211.                               for (k = 0 ; k < (Image->iwidth+7)/8 ; k++)
  212.                                  row_bytes[j][k] = read_byte(f);
  213.                            if ((Image->iwidth & 7) != 0)
  214.                               read_byte(f);
  215.                            }
  216.                         else {
  217.                            nBytes = 0;
  218.                            while (nBytes != (Image->iwidth+7)/8) {
  219.                               c = read_byte(f);
  220.                               if ((c >= 0) && (c <= 127))
  221.                                  for (k = 0 ; k <= c ; k++)
  222.                                     row_bytes[j][nBytes++] = read_byte(f);
  223.                               else if ((c >= 129) && (c <= 255)) {
  224.                                  count = 257-c;
  225.                                  c = read_byte(f);
  226.                                  for (k = 0 ; k < count ; k++)
  227.                                     row_bytes[j][nBytes++] = c;
  228.                                  }
  229.                               }
  230.                              }
  231.  
  232.                         mask = 0x80;
  233.                         byte_index = 0;
  234.                         for (j = 0 ; j < Image->iwidth ; j++) {
  235.                            creg = 0;
  236.                            for (k = nPlanes-1 ; k >= 0 ; k--)
  237.                               if (row_bytes[k][byte_index] & mask)
  238.                                 creg = creg*2 + 1;
  239.                               else
  240.                                 creg *= 2;
  241.  
  242.                            index = (Image->iheight-i-1)*Image->iwidth + j;
  243.  
  244.                            if (viewmodes & HAM) {
  245.                               switch (creg >> 4) {
  246.                                  case 0:
  247.                                     Previous_Red = Image->red[index] = iff_colour_map[creg].Red;
  248.                                     Previous_Green = Image->green[index] = iff_colour_map[creg].Green;
  249.                                     Previous_Blue = Image->blue[index] = iff_colour_map[creg].Blue;
  250.                                     break;
  251.  
  252.                                  case 1:
  253.                                     Image->red[index] = Previous_Red;
  254.                                     Image->green[index] = Previous_Green;
  255.                                     Previous_Blue = Image->blue[index] = ((creg & 0xf)<<4) + (creg&0xf);
  256.                                     break;
  257.  
  258.                                  case 2:
  259.                                     Previous_Red = Image->red[index] = ((creg & 0xf)<<4) + (creg&0xf);
  260.                                     Image->green[index] = Previous_Green;
  261.                                     Image->blue[index] = Previous_Blue;
  262.                                     break;
  263.  
  264.                                  case 3:
  265.                                     Image->red[index] = Previous_Red;
  266.                                     Previous_Green = Image->green[index] = ((creg & 0xf)<<4) + (creg&0xf);
  267.                                     Image->blue[index] = Previous_Blue;
  268.                                     break;
  269.                                  }
  270.                               }
  271.                            else {
  272.                               Image->red[index] = iff_colour_map[creg].Red;
  273.                               Image->green[index] = iff_colour_map[creg].Green;
  274.                               Image->blue[index] = iff_colour_map[creg].Blue;
  275.                               }
  276.  
  277.                            mask >>= 1;
  278.                            if (mask == 0) {
  279.                               mask = 0x80;
  280.                               byte_index++;
  281.                               }
  282.                            }
  283.                         }
  284.  
  285.                      free (row_bytes);
  286.                      fclose (f);
  287.                      return;
  288.          default:
  289.             for (i = 0 ; i < Chunk_Header.size ; i++)
  290.                if (getc(f) == EOF)
  291.                   iff_error();
  292.             break;
  293.          }
  294.       }
  295.    }
  296.