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?

War es hilfreich?

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;
    }
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top