在 C# 中快速处理位图 [英] Fast work with Bitmaps in C#
问题描述
我需要访问位图的每个像素,处理它们,然后将它们保存到位图.
I need to access each pixel of a Bitmap, work with them, then save them to a Bitmap.
使用Bitmap.GetPixel()
和Bitmap.SetPixel()
,我的程序运行缓慢.
Using Bitmap.GetPixel()
and Bitmap.SetPixel()
, my program runs slowly.
如何快速将 Bitmap
转换为 byte[]
并返回?
How can I quickly convert Bitmap
to byte[]
and back?
我需要一个byte[]
,length = (4 * width * height)
,包含每个像素的RGBA数据.
I need a byte[]
with length = (4 * width * height)
, containing RGBA data of each pixel.
推荐答案
您可以通过几种不同的方式来实现.您可以使用 unsafe
直接访问数据,也可以使用封送处理来回复制数据.不安全代码速度更快,但封送处理不需要不安全代码.这是一个 性能对比我之前做过.
You can do it a couple of different ways. You can use unsafe
to get direct access to the data, or you can use marshaling to copy the data back and forth. The unsafe code is faster, but marshaling doesn't require unsafe code. Here's a performance comparison I did a while back.
这是一个使用锁定位的完整示例:
Here's a complete sample using lockbits:
/*Note unsafe keyword*/
public unsafe Image ThresholdUA(float thresh)
{
Bitmap b = new Bitmap(_image);//note this has several overloads, including a path to an image
BitmapData bData = b.LockBits(new Rectangle(0, 0, _image.Width, _image.Height), ImageLockMode.ReadWrite, b.PixelFormat);
byte bitsPerPixel = GetBitsPerPixel(bData.PixelFormat);
/*This time we convert the IntPtr to a ptr*/
byte* scan0 = (byte*)bData.Scan0.ToPointer();
for (int i = 0; i < bData.Height; ++i)
{
for (int j = 0; j < bData.Width; ++j)
{
byte* data = scan0 + i * bData.Stride + j * bitsPerPixel / 8;
//data is a pointer to the first byte of the 3-byte color data
//data[0] = blueComponent;
//data[1] = greenComponent;
//data[2] = redComponent;
}
}
b.UnlockBits(bData);
return b;
}
这是同样的事情,但有编组:
Here's the same thing, but with marshaling:
/*No unsafe keyword!*/
public Image ThresholdMA(float thresh)
{
Bitmap b = new Bitmap(_image);
BitmapData bData = b.LockBits(new Rectangle(0, 0, _image.Width, _image.Height), ImageLockMode.ReadWrite, b.PixelFormat);
/* GetBitsPerPixel just does a switch on the PixelFormat and returns the number */
byte bitsPerPixel = GetBitsPerPixel(bData.PixelFormat);
/*the size of the image in bytes */
int size = bData.Stride * bData.Height;
/*Allocate buffer for image*/
byte[] data = new byte[size];
/*This overload copies data of /size/ into /data/ from location specified (/Scan0/)*/
System.Runtime.InteropServices.Marshal.Copy(bData.Scan0, data, 0, size);
for (int i = 0; i < size; i += bitsPerPixel / 8 )
{
double magnitude = 1/3d*(data[i] +data[i + 1] +data[i + 2]);
//data[i] is the first of 3 bytes of color
}
/* This override copies the data back into the location specified */
System.Runtime.InteropServices.Marshal.Copy(data, 0, bData.Scan0, data.Length);
b.UnlockBits(bData);
return b;
}
这篇关于在 C# 中快速处理位图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!