新开一贴,研究画图的问题

David_Hu 2012-04-27 10:26:12
看了画图大家都比较关心,于是我将我写了几个EXE,分别测试Ce下的刷图函数的
大家可以下载一下,然后测试

http://download.csdn.net/detail/hudaweikevin/4260273

代码我贴在下面,大家看一下这样写有没有问题


#define WIDETH_PIXEL_UNIT 800
#define HEIGHT_PIXEL_UNIT 480

int nBitsPixel= 16;

void DDCreate24BitmapInfo(PBITMAPINFO pbminfo,int dx,int dy)
{
ZeroMemory(pbminfo, sizeof(BITMAPINFO));

// setup bitmap info
pbminfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pbminfo->bmiHeader.biWidth = dx;
pbminfo->bmiHeader.biHeight = dy;
pbminfo->bmiHeader.biPlanes = 1;
pbminfo->bmiHeader.biBitCount = 24;
pbminfo->bmiHeader.biCompression = BI_RGB;
pbminfo->bmiHeader.biSizeImage = dx * dy * 3;// 图片缓冲区大小
return;
}

void
DDCreate16BitmapInfo(PBITMAPINFO pbminfo,int dx,int dy)
{
ZeroMemory(pbminfo, sizeof(BITMAPINFO));

// setup bitmap info
pbminfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pbminfo->bmiHeader.biWidth = dx;
pbminfo->bmiHeader.biHeight = dy;
pbminfo->bmiHeader.biPlanes = 1;
pbminfo->bmiHeader.biBitCount = 16;
pbminfo->bmiHeader.biCompression = BI_RGB;
pbminfo->bmiHeader.biSizeImage = dx * dy * 2;// 图片缓冲区大小
return;
}


void Cpaint_time_testDlg::OnBnClickedButton1()
{
// TODO: Add your control notification handler code here
HDC hdc = ::GetDC(m_hWnd);
BITMAPINFO bmi;
if(nBitsPixel == 16)
DDCreate16BitmapInfo(&bmi,WIDETH_PIXEL_UNIT,HEIGHT_PIXEL_UNIT);
else
DDCreate24BitmapInfo(&bmi,WIDETH_PIXEL_UNIT,HEIGHT_PIXEL_UNIT);

UCHAR * pdata=(UCHAR *)malloc(WIDETH_PIXEL_UNIT*HEIGHT_PIXEL_UNIT*3);


UCHAR temp=0;
int sum=0;
for (int i=0;i<10;i++)
{
memset(pdata,temp,WIDETH_PIXEL_UNIT*HEIGHT_PIXEL_UNIT);
temp=temp+0x44;
memset(pdata+WIDETH_PIXEL_UNIT*HEIGHT_PIXEL_UNIT,temp,WIDETH_PIXEL_UNIT*HEIGHT_PIXEL_UNIT);
temp=temp+0x44;
if(nBitsPixel == 24)
{
memset(pdata+WIDETH_PIXEL_UNIT*HEIGHT_PIXEL_UNIT*2,temp,WIDETH_PIXEL_UNIT*HEIGHT_PIXEL_UNIT);
temp=temp+0x44;
}

int startTime=GetTickCount();
StretchDIBits(hdc,0,0,WIDETH_PIXEL_UNIT,HEIGHT_PIXEL_UNIT,0,0,WIDETH_PIXEL_UNIT,HEIGHT_PIXEL_UNIT,pdata,&bmi,DIB_RGB_COLORS,SRCCOPY);
//SetDIBitsToDevice(hdc,0,0,WIDETH_PIXEL_UNIT,HEIGHT_PIXEL_UNIT,0,0,0,HEIGHT_PIXEL_UNIT,pdata,&bmi,DIB_RGB_COLORS);
int endTime=GetTickCount();
//Sleep(1000);
sum = sum + (endTime -startTime);
}

::ReleaseDC(m_hWnd,hdc) ;
CString result=L"";
result.Format(L"%d",sum/10);
SetDlgItemText(IDC_EDIT1,result);

free(pdata);
}

另外三个测试函数,大概就是替换了
SetDIBitsToDevice(hdc,0,0,WIDETH_PIXEL_UNIT,HEIGHT_PIXEL_UNIT,0,0,0,HEIGHT_PIXEL_UNIT,pdata,&bmi,DIB_RGB_COLORS);
StretchBlt(hdc,0,0,WIDETH_PIXEL_UNIT,HEIGHT_PIXEL_UNIT,hdcMem,0,0,WIDETH_PIXEL_UNIT,HEIGHT_PIXEL_UNIT,SRCCOPY);
BitBlt(hdc,0,0,WIDETH_PIXEL_UNIT,HEIGHT_PIXEL_UNIT,hdcMem,0,0,SRCCOPY);

