Blur Blending Method

Environment: C++

This sample shows a way to code the blur blending method on a RGB bitmap. Use it for a smooth effect or to remove noise.


/////////////////////////////////////////////////////////////////////
//
// Filter Procedure
//
// Blend a RGB color bitmap. Do not work with RGB(555).
//
// Process a blur average blending on the source bitmap. It takes
// all the environnent pixels that are attached to the source pixel.
//
// 1 1 1
// 1 S 1
// 1 1 1
//
// Then it computes the average of the color region.
// If (Pixel.Value – Average) is upper to the LevelDelta then the
// color S is the Average; otherwise, it does not change.
// Set levelDelta to zero to apply Blur Method to each pixels of
// the bitmap.
//
// A blending matrix is use to set the weight of each pixel
// in the average computation
// Change matrix to change the transformation
//
// 1 2 1
// 2 4 2
// 1 2 1
//
// SumColor is the sum of each element. (Sum = 16 in this example)
//
// Average computation is made as follow :
//
// For( i = 0 ; i < MatrixElement ; i ++ )
// Average += ( PixelColor[i] * BlendingMatrix[i] )
// Average = Average / SumColor
//
//
// The following matrix is the Blur Blending Method :
// 1 2 1
// 2 4 2
// 1 2 1
//
// The following matrix is the Blur More Blending Method :
// 1 1 1
// 1 1 1
// 1 1 1
//
//
// NOTE : The format of the source bitmap is not changed.
// NOTE : The code is not optimized for execution but for a good
// read comprehension
// NOTE : This procedure do not assum error managment. It is not the
// subject of this example.
//
/////////////////////////////////////////////////////////////////////
//
// Input : Source DC
// Source Bitmap
// Color Delta
//
// Output : None
// return : None
//
/////////////////////////////////////////////////////////////////////
//
// History : 05/2002 Jean-Rémi PINNA ([email protected]) Wrote it.
//
/////////////////////////////////////////////////////////////////////

