如何在C#中从byte 创建bmp文件

我在TCP Client中收到一个byte []数组。该数组包含一个24位RGB位图文件。如何创建具有给定宽度,高度和数据的位图文件?

在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; } 

我怎么能用C#做到这一点?

如果数组实际包含位图文件,那么您只需将字节保存为文件:

 File.WriteAllBytes(fileName, imageData); 

如果数组仅包含原始像素数据,则可以使用以下数据创建Bitmap对象:

 unsafe { fixed (byte* ptr = imageData) { using (Bitmap image = new Bitmap(width, height, stride, PixelFormat.Format24bppRgb, new IntPtr(ptr))) { image.Save(fileName); } } } 

stride值是扫描线之间的字节数。 如果扫描线之间没有填充,则对于24bpp格式, width * 3

此方法使用数组中的数据,而不在内存中创建整个图像的另一个副本(这就是它需要步幅值的原因)。

如果位图数据颠倒存储在数组中,则stride值应为负值,指针应为内存中最后一条扫描线的起点( ptr + stride * (height - 1) )。

我无法使用您将收到的流进行测试,但这应该可行。

 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; } 

我建议在C#中创建一个位图,并让它自己保存。

例如,请看这篇文章。 (特别是,最后的回答是正确的。)

这是一种方法,在这里我创建了一个自定义事件args,其中包含将图像存储为字节数组的大小。 您可能不需要为此烦恼,这是我创建的代码,用于从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; } 
Interesting Posts