【转】【WPF】wpf 图片指针处理
我一直用GDI+做Winform 的基于指针的图片处理,这次下决心全部移到wpf上(主要是显示布局很方便)
采用的图片是
2512*3307 的大图 830万像素
类库基于WritableBitmapEx 的wpf版本
函数是我自己写的扩展方法,只是利用了 writableBitmapEx提供的环境 ,我懒得从头到尾自己写了
1.标准int32数组遍历计算 release
0.28s
public unsafe static void TestGray1(WriteableBitmap bmp)
{
using (var context = bmp.GetBitmapContext())
{
int height = context.Height;
int width = context.Width;
for (int y = ; y < height; y++)
{
for (int x = ; x < width; x++)
{
int pos = y * context.Width + x;
var c = context.Pixels[pos];
var r = (byte)(c >> );
var g = (byte)(c >> );
var b = (byte)(c); var gray = ((r * + g * + b * ) >> ); var color = ( << ) | (gray << ) | (gray << ) | gray;
context.Pixels[pos] = color;
}
}
}
}
2.标准int32指针遍历计算 release
0.04s
public unsafe static void TestGray2(WriteableBitmap bmp)
{
using (var context = bmp.GetBitmapContext())
{
var ptr = context.Pixels;
int height = context.Height;
int width = context.Width;
for (int y = ; y < height; y++)
{
for (int x = ; x < width; x++)
{
var c = *ptr;
var r = (byte)(c >> );
var g = (byte)(c >> );
var b = (byte)(c); var gray = ((r * + g * + b * ) >> ); var color = ( << ) | (gray << ) | (gray << ) | gray;
*ptr = color; ptr++;
}
}
}
}
3.colorstruct指针 遍历计算
0.02 s
应该是已经到极限速度了[除了后面的并行方式],我已经想不出还有什么方法可以提高处理速度
而且这种方式是最直观的,最容易理解的处理方式,也便于以后维护
[StructLayout(LayoutKind.Sequential)]
public struct PixelColor
{
public byte Blue;
public byte Green;
public byte Red;
public byte Alpha;
}
public unsafe static void TestGray3(WriteableBitmap bmp)
{
using (var context = bmp.GetBitmapContext())
{
var ptr = (PixelColor*)context.Pixels; int height = context.Height;
int width = context.Width;
for (int y = ; y < height; y++)
{
for (int x = ; x < width; x++)
{
var c = *ptr;
var gray = ((c.Red * + c.Green * + c.Blue * ) >> );
(*ptr).Green=(*ptr).Red=(*ptr).Blue = (byte)gray; ptr++;
}
}
}
}
4.作为对比,我又测试了一下 GDI+的 指针处理图片的速度
0.06s
public static unsafe Bitmap ToGray(Bitmap img)
{
var rect = new System.Drawing.Rectangle(, , img.Width, img.Height);
var data = img.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
var ptr = (ColorType*)data.Scan0.ToPointer();
var bytes = new Int32[img.Width * img.Height];
var height = img.Height;
var width = img.Width;
for (int y = ; y < height; y++)
{
for (int x = ; x < width; x++)
{
var color = *ptr;
var gray = ((color.R * + color.G * + color.B * ) >> ); (*ptr).R = (*ptr).G = (*ptr).B = (byte)gray; ptr++;
}
}
img.UnlockBits(data);
return img;
}
5.重头戏来了。我一直对Parallel.For 很迷惑,为什么他的消耗时间是普通for的好几倍。今天仔细研究了一下,发现原来是用错了
0.01秒 release
笔记本i5cpu,如果台式机的I7会更加强悍,速度会成半成半降低。
主要是利用了微软的任务并行库的循环并行化的方法。
注意:默认的并行循环对于函数体很小的情况是很慢的,这种情况必须用Partitioner 创建循环体,这在MSDN有介绍,是关键之中的关键
public unsafe static void TestGray5(WriteableBitmap bmp)
{
using (var context = bmp.GetBitmapContext())
{
int height = context.Height;
int width = context.Width; Parallel.ForEach(Partitioner.Create(, height), (h) =>
{
var ptr = (PixelColor*)context.Pixels;
ptr += h.Item1 * width; for (int y = h.Item1; y < h.Item2; y++)
{
for (int x = ; x < width; x++)
{
var c = *ptr;
var gray = ((c.Red * + c.Green * + c.Blue * ) >> );
(*ptr).Green = (*ptr).Red = (*ptr).Blue = (byte)gray; ptr++;
}
} }); }
}
感想
1.绝对不要在循环体内使用属性或函数,很有可能会降低数倍计算速度。
因为属性本质上是个函数,而在循环体内最好不要再调用函数,如果确实需要用内联代码的方式,c#没有inline,那么copy代码吧,反正为了速度。
2. 用指针移位操作 似乎比 直接数组访问要快10倍啊
我感觉要么是cache命中的原因,要么是 数组本身存取被属性封装了。相当于又调用了函数。
3.TPL 任务并行库果真好用,看来微软早已考虑过大量数据并行的循环优化问题09年,只是我一直用错了方法,才觉得很慢。
摘自 苦力熊
原文地址:http://www.2cto.com/kf/201204/129454.html
【转】【WPF】wpf 图片指针处理的更多相关文章
- WPF 把图片分割成两份自动翻页 WpfFlipPageControl:CtrlBook 书控件
原文:WPF 把图片分割成两份自动翻页 WpfFlipPageControl:CtrlBook 书控件 版权声明:本文为博主原创文章,需要转载尽管转载. https://blog.csdn.net/z ...
- [WPF]自定义鼠标指针
原文:[WPF]自定义鼠标指针 [WPF]自定义鼠标指针 周银辉 看看WPF Cursor类的两个构造函数吧: * f)); g.Flush(); g.D ...
- C# WPF 显示图片和视频显示 EmuguCv、AForge.Net测试(续)
介绍 本文是接着上文<C# WPF 显示图片和视频显示 EmuguCv.AForge.Net测试>写的,建议先看下上文,因为有些代码还需要了解. 增添 接着上文的代码,我们可以在事件处理方 ...
- WPF显示图片
1.WPF显示图片内部一部分 <Rectangle Height="> <Rectangle.Fill > <ImageBrush ImageSource=&q ...
- Silverlight或WPF动态绑定图片路径问题,不用Converter完美解决
关于Silverlight或WPF动态绑定图片路径问题,不用Converter完美解决, 可想,一个固定的字符串MS都能找到,按常理动态绑定也应该没问题的,只需在前面标记它是一个Path类型的值它就能 ...
- WPF 修改图片颜色
原文:WPF 修改图片颜色 本文告诉大家如何修改图片的颜色,如去掉图片的蓝色 在 WPF 可以使用很多图片处理的方法,本文告诉大家的是一个图片处理,可以把处理的图片保存在文件. 在阅读本文,我假设大家 ...
- 使用WPF将图片转变为灰度并加上水印并保存为文件
原文:使用WPF将图片转变为灰度并加上水印并保存为文件 运行效果: (上图中左下角为原图的缩小显示,By:Johnson为TextBlock)保存的结果图片:上图的"Test Words.& ...
- WPF 将图片进行灰度处理
原文:WPF 将图片进行灰度处理 处理前: 处理后: 这个功能使用使用了 FormatConvertedBitmap(为BitmapSource提供像素格式转换功能) 代码如下: ...
- [WPF]获取鼠标指针下的元素
原文:[WPF]获取鼠标指针下的元素 [WPF]获取鼠标指针下的元素 周银辉 以前写过一些GetElementUnderMouse之类的函数,要用到坐标换算而显得有些麻烦(特别是当元素有XXXTr ...
- WPF 自定义图片剪切器 - 头像剪切(扩展与完善、实时截图)
原文:WPF 自定义图片剪切器 - 头像剪切(扩展与完善.实时截图) 一.说明:上一次写的"WPF 自定义图片剪切器 - 头像剪切.你懂得"存在明显的缺陷,由于篇幅较长.重新写了一 ...
随机推荐
- How to Get SharePoint Client Context in SharePoint Apps (Provider Hosted / SharePoint Access ) in CSOM (Client Side Object Model)
http://www.codeproject.com/Articles/581060/HowplustoplusGetplusSharePointplusClientplusContex Downlo ...
- SharePoint 2010 ——自定义上传页面与多文件上传解决方案
最近项目遇到一个很麻烦的问题,原以为很容易解决,结果搞了那么久,先开个头,再慢慢写 SharePoint 2010 ——自定义上传页面与多文件上传解决方案 1.创建Sharepoint空白项目,创建应 ...
- 2015年第4本(英文第3本):Godfather教父
2015年的第4本书,第3本英文书. 书名:Godfather ,中文书名<教父> 作者: Mario Puzo 单词数:17万 词汇量:1万 首万词不重复词数:2200(这个我不太相信) ...
- 多种cell混合使用
有时候我们会碰到一个tableView上有多种cell,这个时候就需要定义多种cell,根据条件判断,当满足某个条件的时候选择某个cell 先看plist文件: Person.h #import &l ...
- git不常用命令
1.删除远程分支 git remote origin :分支名 [解释:意思是提交一个空分支到远程分支] ===持续更新
- 五种创建UIImage的类方法
五种创建UIImage的类方法 UIImage有五个类方法,用来创建UIImage的.下面介绍一下每个类方法的作用和创建实例. 1.使用类方法imageNamed:创建 + (UIImage *)im ...
- 关于移动端click事件绑定的一个细节
click是最常见的点击事件,但是对于移动终端,比如手机,一般都是以touch事件代替的,而click事件在手机也是生效的,只是会有1-2秒左右的延迟,那么当你想要用click而非touch事件的时候 ...
- 使用OLE DB读写Excel
说明: 使用这种技术的好处是无需引用对象,坏处是无法处理类似合并单元格这样的复杂情况 一些更新: 为了使用Office 2010,需要安装Microsoft Access 2010 数据库引擎可再发行 ...
- SAM4E单片机之旅——15、触屏输入与SPI通信
开发板上配了一个电阻触摸屏,它的控制器是ADS7843,使用SPI进行通信.这次实现的功能是通过SPI接口与该控制器交互,获取触摸屏点击的坐标,并显示在LCD上.略为难点的是SPI作为同步时钟的一种, ...
- POI教程之第二讲:创建一个时间格式的单元格,处理不同内容格式的单元格,遍历工作簿的行和列并获取单元格内容,文本提取
第二讲 1.创建一个时间格式的单元格 Workbook wb=new HSSFWorkbook(); // 定义一个新的工作簿 Sheet sheet=wb.createSheet("第一个 ...