c#에서 byte []에서 bmp 파일을 만드는 방법
문제
TCP 클라이언트에 바이트 [] 배열이 수신되어 있습니다. 배열에는 24 비트 RGB 비트 맵 파일이 포함되어 있습니다. 주어진 너비, 높이 및 데이터로 해당 비트 맵 파일을 만드는 방법은 무엇입니까?
C ++에서 나는 이것을 사용합니다
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#에서 어떻게 할 수 있습니까?
해결책
배열에 실제로 비트 맵 파일이 포함 된 경우 바이트를 파일로 저장할 수 있습니다.
File.WriteAllBytes(fileName, imageData);
배열에 원시 픽셀 데이터 만 포함 된 경우 데이터를 사용하여 비트 맵 객체를 만들 수 있습니다.
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)
).
다른 팁
받을 스트림을 사용하여 테스트 할 수는 없지만 작동해야합니다.
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;
}
C#에서 비트 맵을 만들고 자체를 저장하는 것이 좋습니다.
예를 들어, 참조하십시오 이 게시물. (특히 마지막 응답이 정확합니다.)
이것은 그것을 수행하는 한 가지 방법입니다. 여기서는 이미지가 바이트 배열로 저장된 크기를 포함하는 사용자 정의 이벤트 args를 만들었습니다. 당신은 이것으로 귀찮게 할 필요가 없을 수도 있습니다. 이것은 공연 카메라가 저장하고있는 바이트 배열에서 이미지를 다시 만들기 위해 만든 코드였습니다.
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;
}