昨天刚写了《哞哞快的 C# 高斯模糊实现》,里边提到了用原作者的方法实现对图像快速的高斯模糊处理,说实话,我没看懂,主要是没看懂原理,怎么就“把图片给处理了”,大概是调用了 GDIPlus.dll 里边的函数,所以我看不到算法和细节,但这正是我要的——专业的人才做专业的事儿,我不懂图像处理,我只想有个 void 帮我随时把某个图像处理掉,最好还是免费、开源、快速的 ^^

昨天写完这个之后,继续去研究方法里作者提到的一个函数“int GdipBitmapCreateApplyEffect()”,据说可以不修改原图,将处理后的效果写进另一个图像中,自己照猫画虎的写了写,不出意外的,不成功。程序也不报错,调试了一下,发现函数的处理结果是“OK”,那就是我自己写的有问题。冷静想想……找找资料

谷歌出一篇,在 CodePlex 上有一个对图像处理的项目,里边使用到了 GDIPlus.dll,下载下来步步跟踪,发现了自己的问题:函数的参数传递的是 IntPtr,就是句柄,也可以理解为“指针”,经过函数处理之后,即便成功了,也需要额外的工作,就是把处理后的图像“写回”到某个 Bitmap 对象中去。我之前没成功就是因为函数执行完了,以为定义的新的 Bitmap 对象就被自动修改了,实际上没有。

想到了自己的问题,就看人家怎么处理的,结果,又是两个俺不懂的函数,不过不影响理解原理。拷贝到方法内,运行,成功!Project 下载

         /// <summary>
/// 使用高斯模糊效果创建一个新的图像
/// </summary>
/// <returns></returns>
public static Bitmap CreateNewWithEffect(this Bitmap image, ref Rectangle Rect, float Radius = , bool ExpandEdge = false)
{
// 新图像
Bitmap newImage = new Bitmap(image); int Result;
IntPtr BlurEffect;
BlurParameters BlurPara;
if ((Radius < ) || (Radius > ))
{
throw new ArgumentOutOfRangeException("Radius 参数错误,半径必须在 [0,255] 范围内");
}
BlurPara.Radius = Radius;
BlurPara.ExpandEdges = ExpandEdge;
Result = GdipCreateEffect(BlurEffectGuid, out BlurEffect); if (Result == )
{
IntPtr Handle = Marshal.AllocHGlobal(Marshal.SizeOf(BlurPara));
Marshal.StructureToPtr(BlurPara, Handle, true);
GdipSetEffectParameters(BlurEffect, Handle, (uint)Marshal.SizeOf(BlurPara));
// 准备参数
IntPtr scrImagePointer = image.NativeHandle(); // 原图像的句柄
Rectangle newImageRect = new Rectangle(Rect.Location, Rect.Size); // 创建一个和要处理的范围同样尺寸的 Rectangle
IntPtr newImagePointer = IntPtr.Zero; //GdipBitmapApplyEffect(image.NativeHandle(), BlurEffect, ref Rect, false, IntPtr.Zero, 0);
// 使用GdipBitmapCreateApplyEffect函数可以不改变原始的图像,而把模糊的结果写入到一个新的图像中
int ok = GdipBitmapCreateApplyEffect(ref scrImagePointer, , BlurEffect, ref Rect,ref newImageRect,out newImagePointer, false, IntPtr.Zero, ); if (ok == ) // 成功
{
// 执行后,newImagePointer 应不为 IntPtr.Zero
if (newImagePointer != IntPtr.Zero)
{
newImage = newImagePointer.NativeBitmapPtrToBitmap();
}
} GdipDeleteEffect(BlurEffect);
Marshal.FreeHGlobal(Handle);
}
else
{
throw new ExternalException("不支持的GDI+版本,必须为GDI+1.1及以上版本,且操作系统要求为Win Vista及之后版本.");
}
return newImage;
}

下面是函数运行完,负责将处理后的数据“赋值”到新的图像的两个俺不懂的方法

         /// <summary>
/// Gets a Bitmap object for a native GDI+ bitmap handle.
/// </summary>
/// <param name="nativeBitmap">The native handle to get the bitmap for.</param>
/// <returns>A Bitmap.</returns>
public static Bitmap NativeBitmapPtrToBitmap(this IntPtr nativeBitmap)
{
return typeof(Bitmap).InvokeStaticPrivateMethod<Bitmap>("FromGDIplus", nativeBitmap);
} /// <summary>
/// Invokes a non-public static method for a Type.
/// </summary>
/// <typeparam name="TResult">The return type of the static method.</typeparam>
/// <param name="type">The Type to invoke the static method for.</param>
/// <param name="methodName">The name of the static method.</param>
/// <param name="args">The arguments for the static method.</param>
/// <returns>The return value of the static method.</returns>
/// <exception cref="System.InvalidOperationException">Static method could not be located.</exception>
public static TResult InvokeStaticPrivateMethod<TResult>(this Type type, string methodName, params object[] args)
{
MethodInfo lmiInfo = type.GetMethod(methodName,
BindingFlags.Static | BindingFlags.NonPublic); if (lmiInfo != null)
return (TResult)(lmiInfo.Invoke(null, args));
else
throw new InvalidOperationException(
string.Format(
"Static method '{0}' could not be located in object type '{1}'.",
methodName, type.FullName));
}

