home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Fred Fish Collection 1.5
/
ffcollection-1-5-1992-11.iso
/
ff_disks
/
200-299
/
ff218.lzh
/
Mandel
/
src
/
Jiff.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-06-04
|
28KB
|
1,203 lines
/*
* JIFF.H
*/
#define XMAX 640
#define LOXMAX 320
#define YMAX 200
#define XASPECT 5
#define YASPECT 11
/*
* EA handy make a long from 4 chars macros redone to work with Aztec
*/
#define MAKE_ID(a, b, c, d)\
( ((long)(a)<<24) | ((long)(b)<<16) | ((long)(c)<<8) | (long)(d) )
/*
* These are the IFF types I deal with
*/
#define FORM MAKE_ID('F', 'O', 'R', 'M')
#define ILBM MAKE_ID('I', 'L', 'B', 'M')
#define BMHD MAKE_ID('B', 'M', 'H', 'D')
#define CMAP MAKE_ID('C', 'M', 'A', 'P')
#define BODY MAKE_ID('B', 'O', 'D', 'Y')
/*
* And these are the IFF types I ignore but don't squawk about
*/
#define GRAB MAKE_ID('G', 'R', 'A', 'B')
#define DEST MAKE_ID('D', 'E', 'S', 'T')
#define SPRT MAKE_ID('S', 'P', 'R', 'T')
#define CAMG MAKE_ID('C', 'A', 'M', 'G')
#define CRNG MAKE_ID('C', 'R', 'N', 'G')
#define CCRT MAKE_ID('C', 'C', 'R', 'T')
#define EVEN(x) (((x) + 1) & ~1)
#define MANDEL
/*
* Some macros for raster memory allocation ... redefine if you're
* sensible and manage memory locally
*/
#ifndef MANDEL
/*
* ralloc - raster alloc
*/
# define ralloc(amount) (PLANEPTR)AllocMem((long)(amount), MEMF_CHIP)
/*
* rfree - raster free
*/
# define rfree(pt, amount) FreeMem( (pt), (long)(amount) )
#else /* MANDEL */
# include <mandel.h>
/*
* We don't want to allocate a complete raster for the picture, since we
* already have a screen with a window where we want to have it.
* Therefore, we allocate some small buffers, which get blitted into our
* window as soon as they fill up.
*/
# define MAXPLANESIZE 1040L
/*
* ralloc - raster alloc
*/
# define ralloc(amount) (PLANEPTR)AllocMem(MAXPLANESIZE, MEMF_CHIP | MEMF_CLEAR)
/*
* rfree - raster free
*/
# define rfree(pt, amount) FreeMem( (pt), MAXPLANESIZE )
#endif /* !MANDEL */
/*
* line_bytes = the number of words * 2 (for bytes) a raster line takes up
*/
#define line_bytes(width) ((((width) + 15) >> 3) & ~0x0001)
/*
* psize - plane size in bytes (an even number) of a raster given width
* and height
*/
#define psize(width, height) ( line_bytes(width)*height)
/*
* The place to throw excess bits
*/
#define bit_bucket(file, length) fseek(file, (long)EVEN(length), 1)
union bytes4 {
char b4_name[4];
LONG b4_type;
};
struct iff_chunk {
union bytes4 iff_type;
LONG iff_length;
};
struct form_chunk {
union bytes4 fc_type; /* == FORM */
LONG fc_length;
union bytes4 fc_subtype;
};
struct CommodoreAmiga {
struct iff_chunk camg_iffc; /* == CAMG */
LONG camg_data;
};
#ifndef MANDEL /* We have this already in Mandel.h */
struct BitMapHeader {
UWORD w,
h;
UWORD x,
y;
UBYTE nPlanes;
UBYTE masking;
UBYTE compression;
UBYTE pad1;
UWORD transparentColor;
UBYTE xAspect,
yAspect;
WORD pageWidth,
pageHeight;
};
/*
* ILBM_info is the structure win_read_iff returns, and is hopefully all
* you need to deal with out of the iff reader routines below
*/
struct ILBM_info {
struct BitMapHeader header;
UBYTE cmap[MAXCOL * 3];
struct BitMap bitmap;
#ifdef MANDEL
struct Mand *mand;
long mandsize;
#endif
};
#endif /* !MANDEL */
/*-
* I sure wish C function "prototypes" were real and not just ANSI
*
* extern struct ILBM_info *win_read_iff();
* win_read_iff( char *filename, short just_colors, int MandSize,
* APTR MandPointer );
* extern void free_planes(); free_planes( struct BitMap *bitmap);
* extern int write_iff();
* write_iff(char *name, unsigned char *colors, struct Window *window,
* short xoff, short yoff, short compressed);
*/
/*
* Anyone know where some useful minterms are defined?
*/
#define COPY_MINTERM 0x0C0L
/***
A meditation for the guru from the Diamond Sutra -
So shall you think of all this fleeting world:
A star at dawn, a bubble in a stream;
A flash of lightning in a summer cloud,
A flickering lamp, a phantom, and a dream.
***/
/*
* 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 win_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! (* Run through the
* C-Beautifier by Olaf Seibert !! *)
*
* 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 <intuition/intuition.h>
/* #include "jiff.h" */
/*
* This is an all too common state of software development. Get rid of
* this define as soon as it runs.
*/
#undef DEBUG
/* #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...
*/
#undef PARANOID
/*
* This is nice if you want to use a debugger on the STATIC data and
* routines in this file. Redefine only if you don't need a debugger.
*/
#ifdef DEBUG
# undef STATIC
# define STATIC
#endif
STATIC struct ILBM_info *win_read_ilbm();
STATIC struct ILBM_info *win_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 ... ) Well, look in the IFF specs for instance... [Olaf
* Seibert, KosmoSoft]
*/
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;
{
printf("ILBM truncated %d\n", where);
free_planes(&root_info.bitmap);
}
#endif PARANOID
struct ILBM_info *
win_read_iff(name, just_colors, window, MandSize, MandPointer)
char *name;
short just_colors;
struct Window *window;
int MandSize;
APTR MandPointer;
{
struct ILBM_info *info = &root_info;
FILE *file;
struct form_chunk chunk;
if ((file = fopen(name, "r")) == 0) {
#ifdef PARANOID
printf("couldn't fopen %s to read\n", name);
#endif PARANOID
return NULL;
}
if (fread(&chunk, sizeof (struct form_chunk), 1, file) != 1) {
#ifdef PARANOID
iff_truncated(0);
#endif PARANOID
fclose(file);
return NULL;
}
if (chunk.fc_type.b4_type != FORM) {
#ifdef PARANOID
printf("not a FORM - %s\n", name);
#endif PARANOID
fclose(file);
return NULL;
}
if (chunk.fc_subtype.b4_type != ILBM) {
#ifdef PARANOID
printf("FORM not an ILBM - %s\n", name);
#endif PARANOID
fclose(file);
return NULL;
}
#ifdef DEBUG
printf("FORM %ld ILBM\n", chunk.fc_length);
#endif DEBUG
#ifdef MANDEL
info->mand = (struct Mand *) MandPointer;
info->mandsize = MandSize;
info->mand->MandID = 0; /* we have not yet read it */
#endif
info = win_read_ilbm(file, info, chunk.fc_length - sizeof (chunk),
just_colors, window);
#ifdef DEBUG
printf("info = %lx\n", info);
#endif DEBUG
#ifdef MANDEL
/*
* Backward compatibility with non-standard code: We may want to read
* the extra MAND if we have not read it by now.
*/
if (info && MandSize && info->mand->MandID != MAND) {
fread(MandPointer, 1, MandSize, file);
info->mand->Size -= 2 * sizeof (long); /* patch bug */
}
#endif MANDEL
fclose(file);
return info;
}
STATIC struct ILBM_info *
win_read_ilbm(file, info, length, just_colors, window)
FILE *file;
struct ILBM_info *info;
long length;
short just_colors;
struct Window *window;
{
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 (fread(&chunk, sizeof (chunk), 1, file) != 1) {
#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 (fread(&info->header, sizeof (info->header), 1, file) != 1) {
#ifdef PARANOID
iff_truncated(2);
#endif PARANOID
return NULL;
}
got_header = TRUE;
break;
case CMAP:
#ifdef DEBUG
printf("\tCMAP %ld\n", chunk.iff_length);
#endif DEBUG
if (!got_header) {
#ifdef PARANOID
printf("CMAP before BMHD\n");
#endif PARANOID
return NULL;
}
if (chunk.iff_length <= 3 * MAXCOL) {
if (fread(info->cmap, (int) chunk.iff_length, 1, file) != 1) {
#ifdef PARANOID
iff_truncated(3);
#endif PARANOID
return NULL;
}
} else {
#ifdef PARANOID
printf("warning, more than %d colors in ILBM CMAP\n",
MAXCOL);
#endif PARANOID
if (fread(info->cmap, (int) 3 * MAXCOL, 1, file) != 1) {
#ifdef PARANOID
iff_truncated(4);
#endif PARANOID
return NULL;
}
bit_bucket(file, chunk.iff_length - 3 * MAXCOL);
}
got_cmap = TRUE;
if (just_colors)
return info;
break;
case MAND:
#ifdef DEBUG
printf("\tMAND %ld\n", chunk.iff_length);
#endif DEBUG
if (chunk.iff_length + sizeof (chunk) <= info->mandsize) {
if (fread((char *) info->mand + sizeof (chunk),
(int) chunk.iff_length, 1, file) != 1) {
#ifdef DEBUG
printf("fread MAND fails; filepos %ld ferror %d\n",
(long) ftell(file), (int) ferror(file));
#endif
return NULL;
}
*(struct iff_chunk *) info->mand = chunk;
/*
* skip padding byte
*/
if (chunk.iff_length & 1)
getc(file);
} else {
#ifdef DEBUG
printf("skipping MAND; too large for buffer (%ld)\n",
(long) info->mandsize);
#endif
bit_bucket(file, chunk.iff_length);
}
break;
case BODY:
if (!got_cmap) {
#ifdef PARANOID
printf("BODY before CMAP\n");
#endif PARANOID
return NULL;
}
#ifdef DEBUG
printf("\tBODY %ld\n", chunk.iff_length);
#endif DEBUG
return win_read_body(file, info, chunk.iff_length, window);
default: /* Squawk about unknown types if PARANOID */
#ifdef PARANOID
printf("\t unknown type %lx of b4_type\n", chunk.iff_type.b4_type);
case GRAB: /* Ignore documented but unwanted types */
case DEST:
case SPRT:
case CAMG:
case CRNG:
case CCRT:
#endif PARANOID
bit_bucket(file, chunk.iff_length);
break;
}
read_in += EVEN(chunk.iff_length) + sizeof (chunk);
}
#ifdef PARANOID
printf("no BODY in ILBM\n");
#endif PARANOID
return NULL;
}
STATIC struct ILBM_info *
win_read_body(file, info, length, window)
FILE *file;
register struct ILBM_info *info;
long length;
struct Window *window;
{
struct ILBM_header *header;
struct BitMap *bm;
int i,
j;
int rlength;
int plane_offset;
ULONG YSize,
DestX,
DestY;
#ifdef DEBUG
printf("win_read_body( %lx %lx %ld)\n", file, info, length);
#endif DEBUG
#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);
return NULL;
}
#endif PARANOID
/*
* Ok a little more error checking
*/
if (info->header.compression != 0 && info->header.compression != 1) {
#ifdef PARANOID
printf("unrecognized compression type %d\n", info->header.compression);
#endif PARANOID
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) {
#ifdef PARANOID
printf("couldn't alloc plane %d in win_read_body\n", i);
#endif PARANOID
free_planes(&info->bitmap);
return NULL;
}
}
plane_offset = 0;
YSize = (MAXPLANESIZE / info->bitmap.BytesPerRow);
if (window->Flags & GIMMEZEROZERO) {
DestX = 0;
DestY = 0;
} else {
DestX = window->BorderLeft;
DestY = window->BorderTop;
}
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) {
#ifdef PARANOID
iff_truncated(6);
#endif PARANOID
free_planes(&info->bitmap);
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) {
#ifdef DEBUG
printf("NOP\n");
#endif DEBUG
} else if (value > 0) {
count = (int) value + 1;
so_far -= count;
if (fread(dest, count, 1, file) != 1) {
#ifdef PARANOID
iff_truncated(7);
#endif PARANOID
free_planes(&info->bitmap);
return NULL;
}
dest += count;
} else {
count = (int) -value + 1;
so_far -= count;
value = getc(file);
while (--count >= 0) /* This is fastest loop on
* the 68000 */
*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;
if (plane_offset > MAXPLANESIZE - info->bitmap.BytesPerRow) {
BltBitMapRastPort(&info->bitmap, 0L, 0L,
window->RPort, DestX, DestY,
info->bitmap.BytesPerRow * 8L, YSize,
COPY_MINTERM);
plane_offset = 0;
DestY += YSize;
}
}
if (plane_offset) {
BltBitMapRastPort(&info->bitmap, 0L, 0L,
window->RPort, DestX, DestY,
info->bitmap.BytesPerRow * 8L,
(long) plane_offset / info->bitmap.BytesPerRow,
COPY_MINTERM);
}
if (length & 1) {
/*
* Skip padding byte
*/
getc(file);
}
free_planes(&info->bitmap);
return info;
}
void
free_planes(bmap)
register struct BitMap *bmap;
{
PLANEPTR plane;
long length;
short i;
length = bmap->BytesPerRow * bmap->Rows;
for (i = bmap->Depth; --i >= 0;) {
if ((plane = bmap->Planes[i]) != NULL) {
rfree(plane, length);
bmap->Planes[i] = NULL;
}
}
}
#undef DEBUG
/* #define DEBUG/* */
#undef PARANOID
/*----------------------------------------------------------------------*
* jpacker.c Convert data to "cmpByteRun1" run compression.
*
* pack_row() is an adaptation of PackRow()
* by Jerry Morrison and Steve Shaw, Electronic Arts,
* modified and tweaked by Jim Kent, Dancing Flame 05/02/86
*
* control bytes:
* [0..127] : followed by n+1 bytes of data.
* [-1..-127] : followed by byte to be repeated(-n)+1 times.
* -128 : NOOP.
*
*
* write_iff() is the only function you can access in this module.
*----------------------------------------------------------------------*/
/*-
#include <exec/types.h>
#include <graphics/gfx.h>
#include <stdio.h>
#include "jiff.h"
*/
#define DUMP 0
#define RUN 1
#define MINRUN 3
#define MAXRUN 128
#define MAXDAT 128
/*
* pack_row - pass source line pointer, length of line, and file. Returns
* # of bytes after compression. Returns 0 on write error. Pass file =
* NULL to just find out length, otherwise will write compressed row to
* file.
*/
STATIC unsigned int
pack_row(file, source, size)
FILE *file;
char *source;
int size;
{
char c,
lastc = '\0';
short mode = DUMP;
short nbuf = 0; /* Number of chars in buffer */
short rstart = 0; /* Buffer index current run starts */
unsigned short putsize;
#if OLD
char buf[MAXDAT * 3 / 2]; /* I think MAXDAT+1 would
* suffice */
#else
/*
* And I think that buf can be changed into a pointer to the source
* line, to the beginning of a dump. Saves stack space and copying.
*/
char *buf;
#endif
putsize = 0;
#if OLD
buf[0] = lastc = *source++; /* So have valid lastc */
#else
buf = source;
lastc = *source++; /* So have valid lastc */
#endif
nbuf = 1;
size--; /* Since one byte eaten */
for (; size; --size) {
#if OLD
buf[nbuf++] = c = *source++;
#else
nbuf++;
c = *source++;
#endif
switch (mode) {
case DUMP:
/*
* If the buffer is full, write the length byte, then the data
*/
if (nbuf > MAXDAT) {
if (file != NULL) {
if (putc(nbuf - 2, file) == EOF)
return 0;
if (fwrite(buf, nbuf - 1, 1, file) != 1)
return 0;
}
putsize += nbuf;
#if OLD
buf[0] = c;
#else
buf = source - 1; /* Undo the previous source++ */
#endif
nbuf = 1;
rstart = 0;
break;
}
if (c == lastc) {
if (nbuf - rstart >= MINRUN) {
if (rstart > 0) {
if (file != NULL) {
if (putc(rstart - 1, file) == EOF)
return 0;
if (fwrite(buf, rstart, 1, file) != 1)
return 0;
}
putsize += rstart + 1;
}
mode = RUN;
} else if (rstart == 0)
mode = RUN;
/*
* No dump in progress, so can't lose by making these 2 a
* run.
*/
} else
rstart = nbuf - 1; /* First of run */
break;
case RUN:
if ((c != lastc) || (nbuf - rstart > MAXRUN)) {
/*
* Output run
*/
if (file != NULL) {
if (putc(-(nbuf - rstart - 2), file) == EOF)
return 0;
if (putc(lastc, file) == EOF)
return 0;
}
putsize += 2;
#if OLD
buf[0] = c;
#else
buf = source - 1; /* Undo the previous source++ */
#endif
nbuf = 1;
rstart = 0;
mode = DUMP;
}
break;
}
lastc = c;
}
switch (mode) {
case DUMP:
if (file != NULL) {
if (putc(nbuf - 1, file) == EOF)
return 0;
if (fwrite(buf, nbuf, 1, file) != 1)
return 0;
}
putsize += nbuf + 1;
break;
case RUN:
if (file != NULL) {
if (putc(-(nbuf - rstart - 1), file) == EOF)
return 0;
if (putc(lastc, file) == EOF)
return 0;
}
putsize += 2;
break;
}
return putsize;
}
/*
* write_row - pass source line pointer, length of line, and file. Returns
* # of bytes after not compressing. Returns 0 on write error. Pass file
* = NULL to just find out length, otherwise will write non-compressed row
* to file.
*/
STATIC unsigned int
write_row(file, source, size)
FILE *file;
char *source;
int size;
{
if (file) {
if (fwrite(source, size, 1, file) != 1)
return 0;
}
return size;
}
STATIC unsigned long
pack_window(file, window, writer)
FILE *file;
register struct Window *window;
register unsigned int (*writer) ();
{
unsigned short i,
j;
unsigned row_length;
unsigned long compressed_length;
unsigned plane_offset;
int BytesPerRow;
int YSize;
ULONG SrcX,
SrcY;
struct RastPort Rp;
struct BitMap Bitmap;
#ifdef DEBUG
printf("pack_window( %lx %lx)\n", file, window);
#endif DEBUG
compressed_length = 0;
plane_offset = 0;
BytesPerRow = line_bytes(window->GZZWidth);
Bitmap.Depth = window->WScreen->BitMap.Depth;
if (window->Flags & GIMMEZEROZERO) {
SrcX = 0;
SrcY = 0;
} else {
SrcX = window->BorderLeft;
SrcY = window->BorderTop;
}
YSize = MAXPLANESIZE / BytesPerRow;
InitBitMap(&Bitmap, (ULONG) Bitmap.Depth,
(ULONG) (8 * BytesPerRow), (ULONG) YSize);
/*
* Make sure the Planes are all NULL so can free up memory easily on
* error abort
*/
for (i = 0; i < 8; i++)
Bitmap.Planes[i] = NULL;
for (i = 0; i < Bitmap.Depth; i++) {
if ((Bitmap.Planes[i] = ralloc(MAXPLANESIZE)) == NULL) {
#ifdef DEBUG
printf("couldn't alloc plane %d in pack_window\n", i);
printf("pack_window: aborting; free_planes\n");
#endif
free_planes(&Bitmap);
return 0;
}
}
InitRastPort(&Rp);
Rp.BitMap = &Bitmap;
#ifdef DEBUG
printf("pack_window BytesPerRow=%ld Depth=%ld\n", (long) BytesPerRow,
(long) Bitmap.Depth);
#endif
for (i = 0; i < window->GZZHeight; i++) {
if (plane_offset == 0) {
#ifdef DEBUG
printf("pack_window ClipBlit SrcX=%ld SrcY=%ld YSize=%ld\n",
SrcX, SrcY, (ULONG) YSize);
#endif
#define DestX 0L
#define DestY 0L
ClipBlit(window->RPort, SrcX, SrcY,
&Rp, DestX, DestY,
(ULONG) window->GZZWidth, (ULONG) YSize,
COPY_MINTERM);
#undef DestX
#undef DestY
SrcY += YSize;
}
for (j = 0; j < Bitmap.Depth; j++) {
if ((row_length = (*writer) (file, Bitmap.Planes[j] + plane_offset,
BytesPerRow)) == 0) {
#ifdef DEBUG
printf("error packing row %d plane %d\n", i, j);
printf("pack_window: aborting; free_planes\n");
#endif
free_planes(&Bitmap);
return 0;
}
compressed_length += row_length;
}
plane_offset += BytesPerRow;
if (plane_offset > MAXPLANESIZE - BytesPerRow)
plane_offset = 0;
}
#ifdef DEBUG
printf("pack_window: free_planes\n");
#endif
free_planes(&Bitmap);
if (compressed_length & 1) {/* Check to see odd length */
if (file != NULL) {
if (putc(0, file) == EOF) {
return 0;
}
}
/*
* compressed_length++; Deleted!!! Padding should NOT be included
* in the chunk size !!!
*/
}
return compressed_length;
}
int
write_iff(name, colors, window, xoff, yoff, compressed, MandSize, MandPointer)
char *name;
unsigned char *colors;
register struct Window *window;
short xoff,
yoff;
short compressed;
int MandSize;
APTR MandPointer;
{
FILE *file;
struct form_chunk chunk;
struct iff_chunk ichunk;
struct BitMapHeader header;
long bits_size;
short i;
int width = 0;
int Depth;
int BytesPerRow;
#ifdef DEBUG
printf("write_iff\n");
#endif
if ((file = fopen(name, "w")) == 0) {
#ifdef PARANOID
printf("couldn't fopen %s to write\n", name);
#endif PARANOID
goto abort;
}
/*
* Say its a FORM ILBM
*/
chunk.fc_type.b4_type = FORM;
chunk.fc_subtype.b4_type = ILBM;
#ifdef MANDEL
chunk.fc_length = 4 + 3 * sizeof (struct iff_chunk) + MAXCOL * 3 +
sizeof (struct BitMapHeader) + sizeof (struct CommodoreAmiga) + MandSize;
#else
chunk.fc_length = 4 + 3 * sizeof (struct iff_chunk) + MAXCOL * 3 +
sizeof (struct BitMapHeader) + sizeof (struct CommodoreAmiga);
#endif MANDEL
if (window) {
width = window->GZZWidth;
BytesPerRow = line_bytes(width);
Depth = window->WScreen->BitMap.Depth;
if (compressed) {
#ifdef DEBUG
printf("write_iff: call pack_window for sizing\n");
#endif
if ((bits_size = pack_window(NULL, window, pack_row)) == 0)
goto abort;
} else {
bits_size = BytesPerRow * window->GZZHeight * Depth;
}
chunk.fc_length += bits_size;
if (bits_size & 1)
chunk.fc_length++;
}
if (fwrite(&chunk, sizeof (chunk), 1, file) != 1)
goto abort;
/*
* Here comes a BitMapHeader
*/
{
struct iff_chunk ichunk;
ichunk.iff_type.b4_type = BMHD;
ichunk.iff_length = sizeof (header);
if (fwrite(&ichunk, sizeof (ichunk), 1, file) != 1)
goto abort;
}
/*
* Initialize the BitMapHeader to normal values
*/
header.masking = 0;
header.pad1 = 0;
header.transparentColor = 0;
if (compressed)
header.compression = 1;
else
header.compression = 0;
header.pageWidth = width;
header.pageHeight = window ? window->GZZHeight : YMAX;
header.xAspect = width > LOXMAX ? XASPECT : XASPECT * 2;
header.yAspect = YASPECT;
/*
* If it's not just a color map give the dimensions of rasters
*/
if (window) {
header.w = width;
header.h = window->GZZHeight;
header.nPlanes = Depth;
header.x = xoff;
header.y = yoff;
}
if (fwrite(&header, sizeof (header), 1, file) != 1)
goto abort;
/*
* Squirt out the color map
*/
{
struct iff_chunk ichunk;
ichunk.iff_type.b4_type = CMAP;
ichunk.iff_length = MAXCOL * 3;
if (fwrite(&ichunk, sizeof (ichunk), 1, file) != 1)
goto abort;
if (fwrite(colors, (int) 3 * MAXCOL, 1, file) != 1)
goto abort;
}
/*
* Write a CAMG chunk with ViewPort modes
*/
{
struct CommodoreAmiga camg;
camg.camg_iffc.iff_type.b4_type = CAMG;
camg.camg_iffc.iff_length = sizeof (camg) - sizeof (camg.camg_iffc);
camg.camg_data = window->WScreen->ViewPort.Modes;
if (fwrite(&camg, sizeof (camg), 1, file) != 1)
goto abort;
}
#ifdef MANDEL
/*
* We want to write our own private MAND chunk
*/
if (MandSize) {
if (fwrite(MandPointer, MandSize, 1, file) != 1)
goto abort;
}
#endif MANDEL
/*
* If they be bits then squirt out the bits
*/
if (window) {
struct iff_chunk ichunk;
ichunk.iff_type.b4_type = BODY;
ichunk.iff_length = bits_size;
if (fwrite(&ichunk, sizeof (ichunk), 1, file) != 1)
goto abort;
#ifdef DEBUG
printf("write_iff: call pack_window for real\n");
#endif
if (compressed) {
if (pack_window(file, window, pack_row) == 0)
goto abort;
} else {
if (pack_window(file, window, write_row) == 0)
goto abort;
}
}
fclose(file);
return 1;
abort:
#ifdef DEBUG
printf("write_iff: aborting !!!\n");
#endif
fclose(file);
return 0;
}
/*
* put_ea_cmap given an ea-type color map:
*
* an array of unsigned chars of form ea_cmap[] = {r, g, b, r, g, b...}
*
* turn it into an amiga-type color map:
*
* an array of unsigned short of form amiga_cmap = {0xrgb, 0xrgb, ...}
*
* and then tell Dale this is the colors we want for our viewport
*/
void
put_ea_cmap(ea_cmap, colors, Screen)
unsigned char *ea_cmap;
int colors;
struct Screen *Screen;
{
unsigned short amy_cmap[MAXCOL];
register int i;
register short color;
if (colors > MAXCOL) /* Color clipping */
colors = MAXCOL;
for (i = 0; i < colors; i++) {
color = (*ea_cmap++ & 0xF0) << 4;
color |= *ea_cmap++ & 0xF0;
color |= (*ea_cmap++ & 0xF0) >> 4;
amy_cmap[i] = color;
}
LoadRGB4(&Screen->ViewPort, amy_cmap, (long) colors);
}
void
get_ea_cmap(ea_cmap, colors, Screen)
unsigned char *ea_cmap;
int colors;
struct Screen *Screen;
{
register long i;
register unsigned short rgb;
if (colors > MAXCOL) /* Color clipping */
colors = MAXCOL;
for (i = 0; i < colors; i++) {
rgb = GetRGB4(Screen->ViewPort.ColorMap, i);
*ea_cmap++ = (rgb & 0xF00) >> 4;
*ea_cmap++ = (rgb & 0x0F0);
*ea_cmap++ = (rgb & 0x00F) << 4;
}
}