Question

J'ai un tableau d'octet [] reçu dans le client TCP. Le tableau contient un fichier bitmap RVB 24 bits. Comment créer ce fichier bitmap avec une largeur, une hauteur et des données données?

En C ++, j'utilise ceci

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

Comment pourrais-je faire ça en C #?

Était-ce utile?

La solution

Si le tableau contient réellement un fichier bitmap, vous pouvez simplement enregistrer les octets en tant que fichier:

File.WriteAllBytes(fileName, imageData);

Si le tableau ne contient que des données de pixels brutes, vous pouvez créer un objet bitmap à l'aide des données:

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

La stride La valeur est le nombre d'octets entre les lignes de balayage. S'il n'y a pas de rembourrage entre les lignes de scan, c'est width * 3 pour un format 24BPP.

Cette méthode utilise les données du tableau sans créer une autre copie de l'image entière en mémoire (c'est pourquoi elle a besoin de la valeur de foulée).

Si les données bitmap sont stockées à l'envers dans le tableau, le stride La valeur doit être négative et le pointeur doit être le début de la dernière ligne de scan en mémoire (ptr + stride * (height - 1)).

Autres conseils

Je ne peux pas le tester en utilisant le flux que vous recevrez, mais cela devrait fonctionner.

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

Je recommanderais de faire un bitmap en C # et de le laisser se sauver.

Pour un exemple, voir ce post. (En particulier, la dernière réponse est correcte.)

C'est une façon de le faire, ici j'ai créé un événement personnalisé Args qui contient la taille à laquelle l'image a été stockée sous forme de tableau d'octets. Vous n'aurez peut-être pas besoin de vous soucier de cela, c'était du code que j'ai créé pour retarder les images à partir d'un tableau d'octets qu'un appareil photo Gige stockait donc pour moi que cela a fait du sens.

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;
    }
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top