home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Photo CD Demo 1
/
Demo.bin
/
fbm
/
src
/
fliff.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-06-24
|
24KB
|
805 lines
/*****************************************************************
* fliff.c: FBM Release 1.0 25-Feb-90 Michael Mauldin
*
* Copyright (C) 1989,1990 by Michael Mauldin. Permission is granted
* to use this file in whole or in part for any purpose, educational,
* recreational or commercial, provided that this copyright notice
* is retained unchanged. This software is available to all free of
* charge by anonymous FTP and in the UUNET archives.
*
* fliff.c:
*
* CONTENTS
* write_iff (image, stream)
* read_iff (image, stream, mstr, mlen)
*
* EDITLOG
* LastEditDate = Mon Jun 25 00:16:58 1990 - Michael Mauldin
* LastFileName = /usr2/mlm/src/misc/fbm/fliff.c
*
* HISTORY
* 25-Jun-90 Michael Mauldin (mlm@cs.cmu.edu) Carnegie Mellon
* Package for Release 1.0
*
* 06-Sep-89 Michael Mauldin (mlm) at Carnegie Mellon University
* Beta release (version 0.96) mlm@cs.cmu.edu
*
* 04-Mar-89 Michael Mauldin (mlm) at Carnegie Mellon University
* Read and Write support for Amiga IFF (except HAM mode)
*****************************************************************/
# include <stdio.h>
# include <math.h>
# include <ctype.h>
# include "fbm.h"
#ifndef lint
static char *fbmid =
"$FBM fliff.c <1.0> 25-Jun-90 (C) 1989,1990 by Michael Mauldin, source \
code available free from MLM@CS.CMU.EDU and from UUNET archives$";
#endif
/****************************************************************
* from iff.h
****************************************************************/
# define BOOL int /* 1 bit value */
# define SBYTE char /* 8 bits signend */
# define UBYTE unsigned char /* 8 bits unsigned */
# define WORD short /* 16 bits signed */
# define UWORD unsigned short /* 16 bits unsigned */
# define LONG long /* 32 bits signed */
# define ID long
# define MakeID(a,b,c,d) ( (LONG)(a)<<24L | (LONG)(b)<<16L | (c)<<8 | (d) )
# define FORM MakeID('F','O','R','M')
# define PROP MakeID('P','R','O','P')
# define LIST MakeID('L','I','S','T')
# define CAT MakeID('C','A','T',' ')
# define FILLER MakeID(' ',' ',' ',' ')
# define NULL_CHUNK 0L /* No current chunk.*/
# define TRUE 1
# define FALSE 0
/* ---------- Chunk ----------------------------------------------------*/
/* All chunks start with a type ID and a count of the data bytes that
follow--the chunk's "logical size" or "data size". If that number is odd,
a 0 pad byte is written, too. */
typedef struct {
ID ckID;
LONG ckSize;
} ChunkHeader;
typedef struct {
ID ckID;
LONG ckSize;
UBYTE ckData[ 1 /*REALLY: ckSize*/ ];
} Chunk;
/*----------------------------------------------------------------------*
* ILBM.H Definitions for InterLeaved BitMap raster image. 1/23/86
*
* By Jerry Morrison and Steve Shaw, Electronic Arts.
* This software is in the public domain.
*
* This version for the Commodore-Amiga computer.
*----------------------------------------------------------------------*/
# define ID_ILBM MakeID('I','L','B','M')
# define ID_BMHD MakeID('B','M','H','D')
# define ID_CMAP MakeID('C','M','A','P')
# define ID_GRAB MakeID('G','R','A','B')
# define ID_DEST MakeID('D','E','S','T')
# define ID_SPRT MakeID('S','P','R','T')
# define ID_CAMG MakeID('C','A','M','G')
# define ID_BODY MakeID('B','O','D','Y')
/* ---------- BitMapHeader ---------------------------------------------*/
typedef UBYTE Masking; /* Choice of masking technique.*/
# define mskNone 0
# define mskHasMask 1
# define mskHasTransparentColor 2
# define mskLasso 3
typedef UBYTE Compression; /* Choice of compression algorithm applied to
* each row of the source and mask planes. "cmpByteRun1" is the byte run
* encoding generated by Mac's PackBits. See Packer.h . */
# define cmpNone 0
# define cmpByteRun1 1
/* Aspect ratios: The proper fraction xAspect/yAspect represents the pixel
* aspect ratio pixel_width/pixel_height.
*
* For the 4 Amiga display modes:
* 320 x 200: 10/11 (these pixels are taller than they are wide)
* 320 x 400: 20/11
* 640 x 200: 5/11
* 640 x 400: 10/11 */
# define x320x200Aspect 10
# define y320x200Aspect 11
# define x320x400Aspect 20
# define y320x400Aspect 11
# define x640x200Aspect 5
# define y640x200Aspect 11
# define x640x400Aspect 10
# define y640x400Aspect 11
/* A BitMapHeader is stored in a BMHD chunk. */
typedef struct {
UWORD w, h; /* raster width & height in pixels */
WORD x, y; /* position for this image */
UBYTE nPlanes; /* # source bitplanes */
Masking masking; /* masking technique */
Compression compression; /* compression algorithm */
UBYTE pad1; /* UNUSED. For consistency, put 0 here.*/
UWORD transparentColor; /* transparent "color number" */
UBYTE xAspect, yAspect; /* aspect ratio, a rational number x/y */
WORD pageWidth, pageHeight; /* source "page" size in pixels */
} BitMapHeader;
/* RowBytes computes the number of bytes in a row, from the width in pixels.*/
# define RowBytes(w) (2 * (((w) + 15) / 16))
/* ---------- ColorRegister --------------------------------------------*/
/* A CMAP chunk is a packed array of ColorRegisters (3 bytes each). */
typedef struct {
UBYTE red, green, blue; /* MUST be UBYTEs so ">> 4" won't sign extend.*/
} ColorRegister;
/* Use this constant instead of sizeof(ColorRegister). */
# define sizeofColorRegister 3
typedef WORD Color4; /* Amiga RAM version of a color-register,
* with 4 bits each RGB in low 12 bits.*/
# define swapword(X) ((((X) & 0xff) << 8) | (((X) & 0xff00) >> 8))
# define swaplong(X) (((unsigned) ((X) & 0xff000000) >> 24) | \
((unsigned) ((X) & 0x00ff0000) >> 8) | \
((unsigned) ((X) & 0x0000ff00) << 8) | \
((unsigned) ((X) & 0x000000ff) << 24))
# define swapsize(X) ((machine_byte_order () == LITTLE) ? swaplong(X) : (X))
/* Maximum number of bitplanes in RAM. Current Amiga max w/dual playfield. */
# define MaxAmDepth 6
/* Chunks must be padded to align to even boundaries */
# define EVENALIGN(X) (((X) + 1) & ~1)
/* ---------- Point2D --------------------------------------------------*/
/* A Point2D is stored in a GRAB chunk. */
typedef struct {
WORD x, y; /* coordinates (pixels) */
} Point2D;
/* ---------- DestMerge ------------------------------------------------*/
/* A DestMerge is stored in a DEST chunk. */
typedef struct {
UBYTE depth; /* # bitplanes in the original source */
UBYTE pad1; /* UNUSED; for consistency store 0 here */
UWORD planePick; /* how to scatter source bitplanes into destination */
UWORD planeOnOff; /* default bitplane data for planePick */
UWORD planeMask; /* selects which bitplanes to store into */
} DestMerge;
/* ---------- SpritePrecedence -----------------------------------------*/
/* A SpritePrecedence is stored in a SPRT chunk. */
typedef UWORD SpritePrecedence;
/* ---------- Viewport Mode --------------------------------------------*/
/* A Commodore Amiga ViewPort->Modes is stored in a CAMG chunk. */
/* The chunk's content is declared as a LONG. */
/* ---------- CRange ---------------------------------------------------*/
/* A CRange is store in a CRNG chunk. */
typedef struct {
WORD pad1; /* reserved for future use; store 0 here */
WORD rate; /* color cycling rate, 16384 = 60 steps/second */
WORD active; /* nonzero means color cycling is turned on */
UBYTE low, high; /* lower and upper color registers selected */
} CRange;
/*----------------------------------------------------------------------*
* PACKER.H typedefs for Data-Compresser. 1/22/86
*
* This module implements the run compression algorithm "cmpByteRun1"; the
* same encoding generated by Mac's PackBits.
*
* By Jerry Morrison and Steve Shaw, Electronic Arts.
* This software is in the public domain.
*
* This version for the Commodore-Amiga computer.
*----------------------------------------------------------------------*/
/* This macro computes the worst case packed size of a "row" of bytes. */
# define MaxPackedSize(rowSize) ( (rowSize) + ( ((rowSize)+127) >> 7 ) )
/*----------------------------------------------------------------------*
* unpacker.c Convert data from "cmpByteRun1" run compression. 11/15/85
*
* By Jerry Morrison and Steve Shaw, Electronic Arts.
* This software is in the public domain.
*
* control bytes:
* [0..127] : followed by n+1 bytes of data.
* [-1..-127] : followed by byte to be repeated (-n)+1 times.
* -128 : NOOP.
*
* This version for the Commodore-Amiga computer.
*----------------------------------------------------------------------*/
/*----------- UnPackRow ------------------------------------------------*/
# define UGetByte() (*source++)
# define UPutByte(c) (*dest++ = (c))
/* Given POINTERS to POINTER variables, unpacks one row, updating the source
* and destination pointers until it produces dstBytes bytes. */
static UnPackRow(pSource, pDest, srcBytes0, dstBytes0)
char **pSource, **pDest; int srcBytes0, dstBytes0; {
register char *source = *pSource;
register char *dest = *pDest;
register int n;
register char c;
register int srcBytes = srcBytes0, dstBytes = dstBytes0;
BOOL error = TRUE; /* assume error until we make it through the loop */
# ifdef DEBUG
fprintf (stderr, "Unpack called, src %d, dst %d\n",
srcBytes0, dstBytes0);
# endif
while( dstBytes > 0 ) {
if ( (srcBytes -= 1) < 0 ) goto ErrorExit;
n = UGetByte() & 0x0ff;
if (n < 128) {
# ifdef DEBUG
fprintf (stderr, "Got %02x, copying %d bytes...\n", n, n+1);
# endif
n += 1;
if ( (srcBytes -= n) < 0 ) goto ErrorExit;
if ( (dstBytes -= n) < 0 ) goto ErrorExit;
do { UPutByte(UGetByte()); } while (--n > 0);
}
else if (n != 128) {
# ifdef DEBUG
fprintf (stderr, "Got %02x, repeating byte %d times...\n",
n, 257-n);
# endif
n = 257 - n;
if ( (srcBytes -= 1) < 0 ) goto ErrorExit;
if ( (dstBytes -= n) < 0 ) goto ErrorExit;
c = UGetByte();
do { UPutByte(c); } while (--n > 0);
}
}
error = FALSE; /* success! */
ErrorExit:
*pSource = source; *pDest = dest;
if (error)
{ fprintf (stderr, "error in unpack, src %d, dst %d\n",
srcBytes, dstBytes);
}
return(error);
}
/****************************************************************
* read_iff: Read an Amiga format IFF Interleaved Bitmap
****************************************************************/
read_iff (image, rfile, mstr, mlen)
FBM *image;
FILE *rfile;
char *mstr;
int mlen;
{ char magic[8];
long formsize, buflen;
Chunk *form;
int result;
/* First word is magic number */
magic[0] = NEXTMCH(rfile,mstr,mlen) & 0xff;
magic[1] = NEXTMCH(rfile,mstr,mlen) & 0xff;
magic[2] = NEXTMCH(rfile,mstr,mlen) & 0xff;
magic[3] = NEXTMCH(rfile,mstr,mlen) & 0xff;
magic[4] = '\0';
/* If magic number is not FORM, lose */
if (strcmp (magic, "FORM") != 0)
{ if (strncmp (magic, "FOR", 3) == 0 ||
strncmp (magic, "LIS", 3) == 0 ||
strncmp (magic, "CAT", 3) == 0)
{ fprintf (stderr, "Sorry, I only handle FORM type IFF files\n");
return (0);
}
fprintf (stderr,
"read_iff: error, file not a FORM type IFF file, magic '%s'\n",
magic);
return (0);
}
/* Second longword is length of data chunk */
formsize = get_long (rfile, BIG);
form = (Chunk *) malloc (formsize + 8);
form->ckID = FORM;
form->ckSize = formsize;
/* Now read the rest of the chunk */
if ((buflen = fread (form->ckData, 1, formsize, stdin)) < formsize)
{ if (buflen < 0)
{ perror ("stdin"); }
else
{ fprintf (stderr, "error: premature EOF in FORM after %d of %d bytes\n",
buflen, formsize);
}
exit (1);
}
/* Recursively parse the FORM */
result = parse_form (image, form);
/* Now we've read the image (or not) */
free (form);
return (result);
}
/****************************************************************
* parse_form: Parse an IFF form chunk
*
* FORM ::= "FORM" #{ FormType (LocalChunk | FORM | LIST | CAT)* }
* FormType ::= ID
* LocalChunk ::= Property | Chunk
****************************************************************/
parse_form (image, chunk)
FBM *image;
Chunk *chunk;
{ register UBYTE *data, *tail;
register int clrlen, colors;
register BitMapHeader *bmh;
register int i, bits;
long formtype;
int found_bmhd=0, found_cmap=0, found_body=0;
Chunk *part;
data = chunk->ckData;
tail = data + chunk->ckSize;
formtype = MakeID(data[0], data[1], data[2], data[3]);
data += 4;
if (formtype != ID_ILBM)
{ fprintf (stderr, "this FORM doesn't start with ILBM, but %4.4s, sorry.\n",
&formtype);
return (0);
}
while (data < tail)
{ part = (Chunk *) data;
part->ckID = swapsize (part->ckID);
part->ckSize = swapsize (part->ckSize);
data += ( EVENALIGN (part->ckSize) + 8 );
# ifdef DEBUG
fprintf (stderr, "Found %c%c%c%c, size %ld\n",
(part->ckID & 0xff000000) >> 24,
(part->ckID & 0x00ff0000) >> 16,
(part->ckID & 0x0000ff00) >> 8,
(part->ckID & 0x000000ff),
part->ckSize);
# endif
if (part->ckID == ID_BMHD)
{ found_bmhd++;
bmh = (BitMapHeader *) part->ckData;
/* IFF uses BIG byte order, swap if necessary */
if (machine_byte_order () == LITTLE)
{ bmh->w = swapword (bmh->w);
bmh->h = swapword (bmh->h);
bmh->x = swapword (bmh->x);
bmh->y = swapword (bmh->y);
bmh->transparentColor = swapword (bmh->transparentColor);
bmh->pageWidth = swapword (bmh->pageWidth);
bmh->pageHeight = swapword (bmh->pageHeight);
}
image->hdr.rows = bmh->h;
image->hdr.cols = bmh->w;
image->hdr.planes = 1;
image->hdr.bits = bmh->nPlanes;
image->hdr.physbits = 8;
image->hdr.rowlen = 2 * ((image->hdr.cols + 1) / 2);
image->hdr.plnlen = image->hdr.rowlen * image->hdr.rows;
image->hdr.clrlen = 0;
image->hdr.aspect = (double) bmh->yAspect / bmh->xAspect;
image->hdr.title[0] = '\0';
image->hdr.credits[0] = '\0';
}
else if (part->ckID == ID_CMAP)
{ image->hdr.clrlen = part->ckSize;
alloc_fbm (image);
clrlen = image->hdr.clrlen;
colors = clrlen / 3;
for (i=0; i<image->hdr.clrlen; i++)
{ image->cm[(colors * (i%3)) + i/3] = part->ckData[i]; }
/* Compute number of bits in colormap */
for (i=colors, bits=1; i > 2; i /= 2, bits++) ;
if (bits < image->hdr.bits) image->hdr.bits = bits;
found_cmap++;
}
else if (part->ckID == ID_BODY)
{ if (!found_bmhd)
{ fprintf (stderr, "Error, BODY found with no BMHD header\n");
return (0);
}
if (found_cmap == 0)
{ alloc_fbm (image); }
found_body++;
/* Decode body */
fprintf (stderr, "Reading IFF [%dx%dx%d], %d physbits, %1.3lf aspect",
image->hdr.cols, image->hdr.rows,
image->hdr.bits, image->hdr.physbits,
image->hdr.aspect);
if (image->hdr.planes > 1)
{ fprintf (stderr, ", %d planes", image->hdr.planes); }
if (image->hdr.clrlen > 1)
{ fprintf (stderr, ", %d colors", image->hdr.clrlen / 3); }
if (bmh->compression)
{ fprintf (stderr, ", compressed"); }
if (bmh->masking == mskHasMask)
{ fprintf (stderr, ", with mask"); }
fprintf (stderr, "\n");
# ifdef DEBUG
fprintf (stderr,
"masking %d, compression %d, transparent %d, page [%dx%d]\n",
bmh->masking, bmh->compression, bmh->transparentColor,
bmh->pageWidth, bmh->pageHeight);
for (i=0; i<colors; i++)
{ fprintf (stderr, " color %3d: <%3d, %3d, %3d>\n", i,
image->cm[i], image->cm[i+colors], image->cm[i+colors*2]);
}
# endif
return (read_iff_body (image, bmh, part));
}
}
return (0);
}
/****************************************************************
* read_iff_body: Read the bits in the ILBM body into the FBM image
****************************************************************/
read_iff_body (image, bmh, body)
FBM *image;
BitMapHeader *bmh;
Chunk *body;
{ register int r, c, k, pmask, byte, bit;
unsigned char *row, *bp, *buf, *obm, *tail;
int bytlen = image->hdr.cols / 8;
int planes = bmh->nPlanes + ((bmh->masking == mskHasMask) ? 1 : 0);
buf = (unsigned char *) malloc (bytlen);
bp = body->ckData;
tail = bp + body->ckSize;
# ifdef DEBUG
fprintf (stderr, "Body length %d, planes %d: ", tail-bp, planes);
for (c=0; c<20; c++) fprintf (stderr, "%02x", bp[c]);
fprintf (stderr, "\n");
# endif
/* Each iteration reads one scan line */
for (r=0; r<image->hdr.rows; r++)
{
if (bp > tail)
{ fprintf (stderr, "Ran out of data in body after %d of %d rows\n",
r, image->hdr.rows);
return (0);
}
obm = &(image->bm[r * image->hdr.rowlen]);
/* Clear the output row of pixels */
for (c=0; c<image->hdr.cols; c++)
{ obm[c] = 0; }
/* Each loop reads one plane of this scan line */
for (k=0; k<planes; k++)
{
/* First get pointer to data packed 8 bits per byte */
if (bmh->compression == 0)
{ row = bp; bp += RowBytes (bmh->w); }
else
{ row = buf;
if (UnPackRow ((char **)&bp, (char **)&row, (int)(tail-bp),
RowBytes (bmh->w)) != 0)
{ fprintf (stderr,
"%s, row %d of %d, plane %d of %d, bytes per row %d\n",
"Error in UnPackRow",
r, image->hdr.rows, k, planes, RowBytes (bmh->w));
return (0);
}
row = buf;
}
/* Ignore extra planes (including the mask if any) */
if (k >= image->hdr.bits)
continue;
/* Now OR in these bits into the output pixels */
pmask = 1 << k;
for (c=0; c<image->hdr.cols; c++)
{ byte = c >> 3;
bit = 7 - (c & 7);
bit = row[byte] & (1 << bit);
obm[c] |= bit ? pmask : 0;
}
}
}
if (tail-bp > 1)
{ fprintf (stderr, "Warning, %d bytes of data unread\n", tail - bp); }
return (1);
}
/****************************************************************
* write_iff: Write AMIGA IFF format ILBM file
*
* Writes FORM type ILBM
* BMHD
* CMAP (optional)
* BODY (uncompressed)
*
****************************************************************/
write_iff (image, wfile)
FBM *image;
FILE *wfile;
{ BitMapHeader bmhd;
unsigned char *cmap, *body;
int bodylen, cmaplen, bmhdlen, formlen, ilbmbits;
if (image->hdr.planes > 1)
{ fprintf (stderr, "Error, write_iff cannot handle multi-plane images\n");
return (0);
}
/* Determine number of bits in output */
if (image->hdr.clrlen == 0)
{ ilbmbits = image->hdr.bits; }
else
{ int colors = image->hdr.clrlen/3;
for (ilbmbits=1; colors > 2; ilbmbits++, colors >>= 1) ;
}
fprintf (stderr, "Writing \"%s\" [%dx%d] as a %d bit IFF ILBM file\n",
image->hdr.title[0] ? image->hdr.title : "",
image->hdr.cols, image->hdr.rows, ilbmbits);
if (ilbmbits > 5)
{ fprintf (stderr, "%s\n%s\n%s\n",
"Warning: most IFF ILBM displays cannot handle more than",
" 32 colors. You should probably run the image though",
" 'gray2clr -u | fbquant -c32' first.");
}
/* Build BMHD, CMAP, and body chunks */
bmhdlen = build_bmhd (image, &bmhd, ilbmbits) ;
cmaplen = build_cmap (image, &cmap, ilbmbits);
bodylen = build_body (image, &body, ilbmbits);
/* Length of FORM is length of subparts plus 8 for header + 4 for type */
formlen = bmhdlen + cmaplen + bodylen + 12;
/*--------Write out FORM chunk header--------*/
fprintf (wfile, "FORM");
put_long (formlen-8, wfile, BIG);
fprintf (wfile, "ILBM");
/*----Write out BMHD chunk----*/
fprintf (wfile, "BMHD");
put_long (bmhdlen-8, wfile, BIG);
fwrite (&bmhd, bmhdlen-8, 1, wfile);
/* No need to pad BMHD chunk, it must be even */
/*----Write out CMAP chunk----*/
if (cmaplen > 0)
{ fprintf (wfile, "CMAP");
put_long (cmaplen-8, wfile, BIG);
fwrite (cmap, cmaplen-8, 1, wfile);
/* Pad CMAP chunk if necessary */
if (cmaplen & 1) fputc (0, wfile);
}
/*----Write out BODY chunk----*/
fprintf (wfile, "BODY");
put_long (bodylen-8, wfile, BIG);
fwrite (body, bodylen-8, 1, wfile);
/* Pad BODY chunk if necessary */
if (bodylen & 1) fputc (0, wfile);
/*--------Free memory and return--------*/
if (cmap) free (cmap);
if (body) free (body);
return (1);
}
/****************************************************************
* build_bmhd: Build a BitMapHeader, and byte swap it if necessary
****************************************************************/
build_bmhd (image, bmh, bits)
FBM *image;
BitMapHeader *bmh;
int bits;
{
bmh->w = image->hdr.cols;
bmh->h = image->hdr.rows;
bmh->x = 0;
bmh->y = 0;
bmh->nPlanes = bits;
bmh->masking = 0;
bmh->compression = 0;
bmh->pad1 = 0;
bmh->transparentColor = 0;
bmh->xAspect = 100;
bmh->yAspect = (image->hdr.aspect * 100.0) + 0.5;
bmh->pageWidth = bmh->w;
bmh->pageHeight = bmh->h;
/* IFF uses BIG byte order, swap if necessary */
if (machine_byte_order () == LITTLE)
{ bmh->w = swapword (bmh->w);
bmh->h = swapword (bmh->h);
bmh->x = swapword (bmh->x);
bmh->y = swapword (bmh->y);
bmh->transparentColor = swapword (bmh->transparentColor);
bmh->pageWidth = swapword (bmh->pageWidth);
bmh->pageHeight = swapword (bmh->pageHeight);
}
return (sizeof (*bmh) + 8);
}
/****************************************************************
* build_cmap: Convert an FBM format colormap to IFF format
****************************************************************/
build_cmap (image, cmap, bits)
FBM *image;
unsigned char **cmap;
int bits;
{ register int len, i;
register unsigned char *r, *g, *b, *c;
int colors;
colors = image->hdr.clrlen / 3;
r = image->cm;
g = r + colors;
b = g + colors;
len = 3*colors;
*cmap = (unsigned char *) malloc (len);
/* Now convert from three vectors to a vector of triples */
for (i=0, c= *cmap; i<colors; i++)
{ *c++ = *r++;
*c++ = *g++;
*c++ = *b++;
}
/* Return length of chunk, just length of map plus 8 bytes chunk header */
return (len + 8);
}
/****************************************************************
* build_body: Interleave the bits for the byte plane
****************************************************************/
build_body (image, body, bits)
register FBM *image;
unsigned char **body;
int bits;
{ int bpr, size;
register unsigned char *obm, *bmp;
register int r, c, k, mask, byte, bit;
bpr = RowBytes (image->hdr.cols);
size = bpr * image->hdr.rows * bits;
*body = (unsigned char *) malloc (size);
obm = *body;
for (r=0; r < image->hdr.rows; r++)
{ for (k=0; k<bits; k++)
{ mask = 1 << k;
bmp = &(image->bm[r * image->hdr.rowlen]);
# ifdef DEBUG
if (r==23)
{ fprintf (stderr, "Row %d, plane %d, bytes: ", r, k);
for (c=0; c<32; c++) fprintf (stderr, "%02x", bmp[c]);
fprintf (stderr, "\n");
}
# endif
for (c=0, byte=0; c<image->hdr.cols; c++)
{ bit = (*bmp++ & mask) ? 1 : 0;
# ifdef DEBUG
if (r == 23 && c < 32)
{ fprintf (stderr, "%d", bit); }
# endif
byte = (byte << 1) | bit;
if ((c&7) == 7)
{ *obm++ = byte;
# ifdef DEBUG
if (r == 23 && c <32) fprintf (stderr, " %d ", byte);
# endif
byte=0;
}
}
# ifdef DEBUG
if (r == 23) fprintf (stderr, "\n");
# endif
if ((c & 7) != 0)
{ while ((c&7) != 0)
{ c++; byte <<= 1; }
*obm++ = byte;
}
}
}
return (size + 8);
}