我正在编写一个程序来为化学实验室的某些数据创建图像。我们正在研究元素等的发射,并且数据写入包括通过分光镜观察频带的示例。我认为为我做一个程序是很好的,而不是彩色铅笔,所以这一切都很整洁。另外,我没有彩色铅笔。
我将图像数据作为RGB值存储在一个int数组中,长度宽度*我想要的图像高度,宽度为320,高度为50.最后我将它们写为24位文件BGR有序像素。
在将数据写入文件之前,我当然会尝试编写BMP头。 MSDN有一个图表来显示文件部分的一般顺序,其中包含一些关于RBGQuads的内容,但在段落中的解释没有描述如何使用它们。我认为他们是可选的?我发现此图表显示了我所期望的标题中唯一的强制部分: http://www.fastgraph.com/help/bmp_header_format.html,所以我觉得我在那里正确。
然后我得到了endianness,因为在尝试使用Paint或Windows图像查看器打开时,我的文件总是“损坏或损坏”。
所有消息来源都说BMP标题是小端。我尝试在写入时双向交换字节的顺序,但文件仍然无法打开。家庭酿造的腐败文件还有其他常见的罪魁祸首吗?
这是我存储标题信息的地方:
typedef struct
{
char type[2];
unsigned int fsize;
unsigned short res1;
unsigned short res2;
unsigned int data_offset;
} BMPFILEHEADER;
typedef struct
{
unsigned int sizebytes;
int width_pix;
int height_pix; // negative for top down.
unsigned short planes; // must be 1
unsigned short bits_per_pix;
unsigned int compression; // zero for BI_RGB (uncompressed)
unsigned int SizeImage; // may be set to 0 for BI_RGB images.
int pix_per_meter_x;
int pix_per_meter_y;
unsigned int color_used; // set to 0
unsigned int color_important; // set to 0
} BMPINFOHEADER;
当然,我按顺序写下它们。 - type是char []因为它必须是值'B''M'。
首先我尝试用fwrite()编写它们:
fwrite ( &header , 1 , 14 , fhandle );
fwrite ( &headerext , 1 , 40 , fhandle );
然后我尝试这样写:
fputc ( 'B' , fhandle );
fputc ( 'M' , fhandle );
fw_little_end ( fhandle , &header.fsize , 4 );
fw_little_end ( fhandle , &header.res1 , 2);
fw_little_end ( fhandle , &header.res2 , 2);
fw_little_end ( fhandle , &header.data_offset , 4);
其中fw_little_end()如下所示:
void fw_little_end ( FILE * fhandle , void * data , int size )
{
int i;
char * cdata = data;
for ( i = size; i > 0; i-- )
{
fputc ( *(cdata+i-1) , fhandle );
}
}
最初它可能是写入文件little endian并且我的fw_()
函数名称错误,但我也尝试过从size-0和0-size来确定。
如果它听起来相关,那就是写入数据的地方:
int shift1 = 256;
int shift2 = 256*256;
for ( i = 0; i < img_size; i++)
{
fputc ( (unsigned char) (data[i]%256) , fhandle ); // B
fputc ( (unsigned char) (data[i]/shift1)%256 , fhandle ); // G
fputc ( (unsigned char) (data[i]/shift2)%256 , fhandle ); // R
} // theoretically B only needs the typecast, not the %256 but oh well lol.
帖子已经很长了,希望我已经包含了足够的相关代码。我很抱歉,因为我知道那里有很多信息,除此之外对我来说没有任何意义。如果对于如何做这些事情有更好的习语,我很乐意指出正确的方向。
所以,我感谢你提供任何和所有的意见。
答案 0 :(得分:0)
我发布直接答案:
/* ======================================================================================== */
BOOL SaveBitmap24(LPCTSTR pszFilename, LPBYTE pPixelColorTriplets, INT nWidth, INT nHeight)
{
BOOL bState = FALSE;
// sizes
INT nOfsetToPixel = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPCOREHEADER);
INT nPixelSize = nWidth * nHeight * 3;
INT nFileSize = nOfsetToPixel + nPixelSize;
// setup bitmap file header --------------
BITMAPFILEHEADER bmFileHeader = { 0 };
// "BM" signature
bmFileHeader.bfType = 0x4D42;
bmFileHeader.bfOffBits = nOfsetToPixel;
bmFileHeader.bfSize = nFileSize;
// setup bitmap info header --------------
BITMAPCOREHEADER bmCoreHeader = { 0 };
bmCoreHeader.bcSize = sizeof(BITMAPCOREHEADER);
bmCoreHeader.bcWidth = nWidth;
bmCoreHeader.bcHeight = nHeight;
bmCoreHeader.bcBitCount = 24;
bmCoreHeader.bcPlanes = 1;
// write file -----------------------
FILE *fileBitmap = fopen(pszFilename, _T("wb"));
if (fileBitmap)
{ fwrite(&bmFileHeader, sizeof(BITMAPFILEHEADER), 1, fileBitmap);
fwrite(&bmCoreHeader, sizeof(bmCoreHeader), 1, fileBitmap);
fwrite(pPixelColorTriplets, nPixelSize, 1, fileBitmap);
fclose(fileBitmap);
bState = TRUE;
}
return bState;
}