图片的高斯模糊如何做?

大可山人 大可山人 墨衍会员 · AI 创作全网分发 墨衍智能分发 通过墨衍一键同步至各平台 可同步平台 CSDN微信公众号微博知乎掘金百家号博客园抖音小红书 你的文章也可以这样分发 墨衍会员 ¥399起/年,写一次发全网 我也要 + 加入社区
找到一段C++写的,那位可以翻译为C#的,我不懂C++。

// QGaussFilter.cpp
//
// MFC class to apply Unsharp Mask or Blur to a GDI+ Bitmap.
// Use at your own risk. Comments welcome.
//
// Version 1.1, 02/02/2004:
// Bug resolved in handling of small bitmaps. Thanks to Maik Wiege.
//
// Version 1.0 (c) 2003, Sjaak Priester, Amsterdam.
// mailto:sjaak@sjaakpriester.nl

#include "StdAfx.h"
#include "QGaussFilter.h"
#include "Int.h"

#include <math.h>


const ColorMatrix QGaussFilter::MatRGBtoYUV =
{
0.5f, 0.3086f, -0.1681f, 0, 0,
-0.4407f, 0.6094f, -0.3391f, 0, 0,
-0.0593f, 0.082f, 0.5f, 0, 0,
0, 0, 0, 1, 0,
0.5f, 0, 0.5f, 0, 1
};

const ColorMatrix QGaussFilter::MatYUVtoRGB =
{
1.383f, -0.7002f, 0, 0, 0,
1, 1, 1, 0, 0,
0, -0.247f, 1.836f, 0, 0,
0, 0, 0, 1, 0,
-0.6914f, 0.4736f, -0.918f, 0, 1
};

QGaussFilter::QGaussFilter()
: m_FilterVector(NULL)
, m_Denominator(0)
, m_Dim(0)
, m_MaxDim(51)
, m_bStop(false)
, m_Flags(PlaneAll)
, m_pMsgWnd(NULL)
, m_Message(QM_GAUSSFILTER)
, m_pThread(NULL)
, m_pSource(NULL)
, m_bUnsharpMask(false)
, m_pRect(NULL)
{
}

QGaussFilter::~QGaussFilter(void)
{
Stop();
delete[] m_FilterVector;
delete m_pRect;
}

// Make Unsharp Mask bitmap in a separate worker thread
void QGaussFilter::MakeUnsharpMask(Bitmap * pSource, REAL radius, REAL depth,
CWnd * pMsgWnd, UINT message, Rect * pRect, UINT flags)
{
Stop();
m_pSource = pSource;
m_Radius = radius;
m_Depth = depth;
m_pMsgWnd = pMsgWnd;
m_Message = message;
m_Flags = flags;

delete m_pRect;
if (pRect) m_pRect = pRect->Clone();
else m_pRect = NULL;

m_bUnsharpMask = true;
m_pThread = ::AfxBeginThread(ThreadProc, this);
}

// Make Blur bitmap in a separate worker thread
void QGaussFilter::MakeBlur(Bitmap * pSource, REAL radius,
CWnd * pMsgWnd, UINT message, Rect * pRect, UINT flags)
{
Stop();
m_pSource = pSource;
m_Radius = radius;
m_pMsgWnd = pMsgWnd;
m_Message = message;
m_Flags = flags;

delete m_pRect;
if (pRect) m_pRect = pRect->Clone();
else m_pRect = NULL;

m_bUnsharpMask = false;
m_pThread = ::AfxBeginThread(ThreadProc, this);
}

// Stop calculation of Unsharp Mask or Blur in seperate thread
void QGaussFilter::Stop(void)
{
if (m_pThread)
{
m_bStop = true;
::WaitForSingleObject(m_pThread->m_hThread, INFINITE);
}
}

