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: October 29, 2014 @ 11:00 a.m. ET / 8:00 a.m. PT Are you interested in building a cognitive application using the power of IBM Watson? Need a platform that provides speed and ease for rapidly deploying this application? Join Chris Madison, Watson Solution Architect, as he walks through the process of building a Watson powered application on IBM Bluemix. Chris will talk about the new Watson Services just released on IBM bluemix, but more importantly he will do a step by step cognitive …

  • Protecting business operations means shifting the priorities around availability from disaster recovery to business continuity. Enterprises are shifting their focus from recovery from a disaster to preventing the disaster in the first place. With this change in mindset, disaster recovery is no longer the first line of defense; the organizations with a smarter business continuity practice are less impacted when disasters strike. This SmartSelect will provide insight to help guide your enterprise toward better …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds