home *** CD-ROM | disk | FTP | other *** search
- /**************
- * TURBOMANDEL *
- **************/
-
- /* IFF read/write */
-
- #include <stdio.h>
- #include <exec/types.h>
- #include <exec/memory.h>
- #include <graphics/gfx.h>
- #include <intuition/intuition.h>
- #include <libraries/dos.h>
-
- struct iff_chunk { long iff_type, iff_length; };
- struct form_chunk { long fc_type, fc_length, fc_subtype; };
-
- struct BitMapHeader {
- UWORD w, h, x, y;
- UBYTE nPlanes, masking, compression, pad1;
- UWORD transparentColor;
- UBYTE xAspect, yAspect;
- WORD pageWidth, pageHeight;
- };
- struct ILBM_info {
- struct BitMapHeader header;
- struct BitMap bitmap;
- UBYTE cmap[96];
- };
- extern struct MandelChunk {
- ULONG XCoo[2], YCoo[2], XSide[2], YSide[2];
- UWORD Iteration;
- UBYTE Calculation, Flags;
- SHORT TopPos[3], DecrStep[3], ColInt[3];
- } MandChunk;
-
- read_iff (info, name, just_header)
- struct ILBM_info *info;
- char *name;
- int just_header;
- {
- UBYTE bool;
- FILE *file;
- struct form_chunk chunk;
-
- if ((file = fopen (name, "r") ) == 0) return (FALSE);
- if (fread (&chunk, sizeof (struct form_chunk), 1, file) != 1) {
- fclose (file); return (FALSE);
- }
- if (chunk.fc_type != 'FORM' || chunk.fc_subtype != 'ILBM') {
- fclose (file); return (FALSE);
- }
- bool = read_ilbm (file, info, chunk.fc_length - sizeof (chunk), just_header);
- fclose (file);
- return ((int)bool);
- }
-
- read_ilbm (file, info, length, just_header)
- FILE *file;
- struct ILBM_info *info;
- long length;
- int just_header;
- {
- struct iff_chunk chunk;
- long read_in = 0;
- int got_header = FALSE, got_cmap = FALSE;
-
- while (read_in < length) {
- if (fread (&chunk, sizeof (chunk), 1, file) != 1) return (FALSE);
- switch (chunk.iff_type) {
- case 'BMHD':
- if (fread (&info->header, sizeof(info->header), 1, file) != 1)
- return (FALSE);
- got_header = TRUE;
- break;
- case 'MANC': /* read mandel chunk */
- if (fread (&MandChunk, sizeof(MandChunk), 1, file) != 1)
- return (FALSE);
- break;
- case 'CMAP':
- if (!got_header) return (FALSE);
- if (chunk.iff_length <= 96) {
- if (fread (info->cmap, (int)chunk.iff_length, 1, file) != 1)
- return (FALSE);
- }
- else {
- if (fread(info->cmap, 96, 1, file) != 1) return (FALSE);
- fseek (file, (long)chunk.iff_length - sizeof (3 * 32), 1);
- }
- got_cmap = TRUE;
- break;
- case 'BODY':
- if (!got_cmap || !got_header) return (FALSE);
- if (just_header) return (TRUE);
- return (read_body (file, info, chunk.iff_length));
- default:
- fseek (file, (long)chunk.iff_length, 1);
- break;
- }
- read_in += chunk.iff_length + sizeof(chunk);
- }
- return (FALSE);
- }
-
- read_body (file, info, length)
- FILE *file;
- register struct ILBM_info *info;
- long length;
- {
- long i, j, plane_offset;
-
- if (info->header.compression != 0 && info->header.compression != 1)
- return (FALSE);
-
- plane_offset = 0;
- for (i = 0; i < info->bitmap.Rows; i++) {
- 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) return(FALSE);
- }
- else {
- register char *dest, value;
- register int so_far, count;
-
- 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) {
- value = getc (file);
- if (value > 0 && value != 128) {
- count = (int)value + 1;
- so_far -= count;
- if (fread (dest, count, 1, file) != 1) return (FALSE);
- dest += count;
- }
- else {
- count = (int)-value + 1;
- so_far -= count;
- value = getc (file);
- while (--count >= 0) *dest++ = value;
- }
- }
- if (so_far != 0) return (FALSE);
- }
- }
- plane_offset += info->bitmap.BytesPerRow;
- }
- return (TRUE);
- }
-
- #define DUMP 0
- #define RUN 1
-
- ULONG pack_row (source, dest, size)
- char *source, *dest;
- int size;
- {
- char c, lastc = 0, *olddest;
- short mode = DUMP, nbuf = 0, rstart = 0, i;
- char buf[128*3/2];
-
- olddest = dest;
- buf[0] = lastc = *source++;
- nbuf = 1; size--;
- for (; size; --size) {
- buf[nbuf++] = c = *source++;
- if (mode == DUMP) {
- if (nbuf > 128) {
- *dest++ = nbuf - 2;
- for (i = 0; i < nbuf-1; i++) *dest++ = buf[i];
- buf[0] = c; nbuf = 1; rstart = 0;
- }
- else if (c == lastc) {
- if (nbuf - rstart >= 3) {
- if (rstart > 0) {
- *dest++ = rstart - 1;
- for (i = 0; i < rstart; i++) *dest++ = buf[i];
- }
- mode = RUN;
- }
- else if (rstart == 0) mode = RUN;
- }
- else rstart = nbuf - 1;
- }
- else {
- if ((c != lastc) || (nbuf - rstart > 128)) {
- *dest++ = - (nbuf - rstart - 2); *dest++ = lastc;
- buf[0] = c; nbuf = 1; rstart = 0; mode = DUMP;
- }
- }
- lastc = c;
- }
- if (mode == DUMP) {
- *dest++ = nbuf - 1;
- for (i = 0; i < nbuf; i++) *dest++ = buf[i];
- }
- else {
- *dest++ = - nbuf + rstart + 1; *dest++ = lastc;
- }
- return ((ULONG)(dest - olddest));
- }
-
- ULONG pack_bitmap (file, bm)
- FILE *file;
- struct BitMap *bm;
- {
- char packbuffer[256];
- int i, j, row_length;
- ULONG compressed_length = 0, plane_offset = 0;
-
- for (i = 0; i < bm->Rows; i++) {
- for (j = 0; j < bm->Depth; j++) {
- row_length = pack_row
- (bm->Planes[j] + plane_offset, packbuffer, bm->BytesPerRow);
- if (file) if (fwrite(packbuffer, row_length, 1, file) != 1) return (0);
- compressed_length += row_length;
- }
- plane_offset += bm->BytesPerRow;
- }
- if (compressed_length & 1) {
- if (file) if (putc (0, file) == EOF) return(0);
- compressed_length++;
- }
- return (compressed_length);
- }
-
- int write_iff (name, colors, scr, compressed)
- char *name;
- UWORD *colors;
- struct Screen *scr;
- int compressed;
- {
- struct BitMap *bits;
- struct form_chunk chunk;
- struct iff_chunk ichunk;
- struct BitMapHeader header;
- UBYTE rgbcolors[96];
- SHORT i, numcols, j, row_offset;
- ULONG bits_size, viewmodes;
- FILE *file;
-
- if ((file = fopen (name, "w") ) == 0) return(0);
- if (scr) {
- bits = &scr->BitMap;
- if ((numcols = (1 << bits->Depth)) > 32) numcols = 32;
- }
- else numcols = 32;
- chunk.fc_type = 'FORM'; chunk.fc_subtype = 'ILBM';
- chunk.fc_length = 4 + 3 * sizeof (struct iff_chunk) + 12 + 62 +
- numcols * 3 + sizeof(struct BitMapHeader);
- if (scr) {
- if (compressed) {
- if ((bits_size = pack_bitmap (NULL, bits)) == 0) return(0);
- }
- else bits_size = bits->BytesPerRow * bits->Rows * bits->Depth;
- chunk.fc_length += bits_size;
- }
- if (fwrite (&chunk, sizeof(chunk), 1, file) != 1) return(0);
-
- ichunk.iff_type = 'BMHD';
- ichunk.iff_length = sizeof(header);
- if (fwrite (&ichunk, sizeof(ichunk), 1, file) != 1) return(0);
-
- header.masking = header.pad1 = header.transparentColor = 0;
- header.compression = compressed;
- header.pageWidth = bits->BytesPerRow * 8;
- header.pageHeight = bits->Rows;
- header.xAspect = header.yAspect = 10;
-
- /* write bitmapheader */
- if (scr) {
- header.w = bits->BytesPerRow * 8;
- header.h = bits->Rows;
- header.nPlanes = bits->Depth;
- header.x = header.y = 0;
- }
- if (fwrite (&header, sizeof(header), 1, file) != 1) return(0);
-
- /* write camg */
- ichunk.iff_type = 'CAMG'; ichunk.iff_length = 4;
- if (fwrite (&ichunk, sizeof(ichunk), 1, file) != 1) return(0);
- viewmodes = (ULONG)scr->ViewPort.Modes;
- if (fwrite (&viewmodes, 4, 1, file) != 1) return(0);
-
- /* write cmap */
- ichunk.iff_type = 'CMAP'; ichunk.iff_length = numcols * 3;
- if (fwrite (&ichunk, sizeof(ichunk), 1, file) != 1) return(0);
- for (i = 0; i < numcols; i++) {
- rgbcolors[3 * i] = (colors[i] & 0xf00) >> 4;
- rgbcolors[3 * i + 1] = (colors[i] & 0x0f0);
- rgbcolors[3 * i + 2] = (colors[i] & 0x00f) << 4;
- }
- if (fwrite (&rgbcolors[0], numcols * 3, 1, file) != 1) return(0);
-
- /* write mandel chunk */
- ichunk.iff_type = 'MANC'; ichunk.iff_length = sizeof(MandChunk);
- if (fwrite (&ichunk, sizeof(ichunk), 1, file) != 1) return(0);
- if (fwrite (&MandChunk, sizeof(MandChunk), 1, file) != 1) return (0);
-
- if (scr) {
- ichunk.iff_type = 'BODY'; ichunk.iff_length = bits_size;
- if (fwrite(&ichunk, sizeof(ichunk), 1, file) != 1) return(0);
- if (compressed) {
- if (pack_bitmap(file, bits) == 0) return(0);
- }
- else {
- i = bits->Rows;
- row_offset = 0;
- while (--i >= 0) {
- for (j = 0; j < bits->Depth; j++)
- if (fwrite( bits->Planes[j]+row_offset, bits->BytesPerRow,
- 1, file) != 1) return(0);
- row_offset += bits->BytesPerRow;
- }
- }
- }
- fclose (file);
- return (1);
- }
-