home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
594b.lha
/
CrossFade
/
CrossFade.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-12-22
|
11KB
|
364 lines
/* CrossFade : A video crossfade simulator (c) 1990 Dallas J. Hodgson
Usage : CrossFade <ILBM-file1> <ILBM-file2>
CrossFade takes 2 four-color ILBM pictures and smoothly crossfades between
them, using nothing more than color register manipulation! The effect
is similar to that used in pro video equipment, and lends itself to
other applications such as animation, depth-arranging, etc. This idea
could be extended to more bitplanes for extra colors or higher #'s of
simultaneously-crossfadable images.
HOW IT WORKS:
CrossFade opens a 4-bitplane screen and loads each 4-color image into
two bitplanes apiece. This results in a 16-color image, formed by
the colors in image 1, (registers 0,1,2,3) image 2 (registers 0,4,8,12)
and other color registers according to the overlap of bits between
the two images.
To blank out either image, we just set its color registers to the
transparent color - almost. Wherever bits in bitplanes [0,1] (image 1)
and [2,3] (image 2) overlap, other pencolors are formed from the overlap
set { 5,6,7,9,10,11,13,14 }. These color registers have to be filled with
redundant copies of the image colors we wish to display to prevent nasty
XOR-type video effects.
To explain this effect in all of its boolean detail would take up to
much space. Screen-grab a CrossFaded display and manipulate the colors in
DPaint - you'll see what I mean.
Click on the window-close gadget in the upper left corner of the
screen to exit.
*/
#include <exec/memory.h>
#include <libraries/dos.h>
#include <intuition/screens.h>
#include <intuition/intuition.h>
#include <functions.h>
extern struct WBStartup *WBenchMsg;
#define TITLE "CrossFade 1.0 : (c) 1990 John Hodgson\n"
#define MAXWIDTH 376 /* max non-HIRES width */
#define MAXHEIGHT 242 /* max non-interlaced height */
#define MAXCOLORS 32 /* max # colors supported */
#define MakeID(a,b,c,d) ((a)<<24L | (b)<<16L | (c)<<8 | (d))
#define ID_FORM MakeID('F','O','R','M')
#define ID_ILBM MakeID('I','L','B','M')
#define ID_BMHD MakeID('B','M','H','D')
#define ID_CAMG MakeID('C','A','M','G')
#define ID_CMAP MakeID('C','M','A','P')
#define ID_BODY MakeID('B','O','D','Y')
#define cmpByteRun1 1
#define ROUNDODDUP(a) (((a)+1)&(~1L))
typedef struct {
long ckID,ckSize;
} Chunk;
typedef struct {
short w,h,x,y;
char nPlanes,masking,compression,pad1;
short transparentColor;
char xAspect, yAspect;
short pageWidth,pageHeight;
} BitMapHeader;
#define SafeRead(a,b,c) if (Read(a,b,c)==-1L) { Close(a); return(NULL); }
void *IntuitionBase,*GfxBase;
/************************************************************************
* *
* Routine name(s) : ReadILBM() *
* Author : D. John Hodgson *
* Environment : Aztec "C", default *
* *
* ReadILBM attempts to read an IFF file and display it on a freshly *
* opened custom screen. Returns a screen pointer if sucessful, *
* otherwise NULL. *
* *
* LIMITATIONS : no masking, CATS/LISTS/PROPS. CAMG chunks supported. *
************************************************************************/
void *ReadILBM(fspec,size,bmhd,colormap,NewScreen)
char *fspec; /* AmigaDOS filename */
long *size; /* size of allocated buffer */
BitMapHeader *bmhd; /* header for us to fill */
unsigned char colormap[MAXCOLORS][3]; /* colormap for us to fill */
struct NewScreen *NewScreen; /* screen struct for us to fill */
{
struct Screen *screen;
struct FileHandle *fp;
char *sourcebuf;
short i;
long id,ViewModes=0;
char *bufstart;
Chunk header;
setmem(bmhd,sizeof(*bmhd),0); /* start w/fresh structure */
if ((fp=Open(fspec,MODE_OLDFILE))==0) return(NULL);
SafeRead(fp,&header,(long)sizeof(header));
if (header.ckID!=ID_FORM) { Close(fp); return(NULL); }
SafeRead(fp,&id,(long)sizeof(id));
if (id!=ID_ILBM) { Close(fp); return(NULL); }
for (;;) {
SafeRead(fp,&header,(long)sizeof(header));
if (header.ckID==ID_BODY) break;
switch(header.ckID) {
case ID_BMHD: SafeRead(fp,bmhd,(long)sizeof(*bmhd));
break;
case ID_CMAP: SafeRead(fp,&colormap[0][0],(long)header.ckSize);
for (i=0;i<header.ckSize;i++) colormap[0][i]>>=4;
break;
case ID_CAMG: SafeRead(fp,&ViewModes,(long)header.ckSize);
break;
default: Seek(fp,ROUNDODDUP(header.ckSize),OFFSET_CURRENT);
}
}
/* Read planes into RAM for ease of decompression */
sourcebuf=bufstart=AllocMem((long)header.ckSize,MEMF_PUBLIC);
if (sourcebuf==0L) puts("Error allocating memory!");
*size=(long)header.ckSize;
SafeRead(fp,sourcebuf,(long)header.ckSize); Close(fp);
setmem(NewScreen,sizeof(*NewScreen),0); /* start fresh */
NewScreen->LeftEdge=0; NewScreen->TopEdge=0;
NewScreen->Width=bmhd->w; NewScreen->Height=bmhd->h;
NewScreen->Depth=bmhd->nPlanes;
/* make some forced assumptions if CAMG chunk unavailable */
if (!(NewScreen->ViewModes=ViewModes)) {
if (bmhd->w>MAXWIDTH) NewScreen->ViewModes|=HIRES;
if (bmhd->h>MAXHEIGHT) NewScreen->ViewModes|=LACE;
}
NewScreen->Type=CUSTOMSCREEN;
NewScreen->Font=0L;
NewScreen->Gadgets=0L;
return(bufstart);
}
Expand(screen,bmhd,sourcebuf,planeoffset) /* Fast line decompress/deinterleave */
struct Screen *screen;
BitMapHeader *bmhd;
register char *sourcebuf;
short planeoffset;
{
register char n,*destbuf; /* in order of preferred allocation */
register short plane,linelen,rowbytes,i;
linelen=bmhd->w/8;
for (i=0;i<bmhd->h;i++) /* process n lines/screen */
for (plane=0;plane<bmhd->nPlanes;plane++) { /* process n planes/line */
destbuf=(char *)(screen->BitMap.Planes[plane+planeoffset])+linelen*i;
if (bmhd->compression==cmpByteRun1) { /* compressed screen? */
rowbytes=linelen;
while (rowbytes) { /* unpack until 1 scan-line complete */
n=*sourcebuf++; /* fetch block run marker */
/* uncompressed block? copy n bytes verbatim */
if (n>=0) {
movmem(sourcebuf,destbuf,(unsigned int)++n); rowbytes-=n;
destbuf+=n; sourcebuf+=n;
}
else { /* compressed block? expand n duplicate bytes */
n=-n+1; rowbytes-=n;
setmem(destbuf,(unsigned int)n,(unsigned int)*sourcebuf++);
destbuf+=n;
}
} /* finish unpacking line */
}
else { /* uncompressed? just copy */
movmem(sourcebuf,destbuf,(unsigned int)linelen);
sourcebuf+=linelen; destbuf+=linelen;
}
} /* finish interleaved planes, lines */
}
load_colormap(screen,colormap)
struct Screen *screen;
char colormap[MAXCOLORS][3];
{
short i,colorcnt=1<<screen->BitMap.Depth;
/* Sure, LoadRGB is faster, but uses UWORDS for its colors! */
for (i=0;i<colorcnt;i++) {
SetRGB4(&screen->ViewPort,(long)i,
(long)colormap[i][0],(long)colormap[i][1],
(long)colormap[i][2]);
}
}
create_image1x4_colors(srcmap,dstmap)
char srcmap[MAXCOLORS][3],dstmap[MAXCOLORS][3];
{
short i,j;
/* create image 1's color palette. Duplicates image 1 colors
into the xx11 registers. */
for (i=0;i<16;i++)
for (j=0;j<3;j++)
dstmap[i][j]=srcmap[i%4][j];
}
create_image2x4_colors(srcmap,dstmap)
char srcmap[MAXCOLORS][3],dstmap[MAXCOLORS][3];
{
short i,j;
/* create image 2's color palette */
for (i=0;i<=4;i++)
for (j=0;j<3;j++)
dstmap[i*4][j]=srcmap[i][j];
/* Duplicate the image2 colors into the 11xx registers */
for (i=0;i<16;i++) {
if (i%4) {
for (j=0;j<3;j++)
dstmap[i][j]=srcmap[(i & 0x0c)/4][j];
}
}
}
FadeAtoB(screen,srcmap,dstmap)
struct Screen *screen;
char srcmap[MAXCOLORS][3],dstmap[MAXCOLORS][3];
{
short i,j,flag,colorcnt=1<<screen->BitMap.Depth;
do {
flag=0;
for (i=0;i<colorcnt;i++) {
for (j=0;j<3;j++) {
if (srcmap[i][j]!=dstmap[i][j]) {
srcmap[i][j]+=SIGN(dstmap[i][j]-srcmap[i][j]);
flag=1;
}
}
}
load_colormap(screen,srcmap);
Delay(5);
}
while(flag);
}
main(argc,argv)
int argc;
char *argv[];
{
struct Screen *screen=0;
struct Window *window=0;
struct NewWindow nw;
struct NewScreen NewScreen1,NewScreen2;
BitMapHeader bmhd1,bmhd2;
char *buf1=0,*buf2=0;
long size1,size2;
short i;
char colormap1[MAXCOLORS][3],colormap2[MAXCOLORS][3],
colormapA[MAXCOLORS][3],colormapB[MAXCOLORS][3];
GfxBase=OpenLibrary("graphics.library",0L);
IntuitionBase=OpenLibrary("intuition.library",0L);
setmem(&nw,sizeof(nw),0); /* start w/fresh structure */
puts(TITLE); /* CLI title */
if (!(buf1=ReadILBM(argv[1],&size1,&bmhd1,colormap1,&NewScreen1))) {
printf("Error reading IFF file %s.\n",argv[1]);
goto cleanup;
}
if (NewScreen1.Depth!=2) {
printf("ILBM file %s must be 2 bitplanes. %d found.\n",argv[1],NewScreen1.Depth);
goto cleanup;
}
if (!(buf2=ReadILBM(argv[2],&size2,&bmhd2,colormap2,&NewScreen2))) {
printf("Error reading IFF file %s.\n",argv[2]);
goto cleanup;
}
if (NewScreen2.Depth!=2) {
printf("ILBM file %s must be 2 bitplanes. %d found.\n",argv[2],NewScreen2.Depth);
goto cleanup;
}
NewScreen1.Depth+=NewScreen2.Depth;
create_image1x4_colors(colormap1,colormapA);
create_image2x4_colors(colormap2,colormapB);
if (!(screen=OpenScreen(&NewScreen1))) {
puts("Couldn't open screen!");
goto cleanup;
}
load_colormap(screen,colormapA);
nw.IDCMPFlags=CLOSEWINDOW;
nw.Flags=SIMPLE_REFRESH|BORDERLESS|WINDOWCLOSE;
nw.Screen=screen;
nw.Type=CUSTOMSCREEN;
nw.Height=bmhd1.h; nw.Width=bmhd1.w;
if (!(window=OpenWindow(&nw))) { CloseScreen(screen); exit(100); }
Expand(screen,&bmhd1,buf1,0); /* fill bitplanes 0-1, image 1 */
Expand(screen,&bmhd2,buf2,2); /* fill bitplanes 1-2, image 2 */
Delay(100);
while (!GetMsg(window->UserPort)) { /* until CloseWindow */
FadeAtoB(screen,colormapA,colormapB);
create_image1x4_colors(colormap1,colormapB);
create_image2x4_colors(colormap2,colormapA);
Delay(20);
FadeAtoB(screen,colormapA,colormapB);
create_image1x4_colors(colormap1,colormapA);
create_image2x4_colors(colormap2,colormapB);
}
cleanup:
if (buf1) FreeMem(buf1,size1); /* free compressed buffer */
if (buf2) FreeMem(buf2,size2); /* free compressed buffer */
if (window) CloseWindow(window); /* Intuition will ReplyMsg() for us */
if (screen) CloseScreen(screen);
CloseLibrary(IntuitionBase);
CloseLibrary(GfxBase);
}