So erstellen Sie eine BMP -Datei von Byte [] in C#
Frage
Ich habe ein Byte [] Array im TCP-Client empfangen. Das Array enthält eine 24-Bit-RGB-Bitmap-Datei. Wie erstellt diese Bitmap-Datei mit gegebener Breite, Höhe und Daten?
In C ++ verwende ich das
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;
}
Wie könnte ich das in C#machen?
Lösung
Wenn das Array tatsächlich eine Bitmap -Datei enthält, können Sie die Bytes einfach als Datei speichern:
File.WriteAllBytes(fileName, imageData);
Wenn das Array nur Rohpixeldaten enthält, können Sie ein Bitmap -Objekt mit den Daten erstellen:
unsafe {
fixed (byte* ptr = imageData) {
using (Bitmap image = new Bitmap(width, height, stride, PixelFormat.Format24bppRgb, new IntPtr(ptr))) {
image.Save(fileName);
}
}
}
Das stride
Wert ist die Anzahl der Bytes zwischen den Scan -Linien. Wenn es keine Polsterung zwischen den Scan -Linien gibt, ist es width * 3
Für ein 24BPP -Format.
Diese Methode verwendet die Daten im Array, ohne eine andere Kopie des gesamten Bildes im Speicher zu erstellen (weshalb es den Stridwert benötigt).
Wenn die Bitmap -Daten im Array verkehrt herum gespeichert sind, die stride
Der Wert sollte negativ sein, und der Zeiger sollte der Beginn der letzten Scan -Zeile im Speicher sein (ptr + stride * (height - 1)
).
Andere Tipps
Ich kann es nicht mit dem Stream testen, den Sie erhalten, aber dies sollte funktionieren.
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;
}
Ich würde empfehlen, eine Bitmap in C#zu machen und sie selbst zu retten.
Zum Beispiel siehe dieser Beitrag. (Insbesondere die letzte Antwort ist korrekt.)
Dies ist eine Möglichkeit, dies zu tun. Hier habe ich ein benutzerdefiniertes Ereignisargs erstellt, das die Größe enthält, bei der das Bild als Byte -Array gespeichert wurde. Möglicherweise müssen Sie sich nicht darum kümmern, dies war Code, den ich erstellt habe, um Bilder von einem Byte -Array zu retreieren, auf den eine Gige -Kamera aufbewahrt hat. Dies machte dies für mich.
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;
}