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

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

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

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

  1. /// <summary>
  2. /// 使用高斯模糊效果创建一个新的图像
  3. /// </summary>
  4. /// <returns></returns>
  5. public static Bitmap CreateNewWithEffect(this Bitmap image, ref Rectangle Rect, float Radius = , bool ExpandEdge = false)
  6. {
  7. // 新图像
  8. Bitmap newImage = new Bitmap(image);
  9.  
  10. int Result;
  11. IntPtr BlurEffect;
  12. BlurParameters BlurPara;
  13. if ((Radius < ) || (Radius > ))
  14. {
  15. throw new ArgumentOutOfRangeException("Radius 参数错误,半径必须在 [0,255] 范围内");
  16. }
  17. BlurPara.Radius = Radius;
  18. BlurPara.ExpandEdges = ExpandEdge;
  19. Result = GdipCreateEffect(BlurEffectGuid, out BlurEffect);
  20.  
  21. if (Result == )
  22. {
  23. IntPtr Handle = Marshal.AllocHGlobal(Marshal.SizeOf(BlurPara));
  24. Marshal.StructureToPtr(BlurPara, Handle, true);
  25. GdipSetEffectParameters(BlurEffect, Handle, (uint)Marshal.SizeOf(BlurPara));
  26. // 准备参数
  27. IntPtr scrImagePointer = image.NativeHandle(); // 原图像的句柄
  28. Rectangle newImageRect = new Rectangle(Rect.Location, Rect.Size); // 创建一个和要处理的范围同样尺寸的 Rectangle
  29. IntPtr newImagePointer = IntPtr.Zero;
  30.  
  31. //GdipBitmapApplyEffect(image.NativeHandle(), BlurEffect, ref Rect, false, IntPtr.Zero, 0);
  32. // 使用GdipBitmapCreateApplyEffect函数可以不改变原始的图像,而把模糊的结果写入到一个新的图像中
  33. int ok = GdipBitmapCreateApplyEffect(ref scrImagePointer, , BlurEffect, ref Rect,ref newImageRect,out newImagePointer, false, IntPtr.Zero, );
  34.  
  35. if (ok == ) // 成功
  36. {
  37. // 执行后,newImagePointer 应不为 IntPtr.Zero
  38. if (newImagePointer != IntPtr.Zero)
  39. {
  40. newImage = newImagePointer.NativeBitmapPtrToBitmap();
  41. }
  42. }
  43.  
  44. GdipDeleteEffect(BlurEffect);
  45. Marshal.FreeHGlobal(Handle);
  46. }
  47. else
  48. {
  49. throw new ExternalException("不支持的GDI+版本,必须为GDI+1.1及以上版本,且操作系统要求为Win Vista及之后版本.");
  50. }
  51. return newImage;
  52. }

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

  1. /// <summary>
  2. /// Gets a Bitmap object for a native GDI+ bitmap handle.
  3. /// </summary>
  4. /// <param name="nativeBitmap">The native handle to get the bitmap for.</param>
  5. /// <returns>A Bitmap.</returns>
  6. public static Bitmap NativeBitmapPtrToBitmap(this IntPtr nativeBitmap)
  7. {
  8. return typeof(Bitmap).InvokeStaticPrivateMethod<Bitmap>("FromGDIplus", nativeBitmap);
  9. }
  10.  
  11. /// <summary>
  12. /// Invokes a non-public static method for a Type.
  13. /// </summary>
  14. /// <typeparam name="TResult">The return type of the static method.</typeparam>
  15. /// <param name="type">The Type to invoke the static method for.</param>
  16. /// <param name="methodName">The name of the static method.</param>
  17. /// <param name="args">The arguments for the static method.</param>
  18. /// <returns>The return value of the static method.</returns>
  19. /// <exception cref="System.InvalidOperationException">Static method could not be located.</exception>
  20. public static TResult InvokeStaticPrivateMethod<TResult>(this Type type, string methodName, params object[] args)
  21. {
  22. MethodInfo lmiInfo = type.GetMethod(methodName,
  23. BindingFlags.Static | BindingFlags.NonPublic);
  24.  
  25. if (lmiInfo != null)
  26. return (TResult)(lmiInfo.Invoke(null, args));
  27. else
  28. throw new InvalidOperationException(
  29. string.Format(
  30. "Static method '{0}' could not be located in object type '{1}'.",
  31. methodName, type.FullName));
  32. }

三个函数配合后,就会得到一个新的经过高斯模糊的图像,看 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. Swift的笔记和参考

    原文:Swift的笔记和参考 好久没来了,趁着新语言Swift发布,继续钻研中! Create Class 创建类 (多态效果) // Create Class 创建类 class MyClass { ...

  2. 【Python】Python与文本处理langid工具包的文本语言检测和歧视

    1.问题的叙述性说明 使用Python文本处理.文字有时被包括中国.英语.在日本和其他语言文字,进行处理.这个时候就须要判别当前文本是属于哪个语系的. Python中有个langid工具包提供了此功能 ...

  3. linux cat

    cut是一个选取命令,就是将一段数据经过分析,取出我们想要的.一般来说,选取信息通常是针对“行”来进行分析的,并不是整篇信息分析的. (1)其语法格式为:cut  [-bn] [file] 或 cut ...

  4. Windows服务之启动、停止、暂停、继续

    原文:Windows服务之启动.停止.暂停.继续 Windows服务之启动.停止.暂停.继续 2011-11-09 15:07:37     我来说两句 收藏    我要投稿    [字体:小 大] ...

  5. 推荐几个靠谱的VPN

    最近开发scala程序使用sbt构建工程时,下载很慢,有些依赖只能通过VPN才能下载下来.在网上搜索了一大堆提供VPN服务的.有一大部分不提供试用,而且还必须得按年购买,看起来是像骗子. 在这里推荐几 ...

  6. aspnet-webapi-2-contrib

    https://github.com/rdingwall/protobuf-net-data https://github.com/mgravell/protobuf-net https://gith ...

  7. SQL点滴3—一个简单的字符串分割函数

    原文:SQL点滴3-一个简单的字符串分割函数 偶然在电脑里看到以前保存的这个函数,是将一个单独字符串切分成一组字符串,这里分隔符是英文逗号“,”  遇到其他情况只要稍加修改就好了 CREATE FUN ...

  8. HubbleDotNet全文搜索数据库组件(一)

    HubbleDotNet 简介及安装详解 2012-11-05 12:59 来源:9SSSD.COM 作者:starts_2000 字号:T|T [摘要]HubbleDotNet 是一个基于.net ...

  9. 证明中序遍历O(n)

    算法导论12.1 什么是二叉搜索树 二叉搜索树应满足的性质: 设x是二叉搜索树中的一个结点.如果y是x左子树中的一个结点,那么y.key <= x.key.如果y是右子树中的一个结点,那么y.k ...

  10. hadoop编程技巧(3)---定义自己的区划类别Partitioner

    Hadoop代码测试环境:Hadoop2.4 原则:在Hadoop的MapReduce过程.Mapper阅读过程完成后数据.它将数据发送到Partitioner.由Partitioner每个记录应当采 ...