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 (jrpinna@noos.fr) 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


Comments

  • A missing link!?!?

    Posted by Legacy on 06/06/2002 12:00am

    Originally posted by: Bo Krohn

    The link points to NIL... :)

    Reply
  • Source File

    Posted by Legacy on 06/05/2002 12:00am

    Originally posted by: Roger McElfresh

    Source file, what source file?

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • On-demand Event Event Date: March 27, 2014 Teams need to deliver quality software faster and need integrated agile planning, task tracking, source control, auto deploy with continuous builds and a configurable process to adapt to the way you work. Rational Team Concert and DevOps Services (JazzHub) have everything you need to build great software, integrated seamlessly together right out of the box or available immediately in the cloud. And with the Rational Team Concert Client, you can connect your …

  • Given today's threat environment and the increasing connectivity of digital infrastructures, security teams now realize that they must assume their IT environments are subject to periodic compromise. Gone are the days when preventive measures to secure the perimeter or trying to detect malware problems using signature-match technologies were enough. New practices based on an understanding of the phases of an attack, continuous threat monitoring, and rapid attack detection and remediation are necessary. This …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds