提高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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在C++中使用GDI(Graphics Device Interface)显示一张图片,可以按照以下步骤进行操作: 1. 包含必要的头文件: ```cpp #include <Windows.h> ``` 2. 在窗口过程中添加绘图代码: ```cpp LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_PAINT: { PAINTSTRUCT ps; HDC hdc = BeginPaint(hwnd, &ps); // 创建并加载图片 HBITMAP hBitmap = (HBITMAP)LoadImage(NULL, L"path_to_image.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE); // 获取设备上下文 HDC hdcBitmap = CreateCompatibleDC(hdc); SelectObject(hdcBitmap, hBitmap); // 绘制图片 BITMAP bitmap; GetObject(hBitmap, sizeof(BITMAP), &bitmap); BitBlt(hdc, 0, 0, bitmap.bmWidth, bitmap.bmHeight, hdcBitmap, 0, 0, SRCCOPY); // 清理资源 DeleteObject(hBitmap); DeleteDC(hdcBitmap); EndPaint(hwnd, &ps); break; } case WM_DESTROY: { PostQuitMessage(0); break; } default: { return DefWindowProc(hwnd, msg, wParam, lParam); } } return 0; } ``` 3. 创建窗口并运行消息循环: ```cpp int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { // 注册窗口类 WNDCLASS wc = { 0 }; wc.lpfnWndProc = WndProc; wc.hInstance = hInstance; wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); wc.lpszClassName = L"ImageWindowClass"; RegisterClass(&wc); // 创建窗口 HWND hwnd = CreateWindow(L"ImageWindowClass", L"Image Window", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 800, 600, NULL, NULL, hInstance, NULL); // 显示窗口 ShowWindow(hwnd, nCmdShow); // 进入消息循环 MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (int)msg.wParam; } ``` 注意: - 将"path_to_image.bmp"替换为你自己的图片路径。 - 以上代码是基于Windows操作系统的。如果你使用其他操作系统,可能需要使用不同的图形库或API来实现类似的功能。 希望这能帮助到你!如果还有其他问题,请继续提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值