此方法中的b.GetPixel
调用非常慢,是否有办法使用LockBits或其他方法加快此方法的速度?但我不知道如何使用指针来获取像素值等。
背景:我需要float[][]
,因为我在this问题中询问了加权随机化。
public static float[][] ConvertToGrayScale(this Bitmap bm)
{
var b = new Bitmap(bm);
var data = new List<float[]>();
for (var i = 0; i < b.Width; i++)
{
var row = new List<float>();
for (int x = 0; x < b.Height; x++)
{
var oc = b.GetPixel(i, x);
var grayScale = (int)((oc.R * 0.3) + (oc.G * 0.59) + (oc.B * 0.11));
row.Add(grayScale);
}
data.Add(row.ToArray());
}
return data.ToArray();
}
修改
如Paul Sasik所述,我将代码更改为:
public static GrayScaleResult ConvertToGrayScale(this Bitmap bm)
{
var result = new GrayScaleResult(bm);
for (var x = 0; x < result.Width; x++)
{
for (int y = 0; y < result.Height; y++)
{
var oc = bm.GetPixel(x, y);
// casting to int here - you can just use a 2d array of ints
result.Data[x, y] = (int)((oc.R * 0.3) + (oc.G * 0.59) + (oc.B * 0.11));
}
}
return result;
}
public struct GrayScaleResult
{
public float[,] Data;
public int Width;
public int Height;
public GrayScaleResult(Bitmap bm)
{
Width = bm.Width;
Height = bm.Height;
Data = new float[Width, Height];
}
}
我在优化之前和之后使用分析器检查了性能:
有趣的是,getHeight
需要花费大量时间才能在位图对象中缓存?因此我也在结构中存储了Width和Height。
但结果不可能,可以吗?我的意思是瓶颈仍然是GetPixel
,但为什么现在花费更多时间呢?我没有改变任何其他内容,底层位图仍然是相同的。
EDIT2
好的,发现它:问题出乎意料地删除了new Bitmap
所以我再次添加了它:
public static GrayScaleResult ConvertToGrayScale(this Bitmap b)
{
var bm = new Bitmap(b);
var result = new GrayScaleResult(bm);
...
现在代码已优化:
答案 0 :(得分:2)
在尝试使用不安全的代码之前,您可以对当前代码进行一些优化:
public static float[,] ConvertToGrayScale2(this Bitmap bm)
{
var data = new float[bm.Width, bm.Height];
for (var i = 0; i < bm.Width; i++)
{
for (int x = 0; x < bm.Height; x++)
{
var oc = bm.GetPixel(i, x);
// casting to int here - you can just use a 2d array of ints
data[i, x] = (int)((oc.R * 0.3) + (oc.G * 0.59) + (oc.B * 0.11));
}
}
return data;
}
优化:
答案 1 :(得分:1)
为什么不预先创建阵列,而不是使用中间列表?您提前了解维度,因此可以保存为位图的每一行创建列表。这是我能发现的第一个明显的胜利。