如何在 C# 中从 byte[] 创建 bmp 文件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/742236/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to create a bmp file from byte[] in C#
提问by Ivan Prodanov
I have a byte[] array received in TCP Client.The array contains a 24-bit RGB Bitmap file.How to create that bitmap file with given Width ,Height and data?
我在 TCP Client 中收到了一个 byte[] 数组。该数组包含一个 24 位 RGB 位图文件。如何创建具有给定宽度、高度和数据的位图文件?
In C++ I use this
在 C++ 中,我使用这个
int WriteBitmapFile(const char *filename, int width, int height, unsigned char *imageData)
{
FILE *filePtr; // file pointer
BITMAPFILEHEADER bitmapFileHeader; // bitmap file header
BITMAPINFOHEADER bitmapInfoHeader; // bitmap info header
DWORD imageIdx; // used for swapping RGB->BGR
unsigned char tempRGB; // used for swapping
// open file for writing binary mode
filePtr = fopen(filename, "wb");
if (!filePtr)
return 0;
// define the bitmap file header
bitmapFileHeader.bfSize = sizeof(BITMAPFILEHEADER);
bitmapFileHeader.bfType = 0x4D42;
bitmapFileHeader.bfReserved1 = 0;
bitmapFileHeader.bfReserved2 = 0;
bitmapFileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
// define the bitmap information header
bitmapInfoHeader.biSize = sizeof(BITMAPINFOHEADER);
bitmapInfoHeader.biPlanes = 1;
bitmapInfoHeader.biBitCount = 32; // 24-bit
bitmapInfoHeader.biCompression = BI_RGB; // no compression
bitmapInfoHeader.biSizeImage = width * abs(height) * 4; // width * height * (RGB bytes)
bitmapInfoHeader.biXPelsPerMeter = 0;
bitmapInfoHeader.biYPelsPerMeter = 0;
bitmapInfoHeader.biClrUsed = 0;
bitmapInfoHeader.biClrImportant = 0;
bitmapInfoHeader.biWidth = width; // bitmap width
bitmapInfoHeader.biHeight = height; // bitmap height
// switch the image data from RGB to BGR
for(imageIdx = 0; imageIdx < bitmapInfoHeader.biSizeImage; imageIdx+=4)
{
tempRGB = imageData[imageIdx];
imageData[imageIdx] = imageData[imageIdx + 2];
imageData[imageIdx + 2] = tempRGB;
}
// write the bitmap file header
fwrite(&bitmapFileHeader, 1, sizeof(BITMAPFILEHEADER), filePtr);
// write the bitmap info header
fwrite(&bitmapInfoHeader, 1, sizeof(BITMAPINFOHEADER), filePtr);
// write the image data
fwrite(imageData, 1, bitmapInfoHeader.biSizeImage, filePtr);
// close our file
fclose(filePtr);
// Success
return 1;
}
How could I do that in C#?
我怎么能在 C# 中做到这一点?
采纳答案by Guffa
If the array actually contains a bitmap file, then you can just save the bytes as a file:
如果数组实际上包含一个位图文件,那么您可以将字节保存为文件:
File.WriteAllBytes(fileName, imageData);
If the array contains only raw pixel data, you can create a Bitmap object using the data:
如果数组只包含原始像素数据,您可以使用数据创建一个 Bitmap 对象:
unsafe {
fixed (byte* ptr = imageData) {
using (Bitmap image = new Bitmap(width, height, stride, PixelFormat.Format24bppRgb, new IntPtr(ptr))) {
image.Save(fileName);
}
}
}
The stride
value is the number of bytes between the scan lines. If there is no padding between the scan lines, it's width * 3
for a 24bpp format.
该stride
值是扫描线之间的字节数。如果扫描线之间没有填充,width * 3
则为 24bpp 格式。
This method uses the data in the array without creating another copy of the entire image in memory (which is why it needs the stride value).
此方法使用数组中的数据,而无需在内存中创建整个图像的另一个副本(这就是它需要步幅值的原因)。
If the bitmap data is stored upside down in the array, the stride
value should be negative, and the pointer should be the start of the last scan line in memory (ptr + stride * (height - 1)
).
如果位图数据倒置存储在数组中,则该stride
值应为负数,指针应为内存中最后一条扫描线的起点(ptr + stride * (height - 1)
)。
回答by Reed Copsey
I'd recommend making a Bitmap in C#, and letting it save itself.
我建议在 C# 中制作一个位图,并让它自行保存。
For an example, see this post.(Particularly, the last response is correct.)
有关示例,请参阅此帖子。(特别是最后一个回答是正确的。)
回答by Samuel
I can't test it using the stream you will be receiving, but this should work.
我无法使用您将收到的流对其进行测试,但这应该可行。
int WriteBitmapFile(string filename, int width, int height, byte[] imageData)
{
using (var stream = new MemoryStream(imageData))
using (var bmp = new Bitmap(width, height, PixelFormat.Format24bppRgb))
{
BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0,
bmp.Width,
bmp.Height),
ImageLockMode.WriteOnly,
bmp.PixelFormat);
Marshal.Copy(imageData, 0, bmpData.Scan0, imageData.Length);
bmp.UnlockBits(bmpData);
bmp.Save(filename);
}
return 1;
}
回答by Colm Clarke
this is one way of doing it, here i have created a custom Event args that contains the size at which the image was stored as a byte array. You may not need to bother with this, this was code i created to retreive images from a byte array that a gige camera was storing to so for me this made sence.
这是一种方法,在这里我创建了一个自定义事件参数,其中包含将图像存储为字节数组的大小。您可能不需要为此烦恼,这是我创建的代码,用于从 gige 相机存储的字节数组中检索图像,因此对我来说这很有意义。
public Bitmap ShowImage(byte[] sender, EventImageParams e)
{
Bitmap bitmap = new Bitmap(e.width, e.height, PixelFormat.Format24bppRgb);
BitmapData bmData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
ImageLockMode.ReadWrite, bitmap.PixelFormat);
IntPtr pNative = bmData.Scan0;
Marshal.Copy(sender, 0, pNative, (e.width * e.height * 3));
//
bitmap.UnlockBits(bmData);
return bitmap;
}