rsalz@uunet.uu.net (Rich Salz) (06/09/89)
Submitted-by: Michael.Mauldin@NL.CS.CMU.EDU Posting-number: Volume 19, Issue 53 Archive-name: fbm/part07 #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of archive 7 (of 8)." # Contents: fbham.c flgifr.c fliff.c # Wrapped by rsalz@fig.bbn.com on Fri Jun 9 08:38:29 1989 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'fbham.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'fbham.c'\" else echo shar: Extracting \"'fbham.c'\" \(14765 characters\) sed "s/^X//" >'fbham.c' <<'END_OF_FILE' X/***************************************************************** X * fbham.c: FBM Library 0.94 (Beta test) 20-May-89 Michael Mauldin X * X * fbham.c: Write a 24bit RGB file as an Amiga HAM IFF file X * X * USAGE X * % fbham < image1 > image2 X * X * EDITLOG X * LastEditDate = Sat May 20 19:15:08 1989 - Michael Mauldin X * LastFileName = /usr2/mlm/src/misc/fbm/fbham.c X * X * HISTORY X * 20-May-89 Michael Mauldin (mlm) at Carnegie Mellon University X * Beta release (version 0.94) mlm@cs.cmu.edu X * X * 20-Apr-89 C. Harald Koch (chk) at DCIEM Toronto. X * Created. chk@ben.dciem.dnd.ca X * X *================================================================ X * based on ray2.c from DBW_Render, Copyright 1987 David B. Wecker X * X * From: chk@dretor.dciem.dnd.ca (C. Harald Koch) X * Subject: fbham.c - convert a 24bit FBM file to an IFF file using HAM mode X * To: Michael.Mauldin@nl.cs.cmu.edu (Michael Maudlin) X * Date: Mon, 1 May 89 17:21:16 EDT X * X-Mailer: ELM [version 2.2 PL0] X * X * This is the source to my program to convert from a 24bit FBM file to Amiga X * HAM mode. It is based on Dave Wecker's RAY2 program, which converts the X * output of his raytracer to HAM mode. His code uses the Amiga graphics X * library to plot the pixels in a framebuffer for encoding; this version will X * run standalone. X * X * There may be bugs, although it works well for me here. It is probably not in X * the format you want for FBM source; Please go ahead and modify it. There is X * probably room for some command line options for various things (such as the X * verbose output, run length encoding, etc) which I haven't needed and so X * haven't added. X * X * I will send you the IRIS programs when I get them. Enjoy! X * -chk X *****************************************************************/ X X#include <stdio.h> X#include <math.h> X#include "fbm.h" X X# define USAGE "Usage: fbham < image > image" X X#ifndef lint Xstatic char *fbmid = X"$FBM fbham.c <0.93> 03-May-89 (C) 1989 by C. Harald Koch$"; X#endif X X#define DEPTH 6 /* max depth of Amiga HAM image */ X X#define BMHDsize 20L /* chunk sizes */ X#define CMAPsize 96L X#define CAMGsize 4L X#define BODYsize ((long)(16000L)) X#define FORMsize (BODYsize+CAMGsize+CMAPsize+BMHDsize+36L) X Xunsigned char *planes[DEPTH]; /* bitplane pointers */ X Xstatic int comp = 1; /* compress image? */ Xstatic int depth = DEPTH; /* depth of image being created */ Xstatic int colors = 16; /* number of colors in color lookup table */ Xstatic int colorstats[4096][2]; /* color usage statistics */ Xstatic int row_size; /* number of bytes in IFF row of data */ X X/* temp variables for writing IFF file */ Xchar str[40]; Xlong lng, pos1, pos2; Xshort wrd; Xunsigned char byt; Xunsigned char *dest, destbuf[BUFSIZ]; X X Xmain(argc, argv) Xchar *argv[]; X{ X FBM input; X X /* Clear the memory pointers so alloc_fbm won't be confused */ X input.cm = input.bm = (unsigned char *) NULL; X X /* Read the image and rotate it */ X if (!read_bitmap(&input, argc > 0 ? argv[1] : (char *) NULL)) X { X exit(1); X } X X /* slight sanity checks. could be better. */ X if (input.hdr.physbits != 8 || input.hdr.planes != 3) { X fprintf(stderr, "input file must be 24 bit RGB data\n"); X exit(1); X } X X /* convert to HAM */ X if (!fbm2ham(&input, stdout)) { X exit(1); X } X X exit(0); X} X X X/************************ run length encoding from Amiga RKM *****************/ X#define DUMP 0 /* list of different bytes */ X#define RUN 1 /* single run of bytes */ X#define MinRun 3 /* shortest allowed run */ X#define MaxRun 128 /* longest run (length is signed char) */ X#define MaxDat 128 /* longest block of unencoded data */ X#define GetByte() (*source++) X#define PutByte(c) { *dest++ = (c); ++PutSize; } X#define OutDump(nn) dest = PutDump(dest,nn); X#define OutRun(nn,cc) dest = PutRun(dest,nn,cc); X Xint PutSize; Xchar buf[256]; X Xunsigned char * XPutDump(dest, nn) Xunsigned char *dest; Xint nn; X{ X int i; X X PutByte(nn - 1); X for (i = 0; i < nn; i++) X PutByte(buf[i]); X return (dest); X} X Xunsigned char * XPutRun(dest, nn, cc) Xunsigned char *dest; Xint nn, cc; X{ X PutByte(-(nn - 1)); X PutByte(cc); X return (dest); X} X X/* PackRow - pack a row of data using Amiga IFF RLE */ Xint XPackRow(pSource, pDest, RowSize) Xunsigned char **pSource, **pDest; Xint RowSize; X{ X unsigned char *source, *dest; X char c, lastc = '\000'; X int mode = DUMP, nbuf = 0, /* number of chars in buf */ X rstart = 0; /* buf index current run starts */ X X source = *pSource; X dest = *pDest; X X PutSize = 0; X buf[0] = lastc = c = GetByte(); X nbuf = 1; X RowSize--; X X for (; RowSize; --RowSize) { X buf[nbuf++] = c = GetByte(); X X switch (mode) { X case DUMP: X if (nbuf > MaxDat) { X OutDump(nbuf - 1); X buf[0] = c; X nbuf = 1; X rstart = 0; X break; X } X if (c == lastc) { X if (nbuf - rstart >= MinRun) { X if (rstart > 0) X OutDump(rstart); X mode = RUN; X } X else if (rstart == 0) X mode = RUN; X } X else X rstart = nbuf - 1; X break; X X case RUN: X if ((c != lastc) || (nbuf - rstart > MaxRun)) { X OutRun((nbuf - 1) - rstart, lastc); X buf[0] = c; X nbuf = 1; X rstart = 0; X mode = DUMP; X } X break; X } X lastc = c; X } X switch (mode) { X case DUMP: X OutDump(nbuf); X break; X case RUN: X OutRun(nbuf - rstart, lastc); X break; X } X X *pSource = source; X *pDest = dest; X X return (PutSize); X} X/******************* end of RKM RL encoding routines **********************/ X X X/* build_histogram - count frequency of 12bit colors in an FBM image */ Xbuild_histogram(image) XFBM *image; X{ X int i, j, t0, t1, gap, val, used; X unsigned char *rp, *gp, *bp; X int diff; X X /* initialize color statistics. */ X for (i = 0; i < 4096; i++) { X colorstats[i][0] = i; X colorstats[i][1] = 0; X } X X /* obtain pointers to the beginning of each plane (Red, Green, Blue) */ X rp = image->bm; X gp = rp + image->hdr.plnlen; X bp = gp + image->hdr.plnlen; X X /* count the number of occurences of each color in the image */ X for (i = 0 ; i < image->hdr.plnlen ; i++) { X val = ((*rp++ & 0xf0) << 4) + (*gp++ & 0xf0) + ((*bp++ & 0xf0) >> 4); X val %= 4096; X if (colorstats[val][1] < 32767) { X colorstats[val][1]++; X } X } X X /* sort the color stats in order of decreasing usage */ X for (gap = 2048; gap > 0; gap /= 2) { X for (i = gap; i < 4096; i++) { X for (j = i - gap; j >= 0 && X colorstats[j][1] < colorstats[j + gap][1]; j -= gap) { X t0 = colorstats[j][0]; X t1 = colorstats[j][1]; X colorstats[j][0] = colorstats[j + gap][0]; X colorstats[j][1] = colorstats[j + gap][1]; X colorstats[j + gap][0] = t0; X colorstats[j + gap][1] = t1; X } X } X } X X /* count the number of colors actually used in the image */ X for (used = 0; used < 4096 && colorstats[used][1] > 0; used++); X fprintf(stderr, "Used %d colors out of a possible 4096\n", used); X} X X/*- X * plot_pixel - plot a color in an Amiga style bitmap (one plane per bit) X * X * Description: X * A somewhat optimized routine to set/reset one bit in each plane X * at the specified (x,y) coordinates. plane i gets the bit in X * position i of color. a replacement for the Amiga WritePixel call. X-*/ Xplot_pixel(planes, x, y, color) Xunsigned char *planes[]; Xint x, y; Xregister int color; X{ X register int bit; X register unsigned char shifted_bit = 1 << (7-(x%8)); X register int array_offset = y * row_size + x/8; X register int i; X X for (i = 0; color && i < depth; i++) { X bit = color & 1; X color >>= 1; X X if (bit) *(planes[i] + array_offset) |= shifted_bit; X } X} X X X/*- X * fbm2ham - write an FBM image in HAM IFF format on the given file pointer. X * X-*/ Xfbm2ham(image, ofil) XFBM *image; XFILE *ofil; X{ X int i, j, k, gap, t0, t1, prgb, crgb, cpix, ppix, maxdis, used; X int c1, c2, diff; X unsigned char *rp, *gp, *bp; X X fprintf(stderr, "Building a color histogram:\n"); X build_histogram(image); X X /* convert the image to an Amiga HAM bitplane based image */ X cpix = 0; X crgb = colorstats[0][1]; X X rp = image->bm; X gp = rp + image->hdr.plnlen; X bp = gp + image->hdr.plnlen; X X row_size = ((image->hdr.cols + 15) / 16) * 2; X diff = image->hdr.rowlen - image->hdr.cols; X X for (i = 0; i < depth ; i++) { X planes[i] = (unsigned char *)malloc(row_size * image->hdr.rows); X } X X for (i = 0; i < image->hdr.rows; i ++) { X /* verbose output because this program is slow even on a Sun */ X if (i%50 == 0) { fprintf(stderr, "...%d", i); fflush(stderr); } X X /* step through current row, converting FBM pixel to nearest equivalent X * HAM pixel */ X for (j = 0; j < image->hdr.cols; j++) { X prgb = crgb; X crgb = ((*rp++ & 0xf0) << 4) + (*gp++ & 0xf0) + ((*bp++ & 0xf0) >> 4); X crgb %= 4096; X ppix = cpix; X X /* start of scan line is ALWAYS an absolute color */ X if (j == 0) X cpix = getcolor(ppix, &crgb, -1); X else X cpix = getcolor(ppix, &crgb, prgb); X X /* plot the computed pixel */ X plot_pixel(planes, j, i, cpix); X } X rp += diff; X gp += diff; X bp += diff; X } X fprintf(stderr, "\n"); X X /* Now we write the planes[] array we just created in ILBM format */ X sprintf(str, "FORM"); X fwrite(str, 1, 4, ofil); X pos1 = ftell(ofil); X lng = FORMsize; X fwrite(&lng, 4, 1, ofil); X sprintf(str, "ILBM"); X fwrite(str, 1, 4, ofil); X X sprintf(str, "BMHD"); X fwrite(str, 1, 4, ofil); X lng = BMHDsize; X fwrite(&lng, 4, 1, ofil); X wrd = image->hdr.cols; X fwrite(&wrd, 2, 1, ofil); /* width */ X wrd = image->hdr.rows; X fwrite(&wrd, 2, 1, ofil); /* height */ X wrd = 0; X fwrite(&wrd, 2, 1, ofil); /* top */ X wrd = 0; X fwrite(&wrd, 2, 1, ofil); /* left */ X byt = depth; X fwrite(&byt, 1, 1, ofil); /* Depth */ X byt = 0; X fwrite(&byt, 1, 1, ofil); /* mask */ X byt = comp; X fwrite(&byt, 1, 1, ofil); /* compress */ X byt = 0; X fwrite(&byt, 1, 1, ofil); /* pad */ X wrd = 0; X fwrite(&wrd, 2, 1, ofil); /* transparency */ X byt = 10; X fwrite(&byt, 1, 1, ofil); /* aspect x */ X byt = 11; X fwrite(&byt, 1, 1, ofil); /* aspect y */ X wrd = image->hdr.cols; X fwrite(&wrd, 2, 1, ofil); /* page width */ X wrd = image->hdr.rows; X fwrite(&wrd, 2, 1, ofil); /* page height */ X X /* CAMG chunk for displaying files on the Amiga. should include at least X * the HAM flag; I also add lace if the picture is large enough. Perhaps X * this should be an option. -CHK */ X sprintf(str, "CAMG"); X fwrite(str, 1, 4, ofil); X lng = CAMGsize; X fwrite(&lng, 4, 1, ofil); X if (image->hdr.rows > 200) X lng = 0x804L; /* HAM | LACE */ X else X lng = 0x800L; /* HAM */ X fwrite(&lng, 4, 1, ofil); X X /* write out the color lookup table */ X sprintf(str, "CMAP"); X fwrite(str, 1, 4, ofil); X lng = CMAPsize; X fwrite(&lng, 4, 1, ofil); X for (i = 0; i < 32; i++) { X str[0] = (colorstats[i][0] >> 4) & 0xF0; X str[1] = (colorstats[i][0]) & 0xF0; X str[2] = (colorstats[i][0] << 4) & 0xF0; X fwrite(str, 1, 3, ofil); X } X X sprintf(str, "BODY"); X fwrite(str, 1, 4, ofil); X pos2 = ftell(ofil); X lng = BODYsize; X fwrite(&lng, 4, 1, ofil); X X lng = 0L; X X for (i = 0; i < image->hdr.rows; i ++) { X for (j = 0; j < depth; j++) { X if (comp) { X dest = destbuf; X wrd = PackRow(&planes[j], &dest, row_size); X lng += (long) wrd; X fwrite(destbuf, 1, wrd, ofil); X } X else { X fwrite(planes[j], 1, row_size, ofil); X planes[j] += row_size; X } X } X } X if (comp) { X fseek(ofil, (long) pos2, 0); X fwrite(&lng, 4, 1, ofil); X lng -= BODYsize; X lng += FORMsize; X fseek(ofil, (long) pos1, 0); X fwrite(&lng, 4, 1, ofil); X } X X return 1; X} X X/* get the next encoding for a pixel, based on the previous pixel and the X * current 12 bit RGB value */ X X#define BPP 4 /* Bits per pixel */ X#define MAXGRAY (1 << BPP) X#define ABS(x) ((x) < 0 ? -(x) : (x)) X X/*- X * first, check to see if pixel is the same color. if so, return X * check if only one of R, G, B have changed. if so, return new pixel. X * find closest entry in colormap. if exact match, return it. X * modify one of R, G, B (whichever difference is largest) X * compare previous calculation to best match in color table. return X * whichever is a better match. X-*/ Xgetcolor(ppix, crgb, prgb) Xint ppix, *crgb, prgb; X{ X int i, j, val, cr, cg, cb, pr, pg, pb, nr, ng, nb, best, dist, nrgb; X X /* if same color, then do a NOOP (same as previous pixel) */ X if (*crgb == prgb) X return (ppix); X X /* set up for comparisons */ X cb = *crgb & (MAXGRAY - 1); X cg = (*crgb >> BPP) & (MAXGRAY - 1); X cr = (*crgb >> (BPP * 2)) & (MAXGRAY - 1); X X pb = prgb & (MAXGRAY - 1); X pg = (prgb >> BPP) & (MAXGRAY - 1); X pr = (prgb >> (BPP * 2)) & (MAXGRAY - 1); X X /* see if only one plane changed, if so, use HAM encoding */ X if (prgb != -1) { X if (pr == cr && pg == cg) X return (cb + 0x10); X if (pr == cr && pb == cb) X return (cg + 0x30); X if (pg == cg && pb == cb) X return (cr + 0x20); X } X X /* else look for an exact match in the color table (or minimal distance) */ X for (i = 0; i < colors; i++) { X if (colorstats[i][0] == *crgb) X return (i); X if (i == 0) { X best = 0; X dist = distance(colorstats[i][0], *crgb); X } X else if ((j = distance(colorstats[i][0], *crgb)) < dist) { X best = i; X dist = j; X } X } X X /* do a forced absolute */ X if (prgb == -1) { X *crgb = colorstats[best][0]; X return (best); X } X X /* find which color is off the most from previous */ X i = 0; X val = ABS(cr - pr); X if (ABS(cg - pg) > val) { X i = 1; X val = ABS(cg - pg); X } X if (ABS(cb - pb) > val) { X i = 2; X val = ABS(cb - pb); X } X X nr = pr; X ng = pg; X nb = pb; X switch (i) { X case 0: X nr = cr; X val = nr + 0x20; X break; X case 1: X ng = cg; X val = ng + 0x30; X break; X case 2: X nb = cb; X val = nb + 0x10; X break; X } X nrgb = (nr << (2 * BPP)) + (ng << BPP) + nb; X X /* now pick the best */ X if (distance(nrgb, *crgb) < dist) { X X /* do a best relative */ X *crgb = nrgb; X return (val); X } X X /* do a best absolute */ X *crgb = colorstats[best][0]; X return (best); X} X X/* calculate distance between two colors in 3D space */ Xdistance(argb, brgb) X{ X int b, g, r; X X /* set up for comparisons */ X b = argb & (MAXGRAY - 1); X g = (argb >> BPP) & (MAXGRAY - 1); X r = (argb >> (BPP * 2)) & (MAXGRAY - 1); X X b -= brgb & (MAXGRAY - 1); X g -= (brgb >> BPP) & (MAXGRAY - 1); X r -= (brgb >> (BPP * 2)) & (MAXGRAY - 1); X X return (r * r + g * g + b * b); X} END_OF_FILE if test 14765 -ne `wc -c <'fbham.c'`; then echo shar: \"'fbham.c'\" unpacked with wrong size! fi # end of 'fbham.c' fi if test -f 'flgifr.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'flgifr.c'\" else echo shar: Extracting \"'flgifr.c'\" \(13672 characters\) sed "s/^X//" >'flgifr.c' <<'END_OF_FILE' X/***************************************************************** X * flgifr.c: FBM Library 0.91 (Beta test) 26-Apr-89 Michael Mauldin X * X * Copyright (C) 1989 by Michael Mauldin. Permission is granted to X * use this file in whole or in part provided that you do not sell it X * for profit and that this copyright notice is retained unchanged. X * X * Derived from 'giftorle', written by David Koblas X * X * +------------------------------------------------------------------+ X * | Copyright 1989, David Koblas. | X * | You may copy this file in whole or in part as long as you | X * | don't try to make money off it, or pretend that you wrote it. | X * +------------------------------------------------------------------+ X * X * flgifr.c: X * X * CONTENTS X * read_gif (image, stream, mstr, mlen) X * X * HISTORY X * 26-Apr-89 Michael Mauldin (mlm) at Carnegie Mellon University X * Beta release (version 0.91) mlm@cs.cmu.edu X * X * 19-Feb-89 Michael Mauldin (mlm) at Carnegie Mellon University X * Changed name to flgifr from flgif (since there is now an flgifw) X * X * 13-Feb-89 Michael Mauldin (mlm) at Carnegie Mellon University X * Modified from gif2rle program Copyright 1989 by David Koblas. X * Converted to produce FBM image format in memory. X * X * X *****************************************************************/ X X# include <stdio.h> X# include "fbm.h" X X#define MAXCOLORMAPSIZE 256 X X#define TRUE 1 X#define FALSE 0 X#define BAD 0 X#define OK 1 X X#define MAX_LWZ_BITS 12 X X#define ReadOK(file,buffer,len) (fread(buffer,len,1,file)!=0) X#define EasyFail(str,status) while(1){fprintf(stderr,str);return(status);} X#define HardFail(str,status) while(1){fprintf(stderr,str);exit (status);} X X#define LM_to_uint(a,b) (((b)<<8)|(a)) X X#ifndef lint Xstatic char *fbmid = X "$FBM flgifr.c <0.91> 26-Apr-89 (C) 1989 by Michael Mauldin$"; X#endif X Xread_gif (image, fd, mstr, mlen) XFBM *image; XFILE *fd; Xchar *mstr; Xint mlen; X{ X unsigned char buf[16]; X unsigned char c; X int use_global_colormap; X int bit_pixel; X int count = 0; X int rows, cols, rowlen, depth, colors; X X /* Read magic number 'GIF87a' */ X buf[0] = NEXTMCH (fd, mstr, mlen) & 0xff; X buf[1] = NEXTMCH (fd, mstr, mlen) & 0xff; X buf[2] = NEXTMCH (fd, mstr, mlen) & 0xff; X buf[3] = NEXTMCH (fd, mstr, mlen) & 0xff; X buf[4] = NEXTMCH (fd, mstr, mlen) & 0xff; X buf[5] = NEXTMCH (fd, mstr, mlen) & 0xff; X buf[6] = 0; X X if (strcmp (buf, GIF_MAGIC) != 0) X EasyFail("bad magic number (version mismatch?)\n", BAD); X X if (!ReadOK (fd, buf, 7)) X EasyFail("error reading screen descriptor\n", BAD); X X /* Read image data */ X image->hdr.cols = cols = LM_to_uint(buf[0], buf[1]); X image->hdr.rows = rows = LM_to_uint(buf[2], buf[3]); X image->hdr.planes = 1; X image->hdr.bits = depth = (buf[4] & 0x07) + 1; X image->hdr.physbits = 8; X X /* Pad to even byte */ X if (depth == 1) X { image->hdr.rowlen = rowlen = 16 * ((cols + 15) / 16); } X else X { image->hdr.rowlen = rowlen = 2 * ((cols + 1) / 2); } X X image->hdr.plnlen = rowlen * rows; X colors = 1 << depth; X image->hdr.clrlen = 3 * colors; X image->hdr.title[0] = '\0'; X image->hdr.credits[0] = '\0'; X X /* Try to guess aspect ratio */ X if (cols == 320 && rows == 200) { image->hdr.aspect = 1.2; } X else if (cols == 320 && rows == 175) { image->hdr.aspect = 1.2; } X else if (cols == 320 && rows == 400) { image->hdr.aspect = 0.6; } X else if (cols == 320 && rows == 350) { image->hdr.aspect = 0.6; } X else if (cols == 640 && rows == 200) { image->hdr.aspect = 2.4; } X else if (cols == 640 && rows == 175) { image->hdr.aspect = 2.4; } X else if (cols == 640 && rows == 400) { image->hdr.aspect = 1.2; } X else if (cols == 640 && rows == 350) { image->hdr.aspect = 1.2; } X else { image->hdr.aspect = 1.0; } X X# ifdef DEBUG X fprintf (stderr, "\nImage file header:\n\n"); X fprintf (stderr, "cols %d\n", image->hdr.cols); X fprintf (stderr, "rows %d\n", image->hdr.rows); X fprintf (stderr, "planes %d\n", image->hdr.planes); X fprintf (stderr, "bits %d\n", image->hdr.bits); X fprintf (stderr, "physbits %d\n", image->hdr.physbits); X fprintf (stderr, "rowlen %d\n", image->hdr.rowlen); X fprintf (stderr, "plnlen %d\n", image->hdr.plnlen); X fprintf (stderr, "clrlen %d\n", image->hdr.clrlen); X fprintf (stderr, "aspect %1.3lf\n", image->hdr.aspect); X fprintf (stderr, "title '%s'\n", image->hdr.title); X fprintf (stderr, "credits '%s'\n", image->hdr.credits); X# endif X X /* Allocate image */ X alloc_fbm (image); X X /* Read colormap if given */ X if ((buf[4] & 0x80) == 0x80) X { if (ReadColorMap (fd, colors, image->cm) == BAD) X return (BAD); X } X X while (1) X { if (!ReadOK (fd, &c, 1)) X EasyFail("No image data -- EOF\n", BAD); X X if (c == ';') X return OK; X X if (c == '!') X { if (!ReadOK (fd, &c, 1)) X EasyFail("No extention function code -- EOF\n", BAD); X if (IgnoreExtention(fd) == BAD) X return (BAD); X } X X if (c != ',') X { fprintf(stderr, "Bogus character ignoring '%c'\n", c); X continue; X } X X if (count == 1) X HardFail("This file contains more than one image! FAILING\n", 1); X count++; X X if (!ReadOK (fd, buf, 9)) X EasyFail("Couldn't read left/top/width/height\n", TRUE); X X# ifdef DEBUG X fprintf (stderr, "Image description: "); X for (i=0; i<9; i++) fprintf (stderr, "%02x", buf[i]); X fprintf (stderr, "\n"); X# endif X X if ((buf[8] & 0x80) == 0x80) X use_global_colormap = FALSE; X else X use_global_colormap = TRUE; X X bit_pixel = 2 << (buf[8] & 0x07); X X if (!use_global_colormap && bit_pixel > colors) X { HardFail ("Local colormap has more colors than global!\n", BAD); } X X if (!use_global_colormap) X { fprintf (stderr, X "Overriding global colormap (%d) with local (%d)\n", X colors, bit_pixel); X X colors = bit_pixel; X image->hdr.clrlen = 3 * colors; X X if (ReadColorMap(fd, colors, image->cm) == BAD) X return BAD; X } X X fprintf (stderr, "Reading GIF image [%dx%d], %d bits", X image->hdr.cols, image->hdr.rows, image->hdr.bits); X if (image->hdr.clrlen > 0) X { fprintf (stderr, ", %d colors", image->hdr.clrlen / 3); } X else if (image->hdr.bits > 1) X { fprintf (stderr, ", grayscale"); } X X if ((buf[8] & 0x40) == 0x40) X { fprintf (stderr, ", interlaced"); } X fprintf (stderr, "\n"); X X X if ((buf[8] & 0x40) == 0x40) X { X if (ReadInterlaced(fd, X LM_to_uint(buf[4],buf[5]), X LM_to_uint(buf[6],buf[7]), X image->bm, X rowlen) == BAD) X return BAD; X } X else X { if (ReadRaster(fd, X LM_to_uint(buf[4], buf[5]), X LM_to_uint(buf[6], buf[7]), X image->bm, X rowlen) == BAD) X return BAD; X else X return OK; X } X } X} X XReadColorMap (fd, number, buffer) X FILE *fd; X int number; X unsigned char *buffer; X{ X int i; X unsigned char rgb[3], *red, *grn, *blu; X X red = buffer; X grn = buffer + number; X blu = grn + number; X X for (i = 0; i < number; i++) X { if (!ReadOK (fd, rgb, sizeof(rgb))) X EasyFail("Bogus colormap\n", BAD); X X red[i] = rgb[0]; X grn[i] = rgb[1]; X blu[i] = rgb[2]; X } X X return OK; X} X XIgnoreExtention(fd) X FILE *fd; X{ X static char buf[256]; X unsigned char c; X X while (1) X { X if (!ReadOK (fd, &c, 1)) X EasyFail("EOF in extention\n", BAD); X X if (c == 0) X return OK; X X if (read(fd, buf, (int) c) != (int) c) X EasyFail("EOF in extention\n", BAD); X } X} X XGetCode(fd, code_size, flag) X FILE *fd; X int code_size; X int flag; X{ X static unsigned char buf[280]; X static int curbit, lastbit, done, last_byte; X int i, j, ret; X unsigned char count; X X if (flag) X { X curbit = 0; X lastbit = 0; X done = FALSE; X return 0; X } X X if ((curbit + code_size) >= lastbit) X { if (done) X { if (curbit >= lastbit) X EasyFail("Ran off the end of my bits\n", -1); X } X buf[0] = buf[last_byte - 2]; X buf[1] = buf[last_byte - 1]; X X if (!ReadOK (fd, &count, 1)) X { EasyFail("Error in getting buffer size\n", -1); } X X if (count == 0) X { done = TRUE; } X X else if (!ReadOK (fd, &buf[2], count)) X EasyFail("Error in getting buffer\n", -1); X X last_byte = 2 + count; X curbit = (curbit - lastbit) + 16; X lastbit = (2 + count) * 8; X } X X ret = 0; X X for (i = curbit, j = 0; j < code_size; i++, j++) X ret |= ((buf[i / 8] & (1 << (i % 8))) != 0) << j; X X curbit += code_size; X X return ret; X} X XLWZReadByte(fd, flag, input_code_size) X FILE *fd; X int flag; X int input_code_size; X{ X static int fresh = FALSE; X int code, incode; X static int code_size, set_code_size; X static int max_code, max_code_size; X static int firstcode, oldcode; X static int clear_code, end_code; X static int table[2][(1 << MAX_LWZ_BITS)]; X static int stack[(1 << (MAX_LWZ_BITS)) * 2], *sp; X register int i; X X if (flag) X { X set_code_size = input_code_size; X code_size = set_code_size + 1; X clear_code = 1 << set_code_size; X end_code = clear_code + 1; X max_code_size = 2 * clear_code; X max_code = clear_code + 2; X X GetCode(fd, NULL, NULL); X X fresh = TRUE; X X for (i = 0; i < clear_code; i++) X { X table[0][i] = 0; X table[1][i] = i; X } X X for (; i < (1 << MAX_LWZ_BITS); i++) X table[0][i] = table[1][0] = 0; X X sp = stack; X return 0; X } X else if (fresh) X { fresh = FALSE; X do X { firstcode = oldcode = X GetCode(fd, code_size, FALSE); X } while (firstcode == clear_code); X X return firstcode; X } X X if (sp > stack) X return *--sp; X X while ((code = GetCode(fd, code_size, FALSE)) >= 0) X { if (code == clear_code) X { for (i = 0; i < clear_code; i++) X {table[0][i] = 0; X table[1][i] = i; X } X X for (; i < (1 << MAX_LWZ_BITS); i++) X table[0][i] = table[1][i] = 0; X X code_size = set_code_size + 1; X max_code_size = 2 * clear_code; X max_code = clear_code + 2; X sp = stack; X firstcode = oldcode = X GetCode(fd, code_size, FALSE); X return firstcode; X } X else if (code == end_code) X { unsigned char count; X unsigned char junk; X X while (ReadOK (fd, &count, 1) && (count != 0)) X while (count-- != 0 && ReadOK (fd, &junk, 1)); X X if (count != 0) X EasyFail("missing EOD in data stream (common occurance)\n", -3); X X return -2; X } X X incode = code; X X if (code >= max_code) X { *sp++ = firstcode; X code = oldcode; X } X X while (code >= clear_code) X { X *sp++ = table[1][code]; X if (code == table[0][code]) X EasyFail("Circular table entry BIG ERROR\n", -1); X code = table[0][code]; X } X X *sp++ = firstcode = table[1][code]; X X if ((code = max_code) < (1 << MAX_LWZ_BITS)) X { X table[0][code] = oldcode; X table[1][code] = firstcode; X max_code++; X X if ((max_code >= max_code_size) && X (max_code_size < (1 << MAX_LWZ_BITS))) X { X max_code_size *= 2; X code_size++; X } X } X oldcode = incode; X X if (sp > stack) X return *--sp; X } X X return code; X} X XReadInterlaced(fd, len, height, buffer, rowlen) X FILE *fd; X int len, height; X unsigned char *buffer; X int rowlen; X{ X unsigned char c; X register unsigned char *bmp; X register int v; X register int xpos = 0; X register int ypos = 0, pass = 0; X register int maxypos = 0; X X X if (!ReadOK(fd, &c, 1)) X EasyFail("Bogus image data -- EOF\n", BAD); X if (LWZReadByte(fd, TRUE, c) < 0) X return BAD; X X while ((v = LWZReadByte(fd, FALSE, c)) >= 0) X { X if (xpos == 0) X { bmp = &(buffer[ypos * rowlen]); X if (ypos > height) X { fprintf (stderr, "Wanring Too much data, started to read line %d\n", X ypos); X return (OK); X } X } X X *bmp++ = v; X X if (++xpos == len) X { X xpos = 0; X switch (pass) X { X case 0: case 1: ypos += 8; break; X case 2: ypos += 4; break; X case 3: ypos += 2; break; X } X X if (ypos > maxypos) maxypos = ypos; X X if (ypos >= height) X { X switch (++pass) X { X case 1: ypos = 4; break; X case 2: ypos = 2; break; X case 3: ypos = 1; break; X } X } X } X } X X if (maxypos >= height) return OK; X X if (v == (-2)) X return OK; X return BAD; X} X XReadRaster (fd, len, height, buffer, rowlen) X FILE *fd; X int len, height; X unsigned char *buffer; X int rowlen; X{ X unsigned char c; X register unsigned char *bmp; X register int v; X register int xpos = 0; X register int ypos = 0; X X if (!ReadOK (fd, &c, 1)) X EasyFail("Bogus image data -- EOF\n", TRUE); X X if (LWZReadByte(fd, TRUE, c) < 0) X return BAD; X X /* Read the raster data and dump it into the FBM bitmap */ X while ((v = LWZReadByte(fd, FALSE, c)) >= 0) X { X if (xpos == 0) X { bmp = &(buffer[ypos++ * rowlen]); X if (ypos > height) X { fprintf (stderr, "Warning: too much data, started to read line %d\n", X ypos); X return (OK); X } X } X X *bmp++ = v; X X if (++xpos == len) X X if (xpos == len) xpos = 0; X } X X fprintf (stderr, "Done storing bitmap, xpos %d, ypos %d [%dx%d]\n", X xpos, ypos, len, height); X X if (ypos >= height) return OK; X X if (v == (-2)) X return OK; X return BAD; X} END_OF_FILE if test 13672 -ne `wc -c <'flgifr.c'`; then echo shar: \"'flgifr.c'\" unpacked with wrong size! fi # end of 'flgifr.c' fi if test -f 'fliff.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'fliff.c'\" else echo shar: Extracting \"'fliff.c'\" \(23454 characters\) sed "s/^X//" >'fliff.c' <<'END_OF_FILE' X/***************************************************************** X * fliff.c: FBM Library 0.9 (Beta test) 07-Mar-89 Michael Mauldin X * X * Copyright (C) 1989 by Michael Mauldin. Permission is granted to X * use this file in whole or in part provided that you do not sell it X * for profit and that this copyright notice is retained unchanged. X * X * fliff.c: X * X * CONTENTS X * write_iff (image, stream) X * read_iff (image, stream, mstr, mlen) X * X * EDITLOG X * LastEditDate = Mon Mar 20 18:54:08 1989 - Michael Mauldin X * LastFileName = /usr2/mlm/src/misc/fbm/fliff.c X * X * HISTORY X * 07-Mar-89 Michael Mauldin (mlm) at Carnegie Mellon University X * Beta release (version 0.9) mlm@cs.cmu.edu X * X * 04-Mar-89 Michael Mauldin (mlm) at Carnegie Mellon University X * Read and Write support for Amiga IFF (except HAM mode) X *****************************************************************/ X X# include <stdio.h> X# include <math.h> X# include <ctype.h> X# include "fbm.h" X X#ifndef lint Xstatic char *fbmid = X "$FBM fliff.c <0.9> 07-Mar-89 (C) 1989 by Michael Mauldin$"; X#endif X X/**************************************************************** X * from iff.h X ****************************************************************/ X X# define BOOL int /* 1 bit value */ X# define SBYTE char /* 8 bits signend */ X# define UBYTE unsigned char /* 8 bits unsigned */ X# define WORD short /* 16 bits signed */ X# define UWORD unsigned short /* 16 bits unsigned */ X# define LONG long /* 32 bits signed */ X# define ID long X# define MakeID(a,b,c,d) ( (LONG)(a)<<24L | (LONG)(b)<<16L | (c)<<8 | (d) ) X# define FORM MakeID('F','O','R','M') X# define PROP MakeID('P','R','O','P') X# define LIST MakeID('L','I','S','T') X# define CAT MakeID('C','A','T',' ') X# define FILLER MakeID(' ',' ',' ',' ') X# define NULL_CHUNK 0L /* No current chunk.*/ X# define TRUE 1 X# define FALSE 0 X X X/* ---------- Chunk ----------------------------------------------------*/ X X/* All chunks start with a type ID and a count of the data bytes that X follow--the chunk's "logical size" or "data size". If that number is odd, X a 0 pad byte is written, too. */ X Xtypedef struct { X ID ckID; X LONG ckSize; X } ChunkHeader; X Xtypedef struct { X ID ckID; X LONG ckSize; X UBYTE ckData[ 1 /*REALLY: ckSize*/ ]; X } Chunk; X X/*----------------------------------------------------------------------* X * ILBM.H Definitions for InterLeaved BitMap raster image. 1/23/86 X * X * By Jerry Morrison and Steve Shaw, Electronic Arts. X * This software is in the public domain. X * X * This version for the Commodore-Amiga computer. X *----------------------------------------------------------------------*/ X X# define ID_ILBM MakeID('I','L','B','M') X# define ID_BMHD MakeID('B','M','H','D') X# define ID_CMAP MakeID('C','M','A','P') X# define ID_GRAB MakeID('G','R','A','B') X# define ID_DEST MakeID('D','E','S','T') X# define ID_SPRT MakeID('S','P','R','T') X# define ID_CAMG MakeID('C','A','M','G') X# define ID_BODY MakeID('B','O','D','Y') X X/* ---------- BitMapHeader ---------------------------------------------*/ X Xtypedef UBYTE Masking; /* Choice of masking technique.*/ X# define mskNone 0 X# define mskHasMask 1 X# define mskHasTransparentColor 2 X# define mskLasso 3 X Xtypedef UBYTE Compression; /* Choice of compression algorithm applied to X * each row of the source and mask planes. "cmpByteRun1" is the byte run X * encoding generated by Mac's PackBits. See Packer.h . */ X# define cmpNone 0 X# define cmpByteRun1 1 X X/* Aspect ratios: The proper fraction xAspect/yAspect represents the pixel X * aspect ratio pixel_width/pixel_height. X * X * For the 4 Amiga display modes: X * 320 x 200: 10/11 (these pixels are taller than they are wide) X * 320 x 400: 20/11 X * 640 x 200: 5/11 X * 640 x 400: 10/11 */ X# define x320x200Aspect 10 X# define y320x200Aspect 11 X# define x320x400Aspect 20 X# define y320x400Aspect 11 X# define x640x200Aspect 5 X# define y640x200Aspect 11 X# define x640x400Aspect 10 X# define y640x400Aspect 11 X X/* A BitMapHeader is stored in a BMHD chunk. */ Xtypedef struct { X UWORD w, h; /* raster width & height in pixels */ X WORD x, y; /* position for this image */ X UBYTE nPlanes; /* # source bitplanes */ X Masking masking; /* masking technique */ X Compression compression; /* compression algorithm */ X UBYTE pad1; /* UNUSED. For consistency, put 0 here.*/ X UWORD transparentColor; /* transparent "color number" */ X UBYTE xAspect, yAspect; /* aspect ratio, a rational number x/y */ X WORD pageWidth, pageHeight; /* source "page" size in pixels */ X } BitMapHeader; X X/* RowBytes computes the number of bytes in a row, from the width in pixels.*/ X# define RowBytes(w) (2 * (((w) + 15) / 16)) X X X/* ---------- ColorRegister --------------------------------------------*/ X/* A CMAP chunk is a packed array of ColorRegisters (3 bytes each). */ Xtypedef struct { X UBYTE red, green, blue; /* MUST be UBYTEs so ">> 4" won't sign extend.*/ X } ColorRegister; X X/* Use this constant instead of sizeof(ColorRegister). */ X# define sizeofColorRegister 3 X Xtypedef WORD Color4; /* Amiga RAM version of a color-register, X * with 4 bits each RGB in low 12 bits.*/ X X# define swapword(X) ((((X) & 0xff) << 8) | (((X) & 0xff00) >> 8)) X# define swaplong(X) (((unsigned) ((X) & 0xff000000) >> 24) | \ X ((unsigned) ((X) & 0x00ff0000) >> 8) | \ X ((unsigned) ((X) & 0x0000ff00) << 8) | \ X ((unsigned) ((X) & 0x000000ff) << 24)) X X# define swapsize(X) ((machine_byte_order () == LITTLE) ? swaplong(X) : (X)) X X/* Maximum number of bitplanes in RAM. Current Amiga max w/dual playfield. */ X# define MaxAmDepth 6 X X/* Chunks must be padded to align to even boundaries */ X# define EVENALIGN(X) (((X) + 1) & ~1) X X/* ---------- Point2D --------------------------------------------------*/ X/* A Point2D is stored in a GRAB chunk. */ Xtypedef struct { X WORD x, y; /* coordinates (pixels) */ X } Point2D; X X/* ---------- DestMerge ------------------------------------------------*/ X/* A DestMerge is stored in a DEST chunk. */ Xtypedef struct { X UBYTE depth; /* # bitplanes in the original source */ X UBYTE pad1; /* UNUSED; for consistency store 0 here */ X UWORD planePick; /* how to scatter source bitplanes into destination */ X UWORD planeOnOff; /* default bitplane data for planePick */ X UWORD planeMask; /* selects which bitplanes to store into */ X } DestMerge; X X/* ---------- SpritePrecedence -----------------------------------------*/ X/* A SpritePrecedence is stored in a SPRT chunk. */ Xtypedef UWORD SpritePrecedence; X X/* ---------- Viewport Mode --------------------------------------------*/ X/* A Commodore Amiga ViewPort->Modes is stored in a CAMG chunk. */ X/* The chunk's content is declared as a LONG. */ X X/* ---------- CRange ---------------------------------------------------*/ X/* A CRange is store in a CRNG chunk. */ Xtypedef struct { X WORD pad1; /* reserved for future use; store 0 here */ X WORD rate; /* color cycling rate, 16384 = 60 steps/second */ X WORD active; /* nonzero means color cycling is turned on */ X UBYTE low, high; /* lower and upper color registers selected */ X } CRange; X X/*----------------------------------------------------------------------* X * PACKER.H typedefs for Data-Compresser. 1/22/86 X * X * This module implements the run compression algorithm "cmpByteRun1"; the X * same encoding generated by Mac's PackBits. X * X * By Jerry Morrison and Steve Shaw, Electronic Arts. X * This software is in the public domain. X * X * This version for the Commodore-Amiga computer. X *----------------------------------------------------------------------*/ X X/* This macro computes the worst case packed size of a "row" of bytes. */ X# define MaxPackedSize(rowSize) ( (rowSize) + ( ((rowSize)+127) >> 7 ) ) X X/*----------------------------------------------------------------------* X * unpacker.c Convert data from "cmpByteRun1" run compression. 11/15/85 X * X * By Jerry Morrison and Steve Shaw, Electronic Arts. X * This software is in the public domain. X * X * control bytes: X * [0..127] : followed by n+1 bytes of data. X * [-1..-127] : followed by byte to be repeated (-n)+1 times. X * -128 : NOOP. X * X * This version for the Commodore-Amiga computer. X *----------------------------------------------------------------------*/ X X/*----------- UnPackRow ------------------------------------------------*/ X X# define UGetByte() (*source++) X# define UPutByte(c) (*dest++ = (c)) X X/* Given POINTERS to POINTER variables, unpacks one row, updating the source X * and destination pointers until it produces dstBytes bytes. */ Xstatic UnPackRow(pSource, pDest, srcBytes0, dstBytes0) X char **pSource, **pDest; int srcBytes0, dstBytes0; { X register char *source = *pSource; X register char *dest = *pDest; X register int n; X register char c; X register int srcBytes = srcBytes0, dstBytes = dstBytes0; X BOOL error = TRUE; /* assume error until we make it through the loop */ X X X# ifdef DEBUG X fprintf (stderr, "Unpack called, src %d, dst %d\n", X srcBytes0, dstBytes0); X# endif X X while( dstBytes > 0 ) { X if ( (srcBytes -= 1) < 0 ) goto ErrorExit; X n = UGetByte() & 0x0ff; X X if (n < 128) { X# ifdef DEBUG X fprintf (stderr, "Got %02x, copying %d bytes...\n", n, n+1); X# endif X X n += 1; X X if ( (srcBytes -= n) < 0 ) goto ErrorExit; X if ( (dstBytes -= n) < 0 ) goto ErrorExit; X do { UPutByte(UGetByte()); } while (--n > 0); X } X X else if (n != 128) { X# ifdef DEBUG X fprintf (stderr, "Got %02x, repeating byte %d times...\n", X n, 257-n); X# endif X X n = 257 - n; X X if ( (srcBytes -= 1) < 0 ) goto ErrorExit; X if ( (dstBytes -= n) < 0 ) goto ErrorExit; X c = UGetByte(); X do { UPutByte(c); } while (--n > 0); X } X } X error = FALSE; /* success! */ X X ErrorExit: X *pSource = source; *pDest = dest; X X if (error) X { fprintf (stderr, "error in unpack, src %d, dst %d\n", X srcBytes, dstBytes); X } X X return(error); X } X X/**************************************************************** X * read_iff: Read an Amiga format IFF Interleaved Bitmap X ****************************************************************/ X Xread_iff (image, rfile, mstr, mlen) XFBM *image; XFILE *rfile; Xchar *mstr; Xint mlen; X{ char magic[8]; X long formsize, buflen; X Chunk *form; X int result; X X /* First word is magic number */ X magic[0] = NEXTMCH(rfile,mstr,mlen) & 0xff; X magic[1] = NEXTMCH(rfile,mstr,mlen) & 0xff; X magic[2] = NEXTMCH(rfile,mstr,mlen) & 0xff; X magic[3] = NEXTMCH(rfile,mstr,mlen) & 0xff; X magic[4] = '\0'; X X /* If magic number is not FORM, lose */ X if (strcmp (magic, "FORM") != 0) X { if (strncmp (magic, "FOR", 3) == 0 || X strncmp (magic, "LIS", 3) == 0 || X strncmp (magic, "CAT", 3) == 0) X { fprintf (stderr, "Sorry, I only handle FORM type IFF files\n"); X return (0); X } X X fprintf (stderr, X "read_iff: error, file not a FORM type IFF file, magic '%s'\n", X magic); X return (0); X } X X /* Second longword is length of data chunk */ X formsize = get_long (rfile, BIG); X X form = (Chunk *) malloc (formsize + 8); X form->ckID = FORM; X form->ckSize = formsize; X X /* Now read the rest of the chunk */ X if ((buflen = fread (form->ckData, 1, formsize, stdin)) < formsize) X { if (buflen < 0) X { perror ("stdin"); } X else X { fprintf (stderr, "error: premature EOF in FORM after %d of %d bytes\n", X buflen, formsize); X } X X exit (1); X } X X /* Recursively parse the FORM */ X result = parse_form (image, form); X X /* Now we've read the image (or not) */ X free (form); X X return (result); X} X X/**************************************************************** X * parse_form: Parse an IFF form chunk X * X * FORM ::= "FORM" #{ FormType (LocalChunk | FORM | LIST | CAT)* } X * FormType ::= ID X * LocalChunk ::= Property | Chunk X ****************************************************************/ X Xparse_form (image, chunk) XFBM *image; XChunk *chunk; X{ register UBYTE *data, *tail; X register int clrlen, colors; X register BitMapHeader *bmh; X register int i, bits; X long formtype; X int found_bmhd=0, found_cmap=0, found_body=0; X Chunk *part; X X data = chunk->ckData; X tail = data + chunk->ckSize; X X formtype = MakeID(data[0], data[1], data[2], data[3]); X data += 4; X X if (formtype != ID_ILBM) X { fprintf (stderr, "this FORM doesn't start with ILBM, but %4.4s, sorry.\n", X &formtype); X return (0); X } X X while (data < tail) X { part = (Chunk *) data; X part->ckID = swapsize (part->ckID); X part->ckSize = swapsize (part->ckSize); X data += ( EVENALIGN (part->ckSize) + 8 ); X X# ifdef DEBUG X fprintf (stderr, "Found %c%c%c%c, size %ld\n", X (part->ckID & 0xff000000) >> 24, X (part->ckID & 0x00ff0000) >> 16, X (part->ckID & 0x0000ff00) >> 8, X (part->ckID & 0x000000ff), X part->ckSize); X# endif X X if (part->ckID == ID_BMHD) X { found_bmhd++; X bmh = (BitMapHeader *) part->ckData; X X /* IFF uses BIG byte order, swap if necessary */ X if (machine_byte_order () == LITTLE) X { bmh->w = swapword (bmh->w); X bmh->h = swapword (bmh->h); X bmh->x = swapword (bmh->x); X bmh->y = swapword (bmh->y); X bmh->transparentColor = swapword (bmh->transparentColor); X bmh->pageWidth = swapword (bmh->pageWidth); X bmh->pageHeight = swapword (bmh->pageHeight); X } X X image->hdr.rows = bmh->h; X image->hdr.cols = bmh->w; X image->hdr.planes = 1; X image->hdr.bits = bmh->nPlanes; X image->hdr.physbits = 8; X image->hdr.rowlen = 16 * ((image->hdr.cols + 15) / 16); X image->hdr.plnlen = image->hdr.rowlen * image->hdr.rows; X image->hdr.clrlen = 0; X image->hdr.aspect = (double) bmh->yAspect / bmh->xAspect; X image->hdr.title[0] = '\0'; X image->hdr.credits[0] = '\0'; X } X else if (part->ckID == ID_CMAP) X { image->hdr.clrlen = part->ckSize; X X alloc_fbm (image); X X clrlen = image->hdr.clrlen; X colors = clrlen / 3; X X for (i=0; i<image->hdr.clrlen; i++) X { image->cm[(colors * (i%3)) + i/3] = part->ckData[i]; } X X /* Compute number of bits in colormap */ X for (i=colors, bits=1; i > 2; i /= 2, bits++) ; X X if (bits < image->hdr.bits) image->hdr.bits = bits; X X found_cmap++; X } X else if (part->ckID == ID_BODY) X { if (!found_bmhd) X { fprintf (stderr, "Error, BODY found with no BMHD header\n"); X return (0); X } X X if (found_cmap == 0) X { alloc_fbm (image); } X X found_body++; X X /* Decode body */ X fprintf (stderr, "Reading IFF [%dx%dx%d], %d physbits, %1.3lf aspect", X image->hdr.cols, image->hdr.rows, X image->hdr.bits, image->hdr.physbits, X image->hdr.aspect); X if (image->hdr.planes > 1) X { fprintf (stderr, ", %d planes", image->hdr.planes); } X if (image->hdr.clrlen > 1) X { fprintf (stderr, ", %d colors", image->hdr.clrlen / 3); } X if (bmh->compression) X { fprintf (stderr, ", compressed"); } X if (bmh->masking == mskHasMask) X { fprintf (stderr, ", with mask"); } X fprintf (stderr, "\n"); X X# ifdef DEBUG X fprintf (stderr, X "masking %d, compression %d, transparent %d, page [%dx%d]\n", X bmh->masking, bmh->compression, bmh->transparentColor, X bmh->pageWidth, bmh->pageHeight); X X for (i=0; i<colors; i++) X { fprintf (stderr, " color %3d: <%3d, %3d, %3d>\n", i, X image->cm[i], image->cm[i+colors], image->cm[i+colors*2]); X } X# endif X X return (read_iff_body (image, bmh, part)); X } X } X X return (0); X} X X/**************************************************************** X * read_iff_body: Read the bits in the ILBM body into the FBM image X ****************************************************************/ X Xread_iff_body (image, bmh, body) XFBM *image; XBitMapHeader *bmh; XChunk *body; X{ register int r, c, k, pmask, byte, bit; X unsigned char *row, *bp, *buf, *obm, *tail; X int bytlen = image->hdr.cols / 8; X int planes = bmh->nPlanes + ((bmh->masking == mskHasMask) ? 1 : 0); X X buf = (unsigned char *) malloc (bytlen); X X bp = body->ckData; X tail = bp + body->ckSize; X X# ifdef DEBUG X fprintf (stderr, "Body length %d, planes %d: ", tail-bp, planes); X for (c=0; c<20; c++) fprintf (stderr, "%02x", bp[c]); X fprintf (stderr, "\n"); X# endif X X /* Each iteration reads one scan line */ X for (r=0; r<image->hdr.rows; r++) X { X if (bp > tail) X { fprintf (stderr, "Ran out of data in body after %d of %d rows\n", X r, image->hdr.rows); X return (0); X } X X obm = &(image->bm[r * image->hdr.rowlen]); X X /* Clear the output row of pixels */ X for (c=0; c<image->hdr.cols; c++) X { obm[c] = 0; } X X /* Each loop reads one plane of this scan line */ X for (k=0; k<planes; k++) X { X /* First get pointer to data packed 8 bits per byte */ X if (bmh->compression == 0) X { row = bp; bp += RowBytes (bmh->w); } X else X { row = buf; X if (UnPackRow (&bp, &row, (int) (tail-bp), RowBytes (bmh->w)) != 0) X { fprintf (stderr, X "%s, row %d of %d, plane %d of %d, bytes per row %d\n", X "Error in UnPackRow", X r, image->hdr.rows, k, planes, RowBytes (bmh->w)); X return (0); X } X row = buf; X } X X /* Ignore extra planes (including the mask if any) */ X if (k >= image->hdr.bits) X continue; X X /* Now OR in these bits into the output pixels */ X pmask = 1 << k; X X for (c=0; c<image->hdr.cols; c++) X { byte = c >> 3; X bit = 7 - (c & 7); X bit = row[byte] & (1 << bit); X X obm[c] |= bit ? pmask : 0; X } X } X } X X if (tail-bp > 1) X { fprintf (stderr, "Warning, %d bytes of data unread\n", tail - bp); } X X return (1); X} X X/**************************************************************** X * write_iff: Write AMIGA IFF format ILBM file X * X * Writes FORM type ILBM X * BMHD X * CMAP (optional) X * BODY (uncompressed) X * X ****************************************************************/ X Xwrite_iff (image, wfile) XFBM *image; XFILE *wfile; X{ BitMapHeader bmhd; X unsigned char *cmap, *body; X int bodylen, cmaplen, bmhdlen, formlen, ilbmbits; X X if (image->hdr.planes > 1) X { fprintf (stderr, "Error, write_iff cannot handle multi-plane images\n"); X return (0); X } X X /* Determine number of bits in output */ X if (image->hdr.clrlen == 0) X { ilbmbits = image->hdr.bits; } X else X { int colors = image->hdr.clrlen/3; X for (ilbmbits=1; colors > 2; ilbmbits++, colors >>= 1) ; X } X X fprintf (stderr, "Writing \"%s\" [%dx%d] as a %d bit IFF ILBM file\n", X image->hdr.title[0] ? image->hdr.title : "", X image->hdr.cols, image->hdr.rows, ilbmbits); X X if (ilbmbits > 5) X { fprintf (stderr, "%s\n%s\n%s\n", X "Warning: most IFF ILBM displays cannot handle more than", X " 32 colors. You should probably run the image though", X " 'gray2clr -u | fbquant -c32' first."); X } X X /* Build BMHD, CMAP, and body chunks */ X bmhdlen = build_bmhd (image, &bmhd, ilbmbits) ; X cmaplen = build_cmap (image, &cmap, ilbmbits); X bodylen = build_body (image, &body, ilbmbits); X X /* Length of FORM is length of subparts plus 8 for header + 4 for type */ X formlen = bmhdlen + cmaplen + bodylen + 12; X X /*--------Write out FORM chunk header--------*/ X fprintf (wfile, "FORM"); X put_long (formlen-8, wfile, BIG); X fprintf (wfile, "ILBM"); X X /*----Write out BMHD chunk----*/ X fprintf (wfile, "BMHD"); X put_long (bmhdlen-8, wfile, BIG); X fwrite (&bmhd, bmhdlen-8, 1, wfile); X X /* No need to pad BMHD chunk, it must be even */ X X /*----Write out CMAP chunk----*/ X if (cmaplen > 0) X { fprintf (wfile, "CMAP"); X put_long (cmaplen-8, wfile, BIG); X fwrite (cmap, cmaplen-8, 1, wfile); X X /* Pad CMAP chunk if necessary */ X if (cmaplen & 1) fputc (0, wfile); X } X X /*----Write out BODY chunk----*/ X fprintf (wfile, "BODY"); X put_long (bodylen-8, wfile, BIG); X fwrite (body, bodylen-8, 1, wfile); X X /* Pad BODY chunk if necessary */ X if (bodylen & 1) fputc (0, wfile); X X /*--------Free memory and return--------*/ X if (cmap) free (cmap); X if (body) free (body); X X return (1); X} X X/**************************************************************** X * build_bmhd: Build a BitMapHeader, and byte swap it if necessary X ****************************************************************/ X Xbuild_bmhd (image, bmh, bits) XFBM *image; XBitMapHeader *bmh; Xint bits; X{ X bmh->w = image->hdr.cols; X bmh->h = image->hdr.rows; X bmh->x = 0; X bmh->y = 0; X bmh->nPlanes = bits; X bmh->masking = 0; X bmh->compression = 0; X bmh->pad1 = 0; X bmh->transparentColor = 0; X bmh->xAspect = 100; X bmh->yAspect = (image->hdr.aspect * 100.0) + 0.5; X bmh->pageWidth = bmh->w; X bmh->pageHeight = bmh->h; X X /* IFF uses BIG byte order, swap if necessary */ X if (machine_byte_order () == LITTLE) X { bmh->w = swapword (bmh->w); X bmh->h = swapword (bmh->h); X bmh->x = swapword (bmh->x); X bmh->y = swapword (bmh->y); X bmh->transparentColor = swapword (bmh->transparentColor); X bmh->pageWidth = swapword (bmh->pageWidth); X bmh->pageHeight = swapword (bmh->pageHeight); X } X X return (sizeof (*bmh) + 8); X} X X/**************************************************************** X * build_cmap: Convert an FBM format colormap to IFF format X ****************************************************************/ X Xbuild_cmap (image, cmap, bits) XFBM *image; Xunsigned char **cmap; Xint bits; X{ register int len, i; X register unsigned char *r, *g, *b, *c; X int colors; X X colors = image->hdr.clrlen / 3; X X r = image->cm; X g = r + colors; X b = g + colors; X X len = 3*colors; X *cmap = (unsigned char *) malloc (len); X X /* Now convert from three vectors to a vector of triples */ X for (i=0, c= *cmap; i<colors; i++) X { *c++ = *r++; X *c++ = *g++; X *c++ = *b++; X } X X /* Return length of chunk, just length of map plus 8 bytes chunk header */ X return (len + 8); X} X X/**************************************************************** X * build_body: Interleave the bits for the byte plane X ****************************************************************/ X Xbuild_body (image, body, bits) Xregister FBM *image; Xunsigned char **body; Xint bits; X{ int bpr, size; X register unsigned char *obm, *bmp; X register int r, c, k, mask, byte, bit; X X bpr = RowBytes (image->hdr.cols); X X size = bpr * image->hdr.rows * bits; X X *body = (unsigned char *) malloc (size); X X obm = *body; X X for (r=0; r < image->hdr.rows; r++) X { for (k=0; k<bits; k++) X { mask = 1 << k; X bmp = &(image->bm[r * image->hdr.rowlen]); X X# ifdef DEBUG X if (r==23) X { fprintf (stderr, "Row %d, plane %d, bytes: ", r, k); X for (c=0; c<32; c++) fprintf (stderr, "%02x", bmp[c]); X fprintf (stderr, "\n"); X } X# endif X X for (c=0, byte=0; c<image->hdr.cols; c++) X { bit = (*bmp++ & mask) ? 1 : 0; X X X# ifdef DEBUG X if (r == 23 && c < 32) X { fprintf (stderr, "%d", bit); } X# endif X X byte = (byte << 1) | bit; X if ((c&7) == 7) X { *obm++ = byte; X X# ifdef DEBUG X if (r == 23 && c <32) fprintf (stderr, " %d ", byte); X# endif X X byte=0; X } X } X X# ifdef DEBUG X if (r == 23) fprintf (stderr, "\n"); X# endif X X if ((c & 7) != 0) X { while ((c&7) != 0) X { c++; byte <<= 1; } X *obm++ = byte; X } X } X } X X return (size + 8); X X} END_OF_FILE if test 23454 -ne `wc -c <'fliff.c'`; then echo shar: \"'fliff.c'\" unpacked with wrong size! fi # end of 'fliff.c' fi echo shar: End of archive 7 \(of 8\). cp /dev/null ark7isdone MISSING="" for I in 1 2 3 4 5 6 7 8 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 8 archives. rm -f ark[1-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0 -- Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.