假设我有一个位图图像,是否可以迭代图像中的所有单个字节?如果是,怎么样?
答案 0 :(得分:6)
我发现了这个:http://channel9.msdn.com/forums/TechOff/108813-Bitmap-to-byte-array/
说你可以使用Memorystream和.Save方法,它看起来像这样:
System.Drawing.Bitmap bmp = GetTheBitmap();
System.IO.MemoryStream stream = new System.IO.MemoryStream();
bmp.Save(stream, System.Drawing.Imaging.ImageFormat.Bmp);
stream.Position = 0;
byte[] data = new byte[stream.Length];
stream.Read(data, 0, stream.Length);
答案 1 :(得分:5)
如果您需要访问像素信息,超缓慢但超级简单的方法是调用Bitmap对象上的GetPixel和SetPixel方法。
超快且不那么难的方法是调用Bitmap的LockBits方法并使用从它返回的BitmapData对象直接读取和写入Bitmap的字节数据。你可以像在伊利亚的例子中那样使用Marshal类来完成后一部分,或者你可以像这样跳过元帅的开销:
BitmapData data;
int x = 0; //or whatever
int y = 0;
unsafe
{
byte* row = (byte*)data.Scan0 + (y * data.Stride);
int columnOffset = x * 4;
byte B = row[columnOffset];
byte G = row[columnOffset + 1];
byte R = row[columnOffset + 2];
byte A = row[columnOffset + 3];
}
答案 2 :(得分:4)
在Bitmap类上使用LockBits成员获取BitmapData,然后使用Scan0和Marshal.ReadByte来读取字节。这是一个小例子(但不是关于正确的亮度调整):
public static void AdjustBrightness(Bitmap image, int brightness)
{
int offset = 0;
brightness = (brightness * 255) / 100;
// GDI+ still lies to us - the return format is BGR, NOT RGB.
BitmapData bmData = image.LockBits(new Rectangle(0, 0, image.Width, image.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
int stride = bmData.Stride;
IntPtr Scan0 = bmData.Scan0;
int nVal = 0;
int nOffset = stride - image.Width * 3;
int nWidth = image.Width * 3;
for (int y = 0; y < image.Height; ++y)
{
for (int x = 0; x < nWidth; ++x)
{
nVal = Marshal.ReadByte(Scan0, offset) + brightness;
if (nVal < 0)
nVal = 0;
if (nVal > 255)
nVal = 255;
Marshal.WriteByte(Scan0, offset, (byte)nVal);
++offset;
}
offset += nOffset;
}
image.UnlockBits(bmData);
}
答案 3 :(得分:0)
另一种解决方案是使用LockBits和Marshal.Copy将位图转换为数组。我需要这个解决方案,因为我有两个图像只有它们的颜色深度不同而其他提供的解决方案不能很好地处理(或者太慢)。
using (Bitmap bmp = new Bitmap(fname)) {
// Convert image to int32 array with each int being one pixel
int cnt = bmp.Width * bmp.Height * 4 / 4;
BitmapData bmData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height),
ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
Int32[] rgbValues = new Int32[cnt];
// Copy the RGB values into the array.
System.Runtime.InteropServices.Marshal.Copy(bmData.Scan0, rgbValues, 0, cnt);
bmp.UnlockBits(bmData);
for (int i = 0; i < cnt; ++i) {
if (rgbValues[i] == 0xFFFF0000)
Console.WriteLine ("Red byte");
}
}