我有一个原始字节数组,我想从这些字节中生成一个bmp文件。也就是说,我必须填写位图头结构和其他东西,然后写下字节,这样我就有一个正确格式的bmp文件。
由于我只需要一些快速检查,我想知道是否有一个可移植的方法来执行此操作 - 获取原始字节并将它们保存为bmp文件。任何Windows版本都不会像我在Unix上写的那样。
或者,我可以将这些字节保存为任何其他图像格式 - 我只需要快速查看结果图片。
答案 0 :(得分:4)
这是我用于.bmp灰度图像的代码
要保存为彩色位图,请确保不使用调色板(24位)
void SaveBitmapToFile( BYTE* pBitmapBits, LONG lWidth, LONG lHeight,WORD wBitsPerPixel, LPCTSTR lpszFileName )
{
RGBQUAD palette[256];
for(int i = 0; i < 256; ++i)
{
palette[i].rgbBlue = (byte)i;
palette[i].rgbGreen = (byte)i;
palette[i].rgbRed = (byte)i;
}
BITMAPINFOHEADER bmpInfoHeader = {0};
// Set the size
bmpInfoHeader.biSize = sizeof(BITMAPINFOHEADER);
// Bit count
bmpInfoHeader.biBitCount = wBitsPerPixel;
// Use all colors
bmpInfoHeader.biClrImportant = 0;
// Use as many colors according to bits per pixel
bmpInfoHeader.biClrUsed = 0;
// Store as un Compressed
bmpInfoHeader.biCompression = BI_RGB;
// Set the height in pixels
bmpInfoHeader.biHeight = lHeight;
// Width of the Image in pixels
bmpInfoHeader.biWidth = lWidth;
// Default number of planes
bmpInfoHeader.biPlanes = 1;
// Calculate the image size in bytes
bmpInfoHeader.biSizeImage = lWidth* lHeight * (wBitsPerPixel/8);
BITMAPFILEHEADER bfh = {0};
// This value should be values of BM letters i.e 0x4D42
// 0x4D = M 0×42 = B storing in reverse order to match with endian
bfh.bfType = 'B'+('M' << 8);
// <<8 used to shift ‘M’ to end
// Offset to the RGBQUAD
bfh.bfOffBits = sizeof(BITMAPINFOHEADER) + sizeof(BITMAPFILEHEADER) + sizeof(RGBQUAD) * 256;
// Total size of image including size of headers
bfh.bfSize = bfh.bfOffBits + bmpInfoHeader.biSizeImage;
// Create the file in disk to write
HANDLE hFile = CreateFile( lpszFileName,GENERIC_WRITE, 0,NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,NULL);
if( !hFile ) // return if error opening file
{
return;
}
DWORD dwWritten = 0;
// Write the File header
WriteFile( hFile, &bfh, sizeof(bfh), &dwWritten , NULL );
// Write the bitmap info header
WriteFile( hFile, &bmpInfoHeader, sizeof(bmpInfoHeader), &dwWritten, NULL );
// Write the palette
WriteFile( hFile, &palette[0], sizeof(RGBQUAD) * 256, &dwWritten, NULL );
// Write the RGB Data
if(lWidth%4 == 0)
{
WriteFile( hFile, pBitmapBits, bmpInfoHeader.biSizeImage, &dwWritten, NULL );
}
else
{
char* empty = new char[ 4 - lWidth % 4];
for(int i = 0; i < lHeight; ++i)
{
WriteFile( hFile, &pBitmapBits[i * lWidth], lWidth, &dwWritten, NULL );
WriteFile( hFile, empty, 4 - lWidth % 4, &dwWritten, NULL );
}
}
// Close the file handle
CloseHandle( hFile );
}
答案 1 :(得分:2)
您可以使用SOIL,它轻巧,便携,虽然针对OpenGL,但它可以加载图像(还可以保存图像)并返回原始数据。
以下是一些示例用法用法(来自SOIL网站)
/* load an image as a heightmap, forcing greyscale (so channels should be 1) */
int width, height, channels;
unsigned char *ht_map = SOIL_load_image
(
"terrain.tga",
&width, &height, &channels,
SOIL_LOAD_L
);
以下是SOIL提供的可读格式:
Readable Image Formats:
BMP - non-1bpp, non-RLE (from stb_image documentation)
PNG - non-interlaced (from stb_image documentation)
JPG - JPEG baseline (from stb_image documentation)
TGA - greyscale or RGB or RGBA or indexed, uncompressed or RLE
DDS - DXT1/2/3/4/5, uncompressed, cubemaps (can't read 3D DDS files yet)
PSD - (from stb_image documentation)
HDR - converted to LDR, unless loaded with *HDR* functions (RGBE or RGBdivA or RGBdivA2)
编辑:如果您愿意,也可以使用stb_image(也是跨平台和可移植的),其中包含所有文档等单个文件。
答案 2 :(得分:2)
以下内容将为您提供字节数组中的.ppm图像。 "P6"
指定二进制格式每像素3字节,但也支持纯文本和各种形式的灰度。您应该使用它的原因是它很容易,并且大多数* nix系统都有一堆ppmto * -tools:ppmtobmp,ppmtojpeg,...,ppmtopng ...您可以命名。
typedef struct {
int width;
int height;
uint8_t *data;
size_t size;
} ppm_image;
size_t ppm_save(ppm_image *img, FILE *outfile) {
size_t n = 0;
n += fprintf(outfile, "P6\n# THIS IS A COMMENT\n%d %d\n%d\n",
img->width, img->height, 0xFF);
n += fwrite(img->data, 1, img->width * img->height * 3, outfile);
return n;
}
还有ppmtocad ......会猜到谁?
答案 3 :(得分:1)
Boost GIL支持对JPG,TIFF和PNG的读/写。
基于模板,您可以调整图像格式到库中。这可能对你来说太过分了。
答案 4 :(得分:1)
试试EasyBMP,它是一个开源的跨平台C ++库,用它创建BMP文件很有趣:
BMP AnImage;
// Set size to 640 × 480
AnImage.SetSize(640,480);
// Set its color depth to 32-bits
AnImage.SetBitDepth(32);
// Set one of the pixels
AnImage(14,18)->Red = 255;
AnImage(14,18)->Green = 255;
AnImage(14,18)->Blue = 255;
AnImage(14,18)->Alpha = 0;
AnImage.WriteToFile("Output.bmp");
答案 5 :(得分:-2)
只需查看WinGDI中BITMAPFILEHEADER
和BITMAPINFOHEADER
的typedef,字段很简单。确保WORD为16位int,DWORD为32位int。如果您正在使用RGBRGBRGB ...填写标题并写出数据非常容易......