加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

提高GDI显示速度

发布时间:2020-12-14 03:46:52 所属栏目:大数据 来源:网络整理
导读:? ? GDI为API调用,应该好用,但有DC等怪异的概念,网上找找别人的程序,比葫芦画瓢,还是能显示图片的。显示内存位图的BitBlt经测试耗时为4.7ms,感觉慢,思来想去,问题应该出在biBitCount = 24的内存位图排列格式上,改为biBitCount = 32提速至3.3ms,内

? ? GDI为API调用,应该好用,但有DC等怪异的概念,网上找找别人的程序,比葫芦画瓢,还是能显示图片的。显示内存位图的BitBlt经测试耗时为4.7ms,感觉慢,思来想去,问题应该出在biBitCount = 24的内存位图排列格式上,改为biBitCount = 32提速至3.3ms,内存对齐,拷贝加快。以下为主要实现的源代码。

头文件

class CDrawImg
{
  public:

	 BYTE bzSrcImgBuf[MaxImgSize];//图像缓冲区

	 void Set(RECT ClientRect,WORD wFrameWidth,WORD wFrameHeight);// 设置参数
         void UpData(void);// 刷新显示
         void Close(HWND hWnd);// 关闭  
         void Resize(HWND hWnd);// 改变尺寸

	 void Install(HWND hWnd);// 安装
	 void UnInstall(HWND hWnd);// 卸载

  private:
	  
	  BYTE *pDIBImgDst; // 内存位图指针

	  WORD wFrameWidth,//帧宽度
	       wFrameHeight;//帧高度

	  DWORD dwFrameLength;//帧缓冲区长度

	  RECT ClientRect;//窗口客户区矩形

	  HDC hDC,// 设备对象
	      dcMem;// 设备内存对象
	  
	  HBITMAP bmp;// 位图内存对象
};

实现文件

void CDrawImg::Install(HWND hWnd)// 安装
{
	hDC = GetDC(hWnd);//获取设备
	dcMem = CreateCompatibleDC(hDC);//创建兼容设备的内存对象
	if (dcMem == NULL) return;//失败退出
}

void CDrawImg::UnInstall(HWND hWnd)// 卸载
{
	DeleteObject(bmp);//删除DIB
	DeleteDC(dcMem);//删除兼容DC
	ReleaseDC(hWnd,hDC);// 释放绘图设备
}

void CDrawImg::Set(RECT ClientRect,WORD wFrameHeight)// 设置参数
{ 
	this->wFrameWidth = wFrameWidth;
	this->wFrameHeight = wFrameHeight;
	this->ClientRect = ClientRect;
	WORD wLineLength = wFrameWidth * 3;//计算一行长度,调整到4字节的整倍数
	dwFrameLength = wLineLength * wFrameHeight;//计算帧长度
	
	BITMAPINFO bmpInfo; //创建位图 
	bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
	bmpInfo.bmiHeader.biWidth = wFrameWidth;
	bmpInfo.bmiHeader.biHeight = wFrameHeight;
	bmpInfo.bmiHeader.biPlanes = 1;
	bmpInfo.bmiHeader.biBitCount = 32;
	bmpInfo.bmiHeader.biCompression = BI_RGB;
	bmpInfo.bmiHeader.biSizeImage = 0;
	bmpInfo.bmiHeader.biXPelsPerMeter = 0;
	bmpInfo.bmiHeader.biYPelsPerMeter = 0; 

	bmp = CreateDIBSection(NULL,&bmpInfo,DIB_RGB_COLORS,(void **)&pDIBImgDst,NULL,0);//创建DIB
	SelectObject(dcMem,bmp);//从内存读出到兼容设备
}

void CDrawImg::UpData(void)// 刷新显示
{
	BYTE *pDst = pDIBImgDst;//重置初始地址
	InvertedImage(pDst,bzSrcImgBuf,wFrameWidth,wFrameHeight);//3ms
	BitBlt(hDC,ClientRect.left,ClientRect.top,ClientRect.right,ClientRect.bottom,dcMem,SRCCOPY);//拷贝到屏幕 3.3ms
}

void CDrawImg::Close(HWND hWnd)// 关闭
{
   
   
}

void CDrawImg::Resize(HWND hWnd)// 改变尺寸
{

}

倒像、拷贝、交换RB像素

void InvertedImage(void *pDst,void *pSrc,WORD wFrameHeight)//倒像拷贝
{
	WORD wWidth = wFrameWidth * 3;
	_asm
	{
		MOV BX,wFrameHeight;// 传递帧高度
		DEC BX;        // y减一
		MOV EDI,pDst; // 传递目标指针
	L0:
		MOV EAX,0;
		MOV EDX,0;
		MOV AX,wWidth; // 传递被乘数(行长度)
		MUL BX;         // 乘以乘数
		SHL EDX,16; // 左移16位
		OR EDX,EAX; // 合成32位,结果在EDX

		ADD EDX,pSrc; // 加入源目标
		MOV ESI,EDX; // 传递行源目标位置
		MOV CX,wFrameWidth; // 传递一行计数

	L1: 
		mov al,[esi + 0]; //取出B
		mov ah,[esi + 1]; //取出G
		mov dl,[esi + 2]; //取出R

		mov [edi + 0],dl; //存入R
		mov [edi + 1],ah; //存入G
		mov [edi + 2],al; //存入B

		add esi,3;//源步进3字节
		add edi,4;//目标步进4字节
		dec cx; //减一步
		jnz L1; //y判断,一行循环

		DEC BX;
		JNZ L0; //y判断
	}
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读