昨天刚写了《哞哞快的 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. ABP入门教程

    ABP入门教程 ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)”的简称. ASP.NET Boilerplate是一个用最佳实践和流行技术开发现代WEB应 ...

  2. 浅谈JavaScript中的柯里化函数

    首先,不可避免的要引经据典啦,什么是柯里化函数呢(from baidu): 在计算机科学中,柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返 ...

  3. C#中的Params、ref、out的区别

    C# Params params params 关键字可以指定在参数数目可变处采用参数的方法参数. 在方法声明中的 params 关键字之后不允许任何其他参数,并且在方法声明中只允许一个 params ...

  4. 内置在虚拟机上64位操作系统:该主机支持 Intel VT-x,但 Intel VT-x 残

    VT-Virtual Technology. 在这里特别说一下:虚拟64位操作系统,须要特别在BIOS中打开VT支持.怎样提示:此主机不支持Intel VT-x,则不可能虚拟出64位系统. 当提示:此 ...

  5. hdu1848 Fibonacci again and again(SG游戏功能)

    现在的变化是看不清楚SG功能什么寻求方法 临时模板标题是首当 性能mex1它正在寻求g(x) 然后XOR #include<cstdio> #include<iostream> ...

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

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

  7. Thrift官方安装手冊(译)

    本篇是Thrift官网安装文档的翻译,原地址点击这里.Thrift之前是不支持Windows的.可是似乎0.9版本号以后已经支持Window了.介绍了Thrift安装的环境要求以及在centos,De ...

  8. Oracle SQL in 超过1000 的解决方案

    处理 Oracle SQL in 超过1000 的解决方案 处理oracle sql 语句in子句中(where id in (1, 2, ..., 1000, 1001)),如果子句中超过1000项 ...

  9. java ResultSet 结果集处理 createStatement() 里参数的意义(第一弹)

    createStatement(int   resultSetType,int  resultSetConcurrency)参数一:结果集类型可取值:  1.ResultSet.TYPE_FORWOR ...

  10. Appium Android Bootstrap源码分析之启动运行

    通过前面的两篇文章<Appium Android Bootstrap源码分析之控件AndroidElement>和<Appium Android Bootstrap源码分析之命令解析 ...