提高GDI显示速度

    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 wFrameWidth, 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, 0, 0, SRCCOPY);//拷贝到屏幕 3.3ms
}

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

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

}

倒像、拷贝、交换RB像素

void InvertedImage(void *pDst, void *pSrc, WORD wFrameWidth, 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判断
	}
}

 

转载于:https://www.cnblogs.com/hbg200/p/9595916.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值