提高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判断 } } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |