Pregunta

Tengo una matriz de byte [] recibida en el cliente TCP. La matriz contiene un archivo de mapa de bits RGB de 24 bits. ¿Cómo crear ese archivo de mapa de bits con ancho, altura y datos dados?

En c ++ uso esto

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ómo podría hacer eso en C#?

¿Fue útil?

Solución

Si la matriz realmente contiene un archivo de mapas de bits, entonces puede guardar los bytes como un archivo:

File.WriteAllBytes(fileName, imageData);

Si la matriz contiene solo datos de píxeles sin procesar, puede crear un objeto de mapa de bits usando los datos:

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

los stride El valor es el número de bytes entre las líneas de escaneo. Si no hay relleno entre las líneas de escaneo, es width * 3 para un formato de 24bpp.

Este método utiliza los datos en la matriz sin crear otra copia de toda la imagen en la memoria (por lo que necesita el valor de zancada).

Si los datos de mapa de bits se almacenan boca abajo en la matriz, el stride El valor debe ser negativo, y el puntero debe ser el inicio de la última línea de escaneo en la memoria (ptr + stride * (height - 1)).

Otros consejos

No puedo probarlo usando la transmisión que recibirá, pero esto debería funcionar.

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

Recomiendo hacer un mapa de bits en C#y dejar que se salva.

Para un ejemplo, ver esta publicación. (Particularmente, la última respuesta es correcta).

Esta es una forma de hacerlo, aquí he creado un evento personalizado Args que contiene el tamaño en el que la imagen se almacenó como una matriz de bytes. Es posible que no necesite molestarse con esto, este fue el código que creé para recuperar imágenes de una matriz de bytes a la que una cámara de gige estaba almacenando para mí, esto hizo.

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;
    }
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top