COTD submitted by Benjamin Contant [bcontant@videotron.ca] (posted 08/20/2001)

DWORD SrcColor = 0;
DWORD DestColor;
BYTE SrcAlpha, SrcRed, SrcGreen, SrcBlue;
BYTE DestAlpha, DestRed, DestGreen, DestBlue;
BYTE RedError, GreenError, BlueError, AlphaError;

for(int i = 0; i < Height; i++)
{
	//Reset the error after every line because we don't want
	//the error of the last pixel to be used on the first pixel
	//of this line
	RedError = GreenError = BlueError = AlphaError = 0;

	for(int j = 0; j < Width; j++)
	{
		//Read in the source color
		SrcColor = 0;	
		for(int k = 0; k < SrcBytesPerPixel; k++)
		{
			SrcColor += (SrcPtr[k] << (k<<3));
		}

		//Extract the ARGB components
		if(SrcAlphaNumBits > 0)
		{
			SrcAlpha = (SrcColor & SrcAlphaMask) >> SrcAlphaShift;
		}
		else
		{
			SrcAlpha = 255;
		}
		SrcRed   = (SrcColor & SrcRedMask) >> SrcRedShift;
		SrcGreen = (SrcColor & SrcGreenMask) >> SrcGreenShift;
		SrcBlue  = (SrcColor & SrcBlueMask) >> SrcBlueShift;

		//Add the error while clamping to the max color value
		if(SrcAlphaNumBits > 0)
		{
			SrcAlpha = min(MaxSrcAlpha, SrcAlpha + AlphaError);
		}
		SrcRed   = min(MaxSrcRed, SrcRed + RedError);
		SrcGreen = min(MaxSrcGreen, SrcGreen + GreenError);
		SrcBlue  = min(MaxSrcBlue, SrcBlue + BlueError);
		
		//Calculate the resulting destination colors
		if(SrcAlphaNumBits > 0)
		{
			DestAlpha = SrcAlpha >> AlphaBitDiff;
		}
		else
		{
			DestAlpha = SrcAlpha >> (8 - DestAlphaNumBits);
		}
		
		DestRed   = SrcRed   >> RedBitDiff;
		DestGreen = SrcGreen >> GreenBitDiff;
		DestBlue  = SrcBlue  >> BlueBitDiff;

		//Calculate the error
		if(SrcAlphaNumBits > 0)
		{
			AlphaError = SrcAlpha - (DestAlpha << AlphaBitDiff);
		}
		else
		{
			AlphaError = 0;
		}
		RedError = SrcRed - (DestRed << RedBitDiff);
		GreenError = SrcGreen - (DestGreen << GreenBitDiff);
		BlueError = SrcBlue - (DestBlue << BlueBitDiff);

		//Compose the destination pixel
		DestColor = (DestAlpha << DestAlphaShift) +
					(DestRed << DestRedShift) +
					(DestGreen << DestGreenShift) +
					(DestBlue << DestBlueShift);
		
		//Set the destination pixel
		BYTE* DestColorPtr = (BYTE*) &DestColor;
		for(k = 0; k < DestBytesPerPixel; k++)
		{
			DestPtr[k] = DestColorPtr[k];
		}

		//Advance the pointers to the next pixel
		DestPtr += DestBytesPerPixel;
		SrcPtr += SrcBytesPerPixel;
	}

	//Advance the pointers to the next line
	DestPtr += DestPitch - (Width * DestBytesPerPixel);
	SrcPtr += SrcPitch - (Width * SrcBytesPerPixel);
}