找到一段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:[email protected]#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
//
// 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:[email protected]#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
about the image filter.
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;namespace Blur
{
public class Form1 : System.Windows.Forms.Form
{ private System.ComponentModel.IContainer components;
internal System.Windows.Forms.PictureBox PictureBox1;
internal System.Windows.Forms.Button Button1;
internal System.Windows.Forms.ProgressBar Progress;
internal System.Windows.Forms.Label Label1;
internal System.Windows.Forms.PictureBox PictureBox2; /// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.Run(new Form1());
} public Form1()
{
//base.New();
InitializeComponent();
} protected override void Dispose(bool disposing)
{
if (disposing)
{
if (!(components == null))
{
components.Dispose();
}
}
base.Dispose(disposing);
} [System.Diagnostics.DebuggerStepThrough()]
private void InitializeComponent()
{
System.Resources.ResourceManager resources = new System.Resources.ResourceManager(typeof(Form1));
this.PictureBox1 = new System.Windows.Forms.PictureBox();
this.Button1 = new System.Windows.Forms.Button();
this.Progress = new System.Windows.Forms.ProgressBar();
this.Label1 = new System.Windows.Forms.Label();
this.PictureBox2 = new System.Windows.Forms.PictureBox();
this.SuspendLayout();
//
// PictureBox1
//
this.PictureBox1.Image = ((System.Drawing.Image)(resources.GetObject("PictureBox1.Image")));
this.PictureBox1.Location = new System.Drawing.Point(10, 9);
this.PictureBox1.Name = "PictureBox1";
this.PictureBox1.Size = new System.Drawing.Size(192, 172);
this.PictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage;
this.PictureBox1.TabIndex = 0;
this.PictureBox1.TabStop = false;
//
// Button1
//
this.Button1.Location = new System.Drawing.Point(10, 190);
this.Button1.Name = "Button1";
this.Button1.Size = new System.Drawing.Size(393, 24);
this.Button1.TabIndex = 1;
this.Button1.Text = "&Apply";
this.Button1.Click += new System.EventHandler(this.Button1_Click);
//
// Progress
//
this.Progress.Location = new System.Drawing.Point(10, 241);
this.Progress.Name = "Progress";
this.Progress.Size = new System.Drawing.Size(393, 25);
this.Progress.TabIndex = 2;
//
// Label1
//
this.Label1.Location = new System.Drawing.Point(10, 224);
this.Label1.Name = "Label1";
this.Label1.Size = new System.Drawing.Size(316, 25);
this.Label1.TabIndex = 3;
this.Label1.Text = "Pass 1 of 2:";
//
// PictureBox2
//
this.PictureBox2.Image = ((System.Drawing.Image)(resources.GetObject("PictureBox2.Image")));
this.PictureBox2.Location = new System.Drawing.Point(211, 9);
this.PictureBox2.Name = "PictureBox2";
this.PictureBox2.Size = new System.Drawing.Size(192, 172);
this.PictureBox2.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage;
this.PictureBox2.TabIndex = 4;
this.PictureBox2.TabStop = false;
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(6, 14);
this.ClientSize = new System.Drawing.Size(412, 273);
this.Controls.Add(this.PictureBox2);
this.Controls.Add(this.Progress);
this.Controls.Add(this.Label1);
this.Controls.Add(this.Button1);
this.Controls.Add(this.PictureBox1);
this.Name = "Form1";
this.Text = "Blur";
this.ResumeLayout(false); } private Color Average(Size Size, SizeF imageSize, int PixelX, int Pixely)
{
ArrayList pixels = new ArrayList();
//int x;
//int y;
Bitmap bmp = (Bitmap) PictureBox1.Image.Clone();
for (int x = PixelX - System.Convert.ToInt32(Size.Width / 2); x <= PixelX + System.Convert.ToInt32(Size.Width / 2); x++)
{
for (int y = Pixely - System.Convert.ToInt32(Size.Height / 2); y <= Pixely + System.Convert.ToInt32(Size.Height / 2); y++)
{
if ((x > 0 & x < imageSize.Width) & (y > 0 & y < imageSize.Height))
{
pixels.Add(bmp.GetPixel(x, y));
}
}
}
//Color thisColor;
int alpha = 0;
int red = 0;
int green = 0;
int blue = 0;
foreach (Color thisColor in pixels)
{
alpha += thisColor.A;
red += thisColor.R;
green += thisColor.G;
blue += thisColor.B;
}
return Color.FromArgb(alpha / pixels.Count, red / pixels.Count, green / pixels.Count, blue / pixels.Count);
} private void gausianBlur(bool alphaEdgesOnly, Size blurSize)
{
// int PixelY;
// int PixelX;
Bitmap bmp = (Bitmap) PictureBox1.Image.Clone();
Label1.Text = "Applying Gausian Blur of " + blurSize.ToString();
Progress.Maximum = bmp.Height * bmp.Width;
Progress.Minimum = 0;
Progress.Value = 0;
for (int PixelY = 0; PixelY <= bmp.Width - 1; PixelY++)
{
for (int PixelX = 0; PixelX <= bmp.Height - 1; PixelX++)
{
if (!alphaEdgesOnly)
{
bmp.SetPixel(PixelX, PixelY, Average(blurSize, bmp.PhysicalDimension, PixelX, PixelY)); //就是这里出问题了:报使用了无效的参数,调试信息显示PixelX=0;PixelY=300;blurSize为6*6;bmp.PhysicalDimension为300*400;
}
else if (bmp.GetPixel(PixelX, PixelY).A != 255)
{
bmp.SetPixel(PixelX, PixelY, Average(blurSize, bmp.PhysicalDimension, PixelX, PixelY));
}
Progress.Value += 1;
Application.DoEvents();
}
}
PictureBox1.Image =(Image) bmp.Clone();
bmp.Dispose();
} private void Button1_Click(object sender, System.EventArgs e)
{
gausianBlur(false, new Size(6, 6));
}
}
}就是这行出调试错误了:
bmp.SetPixel(PixelX, PixelY, Average(blurSize, bmp.PhysicalDimension, PixelX, PixelY)); //就是这里出问题了:报使用了无效的参数,调试信息显示PixelX=0;PixelY=300;blurSize为6*6;bmp.PhysicalDimension为300*400;
哪位大侠解决一下?
http://www.cnblogs.com/iceshark/category/6055.html