home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fish 'n' More 2
/
fishmore-publicdomainlibraryvol.ii1991xetec.iso
/
fish
/
graphics
/
applications
/
dkbtrace
/
src
/
iff.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-08-26
|
11KB
|
290 lines
/*****************************************************************************
*
* iff.c
*
* from DKBTrace (c) 1990 David Buck
*
* This file implements a simple IFF format file reader.
*
* This software is freely distributable. The source and/or object code may be
* copied or uploaded to communications services so long as this notice remains
* at the top of each file. If any changes are made to the program, you must
* clearly indicate in the documentation and in the programs startup message
* who it was who made the changes. The documentation should also describe what
* those changes were. This software may not be included in whole or in
* part into any commercial package without the express written consent of the
* author. It may, however, be included in other public domain or freely
* distributed software so long as the proper credit for the software is given.
*
* This software is provided as is without any guarantees or warranty. Although
* the author has attempted to find and correct any bugs in the software, he
* is not responsible for any damage caused by the use of the software. The
* author is under no obligation to provide service, corrections, or upgrades
* to this package.
*
* Despite all the legal stuff above, if you do find bugs, I would like to hear
* about them. Also, if you have any comments or questions, you may contact me
* at the following address:
*
* David Buck
* 22C Sonnet Cres.
* Nepean Ontario
* Canada, K2H 8W7
*
* I can also be reached on the following bulleton boards:
*
* ATX (613) 526-4141
* OMX (613) 731-3419
* Mystic (613) 731-0088 or (613) 731-6698
*
* Fidonet: 1:163/109.9
* Internet: David_Buck@Carleton.CA
*
* IBM Port by Aaron A. Collins. Aaron may be reached on the following BBS'es:
*
* Lattice BBS (708) 916-1200
* The Information Exchange BBS (708) 945-5575
* Stillwaters BBS (708) 403-2826
*
*****************************************************************************/
#include "frame.h"
#include "dkbproto.h"
static IMAGE_COLOUR *iff_colour_map;
static int colourmap_size;
static CHUNK_HEADER Chunk_Header;
#define FORM 0x464f524dL
#define ILBM 0x494c424dL
#define BMHD 0x424d4844L
#define CAMG 0x43414d47L
#define CMAP 0x434d4150L
#define BODY 0x424f4459L
#define CMPNONE 0
#define HAM 0x800
void iff_error ()
{
printf ("Invalid iff file\n");
exit(1);
}
int read_byte(f)
FILE *f;
{
int c;
if ((c = getc(f)) == EOF)
iff_error();
return (c);
}
int read_word(f)
FILE *f;
{
int result;
result = read_byte(f)*256;
result += read_byte(f);
return (result);
}
long read_long(f)
FILE *f;
{
int i;
long result;
result = 0;
for (i = 0 ; i < 4 ; i++)
result = result * 256 + read_byte(f);
return (result);
}
void Read_Chunk_Header (f, dest)
FILE *f;
CHUNK_HEADER *dest;
{
dest->name = read_long(f);
dest->size = read_long(f);
}
void read_iff_image(Image, filename)
IMAGE *Image;
char *filename;
{
FILE *f;
unsigned char **row_bytes;
int c, i, j, k, creg, index, nBytes, nBytesRead, nPlanes, compression,
mask, byte_index, count, viewmodes;
int Previous_Red, Previous_Green, Previous_Blue;
if ((f = fopen(filename, "rb")) == NULL) {
printf ("Cannot open IFF file %s\n", filename);
exit(1);
}
Previous_Red = Previous_Green = Previous_Blue = 0;
viewmodes = 0;
while (1) {
Read_Chunk_Header(f, &Chunk_Header);
switch ((int) Chunk_Header.name) {
case FORM: if (read_long(f) != ILBM)
iff_error();
break;
case BMHD: Image->iwidth = read_word(f);
Image->width = (DBL)Image->iwidth;
Image->iheight = read_word(f);
Image->height = (DBL)Image->iheight;
read_word(f); /* x position ignored */
read_word(f); /* y position ignored */
nPlanes = read_byte(f);
colourmap_size = 1<<nPlanes;
read_byte(f); /* masking ignored */
compression = read_byte(f); /* masking ignored */
read_byte(f); /* pad */
read_word(f); /* Transparent colour ignored */
read_word(f); /* Aspect ratio ignored */
read_word(f); /* page width ignored */
read_word(f); /* page height ignored */
break;
case CAMG: viewmodes = (int) read_long(f); /* Viewmodes */
if (viewmodes & HAM)
colourmap_size = 16;
break;
case CMAP: colourmap_size = (int) Chunk_Header.size / 3;
if ((iff_colour_map = (IMAGE_COLOUR *) malloc(sizeof(IMAGE_COLOUR)*colourmap_size)) == NULL)
iff_error();
for (i = 0 ; i < colourmap_size ; i++) {
iff_colour_map[i].Red = read_byte(f);
iff_colour_map[i].Green = read_byte(f);
iff_colour_map[i].Blue = read_byte(f);
}
Previous_Red = iff_colour_map[0].Red;
Previous_Green = iff_colour_map[0].Green;
Previous_Blue = iff_colour_map[0].Blue;
for (i = colourmap_size*3 ; i < Chunk_Header.size ; i++)
read_byte(f);
break;
case BODY: if ((row_bytes = (unsigned char **) malloc (4*nPlanes)) == NULL) {
printf ("Not enough memory\n");
exit(1);
}
for (i = 0 ; i < nPlanes ; i++)
if ((row_bytes[i] = (unsigned char *) malloc((Image->iwidth+7)/8)) == NULL) {
printf ("Not enough memory\n");
exit(1);
}
if (((Image->red = (unsigned char *) malloc(Image->iwidth*Image->iheight))==NULL) ||
((Image->green = (unsigned char *) malloc(Image->iwidth*Image->iheight))==NULL) ||
((Image->blue = (unsigned char *) malloc(Image->iwidth*Image->iheight))==NULL)) {
printf ("Cannot allocate memory for picture\n");
exit(1);
}
for (i = 0 ; i < Image->iheight ; i++) {
for (j = 0 ; j < nPlanes ; j++)
if (compression == CMPNONE) {
for (k = 0 ; k < (Image->iwidth+7)/8 ; k++)
row_bytes[j][k] = read_byte(f);
if ((Image->iwidth & 7) != 0)
read_byte(f);
}
else {
nBytes = 0;
nBytesRead = 0;
while (nBytes != (Image->iwidth+7)/8) {
c = read_byte(f);
nBytesRead++;
if ((c >= 0) && (c <= 127))
for (k = 0 ; k <= c ; k++)
row_bytes[j][nBytes++] = read_byte(f);
else if ((c >= 129) && (c <= 255)) {
count = 257-c;
c = read_byte(f);
nBytesRead++;
for (k = 0 ; k < count ; k++)
row_bytes[j][nBytes++] = c;
}
}
}
mask = 0x80;
byte_index = 0;
for (j = 0 ; j < Image->iwidth ; j++) {
creg = 0;
for (k = nPlanes-1 ; k >= 0 ; k--)
if (row_bytes[k][byte_index] & mask)
creg = creg*2 + 1;
else
creg *= 2;
index = (Image->iheight-i-1)*Image->iwidth + j;
if (viewmodes & HAM) {
switch (creg >> 4) {
case 0:
Previous_Red = Image->red[index] = iff_colour_map[creg].Red;
Previous_Green = Image->green[index] = iff_colour_map[creg].Green;
Previous_Blue = Image->blue[index] = iff_colour_map[creg].Blue;
break;
case 1:
Image->red[index] = Previous_Red;
Image->green[index] = Previous_Green;
Previous_Blue = Image->blue[index] = ((creg & 0xf)<<4) + (creg&0xf);
break;
case 2:
Previous_Red = Image->red[index] = ((creg & 0xf)<<4) + (creg&0xf);
Image->green[index] = Previous_Green;
Image->blue[index] = Previous_Blue;
break;
case 3:
Image->red[index] = Previous_Red;
Previous_Green = Image->green[index] = ((creg & 0xf)<<4) + (creg&0xf);
Image->blue[index] = Previous_Blue;
break;
}
}
else {
Image->red[index] = iff_colour_map[creg].Red;
Image->green[index] = iff_colour_map[creg].Green;
Image->blue[index] = iff_colour_map[creg].Blue;
}
mask >>= 1;
if (mask == 0) {
mask = 0x80;
byte_index++;
}
}
}
free (row_bytes);
fclose (f);
return;
default:
for (i = 0 ; i < Chunk_Header.size ; i++)
if (getc(f) == EOF)
iff_error();
break;
}
}
}