MPEG2AVI
--------
v0.15

documentation file (not source code!)

Conceptual overview of DOWNsizing algorithm.
(Minor modification required for zooming.)



srcW = source bitmap's width
srcH = source bitmap's height
destW= destination bitmap's scaled width

src1bmp, src2bmp, src3bmp - input bitmaps < srcW * srcH >, each is 8bpp array
dest1bmp, dest2bmp, dest3bmp - output bitmaps, each is 8bpp array,
   
   ***output bitmaps have SAME dimensions as input bitmaps ( srcW * srcH )!


void
shrink888x(unsigned char dest1bmp[], unsigned char dest2bmp[],
		  unsigned char dest3bmp[], const unsigned char src1bmp[], 
		  const unsigned char src2bmp[], const unsigned char src3bmp[],
		  short srcW,short srcH, short destW )
{
	short srcXStep; /* source bitmap step size <x-direction> */
	short destXStep; /* dest bitmap step size <x-drection> */
	short diffXAcc;  /* differential accumulator */
	long pixAcc[4];/* pixel-sample accumulator */
	short srcXcount;   /* pixel index <X co-ordinate> */
	short destXcount;   /* pixel index <X co-ordinate> */
	short y; /* for-loop variable, <y> index for dest_bmp[] */
	int pixWeight; /* current source-pixel's relative-weight 
					  toward output-pixel value */

	unsigned char *pSrc1 = NULL, *pSrc2= NULL, *pSrc3 = NULL;
	unsigned char *pDest1= NULL, *pDest2=NULL, *pDest3=NULL;

	srcXStep = destW ; 
	destXStep= srcW ;  

	pixAcc[0]=pixAcc[1]=pixAcc[2]=pixAcc[3]=0;
	srcXcount=0;
	destXcount=0;

  for ( y=0; y < srcH; ++y )
  {
	/* pSrc = points to leftmost pixel on current row [x] in src_bmp */
	pSrc1 = src1bmp + (y*srcW);
	pSrc2 = src2bmp + (y*srcW);
	pSrc3 = src3bmp + (y*srcW);
	
	/* thanks to pDest, output is centered, with respect to 
	   source bitmap's co-ordinate axis */

	/* pDest = points to leftmost pixel on current row [x] in dest_bmp */
	pDest1 = dest1bmp + (y*srcW + ((srcW - destW)>>1) ); 
	pDest2 = dest2bmp + (y*srcW + ((srcW - destW)>>1) ); 
	pDest3 = dest3bmp + (y*srcW + ((srcW - destW)>>1) ); 

	/* prepare to process one output scanline (row)	*/
	diffXAcc = 0;
	srcXcount = 0; /* reset to left of current scan line (row) */
	for( destXcount = 0; destXcount < destW; ++destXcount )
	{
		/* 0) add residual portion of previous pixel (src_bmp[]) to pixelAcc */
		pixWeight = abs( diffXAcc );
		pixAcc[0] = ( pixWeight * pSrc1[ srcXcount ] );
		pixAcc[1] = ( pixWeight * pSrc2[ srcXcount ] );
		pixAcc[2] = ( pixWeight * pSrc3[ srcXcount ] );

		/* if current accumulator shows residual src_bmp[], we just
		   finished it, move to next pixel */

		if ( diffXAcc != 0 ) 
			++srcXcount;  /* advance to next pixel */
		
		diffXAcc += destXStep; /* add increment to diff accumulator */

		/* 1) now, scan through src pixels until accumulator is depleted */
		while ( diffXAcc >= srcXStep )
		{
			diffXAcc -= srcXStep;

			pixWeight = srcXStep; /* pixWeight = pixel's weighted factor */
			/* the maximum ( pixWeight ) = destXStep, in other words, 
			   the SUM of pixWeight's in pixAcc[] = destXStep" */

			/* add whole current pixel (src_bmp[]) to pixel-Accumulator */
			pixAcc[0] += (pixWeight * pSrc1[ srcXcount ] );
			pixAcc[1] += (pixWeight * pSrc2[ srcXcount ] );
			pixAcc[2] += (pixWeight * pSrc3[ srcXcount ] );
			++srcXcount; /* move to next src_bmp pixel */
		}

		/* 2) add fractional of current input pixel to pixel-Acc */
		pixWeight = diffXAcc;
		pixAcc[0] += (pixWeight* pSrc1[ srcXcount ] );
		pixAcc[1] += (pixWeight* pSrc2[ srcXcount ] );
		pixAcc[2] += (pixWeight* pSrc3[ srcXcount ] );

		diffXAcc -= srcXStep; /* diffXAcc is now a negative #, a "residual" */

		/* 3) done with current output pixel, write it to dest_bmp[] */
		pDest1[ destXcount ] = pixAcc[0] / destXstep;
		pDest2[ destXcount ] = pixAcc[1] / destXstep;
		pDest3[ destXcount ] = pixAcc[2] / destXstep;

        /* we don't skip the current source pixel (++srcXcount) just yet...
		   it might be needed for the next output-pixel. */

	} /* endfor( destYcount ) */

  } /* endfor (y=0...) */

}

shrink888y works in an analogous fashion,
the bitmap is scanned column-by-column instead of row-by-row.