home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Creative Computers
/
CreativeComputers.iso
/
shareware
/
fractals
/
mandelsquare
/
mandelsquare-1.06.lha
/
SaveAnim.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-12-20
|
8KB
|
352 lines
/*
** MandelSquare - AmigaDOS 2.0/3.0 Mandelbrot set explorer
**
** SaveAnim.c, Routines to save IFF-ANIM files
**
** Copyright ⌐ 1991-1992 by Olaf `Olsen' Barthel
** All Rights Reserved
*/
/* Animation information. */
struct AnimInfo
{
struct IFFHandle *Handle;
struct ViewPort *VPort;
ULONG ViewModes;
struct BitMap *BitMaps[4],
*Source;
STRPTR FileName;
UWORD Width,
Height,
Depth;
};
/* In skip.c */
extern UBYTE * __regargs skip_comp_plane(UBYTE *in, UBYTE *last_in, UBYTE *out, WORD next_line, WORD rows);
extern WORD __regargs skip_count_plane(UBYTE *in, UBYTE *last_in, WORD next_line, WORD rows);
/* In Packer.c */
extern LONG __regargs PackRow(BYTE **pSource, BYTE **pDest, LONG rowSize);
/* In ILBM.c */
extern VOID FreeCustomBitMap(struct BitMap *BitMap,BYTE Standard);
extern struct BitMap * AllocCustomBitMap(UWORD Depth,UWORD Width,UWORD Height,BYTE Standard);
extern BYTE PutBitMap(struct IFFHandle *Handle,struct BitMap *BitMap);
extern BYTE PutViewModes(struct IFFHandle *Handle,struct ViewPort *VPort);
extern BYTE PutColourMap(struct IFFHandle *Handle,struct ViewPort *VPort);
extern BYTE PutBitMapHeader(struct IFFHandle *Handle,struct Screen *Screen);
/* Local, static routines. */
STATIC VOID __regargs FreeCustomBitMaps(struct AnimInfo *Info);
STATIC BYTE __regargs AllocCustomBitMaps(struct AnimInfo *Info);
STATIC BYTE __regargs PutDelta(struct IFFHandle *Handle,LONG *Data,LONG nData);
/* Exported routines. */
VOID CloseAnim(struct AnimInfo *Info,BYTE Success);
struct AnimInfo * OpenAnim(STRPTR Name,struct Screen *Screen);
BYTE AddAnim(struct AnimInfo *Info);
/* FreeCustomBitMaps(struct AnimInfo *Info):
*
* Free the four auxilary bitmaps.
*/
STATIC VOID __regargs
FreeCustomBitMaps(struct AnimInfo *Info)
{
WORD i;
for(i = 0 ; i < 4 ; i++)
{
if(Info -> BitMaps[i])
FreeCustomBitMap(Info -> BitMaps[i],TRUE);
}
}
/* AllocCustomBitMaps(struct AnimInfo *Info):
*
* Allocate four auxilary bitmaps.
*/
STATIC BYTE __regargs
AllocCustomBitMaps(struct AnimInfo *Info)
{
WORD i;
for(i = 0 ; i < 4 ; i++)
{
if(!(Info -> BitMaps[i] = AllocCustomBitMap(Info -> Depth,Info -> Width,Info -> Height,TRUE)))
{
FreeCustomBitMaps(Info);
return(FALSE);
}
}
return(TRUE);
}
/* PutDelta(struct IFFHandle *Handle,LONG *Data,LONG DataSize):
*
* Save the delta data to the file.
*/
STATIC BYTE __regargs
PutDelta(struct IFFHandle *Handle,LONG *Data,LONG DataSize)
{
AnimationHeader Header;
/* Reset the animation header contents. */
memset(&Header,0,sizeof(AnimationHeader));
/* Fill in compression information and relative
* timing information (1 jiffie = 1/60 second).
*/
Header . operation = 5;
Header . reltime = 1;
if(!PushChunk(Handle,ID_ILBM,ID_FORM,IFFSIZE_UNKNOWN))
{
if(!PushChunk(Handle,0,ID_ANHD,sizeof(AnimationHeader)))
{
if(WriteChunkRecords(Handle,&Header,sizeof(AnimationHeader),1) == 1)
{
if(!PopChunk(Handle))
{
if(!PushChunk(Handle,0,ID_DLTA,DataSize))
{
if(WriteChunkRecords(Handle,Data,DataSize,1) == 1)
{
if(!PopChunk(Handle))
{
if(!PopChunk(Handle))
return(TRUE);
}
}
}
}
}
}
}
return(FALSE);
}
/* CloseAnim(struct AnimInfo *Info,BYTE Success):
*
* Close an animation file, freeing the auxilary data.
*/
VOID
CloseAnim(struct AnimInfo *Info,BYTE Success)
{
if(Info -> Handle)
{
if(PopChunk(Info -> Handle))
Success = FALSE;
CloseIFF(Info -> Handle);
if(Info -> Handle -> iff_Stream)
{
if(!Close(Info -> Handle -> iff_Stream))
Success = FALSE;
}
else
Success = TRUE;
FreeIFF(Info -> Handle);
}
FreeCustomBitMaps(Info);
if(!Success)
DeleteFile(Info -> FileName);
else
SetProtection(Info -> FileName,FIBF_EXECUTE);
FreeVec(Info);
}
/* OpenAnim(STRPTR Name,struct Screen *Screen):
*
* Create an animation file.
*/
struct AnimInfo *
OpenAnim(STRPTR Name,struct Screen *Screen)
{
struct AnimInfo *Info;
WORD Len = strlen(Name),
i;
/* Allocate the auxilary buffer. */
if(Info = (struct AnimInfo *)AllocVec(sizeof(struct AnimInfo) + Len + 1,MEMF_ANY | MEMF_CLEAR))
{
/* Fill in the header information. */
Info -> FileName = (STRPTR)(Info + 1);
Info -> VPort = &Screen -> ViewPort;
Info -> Source = Screen -> RastPort . BitMap;
Info -> ViewModes = GetVPModeID(Info -> VPort);
strcpy(Info -> FileName,Name);
Info -> Width = Screen -> Width;
Info -> Height = Screen -> Height;
Info -> Depth = Info -> Source -> Depth;
/* Allocate the bitmaps. */
if(AllocCustomBitMaps(Info))
{
/* Copy the image information to all three bitmaps. */
for(i = 0 ; i < 3 ; i++)
BltBitMap(Info -> Source,0,0,Info -> BitMaps[i],0,0,Info -> Width,Info -> Height,0xC0,0xFF,NULL);
/* Set up the vanilla iff stuff... */
if(Info -> Handle = AllocIFF())
{
if(Info -> Handle -> iff_Stream = Open(Name,MODE_NEWFILE))
{
InitIFFasDOS(Info -> Handle);
if(!OpenIFF(Info -> Handle,IFFF_WRITE))
{
/* Set up the standard ANIM information. */
if(!PushChunk(Info -> Handle,ID_ANIM,ID_FORM,IFFSIZE_UNKNOWN))
{
if(!PushChunk(Info -> Handle,ID_ILBM,ID_FORM,IFFSIZE_UNKNOWN))
{
if(PutBitMapHeader(Info -> Handle,Screen))
{
if(PutColourMap(Info -> Handle,Info -> VPort))
{
if(PutViewModes(Info -> Handle,Info -> VPort))
{
if(PutBitMap(Info -> Handle,Info -> BitMaps[0]))
{
if(!PopChunk(Info -> Handle))
return(Info);
}
}
}
}
}
}
}
}
}
}
CloseAnim(Info,FALSE);
}
return(NULL);
}
/* AddAnim(struct AnimInfo *Info):
*
* Add another animation frame to the file.
*/
BYTE
AddAnim(struct AnimInfo *Info)
{
struct BitMap *Save;
LONG *DeltaData,
DeltaCount,
PlaneCount[8],
PageSize,
RowBytes,
Rows,
j,i;
BYTE Success = FALSE;
UBYTE *DeltaPtr,
*Planes[2];
/* Move the bitmaps up. */
Save = Info -> BitMaps[3];
for(i = 3 ; i > 0 ; i--)
Info -> BitMaps[i] = Info -> BitMaps[i - 1];
Info -> BitMaps[0] = Save;
/* Copy the new screen bitmap to the first one in the list. */
BltBitMap(Info -> Source,0,0,Save,0,0,Info -> Width,Info -> Height,0xC0,~0,NULL);
/* Set up the startup information. */
RowBytes = Info -> BitMaps[1] -> BytesPerRow;
Rows = Info -> BitMaps[1] -> Rows;
PageSize = RowBytes * Rows;
DeltaCount = 64;
/* Determine the maximum buffer size required for compression. */
for(i = 0 ; i < Info -> BitMaps[1] -> Depth ; i++)
{
Planes[0] = Info -> BitMaps[1] -> Planes[i];
Planes[1] = Info -> BitMaps[3] -> Planes[i];
PlaneCount[i] = 0;
j = PageSize;
while(j--)
{
if(*Planes[0]++ != *Planes[1]++)
{
PlaneCount[i] = skip_count_plane(Info -> BitMaps[1] -> Planes[i],Info -> BitMaps[3] -> Planes[i],RowBytes,Rows);
DeltaCount += PlaneCount[i];
break;
}
}
}
/* Allocate the compression buffer. */
if(DeltaData = (LONG *)AllocVec(DeltaCount,MEMF_ANY | MEMF_CLEAR))
{
DeltaPtr = (UBYTE *)&DeltaData[16];
DeltaCount = 64;
/* Compress the planes. */
for(i = 0 ; i < Info -> BitMaps[1] -> Depth ; i++)
{
if(PlaneCount[i])
{
DeltaData[i] = DeltaCount;
DeltaCount += PlaneCount[i];
DeltaPtr = skip_comp_plane(Info -> BitMaps[1] -> Planes[i],Info -> BitMaps[3] -> Planes[i],DeltaPtr,RowBytes,Rows);
}
}
/* Save the delta data to disk. */
Success = PutDelta(Info -> Handle,DeltaData,DeltaCount);
FreeVec(DeltaData);
}
return(Success);
}