另外我也贴一下我的测试结果:


测试环境 (A)
1024*600的16位深度 RGB16(ms) RGB24(ms)
DM3730,主频800
————————————————————————————————
1024*480 stretchDIBBits 94 stretchDIBBits 101
SetDIBitsToDevice 94 SetDIBitsToDevice 81
StretchBlt 94 StretchBlt 81
BitBlt 94 BitBlt 81
——————————————————————————————————————
800*480 stretchDIBBits 75 stretchDIBBits 79
SetDIBitsToDevice 75 SetDIBitsToDevice 65
StretchBlt 75 StretchBlt 65
BitBlt 75 BitBlt 65
——————————————————————————————————————
640*320 stretchDIBBits 39 stretchDIBBits 40
SetDIBitsToDevice 39 SetDIBitsToDevice 34
StretchBlt 39 StretchBlt 34
BitBlt 39 BitBlt 34


测试环境 (B)
800*480的16位深度 RGB16(ms) RGB24(ms)
DM3730,主频800
————————————————————————————————
1024*480 stretchDIBBits 65 stretchDIBBits 65
SetDIBitsToDevice 65 SetDIBitsToDevice 56
StretchBlt 65 StretchBlt 56
BitBlt 65 BitBlt 56
——————————————————————————————————————
800*480 stretchDIBBits 65 stretchDIBBits 65
SetDIBitsToDevice 65 SetDIBitsToDevice 56
StretchBlt 65 StretchBlt 56
BitBlt 65 BitBlt 56
——————————————————————————————————————
640*320 stretchDIBBits 38 stretchDIBBits 37
SetDIBitsToDevice 38 SetDIBitsToDevice 34
StretchBlt 38 StretchBlt 34
BitBlt 38 BitBlt 34


我没有其它平台,所以不知道其它平台会不会也这么慢,另外昨天跟EI稍微聊了一下,我们一致认为内存的拷贝也是一个重要的影响因素,我之前有做过测试内核空间的内存与用户空间内存的拷贝,1024*600*3大约是44MS,今天到时再做一个具体的测试,然后发上来。

希望大家测试自己的,然后再给一个结果上来大家分享一下,再个看我这些测试代码合不合理,不合理我们再来调整一下,最后整合了下,看是否有更好的效率提升手段。
...全文
175 21 打赏 收藏 转发到动态 举报
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
liangxd09 2012-09-18
  • 打赏
  • 举报
回复
结贴了哦

现在懂了,创建16位的bitmap,BitBlt才会快~~~

我在看一个库,发现
SetDIBitsToDevice 这个也挺快的
David_Hu 2012-04-28
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 的回复:]

这让我想到之前相关的问题:


CBitmap bmp;
bmp.LoadBitmap(IDB_BITMAP1);//800*480
CDC cdc;
cdc.CreateCompatibleDC(pdc);
cdc.SaveDC();
cdc.SelectObject(bmp);

int startTime=GetTickCount();
pdc->BitBlt(0,0……
[/Quote]

很慢是多慢,你的可能没有加速
mce2006 2012-04-28
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 的回复:]
这里有个疑问:定义
typedef struct tagBITMAPINFO {
BITMAPINFOHEADER bmiHeader;
RGBQUAD bmiColors[1];
} BITMAPINFO

bmiColors数组为1,上面代码访问了0、1、2,这是否越界了。
[/Quote]

这个完全不是问题

BITMAPINFO* pbmpInfo = (BITMAPINFO*)new BYTE[sizeof(BITMAPINFO) + sizeof(RGBQUAD) * 2];
liangxd09 2012-04-28
  • 打赏
  • 举报
回复
pbminfo->bmiColors[0].rgbBlue = 0;
pbminfo->bmiColors[0].rgbGreen = 0xF8;
pbminfo->bmiColors[0].rgbRed = 0;
pbminfo->bmiColors[0].rgbReserved = 0;
pbminfo->bmiColors[1].rgbBlue = 0xE0;
pbminfo->bmiColors[1].rgbGreen = 0x07;
pbminfo->bmiColors[1].rgbRed = 0;
pbminfo->bmiColors[1].rgbReserved = 0;
pbminfo->bmiColors[2].rgbBlue = 0x1F;
pbminfo->bmiColors[2].rgbGreen = 0;
pbminfo->bmiColors[2].rgbRed = 0;
pbminfo->bmiColors[2].rgbReserved = 0;



