Optimization of unsafe code
-
Hi, I have the following code in an unsafe section of code:
//...
int scan0 = data.Scan0.ToInt32();byte * colPixel;
byte * rowPixel;byte innerColorB = innerColor.B;
byte innerColorG = innerColor.G;
byte innerColorR = innerColor.R;
byte innerColorA = innerColor.A;int stride = data.Stride;
for (int y = 0; y < height; y ++)
{
rowPixel = (byte *)(scan0 + y * stride);
for (int x = 0; x < width; x++)
{
colPixel = rowPixel + 4 * x;
*colPixel = innerColorB;
*(colPixel + 1) = innerColorG;
*(colPixel + 2) = innerColorR;
*(colPixel + 3) = innerColorA;
}
}
//...I'm basically setting all pixels of a bitmap to a specified color. I know I could use the FillRectangle function but I don't want to :). My question is if anyone here might have an idea how this could be performed better/faster.
-
Hi, I have the following code in an unsafe section of code:
//...
int scan0 = data.Scan0.ToInt32();byte * colPixel;
byte * rowPixel;byte innerColorB = innerColor.B;
byte innerColorG = innerColor.G;
byte innerColorR = innerColor.R;
byte innerColorA = innerColor.A;int stride = data.Stride;
for (int y = 0; y < height; y ++)
{
rowPixel = (byte *)(scan0 + y * stride);
for (int x = 0; x < width; x++)
{
colPixel = rowPixel + 4 * x;
*colPixel = innerColorB;
*(colPixel + 1) = innerColorG;
*(colPixel + 2) = innerColorR;
*(colPixel + 3) = innerColorA;
}
}
//...I'm basically setting all pixels of a bitmap to a specified color. I know I could use the FillRectangle function but I don't want to :). My question is if anyone here might have an idea how this could be performed better/faster.
Robert Rohde wrote:
int scan0 = data.Scan0.ToInt32();
I don't lint the look of this. I always turn it into a byte * from the get go. I'm not sure if C# will magically deal with 64 bit, where this code would be wrong. I think the way I do it is faster, which is to create a byte * out of scan0, then keep adding to it as I go, instead of calculating the position every time. You should read my image processing articles on this site, they all do it the same way. Christian Graus - Microsoft MVP - C++
-
Robert Rohde wrote:
int scan0 = data.Scan0.ToInt32();
I don't lint the look of this. I always turn it into a byte * from the get go. I'm not sure if C# will magically deal with 64 bit, where this code would be wrong. I think the way I do it is faster, which is to create a byte * out of scan0, then keep adding to it as I go, instead of calculating the position every time. You should read my image processing articles on this site, they all do it the same way. Christian Graus - Microsoft MVP - C++
Thanks for your help. Now it performes a bit better (although not really significant):
byte * p = (byte *)(void *)data.Scan0;
int nOffset = data.Stride - bitmap.Width * 4;
for (int y = 0; y < height; ++y)
{
for (int x = 0; x < width; ++x)
{
p[0] = innerColorB;
p[1] = innerColorG;
p[2] = innerColorR;
p[3] = innerColorA;
p += 4;
}
p += nOffset;
}Isn't there a way to set a bunch of bytes in one step instead of having to move through each pixel? As I said the whole bitmap should be filled with one color. Is there a way to prepare a byte array or something containing all bytes for one row and than just copying it y times?
-
Thanks for your help. Now it performes a bit better (although not really significant):
byte * p = (byte *)(void *)data.Scan0;
int nOffset = data.Stride - bitmap.Width * 4;
for (int y = 0; y < height; ++y)
{
for (int x = 0; x < width; ++x)
{
p[0] = innerColorB;
p[1] = innerColorG;
p[2] = innerColorR;
p[3] = innerColorA;
p += 4;
}
p += nOffset;
}Isn't there a way to set a bunch of bytes in one step instead of having to move through each pixel? As I said the whole bitmap should be filled with one color. Is there a way to prepare a byte array or something containing all bytes for one row and than just copying it y times?
I've not found a memcpy type function or a memset, for that matter, in the framework. However, given that the color does not change, you could turn the RGBA values into an int, and then set it in one step for each pixel. nOffset will also be a multiple of 4, so you could set the pointer to be an int * all the way through, instead of having to cast it, just make sure you divide nOffset by 4 to match. Christian Graus - Microsoft MVP - C++