The b.GetPixel
call in this method is pretty slow, is there a way to speed this method up with LockBits or something? But I don't know how to work with pointers to get the pixel value etc.
Background: I need the float[][]
because of weighted randomizing I asked in this question.
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();
}
EDIT
As mentioned below from Paul Sasik I changed the code to this:
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];
}
}
And I checked the performance with a profiler before and after that optimization:
It's interesting that getHeight
takes a lot of time so it seems not to be cached in the bitmap object? Because of that I stored Width and Height in the struct as well.
But the result can't be, can it? I mean the bottleneck is still GetPixel
but why is that taking more time now? I didn't change anything else, the underlying bitmap is still the same.
EDIT2
Ok, found it: The problem was surprisingly the removal of the new Bitmap
so I added it again:
public static GrayScaleResult ConvertToGrayScale(this Bitmap b)
{
var bm = new Bitmap(b);
var result = new GrayScaleResult(bm);
...
And now the Code is optimized: