这一直困扰着我一段时间,我想确保我对位图的理解是正确的,并找到一些帮助发现错误。基本上我要做的是保存一个8位位图文件,同时将它显示在MFC应用程序的图片框中。我想避免使用繁琐的方法来保存位图,然后重新加载它。
保存文件操作大部分都是成功的,但是我改变了我的代码,现在文件中曾经是白色的(在这个例子中它是一个黑白图像)通常是绿色但它会改变。我猜这是因为我的数据可能引用了颜色表中的信息,哪个值是白色的?
HBITMAP ReadWrite::SaveFile(LPCTSTR file, double* data) {
BYTE* bmp = ConvertData(data);
HANDLE hf;
BITMAPINFO* pbmi = WriteHeader(file);
BITMAPFILEHEADER* bmfh = (BITMAPFILEHEADER*)alloca(sizeof(BITMAPFILEHEADER));
bmfh->bfType = 0x4d42; // 'BM'
bmfh->bfReserved1 = 0;
bmfh->bfReserved2 = 0;
bmfh->bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) + pbmi->bmiHeader.biSize + 256 * sizeof(RGBQUAD);
bmfh->bfSize = (DWORD)(bmfh->bfOffBits + pbmi->bmiHeader.biSizeImage);
hf = CreateFile(file, GENERIC_READ | GENERIC_WRITE, (DWORD) 0,
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, (HANDLE) NULL );
if (hf == NULL) // error creating
{
CloseHandle (hf);
return NULL;
}
// write header
unsigned long bwritten;
if (!WriteFile(hf, (LPCVOID)bmfh, sizeof(BITMAPFILEHEADER), &bwritten, NULL))
{
CloseHandle (hf);
return NULL;
}
// write infoheader
if (!WriteFile(hf, (LPCVOID)pbmi, sizeof (BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD), &bwritten, NULL ))
{
CloseHandle (hf);
return NULL;
}
// write image data
if (!WriteFile(hf, (LPCVOID)bmp_data, (int) pbmi->bmiHeader.biSizeImage, &bwritten, NULL ))
{
CloseHandle (hf);
return NULL;
}
// Close
CloseHandle(hf);
// Send back a file to display
return CreateDIBSection(NULL, pbmi, DIB_RGB_COLORS, (void**)bmp_data, NULL, 0);
}
编写infoheader + palette的代码(应该是从黑到白的值?)
BITMAPINFO* ReadWrite::WriteHeader(LPCTSTR fn)
{
int R = ReadWrite::getR();
int C = ReadWrite::getC();
BITMAPINFO* pbmi = (BITMAPINFO*)alloca(sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*256);
pbmi->bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
pbmi->bmiHeader.biWidth = R;
pbmi->bmiHeader.biHeight = -C;
pbmi->bmiHeader.biPlanes = 1;
pbmi->bmiHeader.biBitCount = 8;
pbmi->bmiHeader.biCompression = BI_RGB;
pbmi->bmiHeader.biSizeImage = (((R * pbmi->bmiHeader.biBitCount + 31) & ~31) >> 3) * C;
pbmi->bmiHeader.biClrUsed = 256;
pbmi->bmiHeader.biClrImportant = 0;
for(int i=0; i<256; i++)
{
pbmi->bmiColors[i].rgbRed = i;
pbmi->bmiColors[i].rgbGreen = i;
pbmi->bmiColors[i].rgbBlue = i;
pbmi->bmiColors[i].rgbReserved = 0;
}
//return true;
return pbmi;
}
最后将我的数字数组转换为unsigned char'Bytes':
BYTE* ReadWrite::ConvertData(double* data) {
BYTE* bmp_data;
int R = ReadWrite::getR();
int C = ReadWrite::getC();
bool binary = ReadWrite::getBinary();
bmp_data = new BYTE [R*C];
// convert the values to unsigned char (BYTE)
for(int i=0; i<R*C; i++){
if (data[i] == 1){
data[i] = 255;
}
bmp_data[i] = (unsigned char)data[i];
}
delete [] data;
return bmp_data;
}
回顾一下问题/问题:
感谢您阅读这篇愚蠢的长篇文章。
编辑我设法修复了绿色问题(编号1),我不知道怎么回事,我认为这与标题上的内存大小不一致有关。它仍然无法上传到互联网或显示在程序中,因此它必定是错误的。
答案 0 :(得分:0)
所以我发现我的代码存在导致其他应用程序/互联网出错的问题。
在其中我为图像的高度指定负值以翻转数据,但这是一个完全不正确的解决方案。代替:
// convert the integer values to unsigned char (BYTE) BACKWARDS
for(int i=0; i<R; i++){
for(int j=0; j<C; j++){
if (data[i*R + j] == 1 && binary){
data[i*R + j] = 255;
}
bmp_data[(R-i)*C + (j-C)] = (unsigned char)data[i*C + j];
}
}
这样做是将原始值复制到bmp_data中,向后移动和。这可确保数据正确存储并在应用程序中打开。我目前对DIBSection和内存管理的解决方案是删除所有数据并从文件重新加载图像。通过HBITMAP太过分了。我欢迎那方面的意见,但现在我所有的问题都得到解决。