void _FILTER_BlurMethodBlending( HDC hSrcDc,
HBITMAP hSrcBmp,
BYTE bDeltaMax )
{
BITMAPINFO sBmpInfo;
BYTE * pBmpBytes;

::memset( &sBmpInfo, 0, sizeof(BITMAPINFO) );

BITMAP SrcBmp;
::GetObject(hSrcBmp, sizeof(BITMAP), &SrcBmp);

if( (SrcBmp.bmBitsPixel != 24) && (SrcBmp.bmBitsPixel != 32) )
return;

sBmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
sBmpInfo.bmiHeader.biWidth = SrcBmp.bmWidth;
sBmpInfo.bmiHeader.biHeight = SrcBmp.bmHeight;
sBmpInfo.bmiHeader.biBitCount = SrcBmp.bmBitsPixel;
sBmpInfo.bmiHeader.biPlanes = 1;
sBmpInfo.bmiHeader.biCompression = BI_RGB;
sBmpInfo.bmiHeader.biSizeImage =
SrcBmp.bmBitsPixel*SrcBmp.bmWidth*SrcBmp.bmHeight/8;

pBmpBytes = new BYTE[sBmpInfo.bmiHeader.biSizeImage];

// Fill the buffer with a copy of the bitmap’s bits

::GetDIBits( hSrcDc,
hSrcBmp,
0,
sBmpInfo.bmiHeader.biHeight,
pBmpBytes,
&sBmpInfo,
DIB_RGB_COLORS );

DWORD dwLineWidth, dwByteCount, dwBytesPixel, dwImageSize;

dwLineWidth = SrcBmp.bmBitsPixel*SrcBmp.bmWidth/8;
dwBytesPixel = SrcBmp.bmBitsPixel/8;
dwImageSize = sBmpInfo.bmiHeader.biSizeImage;
dwByteCount = dwBytesPixel;
// Start to second pixel to avoid bug on first pixel
// (Previous bottom point coordinate is 1276)

// Blending Matrix —- This matrix correspond to the Blur More
// blending method
// The middle pixel value is the average
// of all environnent pixels
// Change value of an element modify his
// weight in the computation of the average
//
// BYTE bBlurMoreBlendingMatrix[9] = { 1, 1, 1,
// 1, 1, 1,
// 1, 1, 1 };
//
// BYTE bHalfBlendingMatrix[9] = { 0, 1, 0,
// 1, 1, 1,
// 0, 1, 0 };

// Blending Matrix —- This matrix correspond to the Blur
// blending method
// The sum of the elements of the array
// must not exceed 256
//

BYTE bBlurBlendingMatrix[9] = { 1, 2, 1,
2, 4, 2,
1, 2, 1 };

// This matrix contains the values needed to point on
// corresponding bit
//

long nPosRange[9] = { – (long)(dwLineWidth-dwBytesPixel) ,
– (long)(dwLineWidth) ,
– (long)(dwLineWidth+dwBytesPixel),
– (long)(dwBytesPixel) ,
0 ,
+dwBytesPixel,
+ (dwLineWidth-dwBytesPixel) ,
+ (dwLineWidth) ,
+ (dwLineWidth+dwBytesPixel) };

// Sum Blending Matrix Elements
//

BYTE bMatrixSum = 0;

for( int iSum = 0 ; iSum<9 ; iSum++ )
bMatrixSum += bBlurBlendingMatrix[iSum];

while( dwByteCount < dwImageSize )
{
DWORD bDelta, dwAverage;

// Create array of pixel’s positions
//
long nPosNewRange[9]= { (long)(dwByteCount+nPosRange[0]),
(long)(dwByteCount+nPosRange[1]),
(long)(dwByteCount+nPosRange[2]),
(long)(dwByteCount+nPosRange[3]),
(long)(dwByteCount+nPosRange[4]),
(long)(dwByteCount+nPosRange[5]),
(long)(dwByteCount+nPosRange[6]),
(long)(dwByteCount+nPosRange[7]),
(long)(dwByteCount+nPosRange[8]) };

// Check point validity : ensure points are in the bit array
//
for( int iPos = 0 ; iPos < 9 ; iPos++ )
{
nPosNewRange[iPos] = nPosNewRange[iPos] < 0 ? 0 :
nPosNewRange[iPos] >
(long)dwImageSize ? dwByteCount : nPosNewRange[iPos];
}

// Compute method on each RGB color of the pixel
//
for( int iColor = 0 ; iColor < 3 ; iColor++ )
{
dwAverage = 0;

// Compute Color average
//
BYTE bColorValue[9] = { pBmpBytes[nPosNewRange[0]+iColor],
pBmpBytes[nPosNewRange[1]+iColor],
pBmpBytes[nPosNewRange[2]+iColor],
pBmpBytes[nPosNewRange[3]+iColor],
pBmpBytes[nPosNewRange[4]+iColor],
pBmpBytes[nPosNewRange[5]+iColor],
pBmpBytes[nPosNewRange[6]+iColor],
pBmpBytes[nPosNewRange[7]+iColor],
pBmpBytes[nPosNewRange[8]+iColor] };

// Apply Blendind Matrix to compute color average
//
for( iPos = 0 ; iPos < 9 ; iPos++ )
dwAverage += bColorValue[iPos]*bBlurBlendingMatrix[iPos];

BYTE bAverage = (BYTE)(dwAverage/bMatrixSum);

bDelta = abs( pBmpBytes[dwByteCount]-bAverage );
pBmpBytes[dwByteCount+iColor] =
bDelta > bDeltaMax ? bAverage :
pBmpBytes[dwByteCount+iColor];
}

// Move to next pixel
//
dwByteCount+=dwBytesPixel;
}

::SetDIBits( hSrcDc,
hSrcBmp,
0,
sBmpInfo.bmiHeader.biHeight,
pBmpBytes,
&sBmpInfo,
DIB_RGB_COLORS );

delete pBmpBytes;
}

Downloads

Download source – 7 Kb

More by Author

Must Read