home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Professional / OS2PRO194.ISO / os2 / graphic / dkb / source / iff.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-07-28  |  9.5 KB  |  344 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. *    OMX        (613) 731-3419
  37. *    Mystic    (613) 596-4249  or  (613) 596-4772
  38. *
  39. *  Fidonet:    1:163/109.9
  40. *  Internet:  dbuck@ccs.carleton.ca
  41. *  The "You Can Call Me RAY" BBS    (708) 358-5611
  42. *
  43. *  IBM Port by Aaron A. Collins. Aaron may be reached on the following BBS'es:
  44. *
  45. *    The "You Can Call Me RAY" BBS (708) 358-5611
  46. *    The Information Exchange BBS  (708) 945-5575
  47. *
  48. *****************************************************************************/
  49.  
  50.  
  51. #include "frame.h"
  52. #include "dkbproto.h"
  53.  
  54. static IMAGE_COLOUR *iff_colour_map;
  55. static int colourmap_size;
  56. static CHUNK_HEADER Chunk_Header;
  57.  
  58. #define FORM 0x464f524dL
  59. #define ILBM 0x494c424dL
  60. #define BMHD 0x424d4844L
  61. #define CAMG 0x43414d47L
  62. #define CMAP 0x434d4150L
  63. #define BODY 0x424f4459L
  64. #define CMPNONE 0
  65.  
  66. #define HAM 0x800
  67.  
  68. void iff_error()
  69.     {
  70.     PRINT ("Invalid IFF file\n");
  71.     return;
  72.     }
  73.  
  74. int read_byte(f)
  75.     FILE *f;
  76.     {
  77.     int c;
  78.  
  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, nBytes, nPlanes, compression,
  122.     mask, byte_index, count, viewmodes;
  123.     int Previous_Red, Previous_Green, Previous_Blue;
  124.     struct Image_Line *line;
  125.     unsigned long creg;
  126.  
  127.     if ((f = Locate_File(filename, "rb")) == NULL) {
  128.         PRINT ("Cannot open IFF file %s\n", filename);
  129.         return;
  130.     }
  131.  
  132.     Previous_Red = Previous_Green = Previous_Blue = 0;
  133.  
  134.     viewmodes = 0;
  135.     iff_colour_map = NULL;
  136.  
  137.     while (1) {
  138.     Read_Chunk_Header(f, &Chunk_Header);
  139.     switch ((int) Chunk_Header.name) {
  140.         case FORM:
  141.             if (read_long(f) != ILBM)
  142.             iff_error();
  143.             break;
  144.  
  145.         case BMHD:
  146.             Image->iwidth = read_word(f);
  147.             Image->width = (DBL)Image->iwidth;
  148.             Image->iheight = read_word(f);
  149.             Image->height = (DBL)Image->iheight;
  150.  
  151.             read_word(f);  /* x position ignored */
  152.             read_word(f);  /* y position ignored */
  153.             nPlanes = read_byte(f);
  154.             colourmap_size = 1<<nPlanes;
  155.             read_byte(f);    /* masking ignored */
  156.             compression = read_byte(f);    /* masking ignored */
  157.             read_byte(f);    /* pad */
  158.             read_word(f);    /* Transparent colour ignored */
  159.             read_word(f);    /* Aspect ratio ignored */
  160.             read_word(f);    /* page width ignored */
  161.             read_word(f);    /* page height ignored */
  162.             break;
  163.  
  164.         case CAMG:
  165.             viewmodes = (int) read_long(f);    /* Viewmodes */
  166.             if (viewmodes & HAM)
  167.             colourmap_size = 16;
  168.  
  169.             break;
  170.  
  171.         case CMAP:
  172.             colourmap_size = (int) Chunk_Header.size / 3;
  173.  
  174.             if ((iff_colour_map = (IMAGE_COLOUR *) malloc(sizeof(IMAGE_COLOUR)*colourmap_size)) == NULL) {
  175.                 PRINT("Cannot allocate memory for IFF colour map\n");
  176.                 return;
  177.             }
  178.  
  179.             for (i = 0 ; i < colourmap_size ; i++) {
  180.             iff_colour_map[i].Red = read_byte(f);
  181.             iff_colour_map[i].Green = read_byte(f);
  182.             iff_colour_map[i].Blue = read_byte(f);
  183.             iff_colour_map[i].Alpha = 0;
  184.             }
  185.  
  186.             Previous_Red = iff_colour_map[0].Red;
  187.             Previous_Green = iff_colour_map[0].Green;
  188.             Previous_Blue = iff_colour_map[0].Blue;
  189.             for (i = colourmap_size * 3 ; (long) i < Chunk_Header.size ; i++)
  190.             read_byte(f);
  191.  
  192.             break;
  193.  
  194.         case BODY:
  195.             if ((iff_colour_map == NULL) || (viewmodes & HAM)) {
  196.                 Image->Colour_Map_Size = 0;
  197.                 Image->Colour_Map = NULL;
  198.             } else {
  199.                 Image->Colour_Map_Size = colourmap_size;
  200.                 Image->Colour_Map = iff_colour_map;
  201.             }
  202.  
  203.             if ((row_bytes = (unsigned char **) malloc (4*nPlanes)) == NULL) {
  204.                 PRINT ("Cannot allocate memory for row bytes\n");
  205.                 return;
  206.             }
  207.  
  208.             for (i = 0 ; i < nPlanes ; i++)
  209.                 if ((row_bytes[i] = (unsigned char *)
  210.                         malloc((Image->iwidth+7)/8)) == NULL) {
  211.                     PRINT ("Cannot allocate memory for row bytes\n");
  212.                     return;
  213.                 }
  214.  
  215.             if (Image->Colour_Map == NULL) {
  216.                 if ((Image->data.rgb_lines = (struct Image_Line *)
  217.                         malloc(Image->iheight * sizeof (struct Image_Line)))==NULL) {
  218.                     PRINT ("Cannot allocate memory for picture\n");
  219.                     return;
  220.                 }
  221.             } else {
  222.                 if ((Image->data.map_lines = (unsigned char **)
  223.                         malloc(Image->iheight * sizeof (unsigned char *)))==NULL) {
  224.                     PRINT ("Cannot allocate memory for picture\n");
  225.                     return;
  226.                 }
  227.             }
  228.  
  229.             for (i = 0 ; i < Image->iheight ; i++) {
  230.  
  231.                 if (Image->Colour_Map == NULL) {
  232.                     if (((Image->data.rgb_lines[i].red = (unsigned char *)
  233.                             malloc(Image->iwidth))==NULL) ||
  234.                             ((Image->data.rgb_lines[i].green = (unsigned char *)
  235.                             malloc(Image->iwidth))==NULL) ||
  236.                             ((Image->data.rgb_lines[i].blue = (unsigned char *)
  237.                             malloc(Image->iwidth))==NULL)) {
  238.                         PRINT ("Cannot allocate memory for picture\n");
  239.                         return;
  240.                     }
  241.                 } else {
  242.                     if ((Image->data.map_lines[i] = (unsigned char *)
  243.                             malloc(Image->iwidth * sizeof(unsigned char))) == NULL) {
  244.                         PRINT ("Cannot allocate memory for picture\n");
  245.                         return;
  246.                     }
  247.                 }
  248.  
  249.                 for (j = 0 ; j < nPlanes ; j++)
  250.                     if (compression == CMPNONE) {
  251.                         for (k = 0 ; k < (Image->iwidth+7)/8 ; k++)
  252.                             row_bytes[j][k] = (unsigned char)read_byte(f);
  253.                         if ((Image->iwidth & 7) != 0)
  254.                             read_byte(f);
  255.                     } else {
  256.                         nBytes = 0;
  257.                         while (nBytes != (Image->iwidth+7)/8) {
  258.                             c = read_byte(f);
  259.                             if ((c >= 0) && (c <= 127))
  260.                                 for (k = 0 ; k <= c ; k++)
  261.                                     row_bytes[j][nBytes++] = (unsigned char)read_byte(f);
  262.                             else if ((c >= 129) && (c <= 255)) {
  263.                                 count = 257-c;
  264.                                 c = read_byte(f);
  265.                                 for (k = 0 ; k < count ; k++)
  266.                                     row_bytes[j][nBytes++] = (unsigned char)c;
  267.                             }
  268.                         }
  269.                     }
  270.  
  271.                 mask = 0x80;
  272.                 byte_index = 0;
  273.                 for (j = 0 ; j < Image->iwidth ; j++) {
  274.                     creg = 0;
  275.                     for (k = nPlanes-1 ; k >= 0 ; k--)
  276.                         if (row_bytes[k][byte_index] & mask)
  277.                             creg = creg*2 + 1;
  278.                         else
  279.                             creg *= 2;
  280.  
  281.                     if (viewmodes & HAM) {
  282.                         line = &Image->data.rgb_lines[i];
  283.                         switch (creg >> 4) {
  284.                             case 0:
  285.                                 Previous_Red = line->red[j] = (unsigned char)iff_colour_map[creg].Red;
  286.                                 Previous_Green = line->green[j] = (unsigned char)iff_colour_map[creg].Green;
  287.                                 Previous_Blue = line->blue[j] = (unsigned char)iff_colour_map[creg].Blue;
  288.                                 break;
  289.  
  290.                             case 1:
  291.                                 line->red[j] = (unsigned char)Previous_Red;
  292.                                 line->green[j] = (unsigned char)Previous_Green;
  293.                                 line->blue[j] = (unsigned char)(((creg & 0xf)<<4) + (creg&0xf));
  294.                                 Previous_Blue = (int) line->blue[j];
  295.                                 break;
  296.  
  297.                             case 2:
  298.                                 line->red[j] = (unsigned char)(((creg & 0xf)<<4) + (creg&0xf));
  299.                                 Previous_Red = (int) line->red[j];
  300.                                 line->green[j] = (unsigned char)Previous_Green;
  301.                                 line->blue[j] = (unsigned char)Previous_Blue;
  302.                                 break;
  303.  
  304.                             case 3:
  305.                                 line->red[j] = (unsigned char)Previous_Red;
  306.                                 line->green[j] = (unsigned char)(((creg & 0xf)<<4) + (creg&0xf));
  307.                                 Previous_Green = (int) line->green[j];
  308.                                 line->blue[j] = (unsigned char)Previous_Blue;
  309.                                 break;
  310.                         }
  311.                     } else if (nPlanes == 24) {
  312.                         line = &Image->data.rgb_lines[i];
  313.                         line->red[j] = (unsigned char)((creg >> 16) & 0xFF);
  314.                         line->green[j] = (unsigned char)((creg >> 8) & 0xFF);
  315.                         line->blue[j] = (unsigned char)(creg & 0xFF);
  316.                     } else {
  317.                         if (creg > (unsigned long)Image->Colour_Map_Size) {
  318.                             PRINT ("Error - IFF Image Map Colour out of range\n");
  319.                             return;
  320.                         }
  321.                         Image->data.map_lines[i][j] = (char)creg;
  322.                     }
  323.  
  324.                     mask >>= 1;
  325.                     if (mask == 0) {
  326.                         mask = 0x80;
  327.                         byte_index++;
  328.                     }
  329.                 }
  330.             }
  331.  
  332.             free (row_bytes);
  333.             fclose (f);
  334.             return;
  335.  
  336.         default:
  337.             for (i = 0 ; (long) i < Chunk_Header.size ; i++)
  338.                 if (getc(f) == EOF)
  339.                     iff_error();
  340.             break;
  341.         }
  342.     }
  343. }
  344.