Как создать файл bmp из байта [] в С#

У меня есть массив byte [], полученный в TCP Client.The массив содержит 24-битный файл RGB Bitmap. Как создать этот файл растрового изображения с заданной шириной, высотой и данными?

В С++ я использую этот

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

Как я могу сделать это на С#?

9
задан Ivan Prodanov 12 апр. '09 в 22:10
источник поделиться

4 ответов

Если массив действительно содержит файл растрового изображения, вы можете просто сохранить байты в виде файла:

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 - это количество байтов между линиями сканирования. Если между линиями сканирования нет отступов, оно width * 3 для формата 24bpp.

Этот метод использует данные в массиве без создания другой копии всего изображения в памяти (поэтому для него требуется значение шага).

Если данные растрового изображения хранятся в обратном порядке в массиве, значение stride должно быть отрицательным, а указатель должен начинаться с последней строки сканирования в памяти (ptr + stride * (height - 1)).

13
ответ дан Guffa 12 апр. '09 в 23:38
источник поделиться

Я не могу проверить его с помощью потока, который вы будете получать, но это должно работать.

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;
}
10
ответ дан Samuel 12 апр. '09 в 22:23
источник поделиться

Я бы рекомендовал сделать Bitmap на С# и позволить ему сохранить себя.

В качестве примера см. этот пост. (В частности, последний ответ правильный.)

6
ответ дан Reed Copsey 12 апр. '09 в 22:15
источник поделиться

Это один из способов сделать это, здесь я создал настраиваемые аргументы событий, которые содержат размер, в котором изображение было сохранено как массив байтов. Возможно, вам не нужно беспокоиться об этом, это был код, который я создал для того, чтобы возвращать изображения из массива байтов, который хранила видеокамера 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;
    }
2
ответ дан Colm Clarke 27 июня '13 в 16:26
источник поделиться

Другие вопросы по меткам