home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Fred Fish Collection 1.5
/
ffcollection-1-5-1992-11.iso
/
ff_disks
/
100-199
/
ff114.lzh
/
WBLander
/
Source
/
jiff.c
< prev
next >
Wrap
C/C++ Source or Header
|
1987-11-22
|
9KB
|
376 lines
/**********************************************************************
*
* jiff.c Jim Kent's iff - ilbm reader
*
* This is the (sortof) short (sortof) simple no-frills IFF reader
* to get something out of DPaint, Images, or the Animator. It
* works well with the Aztec C compiler. It should work with Lattice
* but you never know until you try it. I haven't.
*
* The main interface to this is through the routine read_iff(filename).
* This returns a ILBM_info structure-pointer on success, and NULL on
* failure. It cleans up after itself on failure.
*
* I hope you will find this useful and easy to use. Please forgive
* my funky indentation style? Well at least I'm consistent!
*
* [ I didn't forgive it. I changed it -- Peter ]
*
* To demonstrate what a nice guy I am even though I'm far from wild
* about the IFF standard I'm placing this in the public domain. When
* you remove the DEBUG and PARANOID definitions the code is only
* 1536 bytes long.
*
* -Jim Kent April 22, 1986
*
* Cleaned it up and added CAMG chunk handler. Also, fixed indentation
* and removed static reference to root_info, allowing multiple images
* to be loaded.
*
* -Peter da Silva September 27, 1987
************************************************************************/
#include <stdio.h>
#include <exec/types.h>
#include <exec/memory.h>
#include <graphics/gfx.h>
#include <libraries/dos.h>
#include <intuition/intuition.h>
#include "jiff.h"
/* #define DEBUG */
#define PARANOID
#ifdef DEBUG
# define D(x) x
#else
# define D(x)
#endif
#ifdef PARANOID
# define P(x) x
#else
# define P(x)
#endif
static struct ILBM_info *read_ilbm(), *read_body();
static struct ILBM_info *root_info;
void free_image();
#define CHIP (MEMF_PUBLIC|MEMF_CHIP)
#ifdef PARANOID
/* a little paranoid routine that say's where we got before EOF */
static void
iff_truncated(info,where)
struct ILBM_info *info;
int where;
{
printf("ILBM truncated %d\n", where);
free_image(info);
}
#else
#define iff_truncated(i,w) free_image(i)
#endif
struct ILBM_info *
read_iff(name, just_colors)
char *name;
short just_colors;
{
struct ILBM_info *info;
FILE *file;
struct form_chunk chunk;
info = 0;
if((file = fopen(name, "r") ) == 0)
{
P(printf("couldn't Open %s to read\n", name));
return(NULL);
}
if( fread(&chunk, sizeof(struct form_chunk), 1, file) != 1)
{
iff_truncated(NULL, 0);
fclose(file);
return(NULL);
}
if(chunk.fc_type.b4_type != FORM)
{
P(printf("not a FORM - %s\n", name));
fclose(file);
return(NULL);
}
if(chunk.fc_subtype.b4_type != ILBM)
{
P(printf("FORM not an ILBM - %s\n", name));
fclose(file);
return(NULL);
}
D(printf("FORM %ld ILBM\n", chunk.fc_length));
root_info = AllocMem(sizeof(struct ILBM_info), MEMF_PUBLIC);
if(!root_info) {
P(printf("Can't allocate ILBM_info.\n"));
fclose(file);
return NULL;
}
info = read_ilbm(file, root_info, chunk.fc_length - sizeof(chunk), just_colors);
if(info) {
if(info->viewmode & HAM)
info->colors = 16;
if(info->header.h > 298)
info->viewmode |= LACE;
if(info->header.w > 376)
info->viewmode |= HIRES;
}
fclose(file);
D(printf("info = %lx\n", info));
return(info);
}
static
struct ILBM_info *
read_ilbm(file, info, length, just_colors)
FILE *file;
struct ILBM_info *info;
long length;
short just_colors;
{
struct iff_chunk chunk;
int i;
long read_in = 0;
int got_header = FALSE; /*to make sure gots the header first*/
int got_cmap = FALSE; /*make sure get cmap before "BODY" */
info->viewmode = 0L;
/*make sure the Planes are all NULL so can free up memory easily
on error abort */
for (i=0; i<8; i++)
info->bitmap.Planes[i] = NULL;
while (read_in < length)
{
if(fread(&chunk, sizeof(chunk), 1, file) != 1)
{
iff_truncated(info, 1);
return(NULL);
}
switch (chunk.iff_type.b4_type)
{
case BMHD:
D(printf("\tBMHD %ld\n", chunk.iff_length));
if(fread(&info->header, sizeof(info->header), 1, file) != 1)
{
iff_truncated(info, 2);
return(NULL);
}
got_header = TRUE;
break;
case CMAP:
D(printf("\tCMAP %ld\n", chunk.iff_length));
if(!got_header) {
printf("CMAP befor BMHD\n");
free_image(info);
return(NULL);
}
if(chunk.iff_length <= 3*MAXCOL ) {
if(fread(info->cmap, (int)chunk.iff_length, 1, file) != 1) {
iff_truncated(info, 3);
return(NULL);
}
info->colors = chunk.iff_length/3;
} else {
P(printf("warning, more than %d colors in ILBM CMAP\n",
MAXCOL));
if(fread(info->cmap, 3*MAXCOL, 1, file) != 1)
{
iff_truncated(info, 4);
return(NULL);
}
bit_bucket(file, chunk.iff_length - 3*MAXCOL);
info->colors = MAXCOL;
}
got_cmap = TRUE;
if(just_colors)
return(info);
break;
case CAMG:
D(printf("\tCAMG %ld\n", chunk.iff_length));
if(chunk.iff_length <= sizeof(long) ) {
if(fread(&info->viewmode, (int)chunk.iff_length, 1, file) != 1) {
iff_truncated(info, 8);
return(NULL);
}
} else {
P(printf("warning, more than viewport mode in ILBM CMAP\n"));
if(fread(&info->viewmode, sizeof(long), 1, file) != 1) {
iff_truncated(info, 9);
return(NULL);
}
bit_bucket(file, chunk.iff_length - sizeof(long));
}
break;
case BODY:
if(!got_cmap) {
P(printf("BODY before CMAP\n"));
free_image(info);
return(NULL);
}
D(printf("\tBODY %ld\n", chunk.iff_length));
return( read_body(file, info, chunk.iff_length) );
default:
#ifdef PARANOID
printf("Unknown type ");
printf("%c", (chunk.iff_type.b4_type>>24)&0x7F);
printf("%c", (chunk.iff_type.b4_type>>16)&0x7F);
printf("%c", (chunk.iff_type.b4_type>>8)&0x7F);
printf("%c", (chunk.iff_type.b4_type)&0x7F);
printf(" of b4_type\n");
#endif PARANOID
case GRAB: /*ignore documented but unwanted types*/
case DEST:
case SPRT:
case CRNG:
case CCRT:
bit_bucket(file, chunk.iff_length);
break;
}
read_in += chunk.iff_length + sizeof(chunk);
}
P(printf("no BODY in ILBM\n"));
free_image(info);
return(NULL);
}
static
struct ILBM_info *
read_body(file, info, length)
FILE *file;
register struct ILBM_info *info;
long length;
{
struct ILBM_header *header;
struct BitMap *bm;
int i, j;
int rlength;
int plane_offset;
D(printf("read_body( %lx %lx %ld)\n", file, info, length));
#ifdef PARANOID
/* when paranoid do a little error checking first ... fail fast! */
if(info->header.nPlanes > 8) {
printf("Whoa, woe Dale only speaks 8 planes boy, not %d\n",
info->header.nPlanes);
free_image(info);
return(NULL);
}
#endif PARANOID
/* ok a little more error checking */
if(info->header.compression != 0 && info->header.compression != 1) {
P(printf("unrecognized compression type %d\n", info->header.compression));
free_image(info);
return(NULL);
}
/*set up the bitmap part that doesn't involve memory allocation first -
hey this part does get done, and let's be optimistic...*/
info->bitmap.BytesPerRow = line_bytes(info->header.w);
info->bitmap.Rows = info->header.h;
info->bitmap.Depth = info->header.nPlanes;
info->bitmap.Flags = info->bitmap.pad = 0;
rlength = info->bitmap.Rows * info->bitmap.BytesPerRow;
for (i=0; i<info->header.nPlanes; i++) {
if((info->bitmap.Planes[i] = AllocMem(rlength, CHIP)) == NULL) {
P(printf("couldn't alloc plane %d in read_body\n",i));
free_image(info);
return(NULL);
}
}
plane_offset = 0;
for (i=0; i<info->bitmap.Rows; i++) {
/* this test should be in the inner loop for shortest code,
in the outer loop for greatest speed, so sue me I compromised */
if(info->header.compression == 0) {
for (j = 0; j < info->bitmap.Depth; j++) {
if(fread(info->bitmap.Planes[j] + plane_offset,
info->bitmap.BytesPerRow, 1, file) != 1) {
iff_truncated(info, 6);
return(NULL);
}
}
} else {
register char *dest, value;
register int so_far, count; /*how much have unpacked so far*/
for (j = 0; j < info->bitmap.Depth; j++) {
so_far = info->bitmap.BytesPerRow;
dest = (char *)info->bitmap.Planes[j] + plane_offset;
while (so_far > 0) {
if( (value = getc(file)) == 128) {
D(printf("NOP\n"));
} else if(value > 0) {
count = (int)value + 1;
so_far -= count;
if( fread(dest, count, 1, file) != 1) {
iff_truncated(info, 7);
return(NULL);
}
dest += count;
} else {
count = (int)-value + 1;
so_far -= count;
value = getc(file);
while (--count >= 0) /*this is fastest loop in C */
*dest++ = value;
}
}
if(so_far != 0) {
P(printf("compression quite screwed up, aborting %d\n", so_far));
free_image(info);
return(NULL);
}
}
}
plane_offset += info->bitmap.BytesPerRow;
}
return(info);
}
void free_image(info)
struct ILBM_info *info;
{
if(info) {
free_planes(&info->bitmap);
FreeMem(info, sizeof(struct ILBM_info));
}
}
void
free_planes(bmap)
register struct BitMap *bmap;
{
PLANEPTR plane;
long length;
short i;
length = bmap->BytesPerRow * bmap->Rows;
for (i=0; i<8; i++)
if( (plane = bmap->Planes[i]) != NULL)
FreeMem(plane, length);
}