哞哞快的 C# 高斯模糊实现(续)
昨天刚写了《哞哞快的 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# 高斯模糊实现(续)的更多相关文章
- 哞哞快的 C# 高斯模糊实现
冲动来自于 bing best 这个小工具,非常短小精干,里边的设置界面非常精美而且背景是一张模糊效果的图片,十分养眼,遂想,收集一下实现方式放到类库里以后肯定用得上.一通百度.谷歌.博客园,换了好多 ...
- 安装python sklearn经验总结
1. 需要安装 numpy, scipy, 和sklearn和ipython,Cython sklearn,ipython, Cython都可以通过pip来安装.但scipy,可能还有numpy必须通 ...
- v4l2驱动编写篇【转】
转自:http://blog.csdn.net/michaelcao1980/article/details/53008418 大部分所需的信息都在这里.作为一个驱动作者,当挖掘头文件的时候,你可能也 ...
- Redis分布式锁的一点小理解
1.在分布式系统中,我们使用锁机制只能保证同一个JVM中一次只有一个线程访问,但是在分布式的系统中锁就不起作用了,这时候就要用到分布式锁(有多种,这里指 redis) 2.在 redis当中可以使用命 ...
- 《Dotnet9》建站-记录建站过程中使用的一些网址
时间如流水,只能流去不流回! 点赞再看,养成习惯,这是您给我创作的动力! 本文 Dotnet9 https://dotnet9.com 已收录,站长乐于分享dotnet相关技术,比如Winform.W ...
- DHCP服务——服务端 和 客户端 配置
转载注明出处:https://www.cnblogs.com/kelamoyujuzhen/p/9520341.html 实验环境 rhel-server-6.4-x86_64-dvd(ED2000 ...
- .NET CORE下最快比较两个文件内容是否相同的方法 - 续
.NET CORE下最快比较两个文件内容是否相同的方法 - 续 在上一篇博文中, 我使用了几种方法试图找到哪个是.NET CORE下最快比较两个文件的方法.文章发布后,引起了很多博友的讨论, 在此我对 ...
- [译]Godot系列教程三 - 场景实例化(续)
场景实例化(续) 要点 场景实例化带来很多便利的用法,总体来说有: 将场景细分,更便于管理 相对于某些引擎中的Prefab组件更灵活,并且在许多方面更强大 是一种设计更复杂的游戏流程甚至UI的方式 这 ...
- 高斯模糊算法的 C++ 实现
2008 年在一个 PS 讨论群里,有网友不解 Photoshop 的高斯模糊中的半径是什么含义,因此当时我写了这篇文章: 对Photoshop高斯模糊滤镜的算法总结: 在那篇文章中,主要讲解了高斯模 ...
随机推荐
- Swift的笔记和参考
原文:Swift的笔记和参考 好久没来了,趁着新语言Swift发布,继续钻研中! Create Class 创建类 (多态效果) // Create Class 创建类 class MyClass { ...
- 【Python】Python与文本处理langid工具包的文本语言检测和歧视
1.问题的叙述性说明 使用Python文本处理.文字有时被包括中国.英语.在日本和其他语言文字,进行处理.这个时候就须要判别当前文本是属于哪个语系的. Python中有个langid工具包提供了此功能 ...
- linux cat
cut是一个选取命令,就是将一段数据经过分析,取出我们想要的.一般来说,选取信息通常是针对“行”来进行分析的,并不是整篇信息分析的. (1)其语法格式为:cut [-bn] [file] 或 cut ...
- Windows服务之启动、停止、暂停、继续
原文:Windows服务之启动.停止.暂停.继续 Windows服务之启动.停止.暂停.继续 2011-11-09 15:07:37 我来说两句 收藏 我要投稿 [字体:小 大] ...
- 推荐几个靠谱的VPN
最近开发scala程序使用sbt构建工程时,下载很慢,有些依赖只能通过VPN才能下载下来.在网上搜索了一大堆提供VPN服务的.有一大部分不提供试用,而且还必须得按年购买,看起来是像骗子. 在这里推荐几 ...
- aspnet-webapi-2-contrib
https://github.com/rdingwall/protobuf-net-data https://github.com/mgravell/protobuf-net https://gith ...
- SQL点滴3—一个简单的字符串分割函数
原文:SQL点滴3-一个简单的字符串分割函数 偶然在电脑里看到以前保存的这个函数,是将一个单独字符串切分成一组字符串,这里分隔符是英文逗号“,” 遇到其他情况只要稍加修改就好了 CREATE FUN ...
- HubbleDotNet全文搜索数据库组件(一)
HubbleDotNet 简介及安装详解 2012-11-05 12:59 来源:9SSSD.COM 作者:starts_2000 字号:T|T [摘要]HubbleDotNet 是一个基于.net ...
- 证明中序遍历O(n)
算法导论12.1 什么是二叉搜索树 二叉搜索树应满足的性质: 设x是二叉搜索树中的一个结点.如果y是x左子树中的一个结点,那么y.key <= x.key.如果y是右子树中的一个结点,那么y.k ...
- hadoop编程技巧(3)---定义自己的区划类别Partitioner
Hadoop代码测试环境:Hadoop2.4 原则:在Hadoop的MapReduce过程.Mapper阅读过程完成后数据.它将数据发送到Partitioner.由Partitioner每个记录应当采 ...