请大家帮我看看,这是一个用MFC做的打开24位真彩色图像,并进行处理显示的程序。目前有两个问题:
- 本人打开320*240大小的24位真彩色BMP图像,数据大小应该为320*240 = 230400字节,但是代码中变量dataBytes 为何是230402。
-
现在我是先将彩色图像数据进行灰度化(此时数据缩小为原来的1/3),然后把数据扩充(如showData函数所示)到彩色数据的大小,再进行显示。结果图:灰度图能显示完整,但有分布均匀的灰度一致的像素点。另外还有原本图像下半部区域的图像进行了放大并叠加在上半部。
我怀疑是StretchDIBits显示函数和dataBytes 变量存在问题,但找了很久没有发现,忘大家不吝赐教,万分感谢。
BITMAPINFO *pBmpInfo;
unsigned short iBmpWidth,iBmpHeight;
BYTE *pBmpData;
BYTE *pGray;
BYTE *pShowGray;
//picture control 定义
CWnd *pWnd;
CRect rect;
CDC *pDC;
void showData(BYTE *in,BYTE *out,unsigned short width,unsigned short height)
{
unsigned long i;
unsigned long len = width * height;
for(i = 0;i < len; i++)
{
out[i*3] = in[i];
out[i*3+1] = in[i];
out[i*3+2] = in[i];
}
}
/************************24位彩图转8位灰度图——Gray = R*a + G*b + B*c*****************************/
void ColtoGray(BYTE *imageIn,BYTE *imageOut,float a,float b,float c)
{
long area = IMAGEHEIGHT * IMAGEWIDTH;
long index;
unsigned char n;
float sum=0;
for(index = 0;index < area;index ++)
{
for(n=0;n<3;n++)
{
switch(n)
{
case 0:
sum=sum+imageIn[index]*a; break;
case 1:
sum=sum+imageIn[index*3+1]*b; break;
case 2:
sum=sum+imageIn[index*3+2]*c; break;
}
}
imageOut[index]=sum;
sum=0;
}
}
//打开按钮按下,打开24位真彩色图片
void CMFCDlg::OnBnClickedButton2()
{
// TODO: 在此添加控件通知处理程序代码
BITMAPFILEHEADER bmpHeader;//文件头
BITMAPINFOHEADER bmpInfo;//信息头
CFileDialog dlg( TRUE , "(*.bmp)|*.bmp","*.bmp" ,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT ,"位图文件(*.bmp)");
CFile bmpFile;//记录打开文件
CString strFileName;//记录选择文件路径
if (!dlg.DoModal() == IDOK)
return;
strFileName = dlg.GetPathName();
//以只读的方式打开文件
if(!bmpFile.Open(strFileName, CFile::modeRead|CFile::typeBinary))
return;
if (bmpFile.Read(&bmpHeader,sizeof(BITMAPFILEHEADER)) != sizeof(BITMAPFILEHEADER))
{
AfxMessageBox("读取文件失败!");
return;
}
if (bmpHeader.bfType != 0x4d42)
{
AfxMessageBox("未能识别bmp格式文件!");
return;
}
if (bmpFile.Read(&bmpInfo,sizeof(BITMAPINFOHEADER)) != sizeof(BITMAPINFOHEADER))
{
AfxMessageBox("读取bmp文件头失败!");
return;
}
if (bmpInfo.biBitCount != 24)
{
AfxMessageBox("您读取的不是24位真彩色图像!");
return;
}
pBmpInfo = (BITMAPINFO *)new char[sizeof(BITMAPINFOHEADER)];
if (!pBmpInfo)
{
AfxMessageBox("内存分配错误!");
return;
}
//为图像数据申请空间
memcpy(pBmpInfo,&bmpInfo,sizeof(BITMAPINFOHEADER));
DWORD dataBytes = bmpHeader.bfSize - bmpHeader.bfOffBits;
pBmpData = (BYTE*)new char[dataBytes];
if (!pBmpData)
{
AfxMessageBox("内存分配错误!");
delete pBmpData;
return;
}
if (bmpFile.Read(pBmpData,dataBytes) != dataBytes)
{
AfxMessageBox("读取图像数据失败!");
delete pBmpInfo;
delete pBmpData;
return;
}
bmpFile.Close();
pWnd=GetDlgItem(IDC_STATIC);//获得pictrue控件窗口的句柄
//CRect rect;
pWnd->GetClientRect(&rect);//获得pictrue控件所在的矩形区域
pDC=pWnd->GetDC();//获得pictrue控件的DC
//显示图片
pDC->SetStretchBltMode(COLORONCOLOR);
StretchDIBits(pDC->GetSafeHdc(),0,0,rect.Width(),rect.Height(),0,0,bmpInfo.biWidth,bmpInfo.biHeight,pBmpData,pBmpInfo,DIB_RGB_COLORS,SRCCOPY);
iBmpWidth=bmpInfo.biWidth;
iBmpHeight=bmpInfo.biHeight;
}
//灰度化按下
void CMFCDlg::OnBnClickedButton3()
{
// TODO: 在此添加控件通知处理程序代码
pGray = (BYTE*)new char[320*240];
pShowGray = (BYTE*)new char[320*240*3];
ColtoGray(pBmpData,pGray,0.3,0.3,0.3);
showData(pGray,pShowGray,iBmpWidth,iBmpHeight);
pWnd=GetDlgItem(IDC_STATIC);//获得pictrue控件窗口的句柄
//CRect rect;
pWnd->GetClientRect(&rect);//获得pictrue控件所在的矩形区域
pDC=pWnd->GetDC();//获得pictrue控件的DC
//显示图片
pDC->SetStretchBltMode(COLORONCOLOR);
StretchDIBits(pDC->GetSafeHdc(),0,0,rect.Width(),rect.Height(),0,0,iBmpWidth,iBmpHeight,pShowGray,pBmpInfo,DIB_RGB_COLORS,SRCCOPY);
}