昨天刚写了《哞哞快的 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. Ubuntu下怎样切换到ROOT登录

    原文:http://james23dier.iteye.com/blog/721246 近期一直在学习linux,选择ubuntu作为联系的操作系统.然后一直发现自己所创建的用户和root用户不是一个 ...

  2. python_基础学习_03_正则替换文本(re.sub)

    python的正则表达式模块是re,替换相关的方法是sub. 例如我们要做如下的替换将所有的 替换为空格,可以通过下面代码实现: import re input = 'hello world' #第一 ...

  3. Openstack &amp; Hadoop结合项目Sahara

    Openstack 项目Sahara,主要是用来搭建Hadoop集群,利用虚拟出来的计算资源,高速搭建Hadoop集群. Sahara项目与OPenstack其它项目的关系: 图片转自:http:// ...

  4. JavaScript 奇技淫巧

    JavaScript 奇技淫巧 这里记录一下以前学习各种书籍和文章里边出现的JS的小技巧,分享给大家,也供自己查阅,同时感谢那些发现创造和分享这些技巧的前辈和大牛们. 1.遍历一个obj的属性到数组 ...

  5. ListView排序并隔色显示

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.C ...

  6. MySQL 升级方法指南大全

    原文:MySQL 升级方法指南大全 通常,从一个发布版本升级到另一个版本时,我们建议按照顺序来升级版本.例如,想要升级 MySQL 3.23 时,先升级到 MySQL 4.0,而不是直接升级到 MyS ...

  7. vim跳转

    w 跳到下一个单词的开始 e 跳到单词的结束 b 向后跳 gg 跳到文件的开始 G 跳到文件的结束 10gg 或10G 跳到第10行 ta 跳到下一个a 前面 fa 跳到下一个a 大写的意思相反 另外 ...

  8. poj 3273 Monthly Expense (二分)

    //最大值最小 //天数的a[i]值是固定的 不能改变顺序 # include <algorithm> # include <string.h> # include <s ...

  9. SOA面向服务架构

    SOA面向服务架构 风尘浪子 只要肯努力,梦想总有一天会实现 随笔分类 - SOA面向服务架构 结合领域驱动设计的SOA分布式软件架构 摘要: 领域驱动设计DDD的总体结构,Repository层使用 ...

  10. PHP 15:异常

    原文:PHP 15:异常 看完了out_put_fns.php文件,让我们再看看db_fns.php文件.其代码非常简单,如下:    ?> 其作用是连接数据库,并返回一个数据库连接.在这里我们 ...