这里有个疑问:定义
typedef struct tagBITMAPINFO {
BITMAPINFOHEADER bmiHeader;
RGBQUAD bmiColors[1];
} BITMAPINFO

bmiColors数组为1,上面代码访问了0、1、2,这是否越界了。


liangxd09 2012-04-28
  • 打赏
  • 举报
回复
这让我想到之前相关的问题:


CBitmap bmp;
bmp.LoadBitmap(IDB_BITMAP1);//800*480
CDC cdc;
cdc.CreateCompatibleDC(pdc);
cdc.SaveDC();
cdc.SelectObject(bmp);

int startTime=GetTickCount();
pdc->BitBlt(0,0,WIDETH_PIXEL_UNIT,HEIGHT_PIXEL_UNIT,&cdc,0,0,SRCCOPY);
int endTime=GetTickCount();

CString result=L"";
result.Format(L"%d",endTime - startTime);
SetDlgItemText(IDC_EDIT1,result);

cdc.RestoreDC(-1);
bmp.DeleteObject();
cdc.DeleteDC();
ReleaseDC(pdc);


用这种方式来显示,很慢。
怎么改进??

IDB_BITMAP1:为16位和24位的bmp时。都没有改善。
csfinal9 2012-04-28
  • 打赏
  • 举报
回复
楼主,你的那个DDcreate16BitmapInfo()
是哪里的函数呢,我怎么搜了下没搜到
是DirectShow里的?
mce2006 2012-04-27
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 的回复:]
楼上英明,改了楼上的后,16位的刷图,1000*480都只要4个Ms了,
那为什么24位转成16位速度会差这么多

另外一个问题,假使我把系统颜色深度调整成为24,这个怎么改?

那改成24位颜色深度后,我刷新24位和图速度是不是会快,10个MS内解决
[/Quote]
是的,如果显示屏参是RGB888格式的,24位深度,10MS内照样可以搞写
你用16位565图快的原因,你的屏参是RGB565的
只要贴图参数和屏输出参数一致,不管多少位,速度都很快
David_Hu 2012-04-27
  • 打赏
  • 举报
回复
楼上英明,改了楼上的后,16位的刷图,1000*480都只要4个Ms了,
那为什么24位转成16位速度会差这么多

另外一个问题,假使我把系统颜色深度调整成为24,这个怎么改?

那改成24位颜色深度后,我刷新24位和图速度是不是会快,10个MS内解决
Reallyu 2012-04-27
  • 打赏
  • 举报
回复
void
DDCreate16BitmapInfo(PBITMAPINFO pbminfo,int dx,int dy)
{
ZeroMemory(pbminfo, sizeof(BITMAPINFO));

// setup bitmap info
pbminfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pbminfo->bmiHeader.biWidth = dx;
pbminfo->bmiHeader.biHeight = dy;
pbminfo->bmiHeader.biPlanes = 1;
pbminfo->bmiHeader.biBitCount = 16;
pbminfo->bmiHeader.biCompression = BI_RGB;
pbminfo->bmiHeader.biSizeImage = dx * dy * 2;// 图片缓冲区大小
return;
}

代码有问题,就算模拟器也比这个快,800x480全屏刷新大概30ms吧
首先要明确你的DIB和DDB格式一致,并且不缩放的时候速度是最快的
平台是16位色深度,也就是ddb是16位色的,一般是RGB565
所以16位色bmp的代码应该这样写

void
DDCreate16BitmapInfo(PBITMAPINFO pbminfo,int dx,int dy)
{
ZeroMemory(pbminfo, sizeof(BITMAPINFO));

// setup bitmap info
pbminfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pbminfo->bmiHeader.biWidth = dx;
pbminfo->bmiHeader.biHeight = dy;
pbminfo->bmiHeader.biPlanes = 1;
pbminfo->bmiHeader.biBitCount = 16;
pbminfo->bmiHeader.biCompression = BI_BITFIELDS;
pbminfo->bmiHeader.biSizeImage = 0;
// pbminfo 需要分配额外的空间来存放掩码
pbminfo->bmiColors[0].rgbBlue = 0;
pbminfo->bmiColors[0].rgbGreen = 0xF8;
pbminfo->bmiColors[0].rgbRed = 0;
pbminfo->bmiColors[0].rgbReserved = 0;
pbminfo->bmiColors[1].rgbBlue = 0xE0;
pbminfo->bmiColors[1].rgbGreen = 0x07;
pbminfo->bmiColors[1].rgbRed = 0;
pbminfo->bmiColors[1].rgbReserved = 0;
pbminfo->bmiColors[2].rgbBlue = 0x1F;
pbminfo->bmiColors[2].rgbGreen = 0;
pbminfo->bmiColors[2].rgbRed = 0;
pbminfo->bmiColors[2].rgbReserved = 0;
return;
}
David_Hu 2012-04-27
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 的回复:]

