MFC读取24位bmp图像出问题了,求大神来解决

baidu_25665887 2015-02-03 04:28:42
我要实现的是将24位bmp文件读入并在用户区显示,但是显示结果都不对的,谁能来帮忙看下?

注:因为对bmp文件还要做后续的处理(比如RGB转CMYK这样的),所以我现在写的代码只是一个测试是否正确读取bmp的程序。用其它控件去读取图片对我来说是毫无用处的。

这是我的代码:
void CMy3View::OnLoad()
{
// TODO: 在此添加命令处理程序代码
CString strFilter,strFilename,info;
unsigned short format,bit_per_pix,r,g,b;
unsigned int offset,bmp_width;
int bmp_height;
//打开bmp文件
strFilter=_T("bmp images(*.bmp)|*.bmp||");
CFileDialog dlg(true,NULL,NULL,OFN_EXPLORER|OFN_ENABLESIZING|OFN_FILEMUSTEXIST,strFilter);
if(dlg.DoModal()==IDOK){
strFilename=dlg.GetPathName();
CFile m_bmp(strFilename,CFile::modeRead);
m_bmp.SeekToBegin();
//读取bmp文件头
m_bmp.Read(&format,sizeof(unsigned short));
if(0x4d42!=format){//查看图片文件格式
AfxMessageBox(_T("The format of this bmp image is not supported by Windows!"));
}
m_bmp.Seek(0xa,CFile::begin); //读取到位图数据需要的偏移量
m_bmp.Read(&offset,sizeof(unsigned int));
m_bmp.Seek(0x12,CFile::begin); //读取位图宽高
m_bmp.Read(&bmp_width,sizeof(unsigned int));
m_bmp.Read(&bmp_height,sizeof(int));
m_bmp.Seek(0x1c,CFile::begin); //读取位图格式(256色,24位,32位)
m_bmp.Read(&bit_per_pix,sizeof(unsigned short));
m_bmp.Seek(offset,CFile::begin);//定位到位图数据
CClientDC dc(this);
int x,y;
if(24==bit_per_pix){ //如果是24位位图,则执行下列代码
if(bmp_height>0)
for(y=0;y<bmp_height;y++){
for(x=0;x<(int)bmp_width;x++){
m_bmp.Read(&b,sizeof(unsigned short));
m_bmp.Read(&g,sizeof(unsigned short));
m_bmp.Read(&r,sizeof(unsigned short));
dc.SetPixel(x,(bmp_height-y-1),RGB(r,g,b));
}
}
}

m_bmp.Close();
}
}
这是原始图片:

这是我的程序读取的结果:
...全文
393 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
worldy 2015-02-04
  • 打赏
  • 举报
回复
LZ读出来的图片比原图漂亮啊,就这样吧
hushoubo 2015-02-04
  • 打赏
  • 举报
回复
感觉是数据位错位了,颜色失真
schlafenhamster 2015-02-03
  • 打赏
  • 举报
回复
简单的

