home *** CD-ROM | disk | FTP | other *** search
- /* 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);
- }
-