// Calculate and return Unsharp Mask bitmap
Bitmap * QGaussFilter::GetUnsharpMask(Bitmap * pSrc, REAL radius, REAL depth, Rect * pRect, UINT flags)
{
// Start with blur
Bitmap * pResult = GetBlur(pSrc, radius, pRect, flags, false);
if (pResult)
{
// Subtract blurred bitmap from original to get Unsharp Mask
Rect rcSrc(0, 0, pSrc->GetWidth(), pSrc->GetHeight());
if (pRect) rcSrc.Intersect(* pRect);

BitmapData dataSrc;
Status s = pSrc->LockBits(& rcSrc, ImageLockModeRead,
PixelFormat24bppRGB, & dataSrc);
if (s != Ok)
{
delete pResult;
return NULL;
}

Rect rcResult(0, 0, pResult->GetWidth(), pResult->GetHeight());

BitmapData dataResult;
s = pResult->LockBits(& rcResult, ImageLockModeRead | ImageLockModeWrite,
PixelFormat24bppRGB, & dataResult);
if (s != Ok)
{
pSrc->UnlockBits(& dataSrc);
delete pResult;
return NULL;
}

const int nPlanes = 3;

// On modern systems, the difference is not big, but real math is still somewhat
// slower than integer math. But if this ever changes, you may define REAL_MATH.
#ifdef REAL_MATH
REAL depthPlus = depth + 1.0f;
#else
int denom = 10000; // use an arbitrary denominator, not too small
int dpt = Int((REAL) denom * depth);
int dptplus = dpt + denom;
#endif

BYTE * pStartSrc = (BYTE *) dataSrc.Scan0;
BYTE * pStartResult = (BYTE *) dataResult.Scan0;

for (int plane = 0; plane < nPlanes; plane++) // loop through color planes
{
bool bThisPlane = (flags & 1) != 0;
flags >>= 1;

BYTE * pLineSrc = pStartSrc;
BYTE * pLineResult = pStartResult;

if (bThisPlane)
{
for (UINT line = 0; line < dataResult.Height; line++) // loop through lines
{
BYTE * pPixelSrc = pLineSrc;
BYTE * pPixelResult = pLineResult;

for (UINT pxl = 0; pxl < dataResult.Width; pxl++) // loop through pixels
{
#ifdef REAL_MATH
REAL v = depthPlus * *pPixelSrc - depth * *pPixelResult;
if (v > 255.0f) v = 255.0f;
if (v < 0.0f) v = 0.0f;
#else
int v = dptplus * *pPixelSrc - dpt * *pPixelResult;
v /= denom;

// Clipping is very essential here. for large values of depth
// (> 5.0f) more than half of the pixel values are clipped.
if (v > 255) v = 255;
if (v < 0) v = 0;
#endif
* pPixelResult = (BYTE) v;
pPixelSrc += nPlanes;
pPixelResult += nPlanes;
}
if (m_bStop) break;
pLineSrc += dataSrc.Stride;
pLineResult += dataResult.Stride;
}
}
else // no subtraction, just copy
{
for (UINT line = 0; line < dataResult.Height; line++) // loop through lines
{
BYTE * pPixelSrc = pLineSrc;
BYTE * pPixelResult = pLineResult;

for (UINT pxl = 0; pxl < dataResult.Width; pxl++)
{
* pPixelResult = * pPixelSrc;
pPixelSrc += nPlanes;
pPixelResult += nPlanes;
}

if (m_bStop) break;
pLineSrc += dataSrc.Stride;
pLineResult += dataResult.Stride;
} // next line
}

if (m_bStop) break;
pStartSrc++;
pStartResult++;
} // next plane

pResult->UnlockBits(& dataResult);
pSrc->UnlockBits(& dataSrc);

if (m_bStop)
{
delete pResult;
pResult = NULL;
}
}
return pResult;
}
----------------------------
http://community.csdn.net/Expert/topic/3479/3479414.xml?temp=.9337427
...全文

相关推荐

评论 10
收藏 已收藏
分享
返回顶部
大可山人
大可山人 领域专家: 后端开发技术领域 领域专家: 后端开发技术领域
.NET社区 62,272 成员 668,968 内容