我只是想分享 Minhas Kamal 代码的改进版本,因为尽管它对于大多数应用程序来说都足够好,但我仍然遇到了一些问题。要记住两件非常重要的事情:
- 代码(在撰写本文时)在两个静态数组上调用 free()。这将导致您的程序崩溃。所以我把这些行注释掉了。
- 切勿假设像素数据的间距始终为 (Width*BytesPerPixel)。最好让用户指定音高值。示例:在 Direct3D 中操作资源时,永远不能保证 RowPitch 是正在使用的字节深度的偶数倍。这可能会导致生成的位图出错(尤其是在奇怪的分辨率下,例如 1366x768)。
下面,你可以看到我对他的代码的修改:
const int bytesPerPixel = 4; /// red, green, blue
const int fileHeaderSize = 14;
const int infoHeaderSize = 40;
void generateBitmapImage(unsigned char *image, int height, int width, int pitch, const char* imageFileName);
unsigned char* createBitmapFileHeader(int height, int width, int pitch, int paddingSize);
unsigned char* createBitmapInfoHeader(int height, int width);
void generateBitmapImage(unsigned char *image, int height, int width, int pitch, const char* imageFileName) {
unsigned char padding[3] = { 0, 0, 0 };
int paddingSize = (4 - (/*width*bytesPerPixel*/ pitch) % 4) % 4;
unsigned char* fileHeader = createBitmapFileHeader(height, width, pitch, paddingSize);
unsigned char* infoHeader = createBitmapInfoHeader(height, width);
FILE* imageFile = fopen(imageFileName, "wb");
fwrite(fileHeader, 1, fileHeaderSize, imageFile);
fwrite(infoHeader, 1, infoHeaderSize, imageFile);
int i;
for (i = 0; i < height; i++) {
fwrite(image + (i*pitch /*width*bytesPerPixel*/), bytesPerPixel, width, imageFile);
fwrite(padding, 1, paddingSize, imageFile);
}
fclose(imageFile);
//free(fileHeader);
//free(infoHeader);
}
unsigned char* createBitmapFileHeader(int height, int width, int pitch, int paddingSize) {
int fileSize = fileHeaderSize + infoHeaderSize + (/*bytesPerPixel*width*/pitch + paddingSize) * height;
static unsigned char fileHeader[] = {
0,0, /// signature
0,0,0,0, /// image file size in bytes
0,0,0,0, /// reserved
0,0,0,0, /// start of pixel array
};
fileHeader[0] = (unsigned char)('B');
fileHeader[1] = (unsigned char)('M');
fileHeader[2] = (unsigned char)(fileSize);
fileHeader[3] = (unsigned char)(fileSize >> 8);
fileHeader[4] = (unsigned char)(fileSize >> 16);
fileHeader[5] = (unsigned char)(fileSize >> 24);
fileHeader[10] = (unsigned char)(fileHeaderSize + infoHeaderSize);
return fileHeader;
}
unsigned char* createBitmapInfoHeader(int height, int width) {
static unsigned char infoHeader[] = {
0,0,0,0, /// header size
0,0,0,0, /// image width
0,0,0,0, /// image height
0,0, /// number of color planes
0,0, /// bits per pixel
0,0,0,0, /// compression
0,0,0,0, /// image size
0,0,0,0, /// horizontal resolution
0,0,0,0, /// vertical resolution
0,0,0,0, /// colors in color table
0,0,0,0, /// important color count
};
infoHeader[0] = (unsigned char)(infoHeaderSize);
infoHeader[4] = (unsigned char)(width);
infoHeader[5] = (unsigned char)(width >> 8);
infoHeader[6] = (unsigned char)(width >> 16);
infoHeader[7] = (unsigned char)(width >> 24);
infoHeader[8] = (unsigned char)(height);
infoHeader[9] = (unsigned char)(height >> 8);
infoHeader[10] = (unsigned char)(height >> 16);
infoHeader[11] = (unsigned char)(height >> 24);
infoHeader[12] = (unsigned char)(1);
infoHeader[14] = (unsigned char)(bytesPerPixel * 8);
return infoHeader;
}