home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / mac / developm / source / povsrc.sit / SOURCE / IFF.C < prev    next >
Encoding:
C/C++ Source or Header  |  1992-07-03  |  10.1 KB  |  324 lines

  1. /****************************************************************************
  2. *                   iff.c
  3. *
  4. *  This file implements a simple IFF format file reader.
  5. *
  6. *  from Persistence of Vision Raytracer 
  7. *  Copyright 1992 Persistence of Vision Team
  8. *---------------------------------------------------------------------------
  9. *  Copying, distribution and legal info is in the file povlegal.doc which
  10. *  should be distributed with this file. If povlegal.doc is not available
  11. *  or for more info please contact:
  12. *
  13. *       Drew Wells [POV-Team Leader] 
  14. *       CIS: 73767,1244  Internet: 73767.1244@compuserve.com
  15. *       Phone: (213) 254-4041
  16. * This program is based on the popular DKB raytracer version 2.12.
  17. * DKBTrace was originally written by David K. Buck.
  18. * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
  19. *
  20. *****************************************************************************/
  21.  
  22.  
  23. #include "frame.h"
  24. #include "povproto.h"
  25.  
  26. static IMAGE_COLOUR *iff_colour_map;
  27. static int colourmap_size;
  28. static CHUNK_HEADER Chunk_Header;
  29.  
  30. #define FORM 0x464f524dL
  31. #define ILBM 0x494c424dL
  32. #define BMHD 0x424d4844L
  33. #define CAMG 0x43414d47L
  34. #define CMAP 0x434d4150L
  35. #define BODY 0x424f4459L
  36. #define CMPNONE 0
  37.  
  38. #define HAM 0x800
  39.  
  40. void iff_error()
  41. {
  42.    fprintf (stderr, "Invalid IFF file\n");
  43.    exit(1);
  44. }
  45.  
  46. int read_byte(f)
  47. FILE *f;
  48. {
  49.    int c;
  50.    if ((c = getc(f)) == EOF)
  51.       iff_error();
  52.    return (c);
  53. }
  54.  
  55. int read_word(f)
  56. FILE *f;
  57. {
  58.    int result;
  59.  
  60.    result = read_byte(f)*256;
  61.    result += read_byte(f);
  62.    return (result);
  63. }
  64.  
  65. long read_long(f)
  66. FILE *f;
  67. {
  68.    int i;
  69.    long result;
  70.  
  71.    result = 0;
  72.    for (i = 0 ; i < 4 ; i++)
  73.       result = result * 256 + read_byte(f);
  74.  
  75.    return (result);
  76. }
  77.  
  78. void Read_Chunk_Header (f, dest)
  79. FILE *f;
  80. CHUNK_HEADER *dest;
  81. {
  82.    dest->name = read_long(f);
  83.    dest->size = read_long(f);
  84. }
  85.  
  86. void Read_Iff_Image(Image, filename)
  87. IMAGE *Image;
  88. char *filename;
  89. {
  90.    FILE *f;
  91.    unsigned char **row_bytes;
  92.    int c, i, j, k, nBytes, nPlanes, compression,
  93.    mask, byte_index, count, viewmodes;
  94.    int Previous_Red, Previous_Green, Previous_Blue;
  95.    struct Image_Line *line;
  96.    unsigned long creg;
  97.  
  98.    if ((f = Locate_File(filename, READ_FILE_STRING)) == NULL) {
  99.       fprintf (stderr, "Cannot open IFF file %s\n", filename);
  100.       exit(1);
  101.    }
  102.  
  103.    Previous_Red = Previous_Green = Previous_Blue = 0;
  104.  
  105.    viewmodes = 0;
  106.    iff_colour_map = NULL;
  107.  
  108.    while (1) {
  109.       Read_Chunk_Header(f, &Chunk_Header);
  110.       switch ( IFF_SWITCH_CAST Chunk_Header.name) {
  111.       case FORM:  
  112.          if (read_long(f) != ILBM)
  113.             iff_error();
  114.          break;
  115.  
  116.       case BMHD:  
  117.          Image->iwidth = read_word(f);
  118.          Image->width = (DBL)Image->iwidth;
  119.          Image->iheight = read_word(f);
  120.          Image->height = (DBL)Image->iheight;
  121.  
  122.          read_word(f);  /* x position ignored */
  123.          read_word(f);  /* y position ignored */
  124.          nPlanes = read_byte(f);
  125.          colourmap_size = 1<<nPlanes;
  126.          read_byte(f);   /* masking ignored */
  127.          compression = read_byte(f);   /* masking ignored */
  128.          read_byte(f);   /* pad */
  129.          read_word(f);   /* Transparent colour ignored */
  130.          read_word(f);   /* Aspect ratio ignored */
  131.          read_word(f);   /* page width ignored */
  132.          read_word(f);   /* page height ignored */
  133.          break;
  134.  
  135.       case CAMG:  
  136.          viewmodes = (int) read_long(f);   /* Viewmodes */
  137.          if (viewmodes & HAM)
  138.             colourmap_size = 16;
  139.  
  140.          break;
  141.  
  142.       case CMAP:  
  143.          colourmap_size = (int) Chunk_Header.size / 3;
  144.  
  145.          if ((iff_colour_map = (IMAGE_COLOUR *) malloc(sizeof(IMAGE_COLOUR)*colourmap_size)) == NULL) {
  146.             fprintf(stderr, "Cannot allocate memory for IFF colour map\n");
  147.             exit(1);
  148.          }
  149.  
  150.          for (i = 0 ; i < colourmap_size ; i++) {
  151.             iff_colour_map[i].Red = read_byte(f);
  152.             iff_colour_map[i].Green = read_byte(f);
  153.             iff_colour_map[i].Blue = read_byte(f);
  154.             iff_colour_map[i].Alpha = 0;
  155.          }
  156.  
  157.          Previous_Red = iff_colour_map[0].Red;
  158.          Previous_Green = iff_colour_map[0].Green;
  159.          Previous_Blue = iff_colour_map[0].Blue;
  160.          for (i = colourmap_size * 3 ; (long) i < Chunk_Header.size ; i++)
  161.             read_byte(f);
  162.  
  163.          break;
  164.  
  165.       case BODY:  
  166.          if ((iff_colour_map == NULL) || (viewmodes & HAM)) {
  167.             Image->Colour_Map_Size = 0;
  168.             Image->Colour_Map = NULL;
  169.          }
  170.          else {
  171.             Image->Colour_Map_Size = colourmap_size;
  172.             Image->Colour_Map = iff_colour_map;
  173.          }
  174.  
  175.             if ((row_bytes = (unsigned char **) malloc (4*nPlanes)) == NULL) {
  176.                fprintf (stderr, "Cannot allocate memory for row bytes\n");
  177.                exit(1);
  178.             }
  179.  
  180.          for (i = 0 ; i < nPlanes ; i++)
  181.             if ((row_bytes[i] = (unsigned char *)
  182.                malloc((Image->iwidth+7)/8)) == NULL) {
  183.                fprintf (stderr, "Cannot allocate memory for row bytes\n");
  184.                exit(1);
  185.             }
  186.  
  187.          if (Image->Colour_Map == NULL) {
  188.             if ((Image->data.rgb_lines = (struct Image_Line *)
  189.                malloc(Image->iheight * sizeof (struct Image_Line)))==NULL) {
  190.                fprintf (stderr, "Cannot allocate memory for picture\n");
  191.                exit(1);
  192.             }
  193.          }
  194.          else {
  195.             if ((Image->data.map_lines = (unsigned char **)
  196.                malloc(Image->iheight * sizeof (unsigned char *)))==NULL) {
  197.                fprintf (stderr, "Cannot allocate memory for picture\n");
  198.                exit(1);
  199.             }
  200.          }
  201.  
  202.          for (i = 0 ; i < Image->iheight ; i++) {
  203.  
  204.             if (Image->Colour_Map == NULL) {
  205.                if (((Image->data.rgb_lines[i].red = (unsigned char *)
  206.                   malloc(Image->iwidth))==NULL) ||
  207.                   ((Image->data.rgb_lines[i].green = (unsigned char *)
  208.                   malloc(Image->iwidth))==NULL) ||
  209.                   ((Image->data.rgb_lines[i].blue = (unsigned char *)
  210.                   malloc(Image->iwidth))==NULL)) {
  211.                   fprintf (stderr, "Cannot allocate memory for picture\n");
  212.                   exit(1);
  213.                }
  214.             }
  215.             else {
  216.                if ((Image->data.map_lines[i] = (unsigned char *)
  217.                   malloc(Image->iwidth * sizeof(unsigned char))) == NULL) {
  218.                   fprintf (stderr, "Cannot allocate memory for picture\n");
  219.                   exit(1);
  220.                }
  221.             }
  222.  
  223.             for (j = 0 ; j < nPlanes ; j++)
  224.                if (compression == CMPNONE) {
  225.                   for (k = 0 ; k < (Image->iwidth+7)/8 ; k++)
  226.                      row_bytes[j][k] = (unsigned char)read_byte(f);
  227.                   if ((k & 1) != 0)
  228.                      read_byte(f);
  229.                }
  230.  
  231.                else {
  232.                   nBytes = 0;
  233.                   while (nBytes != (Image->iwidth+7)/8) {
  234.                      c = read_byte(f);
  235.                      if ((c >= 0) && (c <= 127))
  236.                         for (k = 0 ; k <= c ; k++)
  237.                            row_bytes[j][nBytes++] = (unsigned char)read_byte(f);
  238.                      else if ((c >= 129) && (c <= 255)) {
  239.                         count = 257-c;
  240.                         c = read_byte(f);
  241.                         for (k = 0 ; k < count ; k++)
  242.                            row_bytes[j][nBytes++] = (unsigned char)c;
  243.                      }
  244.                   }
  245.                }
  246.  
  247.             mask = 0x80;
  248.             byte_index = 0;
  249.             for (j = 0 ; j < Image->iwidth ; j++) {
  250.                creg = 0;
  251.                for (k = nPlanes-1 ; k >= 0 ; k--)
  252.                   if (row_bytes[k][byte_index] & mask)
  253.                      creg = creg*2 + 1;
  254.                   else
  255.                      creg *= 2;
  256.  
  257.  
  258.                if (viewmodes & HAM) {
  259.                   line = &Image->data.rgb_lines[i];
  260.                   switch (creg >> 4) {
  261.                   case 0:
  262.                      Previous_Red = line->red[j] = (unsigned char)iff_colour_map[creg].Red;
  263.                      Previous_Green = line->green[j] = (unsigned char)iff_colour_map[creg].Green;
  264.                      Previous_Blue = line->blue[j] = (unsigned char)iff_colour_map[creg].Blue;
  265.                      break;
  266.  
  267.                   case 1:
  268.                      line->red[j] = (unsigned char)Previous_Red;
  269.                      line->green[j] = (unsigned char)Previous_Green;
  270.                      line->blue[j] = (unsigned char)(((creg & 0xf)<<4) + (creg&0xf));
  271.                      Previous_Blue = (int) line->blue[j];
  272.                      break;
  273.  
  274.                   case 2:
  275.                      line->red[j] = (unsigned char)(((creg & 0xf)<<4) + (creg&0xf));
  276.                      Previous_Red = (int) line->red[j];
  277.                      line->green[j] = (unsigned char)Previous_Green;
  278.                      line->blue[j] = (unsigned char)Previous_Blue;
  279.                      break;
  280.  
  281.                   case 3:
  282.                      line->red[j] = (unsigned char)Previous_Red;
  283.                      line->green[j] = (unsigned char)(((creg & 0xf)<<4) + (creg&0xf));
  284.                      Previous_Green = (int) line->green[j];
  285.                      line->blue[j] = (unsigned char)Previous_Blue;
  286.                      break;
  287.                   }
  288.                }
  289.                else if (nPlanes == 24) {
  290.                   line = &Image->data.rgb_lines[i];
  291.                   line->red[j] = (unsigned char)((creg >> 16) & 0xFF);
  292.                   line->green[j] = (unsigned char)((creg >> 8) & 0xFF);
  293.                   line->blue[j] = (unsigned char)(creg & 0xFF);
  294.                }
  295.                else {
  296.                   if (creg > (unsigned long)Image->Colour_Map_Size) {
  297.                      fprintf (stderr, "Error - IFF Image Map Colour out of range\n");
  298.                      exit(1);
  299.                   }
  300.                   Image->data.map_lines[i][j] = (char)creg;
  301.                }
  302.  
  303.                mask >>= 1;
  304.                if (mask == 0) {
  305.                   mask = 0x80;
  306.                   byte_index++;
  307.                }
  308.             }
  309.          }
  310.  
  311.          free (row_bytes);
  312.          fclose (f);
  313.          return;
  314.  
  315.       default:
  316.          for (i = 0 ; (long) i < Chunk_Header.size ; i++)
  317.             if (getc(f) == EOF)
  318.                iff_error();
  319.          break;
  320.       }
  321.    }
  322. }
  323.