home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Frozen Fish 1: Amiga
/
FrozenFish-Apr94.iso
/
bbs
/
alib
/
d3xx
/
d326
/
vsnap.lha
/
VSnap
/
iffpic.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-03-05
|
9KB
|
403 lines
/** routine for saveing an IFF picture to the clipboard...
By Stephen Vermeulen 1989.
**/
struct IOClipReq clipboardIO = 0;
struct MsgPort clipboardMsgPort = 0;
struct MsgPort satisfyMsgPort = 0;
#ifndef MakeID
#define MakeID(a, b, c, d)\
( ((long) (a)<<24) + ((long) (b)<<16) + ((long)(c)<<8) + (long)(d) )
#endif
short CBisOpen; /** this will be set to 1 when the clipboard has
been successfully opened.
**/
/** the following two routines are from a CBM example somewhere on the
Fish Disks...
**/
int CBOpen(unit)
int unit;
{
int error;
/* open the clipboard device */
if ((error = OpenDevice("clipboard.device", (long) unit, &clipboardIO, 0L)) != 0)
CBisOpen = 0;
/* Set up the message port in the I/O request */
clipboardMsgPort.mp_Node.ln_Type = NT_MSGPORT;
clipboardMsgPort.mp_Flags = 0;
clipboardMsgPort.mp_SigBit = AllocSignal(-1L);
clipboardMsgPort.mp_SigTask = (struct Task *) FindTask((char *) NULL);
AddPort(&clipboardMsgPort);
clipboardIO.io_Message.mn_ReplyPort = &clipboardMsgPort;
satisfyMsgPort.mp_Node.ln_Type = NT_MSGPORT;
satisfyMsgPort.mp_Flags = 0;
satisfyMsgPort.mp_SigBit = AllocSignal(-1L);
satisfyMsgPort.mp_SigTask = (struct Task *) FindTask((char *) NULL);
AddPort(&satisfyMsgPort);
CBisOpen = 1;
}
CBClose()
{
if (CBisOpen)
{
if (clipboardMsgPort.mp_SigBit > 0)
FreeSignal(clipboardMsgPort.mp_SigBit);
if (satisfyMsgPort.mp_SigBit > 0)
FreeSignal(satisfyMsgPort.mp_SigBit);
RemPort(&satisfyMsgPort);
RemPort(&clipboardMsgPort);
CloseDevice(&clipboardIO);
CBisOpen = 0;
}
}
/** the rest of the clipboard routines are my own work **/
/** this is used to set the mode of the clipboard, to either read
or write (0 or 1)
**/
CBSetMode(mode)
int mode;
{
if (mode) /** write **/
{
clipboardIO.io_Command = CMD_WRITE;
clipboardIO.io_Offset = 0;
clipboardIO.io_ClipID = 0;
}
else
{
clipboardIO.io_Command = CMD_READ;
clipboardIO.io_Offset = 0;
clipboardIO.io_ClipID = 0;
}
}
/** the following is the function that replaces fread(), calling
the clipboard instead.
**/
gfread(data, length, n)
UBYTE *data;
int length, n;
{
if (CBisOpen)
{
while (n)
{
clipboardIO.io_Command = CMD_READ;
clipboardIO.io_Data = (STRPTR) data;
clipboardIO.io_Length = length;
DoIO(&clipboardIO);
data += length;
--n;
}
}
}
gputc(c)
char c;
{
if (CBisOpen)
{
clipboardIO.io_Command = CMD_WRITE;
clipboardIO.io_Data = (STRPTR) &c;
clipboardIO.io_Length = 1;
DoIO(&clipboardIO);
}
}
gfwrite(data, length, n)
UBYTE *data;
int length, n;
{
if (CBisOpen)
{
while (n)
{
clipboardIO.io_Command = CMD_WRITE;
clipboardIO.io_Data = (STRPTR) data;
clipboardIO.io_Length = length;
DoIO(&clipboardIO);
data += length;
--n;
}
}
}
CBEndSession(mode)
int mode;
{
if (!CBisOpen) return;
if (mode) /** end of writing **/
{
clipboardIO.io_Command = CMD_UPDATE;
DoIO(&clipboardIO);
}
else /** end of reading **/
{
clipboardIO.io_Command = CMD_READ;
clipboardIO.io_Offset = 2000000000; /** don't use -1L here!
the clipboard treats this
as a SIGNED quantity! **/
clipboardIO.io_Length = 1;
clipboardIO.io_Data = (STRPTR) 0;
DoIO(&clipboardIO);
}
}
/** note the following does not support seeking relative to the end
of the clip...
**/
gfseek(offset, origin)
long offset;
int origin;
{
if (CBisOpen)
{
switch (origin)
{
case 0: /** rel to begining **/
clipboardIO.io_Offset = offset;
break;
case 1: /** rel to current pos **/
clipboardIO.io_Offset += offset;
break;
}
}
}
long gftell()
{
if (CBisOpen)
{
return(clipboardIO.io_Offset);
}
else
return(NULL);
}
gfopen(mode)
char *mode;
{
if (mode[0] == 'r') CBSetMode(0);
else CBSetMode(1);
}
gfclose(mode)
char *mode;
{
if (mode[0] == 'r')
{
/** we must force a read beyond the end of the file to tell
clipboard we are done with it!
**/
CBEndSession(0);
}
else CBEndSession(1);
}
#define MaxPackedSize(rowSize) ( (rowSize) + ( ((rowSize) + 127) >> 7) )
#define RowBytes(w) ((((w) + 15) >> 4) << 1)
/************************************************************
The following are the IFF read and write routines
************************************************************/
#define FORM MakeID('F', 'O', 'R', 'M')
#define ILBM MakeID('I', 'L', 'B', 'M')
#define BMHD MakeID('B', 'M', 'H', 'D')
#define BODY MakeID('B', 'O', 'D', 'Y')
#define VDFL MakeID('V', 'D', 'F', 'L')
#define CMAP MakeID('C', 'M', 'A', 'P')
#define GRAB MakeID('G', 'R', 'A', 'B')
#define CAMG MakeID('C', 'A', 'M', 'G')
#define CRNG MakeID('C', 'R', 'N', 'G')
struct BMHdr
{
USHORT w, h;
SHORT x, y;
UBYTE nPlanes, masking, compression, pad1;
USHORT transparentColor;
UBYTE xAspect, yAspect;
SHORT pageWidth, pageHeight;
};
struct PictHdr
{
LONG IFFid, filelen, ILBMid, BMHDid, BMHDsize;
struct BMHdr bmhdr;
};
char comp_buf[1036]; /* buffer to hold the compressed input data */
short comp_buf_len; /* number of bytes in the compressed buffer */
/***************************************************************
Quicky little routine that just writes a long word to the file
****************************************************************/
void write_WORD(i)
LONG i;
{
(void) gfwrite( (char *) &i, 4, 1);
}
void write_CMAP(s, d)
struct Screen *s;
short d;
{
short i, colour;
if (d == 6) d == 5; /* cause of ehb */
write_WORD(CMAP);
write_WORD(3L * (1L << d));
for (i = 0; i < (1 << d); ++i)
{
colour = GetRGB4(s->ViewPort.ColorMap, (long) i);
gputc((colour & 0x0f00) >> 4); /****** red ******/
gputc((colour & 0x00f0)); /***** green *****/
gputc((colour & 0x000f) << 4); /****** blue *****/
}
}
/************************************************************
The following routine is used by the IFF saving routines
to write the body section of the image.
Returns true if sucessful, else it returns FALSE.
************************************************************/
int save_BODY(bm, comp)
struct BitMap *bm;
short comp;
{
short y, nbytes, bwidth, depth;
short p;
struct BitMap mybm;
char *source, *dest, *bp;
nbytes = bwidth = bm->BytesPerRow;
mybm = *bm;
depth = bm->Depth;
/*******************
scan down the rows
********************/
for (y = 0; y < bm->Rows; ++y)
{
/**************************
Sweep down the bit planes
***************************/
for (p = 0; p < depth; ++p)
{
bp = (char *) mybm.Planes[p];
if (comp)
{
/****************
pack this row
*****************/
source = bp;
dest = &comp_buf[0];
nbytes = PackRow(&source, &dest, bwidth);
bp = &comp_buf[0];
}
/************************
Now write out the data
*************************/
gfwrite((char *) bp, nbytes, 1);
mybm.Planes[p] += bwidth;
} /* end for bitplanes */
} /* end for rows */
return(1);
}
/************************************************************
The routine to save designated area of a raster port in
IFF format.
************************************************************/
short save_bm(bm, s)
struct BitMap *bm;
struct Screen *s;
{
LONG vmode, body_start, body_len, file_len;
struct PictHdr Pict;
short i;
FILE *out;
char *name;
CBOpen(0);
if (!CBisOpen) return(0);
gfopen("w");
Pict.bmhdr.w = bm->BytesPerRow << 3;
Pict.bmhdr.h = bm->Rows;
Pict.bmhdr.x = 0;
Pict.bmhdr.y = 0;
Pict.bmhdr.nPlanes = bm->Depth;
Pict.bmhdr.masking = 0;
Pict.bmhdr.compression = 1;
Pict.bmhdr.pad1 = 0;
Pict.bmhdr.transparentColor = 0;
Pict.bmhdr.xAspect = (s->Width > 400) ? 10 : 20;
Pict.bmhdr.yAspect = (s->Height > 280) ? 11 : 22;
Pict.bmhdr.pageWidth = s->Width;
Pict.bmhdr.pageHeight = s->Height;
Pict.IFFid = FORM;
Pict.filelen = 0; /* fill in later */
Pict.ILBMid = ILBM;
Pict.BMHDid = BMHD;
Pict.BMHDsize = sizeof(struct BMHdr);
gfwrite( (char *) &Pict, (short) sizeof(struct PictHdr), 1);
write_CMAP(s, bm->Depth);
vmode = s->ViewPort.Modes;
vmode &= HIRES | LACE | EXTRA_HALFBRITE | HAM;
write_WORD(CAMG, out);
write_WORD(4L, out);
write_WORD(vmode, out);
/*********************
Write the BODY chunk
**********************/
write_WORD(BODY);
write_WORD(0L); /* fill in later */
body_start = gftell();
save_BODY(bm, 1);
body_len = gftell() - body_start; /* length of body chunk */
if (gftell() & 0x01L) gputc(0); /* pad byte if needed */
file_len = gftell();
/**************************
Reposition in the file
and write the actual body
and file lengths.
***************************/
gfseek(body_start - 4L, 0); /* body length */
write_WORD(body_len);
gfseek(4L, 0); /* file length */
write_WORD(file_len - 8L);
gfclose("w");
CBClose();
return(1);
}