BMP格式图片的读取与显示(MFC)

BMP格式图片的读取与显示(MFC)

BMP格式示意图

BMP格式简图(上述指针在读取图片会用到)

1.构造Dib类

class CDib : public CObject
{
    
    
public:
	CDib();
	~CDib();

	BOOL LoadFromFile(LPCTSTR path);//从文件加载图片
	BOOL SaveToFile(LPCTSTR path);//保存图片到文件
	LPCTSTR GetFileName();//获取文件名
	LONG GetWidth();//获取图片宽度
	LONG GetHeight();//获取图像高度
	CSize GetDimension();//获取图像的高度和宽度
	DWORD GetSize();//获取图片大小
	WORD GetBitCount();//获取单个比特的大小
	UINT GetLineByte();//获取每行像素所占字节数
	DWORD GetNumOfColor();//获取位图颜色数
	LPRGBQUAD GetRgbQuad();//获取图片颜色表
	LPBYTE GetData();//获取图片数据
	BOOL Draw(CDC* pDC, CRect rect);//显示图片
	BOOL RgbToGrade();//24位彩色转8位灰度

	BOOL IsVaild();//判断是否有效
	BOOL IsGrade();//判断是否灰度图
	BOOL HasRgbQuad();//判断是否有颜色表

protected:
	DWORD CalcRgbQuadLength();//计算颜色表长度
	void Empty(BOOL bFlag = TRUE);//清理空间
	
private:
	char m_fileName[255];//文件名
	LPBITMAPFILEHEADER m_lpBmpFileHeader;//位图文件头指针
	LPBITMAPINFOHEADER m_lpBmpInfoHeader;//位图信息头指针,需要动态分配和释放
	LPBYTE m_lpDib;//位图指针,包含除了文件头以外的所有部分。
	LPBITMAPINFO m_lpBmpInfo;//位图信息指针
	LPRGBQUAD m_lpRgbQuad;//位图颜色表指针
	LPBYTE m_lpData;//位图数据指针
	HPALETTE m_hpalette;//调色板句柄
	BOOL m_bHasRgbQuad;//颜色表判断
	BOOL m_bVaild;//位图有效性判断
};

读取与显示图片只需要实现以下方法即可:
BOOL LoadFromFile(LPCTSTR path);//从文件加载图片
BOOL SaveToFile(LPCTSTR path);//保存图片到文件
LONG GetWidth();//获取图片宽度
LONG GetHeight();//获取图像高度
DWORD GetNumOfColor();//获取位图颜色数
LPRGBQUAD GetRgbQuad();//获取图片颜色表
BOOL Draw(CDC* pDC, CRect rect);//显示图片

2.图片的读取

从路径中读取图片

BOOL CDib::LoadFromFile(LPCTSTR lpszPath)
{
    
    
	strcpy(m_fileName, lpszPath);//文件名记录
	//LPCTSTR(m_fileName);//强制转换,为了迎合下面的.open方法
	CFile dibFile;//实例化一个DC
	//以只读模式打开文件
	if (!dibFile.Open(m_fileName, CFile::modeRead | CFile::shareDenyWrite))
	{
    
    
		return FALSE;
	}
	
	//为位图头文件分配空间
	m_lpBmpFileHeader = (LPBITMAPFILEHEADER)new BYTE[sizeof(BITMAPFILEHEADER)];//分配bmp头文件大小的数组,BYTE是控制头文件最小单位是8bit
	memset(m_lpBmpFileHeader, 0, sizeof(BITMAPFILEHEADER));//初始化为0
	//读取文件头
	int nCount = dibFile.Read((void*)m_lpBmpFileHeader, sizeof(BITMAPFILEHEADER));//强制转换为 void*
	if (nCount != sizeof(BITMAPFILEHEADER)) return FALSE;
	if (m_lpBmpFileHeader->bfType == 0x4d42)//判断是否位图,0x4d42代表BMP格式
	{
    
    
		//若是位图文件,计算除了位图文件头的空间大小,分配空间并初始化为0
		DWORD dwDibSize = dibFile.GetLength() - sizeof(BITMAPFILEHEADER);//除了bmfh的大小
		m_lpDib = new BYTE[dwDibSize];
		memset(m_lpDib, 0, dwDibSize);//初始化位图数据除了bmfh的部分
		dibFile.Read(m_lpDib, dwDibSize);//读取除了bmfh的所有部分
		dibFile.Close();//关闭位图文件
		m_lpBmpInfo = (LPBITMAPINFO)m_lpDib;//设置位图信息指针
		m_lpBmpInfoHeader = (LPBITMAPINFOHEADER)m_lpDib;//设置位图信息头指针

		m_lpRgbQuad = (LPRGBQUAD)(m_lpDib + m_lpBmpInfoHeader->biSize);//	颜色表指针
		if (m_lpBmpInfoHeader->biClrUsed == 0)//当没有设置使用的颜色数时使用
		{
    
    
			m_lpBmpInfoHeader->biClrUsed = GetNumOfColor();
		}
		DWORD dwRgbQuadLength = CalcRgbQuadLength();//计算颜色表长度

		m_lpData = m_lpDib + m_lpBmpInfoHeader->biSize + dwRgbQuadLength;//数据指针,指向图片数据头

		if (m_lpRgbQuad == ((LPRGBQUAD)m_lpData))//如果不存在颜色表
		{
    
    
			m_lpRgbQuad = nullptr;//置空指针
			m_bHasRgbQuad = FALSE;//无颜色表
		}
		else
		{
    
    
			m_bHasRgbQuad = TRUE;
			//生成调色板略
		}
		//设置颜色表略
		m_lpBmpInfoHeader->biSizeImage = GetSize();//设置位图大小
		m_bVaild = TRUE;
		return TRUE;
	}
	else
 {
    
    
		m_bVaild = FALSE;
		return FALSE;
	}
	
}

