zoukankan      html  css  js  c++  java
  • BMP文件的读取与显示

    有三个函数可以完成这一功能

    1.BitBlt   

    BitBlt 用于从原设备中复制位图到目标设备


    void CMFCApplication1View::OnDraw(CDC* pDC)
    {
    	CMFCApplication1Doc* pDoc = GetDocument();
    	ASSERT_VALID(pDoc);
    	if (!pDoc)
    		return;
    
    	CDC memDC;//定义一个设备上下文
    	memDC.CreateCompatibleDC(pDC);//创建兼容的设备上下文
    	CBitmap bmp;//定义位图对象
    	bmp.LoadBitmap(IDB_BITMAP1);//加载位图
    	memDC.SelectObject(&bmp);//选中位图对象
    	pDC->BitBlt(30, 20, 180, 180, &memDC, 1, 1, SRCCOPY);//绘制位图
    }


    2.StretchBlt   


    从源矩形中复制一个位图到目标矩形,必要时按目标设备设置的模式进行图像的拉伸或压缩,如果目标设备是窗口DC,则意味着在窗口绘制位图。
    函数从源矩形中复制一个位图到目标矩形,必要时按目标设备设置的模式进行图像的拉伸或压缩。也即是将内存中的位图拷贝到屏幕上,并且可以根据屏幕画图区的大小来进行伸缩,适应响应的屏幕(或图像控件)


    BOOL StretchBlt( int x, int y, int nWidth, int nHeight, CDC* pSrcDC, int xSrc, int ySrc, int nSrcWidth, int nSrcHeight, DWORD dwRop );
    x:逻辑单元x轴左上角坐标; (获取图像控件的DC后,该值一般设为 0 ) 
    y:逻辑单元y轴左上角坐标; (获取图像控件的DC后,该值一般设为 0 ) 
    nWidth: 设备矩形宽度;(即是图像控件的宽度,通过int rcWidth = rc.right - rc.left;来获得,rc为保存了图像控件矩形区坐标信息)
    nHeight:设备矩形高度;  (即是图像控件的高度,通过int rcHeight = rc.bottom - rc.top;来获得)
    pSrcDC: 源设备上下文;   (就是我们定义的内存DC,然后取地址)
    xSrc :源矩形x轴左上角坐标;   (一般都是整幅图片拷贝,所以该值为 0 )
    ySrc: 源矩形y轴左上角坐标;  (一般都是整幅图片拷贝,所以该值为 0 )
    Specifies the x-coordinate (in logical units) of the upper-left corner of the source rectangle.
    nSrcWidth:源矩形宽度;(如果我们定义了一个结构体BITMAP类型m_bmp保存位图信息,那么可以用m_bmp.bmWidth获取宽度)
    nSrcHeight:源矩形高度 ( 如果我们定义了一个结构体BITMAP类型m_bmp保存位图信息,那么可以用m_bmp.bmHeight获取宽度)
    dwRop:指定要进行的光栅操作。(这个有很多选择,我们一般选择SRCCOPY:将源矩形区域直接拷贝到目标矩形区域。)


    StretchBlt与BitBlt不同在于StretchBlt方法能够延伸或收缩位图以适应目标区域的大小

    void CMFCApplication1View::OnDraw(CDC* pDC)
    {
    	CMFCApplication1Doc* pDoc = GetDocument();
    	ASSERT_VALID(pDoc);
    	if (!pDoc)
    		return;
    	CDC memDC;//定义一个设备上下文
    	memDC.CreateCompatibleDC(pDC);//创建兼容的设备上下文
    	CBitmap bmp;//定义位图对象
    	bmp.LoadBitmap(IDB_BITMAP1);//加载位图
    	memDC.SelectObject(&bmp);//选中位图对象
    	CRect rc(30, 20, 210, 200);//定义一个区域
    	CBrush brush(RGB(0, 0, 0));//定义一个黑色的画刷
    	pDC->FrameRect(rc, &brush);//绘制矩形边框
    	//只是用来观察两者区别的,绘制一个矩形框
    	rc.OffsetRect(220, 0);//移动区域
    	//下边是利用StretchBlt绘制的位图
    	BITMAP BitInfo;//定义位图结构
    	bmp.GetBitmap(&BitInfo);//获取位图信息
    	int x = BitInfo.bmWidth;//获取位图宽度
    	int y = BitInfo.bmHeight; //获取位图高度
    	pDC->StretchBlt(rc.left, rc.top, rc.Width(), rc.Height(), &memDC, 0, 0, x, y, SRCCOPY);//绘制位图
    	pDC->FrameRect(rc, &brush);//绘制边框
    	brush.DeleteObject();//释放画刷
    	memDC.DeleteDC();//释放设备上下文
    	bmp.DeleteObject();//释放位图对象
    }




    3.StretchDIBits函数实现

    该函数将DIB(设备无关位图)中矩形区域内像素使用的颜色数据拷贝到指定的目标矩形中,如果目标设备是窗口DC,同样意味着在窗口绘制位图。


    StretchDIBits操作的是设备无关位图是内存中的RGB数据,你必须告诉这个函数关于位图的调色板、大小等信息,也就是位图头。


    完成功能:

    对话框程序,添加一个按钮,点击按钮后显示图片


    (1)设置BYTE*m_pBmpData为类的成员变量,我们要把图片的RGB数据装进去。


    (2)按钮的后台代码


    void Cbmp_readDlg::OnBnClickedShowbmp()
    {
    	CFile file;								//定义一个文件对象
    	file.Open(CString("C:\Users\jian\Desktop\z.bmp"), CFile::modeRead);//打开文件
    	DWORD  dwLen = file.GetLength();					//获取文件长度
    	file.Seek(14, CFile::begin);						//略过位图文件头
    	if (m_pBmpData != NULL)
    	{
    		delete[] m_pBmpData;
    		m_pBmpData = NULL;
    	}
    	m_pBmpData = new BYTE[dwLen - 14];					//为缓冲区分配空间
    	file.Read(m_pBmpData, dwLen - 14);					//读取文件数据到缓冲区
    	file.Close();								//关闭文件
    	OnPaint();
    }
    

    (3)重写OnPaint函数


    void Cbmp_readDlg::OnPaint()
    {
    	/*******************分隔线之间的代码自动生成的,不用管************************/
    	if (IsIconic())
    	{
    		CPaintDC dc(this); // 用于绘制的设备上下文
    
    		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
    
    		// 使图标在工作区矩形中居中
    		int cxIcon = GetSystemMetrics(SM_CXICON);
    		int cyIcon = GetSystemMetrics(SM_CYICON);
    		CRect rect;
    		GetClientRect(&rect);
    		int x = (rect.Width() - cxIcon + 1) / 2;
    		int y = (rect.Height() - cyIcon + 1) / 2;
    
    		// 绘制图标
    		dc.DrawIcon(x, y, m_hIcon);
    	}
    
    	/*******************分隔线之间的代码自动生成的,不用管。下面是添加的代码************************/
    	else
    	{
    		if (m_pBmpData != NULL)
    		{
    			BYTE *pHeader = m_pBmpData;			//定义一个临时缓冲区
    			BITMAPINFO BitInfo;			        //定义位图信息对象
    			memset(&BitInfo, 0, sizeof(BITMAPINFO));	//初始化位图信息对象
    			memcpy(&BitInfo, pHeader, sizeof(BITMAPINFO));	//为位图信息对象赋值
    			int nWidth = BitInfo.bmiHeader.biWidth;		//获取位图宽度
    			int nHeight = BitInfo.bmiHeader.biHeight;	//获取位图高度
    			pHeader += 40;					//指向位图数据
    			//输出位图信息,这里完成显示
    			StretchDIBits(GetDC()->m_hDC, 10, 40, nWidth, nHeight, 0, 0, nWidth, nHeight,
    				pHeader, &BitInfo, DIB_RGB_COLORS, SRCCOPY);
    		}
    		CDialogEx::OnPaint();
    	}
    }


    SetStretchBltMode


    当用StretchBlt缩小时,我们经常发现它会失真:其原因为当StrecthBlt() 的DestRect比SrcRECT小時 必須要將一些点去掉,他的预设做法 是將要去掉的点与旁边的点做AND运算,所以导致像素错误,在调用StretchBlt之前使用SetStretchBltMode函数,该函数可以设置指定设备环境中的位图拉伸模式,
    int SetStretchBltMode(HDC hdc, int iStretchMode)
    iStretchMode一般选用COLORONCOLOR,即直接將不要的点删掉。


    版权声明:

  • 相关阅读:
    数据库设计范式
    SQL 触发器
    SQL查询上月和本月两个月的语句
    angularjs学习总结 详细教程
    指令
    重复 HTML 元素
    AngularJS 数据绑定
    AngularJS 指令.
    AngularJS 数组
    AngularJS 对象
  • 原文地址:https://www.cnblogs.com/walccott/p/4956904.html
Copyright © 2011-2022 走看看