我一直用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 图片指针处理的更多相关文章

  1. WPF 把图片分割成两份自动翻页 WpfFlipPageControl:CtrlBook 书控件

    原文:WPF 把图片分割成两份自动翻页 WpfFlipPageControl:CtrlBook 书控件 版权声明:本文为博主原创文章,需要转载尽管转载. https://blog.csdn.net/z ...

  2. [WPF]自定义鼠标指针

    原文:[WPF]自定义鼠标指针 [WPF]自定义鼠标指针 周银辉 看看WPF Cursor类的两个构造函数吧:  * f));            g.Flush();            g.D ...

  3. C# WPF 显示图片和视频显示 EmuguCv、AForge.Net测试(续)

    介绍 本文是接着上文<C# WPF 显示图片和视频显示 EmuguCv.AForge.Net测试>写的,建议先看下上文,因为有些代码还需要了解. 增添 接着上文的代码,我们可以在事件处理方 ...

  4. WPF显示图片

    1.WPF显示图片内部一部分 <Rectangle Height="> <Rectangle.Fill > <ImageBrush ImageSource=&q ...

  5. Silverlight或WPF动态绑定图片路径问题,不用Converter完美解决

    关于Silverlight或WPF动态绑定图片路径问题,不用Converter完美解决, 可想,一个固定的字符串MS都能找到,按常理动态绑定也应该没问题的,只需在前面标记它是一个Path类型的值它就能 ...

  6. WPF 修改图片颜色

    原文:WPF 修改图片颜色 本文告诉大家如何修改图片的颜色,如去掉图片的蓝色 在 WPF 可以使用很多图片处理的方法,本文告诉大家的是一个图片处理,可以把处理的图片保存在文件. 在阅读本文,我假设大家 ...

  7. 使用WPF将图片转变为灰度并加上水印并保存为文件

    原文:使用WPF将图片转变为灰度并加上水印并保存为文件 运行效果: (上图中左下角为原图的缩小显示,By:Johnson为TextBlock)保存的结果图片:上图的"Test Words.& ...

  8. WPF 将图片进行灰度处理

    原文:WPF 将图片进行灰度处理 处理前:      处理后:   这个功能使用使用了 FormatConvertedBitmap(为BitmapSource提供像素格式转换功能)   代码如下:   ...

  9. [WPF]获取鼠标指针下的元素

    原文:[WPF]获取鼠标指针下的元素   [WPF]获取鼠标指针下的元素 周银辉 以前写过一些GetElementUnderMouse之类的函数,要用到坐标换算而显得有些麻烦(特别是当元素有XXXTr ...

  10. WPF 自定义图片剪切器 - 头像剪切(扩展与完善、实时截图)

    原文:WPF 自定义图片剪切器 - 头像剪切(扩展与完善.实时截图) 一.说明:上一次写的"WPF 自定义图片剪切器 - 头像剪切.你懂得"存在明显的缺陷,由于篇幅较长.重新写了一 ...

随机推荐

  1. MySQL数据库中字符集的问题

    今天在做Hibernate案例,往mysql中写记录的时候,出现ERROR: Incorrect string value: '\xE5\x8A\xA0\xE5\x86\x85...' for col ...

  2. Python基础(9)--正则表达式

    正则表达式是一个很有用的工具,可处理复杂的字符匹配和替换工作.在Python中内置了一个re模块以支持正则表达式. 正则表达式有两种基本的操作,分别是匹配和替换. 匹配就是在一个文本字符串中搜索匹配一 ...

  3. IOS客户端Coding项目记录(五)

    1:统一修改导航栏的样式,在 AppDelegate.m中 - (BOOL)application:(UIApplication *)application didFinishLaunchingWit ...

  4. IOS 网络浅析-(八 NSURLSession简介)

    就在不长也不短的时间前,苹果正式命令咱们要向NSURLSession看,因此我们不得不认认真真的听从老大的教导,努力认知NSURLSession.其实呢,三方早已为我们解决了问题,但是呢,我们还是有必 ...

  5. CocoaPods的使用

    一.安装Cocoapods步骤:(在终端安装) 1.在安装前,需确保已经安装了Ruby环境 mac 下安装Ruby环境步骤: (1).安装RVM $ curl -L https://get.rvm.i ...

  6. Swift55个协议的分类和讲解分析

    首先我只想问:为什么是协议?为什么面向协议编程?如果我们回到过去那段年少无知少不更事的面相对象编程时期,我们很多人最初学习的是Objective-C,这意味着我们免受多继承的专横.又或者你是这个房间里 ...

  7. 开源项目go2o - golang版的o2o项目

    发一个github上唯一用golang实现的o2o项目 What's Go2o Golang combine simple o2o DDD domain-driven design realizati ...

  8. javascript 特效实现(3)—— 鼠标滑过显示二级菜单效果

    1. 关键代码:使用 switch 或 if 判断语句,改变对应的二级菜单显示方式为 block 或 none function selectTabMenu(i){ switch(i){ case 7 ...

  9. Hadoop 1.0 和 2.0 中的数据处理框架 - MapReduce

    1. MapReduce - 映射.化简编程模型 1.1 MapReduce 的概念 1.1.1 map 和 reduce 1.1.2 shufftle 和 排序 MapReduce 保证每个 red ...

  10. OpenXml入门----给Word文档添加表格

    下面将展示如何使用Openxm向Word添加表格. 代码中表头和数据我用的同一个TableRow来添加,其实可以通过TableHeader来,其实都一样.后面教程我会给出如何设置单元格样式.表头那一行 ...