位图颜色数获取

DWORD CDib::GetNumOfColor()//获取位图颜色数,DWORD表示颜色数
{
    
    
	UINT dwNumOfColor;//颜色数量
	if ((m_lpBmpInfoHeader->biClrUsed == 0) && (m_lpBmpInfoHeader->biBitCount < 9))//不超过256的图片biClrUsed都为0
	{
    
                                                                                               //biClrUsed 是指使用的颜色数量,256以下的都没颜色
		switch (m_lpBmpInfoHeader->biBitCount)
		{
    
    
		case 1: dwNumOfColor = 2; break;//2位位图
		case 4: dwNumOfColor = 16; break;//4位位图
		case 8: dwNumOfColor = 256; //8位灰度图
		}
	}
	else
	{
    
    
		dwNumOfColor = m_lpBmpInfoHeader->biClrUsed;
	}
	return dwNumOfColor;
}

计算颜色表长度

DWORD CDib::CalcRgbQuadLength()//计算位图颜色表长度
{
    
    
	DWORD dwNumOfColor = GetNumOfColor();
	if (dwNumOfColor > 256)
	{
    
    
		dwNumOfColor = 0;//24位真彩色图无调色板
	}
		return dwNumOfColor * sizeof(RGBQUAD);
}

获取位图尺寸与大小

LONG CDib::GetWidth()
{
    
    
	return m_lpBmpInfoHeader->biWidth;
}

LONG CDib::GetHeight()
{
    
    
	return m_lpBmpInfoHeader->biHeight;
}

DWORD CDib::GetSize()//获取位图大小
{
    
    
	if (m_lpBmpInfoHeader->biSizeImage != 0)
	{
    
    
		return m_lpBmpInfoHeader->biSizeImage;
	}
	else
	{
    
    
		return GetWidth() * GetHeight();
	}
}

3.图片的显示

BOOL CDib::Draw(CDC* pDC, CRect rect )
{
    
    
	if (!IsVaild()) return FALSE; // 位图无效
	HPALETTE hOldPalette = NULL;//旧的调色板句柄
	if (m_lpDib == NULL) return FALSE;//判断是否有数据
	if (m_hpalette != NULL)//如果有调色板,则选进设备环境里
	{
    
    
		hOldPalette = SelectPalette(pDC->GetSafeHdc(), m_hpalette, TRUE);
	}
	pDC->SetStretchBltMode(COLORONCOLOR);//设置位图伸缩模式
	将位图在设备上显示//
	StretchDIBits(pDC->GetSafeHdc(), rect.left, rect.top, rect.right-rect.left, 
		rect.bottom-rect.top, 0, 0, GetWidth(), GetHeight(), m_lpData, m_lpBmpInfo,
		DIB_RGB_COLORS, SRCCOPY);

	if (hOldPalette != nullptr)
	{
    
    
		SelectPalette(pDC->GetSafeHdc(), hOldPalette, TRUE);//恢复旧的调色板
	}
	return TRUE;
}

最后是一些判断语句

BOOL CDib::IsVaild()
{
    
    
	return m_bVaild;
}

BOOL CDib::HasRgbQuad()
{
    
    
	return m_bHasRgbQuad;
}

猜你喜欢

转载自blog.csdn.net/Dec1steee/article/details/127000098