引用 12 楼 的回复:

引用 9 楼 的回复:

来汇报了:16位的不论大小都是47
24位的不论大小都是5
这是个什么结果呢?

HDC dc = ::GetDC(NULL);
nBitsPixel = ::GetDeviceCaps(dc, BITSPIXEL);
::ReleaseDC(NULL, dc);
你看一下你的机器是不是24位深度的,
另外我开始说……
[/Quote]

你的16bit慢是因为我的程序有问题,要按上面有人说的改一下

我程序的意图就是测试刷图的速度
zhengmeifu 2012-04-27
  • 打赏
  • 举报
回复
我是不明白你程序的意图。能解释一下吗?测试结果说明了什么呢?
csfinal9 2012-04-27
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 的回复:]

引用 9 楼 的回复:

来汇报了:16位的不论大小都是47
24位的不论大小都是5
这是个什么结果呢?

HDC dc = ::GetDC(NULL);
nBitsPixel = ::GetDeviceCaps(dc, BITSPIXEL);
::ReleaseDC(NULL, dc);
你看一下你的机器是不是24位深度的,
另外我开始说的线程里画图慢的问题清楚了,
……
[/Quote]

测过了,机器是16位深度的
David_Hu 2012-04-27
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 的回复:]

来汇报了:16位的不论大小都是47
24位的不论大小都是5
这是个什么结果呢?
[/Quote]
HDC dc = ::GetDC(NULL);
nBitsPixel = ::GetDeviceCaps(dc, BITSPIXEL);
::ReleaseDC(NULL, dc);
你看一下你的机器是不是24位深度的,
另外我开始说的线程里画图慢的问题清楚了,
BITMAPINFO bmi; 这个不能声明为全局变量,声明为全局变量就慢了

要声明成全局指针再去开辟空间
PBITMAPINFO bmi;
bmi = (BITMAPINFO*)malloc(sizeof(BITMAPINFO)+sizeof(RGBQUAD)*3);
DDCreate16BitmapInfo(bmi,WIDETH_PIXEL_UNIT,HEIGHT_PIXEL_UNIT);
csfinal9 2012-04-27
  • 打赏
  • 举报
回复
我的机器是三星6410主频不高600多M吧
csfinal9 2012-04-27
  • 打赏
  • 举报
回复
我的机器是三星6410主频不高600多M吧
csfinal9 2012-04-27
  • 打赏
  • 举报
回复
来汇报了:16位的不论大小都是47
24位的不论大小都是5
这是个什么结果呢?
David_Hu 2012-04-27
  • 打赏
  • 举报
回复
有人这样解释:
有可能会说得通了
线程调度和时间片大小有很大关系,时间片大小一般在OEMinit()中初始化,也可以通过SetThreadQuantum来修改,当然也有对应的Get函数。一般默认是100ms。
David_Hu 2012-04-27
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 的回复:]

什么意思呀?我下载800*480到目标机上,运行只有4个白框,测试结果是:6 6 6 4呀。这几项什么意思呀?
[/Quote]
实在不行,你按上面的源码自己写着试一下
David_Hu 2012-04-27
  • 打赏
  • 举报
回复
哈哈问题又来了,我的刷图是在MFC按钮事件里完成的,所以非常快,现在我做成一个线程在运行,刷图就是100多MS了,这是何解?
woshi_ziyu 2012-04-27
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 的回复:]

void
DDCreate16BitmapInfo(PBITMAPINFO pbminfo,int dx,int dy)
{
ZeroMemory(pbminfo, sizeof(BITMAPINFO));

// setup bitmap info
pbminfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pbminfo-……
[/Quote]
++
加载更多回复(1)

19,502

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 嵌入开发(WinCE)
社区管理员
  • 嵌入开发(WinCE)社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