home *** CD-ROM | disk | FTP | other *** search
/ Fish 'n' More 2 / fishmore-publicdomainlibraryvol.ii1991xetec.iso / dirs / dkbtrace_397.lzh / DKBTrace / DKBSource.LZH / iff.c < prev    next >
C/C++ Source or Header  |  1990-08-26  |  11KB  |  290 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, nBytesRead, 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.                      read_word(f);  /* x position ignored */
  146.                      read_word(f);  /* y position ignored */
  147.                      nPlanes = read_byte(f);
  148.                      colourmap_size = 1<<nPlanes;
  149.                      read_byte(f);   /* masking ignored */
  150.                      compression = read_byte(f);   /* masking ignored */
  151.                      read_byte(f);   /* pad */
  152.                      read_word(f);   /* Transparent colour ignored */
  153.                      read_word(f);   /* Aspect ratio ignored */
  154.                      read_word(f);   /* page width ignored */
  155.                      read_word(f);   /* page height ignored */
  156.                      break;
  157.  
  158.          case CAMG:  viewmodes = (int) read_long(f);   /* Viewmodes */
  159.                      if (viewmodes & HAM)
  160.                         colourmap_size = 16;
  161.                      break;
  162.  
  163.          case CMAP:  colourmap_size = (int) Chunk_Header.size / 3;
  164.  
  165.                      if ((iff_colour_map = (IMAGE_COLOUR *) malloc(sizeof(IMAGE_COLOUR)*colourmap_size)) == NULL)
  166.                         iff_error();
  167.  
  168.                      for (i = 0 ; i < colourmap_size ; i++) {
  169.                         iff_colour_map[i].Red = read_byte(f);
  170.                         iff_colour_map[i].Green = read_byte(f);
  171.                         iff_colour_map[i].Blue = read_byte(f);
  172.                         }
  173.                      Previous_Red = iff_colour_map[0].Red;
  174.                      Previous_Green = iff_colour_map[0].Green;
  175.                      Previous_Blue = iff_colour_map[0].Blue;
  176.                      for (i = colourmap_size*3 ; i < Chunk_Header.size ; i++)
  177.                         read_byte(f);
  178.  
  179.                      break;
  180.  
  181.          case BODY:  if ((row_bytes = (unsigned char **) malloc (4*nPlanes)) == NULL) {
  182.                         printf ("Not enough memory\n");
  183.                         exit(1);
  184.                         }
  185.  
  186.                      for (i = 0 ; i < nPlanes ; i++)
  187.                         if ((row_bytes[i] = (unsigned char *) malloc((Image->iwidth+7)/8)) == NULL) {
  188.                            printf ("Not enough memory\n");
  189.                            exit(1);
  190.                         }
  191.  
  192.                      if (((Image->red = (unsigned char *) malloc(Image->iwidth*Image->iheight))==NULL) ||
  193.                          ((Image->green = (unsigned char *) malloc(Image->iwidth*Image->iheight))==NULL) ||
  194.                          ((Image->blue = (unsigned char *) malloc(Image->iwidth*Image->iheight))==NULL)) {
  195.                         printf ("Cannot allocate memory for picture\n");
  196.                         exit(1);
  197.                         }
  198.  
  199.                      for (i = 0 ; i < Image->iheight ; i++) {
  200.                         for (j = 0 ; j < nPlanes ; j++)
  201.                            if (compression == CMPNONE) {
  202.                               for (k = 0 ; k < (Image->iwidth+7)/8 ; k++)
  203.                                  row_bytes[j][k] = read_byte(f);
  204.                            if ((Image->iwidth & 7) != 0)
  205.                               read_byte(f);
  206.                            }
  207.                         else {
  208.                            nBytes = 0;
  209.                            nBytesRead = 0;
  210.                            while (nBytes != (Image->iwidth+7)/8) {
  211.                               c = read_byte(f);
  212.                               nBytesRead++;
  213.                               if ((c >= 0) && (c <= 127))
  214.                                  for (k = 0 ; k <= c ; k++)
  215.                                     row_bytes[j][nBytes++] = read_byte(f);
  216.                               else if ((c >= 129) && (c <= 255)) {
  217.                                  count = 257-c;
  218.                                  c = read_byte(f);
  219.                                  nBytesRead++;
  220.                                  for (k = 0 ; k < count ; k++)
  221.                                     row_bytes[j][nBytes++] = c;
  222.                                  }
  223.                               }
  224.                              }
  225.  
  226.                         mask = 0x80;
  227.                         byte_index = 0;
  228.                         for (j = 0 ; j < Image->iwidth ; j++) {
  229.                            creg = 0;
  230.                            for (k = nPlanes-1 ; k >= 0 ; k--)
  231.                               if (row_bytes[k][byte_index] & mask)
  232.                                 creg = creg*2 + 1;
  233.                               else
  234.                                 creg *= 2;
  235.  
  236.                            index = (Image->iheight-i-1)*Image->iwidth + j;
  237.  
  238.                            if (viewmodes & HAM) {
  239.                               switch (creg >> 4) {
  240.                                  case 0:
  241.                                     Previous_Red = Image->red[index] = iff_colour_map[creg].Red;
  242.                                     Previous_Green = Image->green[index] = iff_colour_map[creg].Green;
  243.                                     Previous_Blue = Image->blue[index] = iff_colour_map[creg].Blue;
  244.                                     break;
  245.  
  246.                                  case 1:
  247.                                     Image->red[index] = Previous_Red;
  248.                                     Image->green[index] = Previous_Green;
  249.                                     Previous_Blue = Image->blue[index] = ((creg & 0xf)<<4) + (creg&0xf);
  250.                                     break;
  251.  
  252.                                  case 2:
  253.                                     Previous_Red = Image->red[index] = ((creg & 0xf)<<4) + (creg&0xf);
  254.                                     Image->green[index] = Previous_Green;
  255.                                     Image->blue[index] = Previous_Blue;
  256.                                     break;
  257.  
  258.                                  case 3:
  259.                                     Image->red[index] = Previous_Red;
  260.                                     Previous_Green = Image->green[index] = ((creg & 0xf)<<4) + (creg&0xf);
  261.                                     Image->blue[index] = Previous_Blue;
  262.                                     break;
  263.                                  }
  264.                               }
  265.                            else {
  266.                               Image->red[index] = iff_colour_map[creg].Red;
  267.                               Image->green[index] = iff_colour_map[creg].Green;
  268.                               Image->blue[index] = iff_colour_map[creg].Blue;
  269.                               }
  270.  
  271.                            mask >>= 1;
  272.                            if (mask == 0) {
  273.                               mask = 0x80;
  274.                               byte_index++;
  275.                               }
  276.                            }
  277.                         }
  278.  
  279.                      free (row_bytes);
  280.                      fclose (f);
  281.                      return;
  282.          default:
  283.             for (i = 0 ; i < Chunk_Header.size ; i++)
  284.                if (getc(f) == EOF)
  285.                   iff_error();
  286.             break;
  287.          }
  288.       }
  289.    }
  290.