三个函数配合后,就会得到一个新的经过高斯模糊的图像,看 MSDN 介绍,有个很重要的四儿:经过“GdiBitmapCreateApplyEffect()”会返回一个指向新图像的指针对象,在资源不用时需要手动进行释放,我的方法里还没有添加完善的释放资源的逻辑,回头还需要研究研究。原文地址是:http://msdn.microsoft.com/en-us/library/windows/desktop/ms536320(v=vs.85).aspx

运行后

哞哞快的 C# 高斯模糊实现(续)的更多相关文章

  1. 哞哞快的 C# 高斯模糊实现

    冲动来自于 bing best 这个小工具,非常短小精干,里边的设置界面非常精美而且背景是一张模糊效果的图片,十分养眼,遂想,收集一下实现方式放到类库里以后肯定用得上.一通百度.谷歌.博客园,换了好多 ...

  2. 安装python sklearn经验总结

    1. 需要安装 numpy, scipy, 和sklearn和ipython,Cython sklearn,ipython, Cython都可以通过pip来安装.但scipy,可能还有numpy必须通 ...

  3. v4l2驱动编写篇【转】

    转自:http://blog.csdn.net/michaelcao1980/article/details/53008418 大部分所需的信息都在这里.作为一个驱动作者,当挖掘头文件的时候,你可能也 ...

  4. Redis分布式锁的一点小理解

    1.在分布式系统中,我们使用锁机制只能保证同一个JVM中一次只有一个线程访问,但是在分布式的系统中锁就不起作用了,这时候就要用到分布式锁(有多种,这里指 redis) 2.在 redis当中可以使用命 ...

  5. 《Dotnet9》建站-记录建站过程中使用的一些网址

    时间如流水,只能流去不流回! 点赞再看,养成习惯,这是您给我创作的动力! 本文 Dotnet9 https://dotnet9.com 已收录,站长乐于分享dotnet相关技术,比如Winform.W ...

  6. DHCP服务——服务端 和 客户端 配置

    转载注明出处:https://www.cnblogs.com/kelamoyujuzhen/p/9520341.html  实验环境 rhel-server-6.4-x86_64-dvd(ED2000 ...

  7. .NET CORE下最快比较两个文件内容是否相同的方法 - 续

    .NET CORE下最快比较两个文件内容是否相同的方法 - 续 在上一篇博文中, 我使用了几种方法试图找到哪个是.NET CORE下最快比较两个文件的方法.文章发布后,引起了很多博友的讨论, 在此我对 ...

  8. [译]Godot系列教程三 - 场景实例化(续)

    场景实例化(续) 要点 场景实例化带来很多便利的用法,总体来说有: 将场景细分,更便于管理 相对于某些引擎中的Prefab组件更灵活,并且在许多方面更强大 是一种设计更复杂的游戏流程甚至UI的方式 这 ...

  9. 高斯模糊算法的 C++ 实现

    2008 年在一个 PS 讨论群里,有网友不解 Photoshop 的高斯模糊中的半径是什么含义,因此当时我写了这篇文章: 对Photoshop高斯模糊滤镜的算法总结: 在那篇文章中,主要讲解了高斯模 ...

随机推荐

  1. 阿里云server安全设定

    1.打开所有的服务云盾 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvamVkaWFlbF9sdQ==/font/5a6L5L2T/fontsize/400 ...

  2. HDU 1686 Oulipo(kmp)

    Problem Description The French author Georges Perec (1936–1982) once wrote a book, La disparition, w ...

  3. 使用SharePoint创建和定义自己的网站页面

    使用SharePoint创建和定义自己的网站页面 1. 打开SharePoint Designer 2010. 2. 点击网站页面导航. 3. 在功能区点击Web部件页面,新建Employee.axp ...

  4. 项目开发经常使用PHP功能

    日期操作 为了便于存储.比较和交付.我们通常使用strtotime()功能转换的日期UNIX时间戳.有仅用于在显示给用户时date()成经常使用的时间格式. strtotime()  函数将不论什么英 ...

  5. http层负载均衡之haproxy

    http层负载均衡之haproxy实践篇(一) 方案 上篇文章讲到了负载均衡的相关理论知识,这篇文章我打算讲讲实践方法以及实践中遇到的问题 方案:haproxy http层负载均衡 安装一个hapro ...

  6. DevExpress的Web控件汉化方法

    原文:DevExpress的Web控件汉化方法 项目中用到devexpress的web控件,机器没有安装devexpress控件,直接在项目中引用的dev的dll,项目运行时发现都是英文界面,所以解决 ...

  7. HDU 2544-最短路(最短路spfa)

    最短路 Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submis ...

  8. JAVA异常处理、常用类、反射、集合

    异常 异常:在Java中是指被一个方法抛出的对象. 分类:检查异常.运行时异常.错误 运行时异常(uncheckd):RuntimeException和其子类 检查异常(checkd/搜检异常):指E ...

  9. C#中使用REDIS

    C#中使用REDIS 上一篇>> 摘要 上一篇讲述了安装redis客户端和服务器端,也大体地介绍了一下redis.本篇着重讲解.NET4.0 和 .NET4.5中如何使用redis和C# ...

  10. C# 我的注册表操作类

    using System; using System.Collections.Generic; using System.Text; using Microsoft.Win32; using Syst ...