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 …

  • Live Event Date: November 13, 2014 @ 2:00 p.m. ET / 11:00 a.m. PT APIs can be a great source of competitive advantage. The practice of exposing backend services as APIs has become pervasive, however their use varies widely across companies and industries. Some companies leverage APIs to create internal, operational and development efficiencies, while others use them to drive ancillary revenue channels. Many companies successfully support both public and private programs from the same API by varying levels …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds