home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The CDPD Public Domain Collection for CDTV 3
/
CDPDIII.bin
/
pd
/
commodities
/
superdark
/
iff
/
jiff.c
next >
Wrap
C/C++ Source or Header
|
1992-11-07
|
8KB
|
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.
*
* I've included a simple main program. This is just to make it
* stand alone. Since amiga screen initializations are massive, all
* it does as is is read it into a BitMap, and then free up the BitMap.
* Should crash it if it's gonna crash though.
*
* 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!
*
* 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
************************************************************************/
#include <stdio.h>
#include <exec/types.h>
#include <exec/memory.h>
#include <graphics/gfx.h>
#include <libraries/dos.h>
#include "jiff.h"
#define TAILLE_BUFFER 1024
char buffer[TAILLE_BUFFER];
int nb=0;
/*this is an all too common state of software development. Get rid
of this define as soon as it runs*/
/*
#define DEBUG
*/
/*this is the normal state of software development. Seriously undefine
this to make it shut up about errors and reduce code size half way
through beta testing... */
/*
#define PARANOID
*/
static struct ILBM_info *read_ilbm(), *read_body();
/* OK this code is almost re-entrant. Pass this guy from above to
make it really re-entrant. (Why do you need a reentrant ILBM
reader though?? Maybe for Dale ... ) */
static struct ILBM_info root_info; /*static so get initialized to zero*/
#ifdef PARANOID
/* a little paranoid routine that say's where we got before EOF */
static void
iff_truncated(where)
int where;
{
free_planes(&root_info.bitmap);
}
#endif PARANOID
int my_Read(hdlr,p,taille)
BPTR hdlr;
char *p;
int taille;
{
int i;
for(i=0;i<taille;i++){
if(nb==0){
Read(hdlr,&buffer,TAILLE_BUFFER);
nb=TAILLE_BUFFER;
}
p[i]=buffer[TAILLE_BUFFER-nb];
nb--;
}
return(taille);
}
int my_Seek(hdlr,taille,type)
BPTR hdlr;
int taille,type;
{
int i;
if(taille<=nb){
nb=nb-taille;
}else{
taille=taille-nb;
Seek(hdlr,taille,type);
}
}
BPTR my_Open(name,mode)
char *name;
long int mode;
{
nb=0;
return(Open(name,mode));
}
struct ILBM_info *
read_iff(name, just_colors)
char *name;
short just_colors;
{
struct ILBM_info *info = &root_info;
BPTR hdlr;
struct form_chunk chunk;
info->camg=0;
if ((hdlr = my_Open(name, MODE_OLDFILE) ) == 0)
{
return(NULL);
}
if ( my_Read(hdlr,&chunk, sizeof(struct form_chunk)) !=sizeof(struct form_chunk))
{
#ifdef PARANOID
iff_truncated(0);
#endif PARANOID
Close(hdlr);
return(NULL);
}
if (chunk.fc_type.b4_type != FORM)
{
Close(hdlr);
return(NULL);
}
if (chunk.fc_subtype.b4_type != ILBM)
{
#ifdef PARANOID
printf("FORM not an ILBM - %s\n", name);
#endif PARANOID
Close(hdlr);
return(NULL);
}
#ifdef DEBUG
printf("FORM %ld ILBM\n", chunk.fc_length);
#endif DEBUG
info = read_ilbm(hdlr, info, chunk.fc_length - sizeof(chunk), just_colors);
Close(hdlr);
return(info);
}
static
struct ILBM_info *
read_ilbm(hdlr, info, length, just_colors)
BPTR *hdlr;
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" */
/*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 (my_Read(hdlr,&chunk, sizeof(chunk)) !=sizeof(chunk))
{
#ifdef PARANOID
iff_truncated(1);
#endif PARANOID
return(NULL);
}
switch (chunk.iff_type.b4_type)
{
case BMHD:
#ifdef DEBUG
printf("\tBMHD %ld\n", chunk.iff_length);
#endif DEBUG
if (my_Read(hdlr,&info->header, sizeof(info->header)) != sizeof(info->header))
{
#ifdef PARANOID
iff_truncated(2);
#endif PARANOID
return(NULL);
}
got_header = TRUE;
break;
case CAMG:
my_Read(hdlr,&info->camg, 4);
break;
case CMAP:
if (!got_header){
return(NULL);
}
if (chunk.iff_length <= 3*MAXCOL ){
if (my_Read(hdlr,info->cmap, (int)chunk.iff_length) !=(int)chunk.iff_length){
return(NULL);
}
}else{
if (my_Read(hdlr,info->cmap, 3*MAXCOL) != 3*MAXCOL){
return(NULL);
}
bit_bucket(hdlr, chunk.iff_length - sizeof(3*MAXCOL));
}
got_cmap = TRUE;
if (just_colors)
return(info);
break;
case BODY:
if (!got_cmap)
{
return(NULL);
}
return( read_body(hdlr, info, chunk.iff_length) );
default: /*squawk about unknown types if PARANOID */
case GRAB: /*ignore documented but unwanted types*/
case DEST:
case SPRT:
case CRNG:
case CCRT:
bit_bucket(hdlr, chunk.iff_length);
break;
}
read_in += chunk.iff_length + sizeof(chunk);
}
return(NULL);
}
static
struct ILBM_info *
read_body(hdlr, info, length)
BPTR hdlr;
register struct ILBM_info *info;
long length;
{
struct ILBM_header *header;
struct BitMap *bm;
int i, j;
int rlength;
int plane_offset;
/* ok a little more error checking */
if (info->header.compression != 0 && info->header.compression != 1)
{
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] = ralloc(rlength)) == NULL)
{
free_planes( &info->bitmap );
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 ( my_Read(hdlr,info->bitmap.Planes[j] + plane_offset,
info->bitmap.BytesPerRow) !=info->bitmap.BytesPerRow)
{
#ifdef PARANOID
iff_truncated(6);
#endif PARANOID
free_planes( &info->bitmap);
return(NULL);
}
}
}
else
{
register char *dest;
char 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)
{
my_Read(hdlr,&value,1);
if (value == 128)
{
}
else if (value > 0)
{
count = (int)value + 1;
so_far -= count;
if ( my_Read(hdlr,dest, count) !=count)
{
#ifdef PARANOID
iff_truncated(7);
#endif PARANOID
free_planes( &info->bitmap);
return(NULL);
}
dest += count;
}
else
{
count = (int)-value + 1;
so_far -= count;
my_Read(hdlr,&value,1);
while (--count >= 0) /*this is fastest loop in C */
*dest++ = value;
}
}
if (so_far != 0)
{
#ifdef PARANOID
printf("compression quite screwed up, aborting %d\n", so_far);
#endif PARANOID
free_planes( &info->bitmap);
return(NULL);
}
}
}
plane_offset += info->bitmap.BytesPerRow;
}
return(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)
rfree(plane, length);
}