【转】【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 = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
int pos = y * context.Width + x;
var c = context.Pixels[pos];
var r = (byte)(c >> 16);
var g = (byte)(c >> 8);
var b = (byte)(c);

var gray = ((r * 38 + g * 75 + b * 15) >> 7);

var color = (255 << 24) | (gray << 16) | (gray << 8) | 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 = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
var c = *ptr;
var r = (byte)(c >> 16);
var g = (byte)(c >> 8);
var b = (byte)(c);

var gray = ((r * 38 + g * 75 + b * 15) >> 7);

var color = (255 << 24) | (gray << 16) | (gray << 8) | 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 = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
var c = *ptr;
var gray = ((c.Red * 38 + c.Green * 75 + c.Blue * 15) >> 7);
(*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(0, 0, 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 = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
var color = *ptr;
var gray = ((color.R * 38 + color.G * 75 + color.B * 15) >> 7);

(*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(0, height), (h) =>
{
var ptr = (PixelColor*)context.Pixels;
ptr += h.Item1 * width;

for (int y = h.Item1; y < h.Item2; y++)
{
for (int x = 0; x < width; x++)
{
var c = *ptr;
var gray = ((c.Red * 38 + c.Green * 75 + c.Blue * 15) >> 7);
(*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

时间: 2024-10-10 04:04:19

【转】【WPF】wpf 图片指针处理的相关文章

WPF显示图片

1.WPF显示图片内部一部分 <Rectangle Height="12" Width="60"> <Rectangle.Fill > <ImageBrush ImageSource="Pic\icon_tubiao1.png" ViewboxUnits="Absolute" Viewbox="448,407,60,12"></ImageBrush> <

WPF(C#)图片色彩的纠正-上

WPF(C#)图片色彩的纠正-上 WPF(C#)图片色彩的纠正-下 前言 对图片进行色彩的纠正,其实与WPF是没有什么关系的,为什么标题又是“WPF(C#)图片色彩的纠正”呢,因为这些图片色彩的纠正功能都是承载在WPF界面上的,并且我也很想介绍一些关于WPF方面的知识,所以就命名了此标题. 这个软件的主要功能是通过设置Tint, BlackEnhance, ColorVibrancy, Automatic, Sharpen, Depth,Bias等参数来对图片的色彩进行纠正(参数属于专业领域词汇

WPF 无缝图片滚动

上图是效果  可以双方向拖动 废话不多说上代码 界面: 1 <Window x:Class="FlashPrac2.MainWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 Title="MainWindow&qu

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

关于Silverlight或WPF动态绑定图片路径问题,不用Converter完美解决, 可想,一个固定的字符串MS都能找到,按常理动态绑定也应该没问题的,只需在前面标记它是一个Path类型的值它就能找到了. 具体问题: 1.固定的图片路径是可以的,如下: <Image Source="../Assets/icons/large/1389966549_Analytics_two.png" /> 2.绑定的Path是一个String类型的图片路径,而实际情况它需要的是一个Im

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

原文:[WPF]获取鼠标指针下的元素   [WPF]获取鼠标指针下的元素 周银辉 以前写过一些GetElementUnderMouse之类的函数,要用到坐标换算而显得有些麻烦(特别是当元素有XXXTransform的时候) 今天看到Mouse类居然有一个DirectlyOver属性,可以获得鼠标下的元素, 很奇怪,我的MSDN文档以及VS2008智能提示中都没有显示该属性,但反编译一下可以看到. 但必须注意到的一点是,WPF控件是由各个元素复合而成的,但Mouse类可不知道这概念,所以不要期望它

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

原文:使用WPF将图片转变为灰度并加上水印并保存为文件 运行效果: (上图中左下角为原图的缩小显示,By:Johnson为TextBlock) 保存的结果图片:上图的"Test Words."为水印文字. XAML代码:<Window?xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"?xmlns:x="http://schemas.microsoft.com/winfx

WPF 修改图片颜色

原文:WPF 修改图片颜色 本文告诉大家如何修改图片的颜色,如去掉图片的蓝色 在 WPF 可以使用很多图片处理的方法,本文告诉大家的是一个图片处理,可以把处理的图片保存在文件. 在阅读本文,我假设大家是熟悉 WPF 的,至少了解 C# ,也知道图片的格式. 在 WPF 可以使用 ARBG 数组表示图片,本文修改图片颜色的方法就是使用 ARBG 数组的方法修改,修改里面的元素的值. 如我需要去掉图片的蓝色,就可以通过修改 ARBG 数组的元素,设置所有蓝色为 0 ,去掉蓝色. 读取图片 首先找到一

WPF 自定义图片按钮

原文:WPF 自定义图片按钮 此文档仅仅是一个BaseCode,已做后续查阅 XAML代码: <Button x:Class="IM.UI.UC.IM_ImageButton" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc=&qu

WPF的图片操作效果(一):RenderTransform

一.RenderTransform类的成员: 1.TranslateTransform 平移效果 2.RotateTransform 旋转效果 3.ScaleTransform       缩放效果 4.SkewTransform      扭转效果 5.TransformGroup 组合效果 6.MatrixTransform 是其他几个变形类的基类,矩阵方式实现效果 二.简单效果介绍 1.TranslateTransform 平移效果 <Image Source="logo.png&q