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判断
}
}