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

  • Live Event Date: August 14, 2014 @ 2:00 p.m. ET / 11:00 a.m. PT Data protection has long been considered "overhead" by many organizations in the past, many chalking it up to an insurance policy or an extended warranty you may never use. The realities of today make data protection a must-have, as we live in a data driven society. The digital assets we create, share, and collaborate with others on must be managed and protected for many purposes. Check out this upcoming eSeminar and join eVault Chief Technology …

  • Mobile is introducing sweeping changes throughout your workplace. As a senior stakeholder driving mobile initiatives in your organization, you may be lost in a sea of technologies and claims from vendors promising rapid delivery of applications to your employees, customers, and partners. To help explain some of the topics you will need to be aware of, and to separate the must-haves from the nice-to-haves, this reference guide can help you with applying a mobile strategy in the context of application …

Most Popular Programming Stories

More for Developers

RSS Feeds