有效填充字节数组的更快方法是什么?每个字节代表一个Bitmap类的像素(黑色或白色:<125 =黑色,> 125 =白色)?
我用它来制作彩色图像:Better/faster way to fill a big array in C#
然而现在我正在寻找不同的东西(我甚至可以使用像Red这样的单一颜色来填充它,这无关紧要只是我应该选择的东西),因为数组格式发生了变化。
有什么建议吗?实际上我正在使用这个代码,这显然不是最好的主意
for (int x = 0; x < LgLcd.NativeConstants.LGLCD_BMP_WIDTH; ++x)
{
for (int y = 0; y < LgLcd.NativeConstants.LGLCD_BMP_HEIGHT; ++y)
{
tmp = bmp.GetPixel(x, y);
array[y * LgLcd.NativeConstants.LGLCD_BMP_WIDTH + x] = (byte)((tmp.R == 255 && tmp.G == 255 && tmp.B == 255) ? 0 : 255);
//array[y * x] = (byte)0;
}
}
我的想法是将所有内容并行化(是的,每行可能有1个帖子?(或每列)),这应该对我有所帮助。
修改
好的,首先,我需要一种方法可以同时访问图像的不同字节,Brandon Moretz建议使用lockbits访问字节的正确方法。但是,我想避免使用不安全的代码。 Lockbits是否涉及不安全的代码?
其次,我对并行化的想法是使用Parallel.For。这个方法应该使用ThreadPool类,它将使用不大于你的cpu核心的线程数量,并且它们是预先分配的。
这种方法会被调用很多次,所以我认为这不是一个大麻烦,因为线程池在第一次调用后会被大量使用。
我说的是对的吗?
答案 0 :(得分:3)
使用“不安全”代码阻止选项吗?您可以在位图上使用LockBits来获取BitmapData,然后使用Scan0&amp;跨越属性以迭代它。
如果它是255种颜色,我假设每个像素有一个字节,所以就像这样:
*( ( ( byte* )bmpData.Scan0 ) + ( y * bmpData.Stride ) + x ) = (byte)((tmp.R == 255 && tmp.G == 255 && tmp.B == 255) ? 0 : 255);
答案 1 :(得分:1)
一般方法是将图像划分为区域然后处理。即你可以使用:
线程1)for (int x = 0; x < LGLCD_BMP_WIDTH /2; ++x) { ... }
线程2)for (int x = LGLCD_BMP_WIDTH / 2; x < LGLCD_BMP_WIDTH; ++x) { ... }
您将有两半图像由不同的线程处理。您可以根据需要进一步划分为4,8等。每行的一个线程将是多余的,因为线程创建开销将大大超过好处。
答案 2 :(得分:1)
我自己找到了答案,使用了lockbits和Marshal.ReadByte并获得了非常好的快速结果:
public void SetPixels(Bitmap image)
{
byte[] array = Pixels;
var data = image.LockBits(new Rectangle(0, 0, image.Width, image.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
Parallel.For(0, data.Height, new Action<int>(i =>
{
byte tmp;
int pixel4bpp, pixelPerbpp;
pixelPerbpp = data.Stride / data.Width;
for (pixel4bpp = 0; pixel4bpp < data.Stride; pixel4bpp += pixelPerbpp)
{
tmp = (byte)((
Marshal.ReadByte(data.Scan0, 0 + (data.Stride * i) + pixel4bpp)
+ Marshal.ReadByte(data.Scan0, 1 + (data.Stride * i) + pixel4bpp)
+ Marshal.ReadByte(data.Scan0, 2 + (data.Stride * i) + pixel4bpp)
+ Marshal.ReadByte(data.Scan0, 3 + (data.Stride * i) + pixel4bpp)
) / pixelPerbpp);
array[i * data.Width + (pixel4bpp / pixelPerbpp)] = tmp;
}
}));
image.UnlockBits(data);
}