BITMAPINFO * LoadBMPFile(const TCHAR * pFileName)
{
	if ( pFileName==NULL )
		return NULL;

	HANDLE handle = CreateFile(pFileName, GENERIC_READ, FILE_SHARE_READ, 
		NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
	
	if ( handle == INVALID_HANDLE_VALUE )
		return NULL;

    BITMAPFILEHEADER bmFH;

	DWORD dwRead = 0;
	ReadFile(handle, & bmFH, sizeof(bmFH), & dwRead, NULL);

	BITMAPINFO * pDIB = NULL;

	if ( (bmFH.bfType == 0x4D42) && (bmFH.bfSize<=GetFileSize(handle, NULL)) )
	{
		pDIB = (BITMAPINFO *) new BYTE[bmFH.bfSize];
		
		if ( pDIB )
			ReadFile(handle, pDIB, bmFH.bfSize, & dwRead, NULL);
	}
	CloseHandle(handle);

	return pDIB;
}
schlafenhamster 2015-02-03
  • 打赏
  • 举报
回复

//
#define WIDTHBYTES(i)    ((i+31)/32*4)
//
BITMAPFILEHEADER   g_bf;
BITMAPV5HEADER	   g_bi;
DWORD              LineBytes;
DWORD              NumColors;
DWORD              ImgWidth=0 , ImgHeight=0;
HGLOBAL            hImgData=NULL;
HPALETTE           hPalette=NULL;
HBITMAP            hBitmap=NULL;
char			   g_BmpFileName[260]=""; 
//
BOOL LoadBmpFile (char *BmpFileName)
{   
    HFILE              hf;
    LPBITMAPV5HEADER   lpImgData;// LCS_sRGB='sRGB' BITMAPV4HEADER
    LOGPALETTE         *pPal;
    LPRGBQUAD          lpRGB;
    HPALETTE           hPrevPalette; 
    HDC                hDc;
	HLOCAL             hPal;
	DWORD 		       ImgSize;
	DWORD              i,all;
//	DWORD			   mask3[3];// [0]=0xFF00 0000; [1]=0x00FF 0000 ;[2]=0x0000 FF00

    all= sizeof(BITMAPINFOHEADER);  // 0x28
    all= sizeof(BITMAPV4HEADER);    // 0x6C
    all= sizeof(BITMAPV5HEADER);    // 0x7C

	if((hf=_lopen(BmpFileName,OF_READ))==HFILE_ERROR)
	{
        MessageBox(0,BmpFileName,"Error Not Found",MB_OK|MB_ICONEXCLAMATION);
        return FALSE;
	}
	strcpy(g_BmpFileName,BmpFileName);
//
	_lread(hf,(LPSTR)&g_bf,sizeof(BITMAPFILEHEADER)); 
	_lread(hf,(LPSTR)&g_bi,sizeof(BITMAPV5HEADER));
	ImgWidth=g_bi.bV5Width;  //900
	ImgHeight=g_bi.bV5Height;//1257
//	if(bi.biCompression == BI_BITFIELDS)//3
//	{//DWORD RedMask; DWORD GreenMask; DWORD BlueMask;
//		_lread(hf,mask3,sizeof(mask3)); 
//	}
	LineBytes=(DWORD)WIDTHBYTES(g_bi.bV5Width*g_bi.bV5BitCount);
	ImgSize=(DWORD)LineBytes*g_bi.bV5Height;
    if(g_bi.bV5ClrUsed!=0)
		NumColors=(DWORD)g_bi.bV5ClrUsed;
	else
	{
        switch(g_bi.bV5BitCount)
		{
	       	case 1:
        	    NumColors=2;
        	    break;
        	case 4:
        	    NumColors=16;
        	    break;
        	case 8:
        	    NumColors=256;
        	    break;
        	case 24:
        	    NumColors=0;
        	    break;
         	case 32:
        	    NumColors=0;
        	    break;
             default:
                  MessageBox(0,"Invalid color numbers!","Error Message",MB_OK|MB_ICONEXCLAMATION);
                  _lclose(hf);
                  return FALSE; 
        }
	}
	if(g_bf.bfOffBits!=(DWORD)(NumColors*sizeof(RGBQUAD)+sizeof(BITMAPFILEHEADER)
							+sizeof(BITMAPV5HEADER)))
	{
    	MessageBox(0,"Invalid color numbers!","Error Message" ,MB_OK|MB_ICONEXCLAMATION);
		_lclose(hf);
		return FALSE; 
	}
	g_bf.bfSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPV5HEADER)+NumColors*sizeof(RGBQUAD)+ImgSize;
	if((hImgData=GlobalAlloc(GHND,(DWORD)(sizeof(BITMAPV5HEADER)+
						     NumColors*sizeof(RGBQUAD)+ImgSize)))==NULL)
	{
    	MessageBox(0,"Error alloc memory!","ErrorMessage",MB_OK|
                   MB_ICONEXCLAMATION);
	    _lclose(hf);
		return FALSE;
	}
  
	lpImgData=(LPBITMAPV5HEADER)GlobalLock(hImgData); 
    _llseek(hf,sizeof(BITMAPFILEHEADER),FILE_BEGIN);
	_hread(hf,(char *)lpImgData,(long)sizeof(BITMAPV5HEADER)+(long)NumColors*sizeof(RGBQUAD)+ImgSize);
	_lclose(hf);
    if(NumColors!=0)
	{                    
	    hPal=LocalAlloc(LHND,sizeof(LOGPALETTE) + NumColors* sizeof(PALETTEENTRY));
	    pPal =(LOGPALETTE *)LocalLock(hPal);
	    pPal->palNumEntries =(WORD) NumColors;
		pPal->palVersion    = 0x300;
	    lpRGB = (LPRGBQUAD)((LPSTR)lpImgData + (DWORD)sizeof(BITMAPV5HEADER));
		for (i = 0; i < NumColors; i++) 
		{
     		pPal->palPalEntry[i].peRed=lpRGB->rgbRed;
			pPal->palPalEntry[i].peGreen=lpRGB->rgbGreen;
			pPal->palPalEntry[i].peBlue=lpRGB->rgbBlue;
			pPal->palPalEntry[i].peFlags=(BYTE)0;
			lpRGB++;
		}
		hPalette=CreatePalette(pPal);
		LocalUnlock(hPal);
		LocalFree(hPal);
	}
	hDc=GetDC(0);
	if(hPalette)
	{
        hPrevPalette=SelectPalette(hDc,hPalette,FALSE);
		RealizePalette(hDc);
	}// int WINAPI GetDIBits(HDC, HBITMAP, UINT, UINT, LPVOID, LPBITMAPINFO, UINT);
	hBitmap=CreateDIBitmap(hDc,	(LPBITMAPINFOHEADER)lpImgData, (LONG)CBM_INIT,
				(LPSTR)lpImgData+sizeof(BITMAPV5HEADER) +NumColors*sizeof(RGBQUAD),
   				(LPBITMAPINFO)lpImgData,
				DIB_RGB_COLORS);
	if(hPalette && hPrevPalette)
	{
		SelectPalette(hDc,hPrevPalette,FALSE);
		RealizePalette(hDc);
	}
 
	ReleaseDC(0,hDc);
	GlobalUnlock(hImgData);
	return TRUE; 
}
缄默笔记 2015-02-03
  • 打赏
  • 举报
回复
BMP位图比较特殊注意一下几点: 1. 每行字节数,是32bit的整数倍,若每个像素是8bit(0—255),则图像宽为4的整数倍。 2. 24位图,数据是按(BGR)存储的,不是(RGB),所以楼主显示时,图像颜色不对,是RGB搞翻了。
schlafenhamster 2015-02-03
  • 打赏
  • 举报
回复
顺序文件 读 (2字节) 后 文件 指针 自动 移到下个 字节处 , 所以 m_bmp.Seek(0xa,CFile::begin); 是不必要的。 按 bmp 的 格式 读,

19,468

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 图形处理/算法
社区管理员
  • 图形处理/算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