#include <windows.h>
#include "animate.h"

extern HANDLE ghBitmap;                        //global handle to bitmap buffer
/**************************************************************************
*  Function Name:  FrameDelta
*  Purpose: Computes an array of deltas between frame2 and frame1 and
*  RLE encodes the deltas
**************************************************************************/
DWORD FrameDelta (int iFrame1, int iFrame2, HANDLE hBitinfo, BYTE *pRLEbuf)
{
static int i, j, jo;
static int  iOver, iDown;
static PIXEL pPix1, pPix2;
static BYTE huge *pBitmap;
static BITMAPINFO *pBitInfo;
static int iImageWidth;         //in pixels
static int iImageHeight;       //in pixels
static int iWriteIndex;

    pBitmap = (BYTE huge *) GlobalLock (ghBitmap);
    pBitInfo = (BITMAPINFO *) LocalLock (hBitinfo);
    iImageWidth= pBitInfo->bmiHeader.biWidth;
    iImageHeight= pBitInfo->bmiHeader.biHeight;
    iWriteIndex = 0;
    jo=0;

    for (i=FRAMEHEIGHT-1;i>0;i--) {
        for (j=0, jo=0;j<FRAMEWIDTH;j++) {
                //Determine the position of the pixel in the first frame
            iOver = (iFrame1 % FRAMESACROSS) * (FRAMEWIDTH+1) + j;
            iDown = (iFrame1/FRAMESACROSS) * (FRAMEHEIGHT+1) + i;
            iDown = (iImageHeight-1) - iDown;
                //Get the pixel from the first frame...
            pPix1 = anGetPixel (pBitmap, iImageWidth, iOver, iDown);
                //and from the second frame...
            iOver = (iFrame2 % FRAMESACROSS) * (FRAMEWIDTH+1) + j;
            iDown = (iFrame2/FRAMESACROSS) * (FRAMEHEIGHT+1) + i;
            iDown = (iImageHeight-1) - iDown;
            pPix2 = anGetPixel (pBitmap, iImageWidth, iOver, iDown);
                //Encode the pixel if it's different
            if (pPix1 != pPix2) {
                   //Escape sequence to indicate a delta
                pRLEbuf[iWriteIndex++]=0x00;
                pRLEbuf[iWriteIndex++]=0x02;
                    //Amount of the x delta
                pRLEbuf[iWriteIndex++]= j-jo-1;
                    //y delta is always 0
                pRLEbuf[iWriteIndex++]= 0;
                    //one pixel run
                pRLEbuf[iWriteIndex++]= 0x01;
                    //save the pixel
                pRLEbuf[iWriteIndex++]= ((pPix2 << 4) & 0xf0);
                jo = j;
            } //End if (pixels are different)
        } //End for (each column in frame)
            //end of scanline sequence
        pRLEbuf[iWriteIndex++]=0x00;
        pRLEbuf[iWriteIndex++]=0x00;
    } //End for (each row in frame)
        //end of bitmap sequence
    pRLEbuf[iWriteIndex++]=0x00;
    pRLEbuf[iWriteIndex++]=0x01;

    GlobalUnlock (ghBitmap);
    LocalUnlock (hBitinfo);
    return (DWORD)iWriteIndex;
} //End function (FrameDelta)
/**************************************************************************
*  Function Name:  GetPixel
*  Purpose:  Returns the pixel from the memory location.
**************************************************************************/
PIXEL anGetPixel (BYTE huge *pBuf, int iImageWidth, int iOver, int iDown)
{
static LONG lByteIndex;
     lByteIndex = (LONG)iDown * (LONG)(iImageWidth/2) + (LONG)(iOver/2);
     if (EVEN(iOver))
         return (PIXEL) ((pBuf[lByteIndex] >> 4) & 0x0f);
     else
         return (PIXEL) (pBuf[lByteIndex] & 0x0f);
} //End function (anGetPixel)
