讨论: 如何提高绘图效率(GDI,GDI++,Directx)

bigdiesel 2009-03-18 05:30:49

目前正在做一个信号处理的工作,要求将信号数据以谱图形式显示。当收到新的数据后,根据每组数据的大小计算出应该显示的颜色,同时将原来位图上移一位,在picturebox控件最下方显示出新的颜色点,达到平滑移动的效果。我目前采用了GDI的双缓存技术,但是画图的速度远远没有跟的上接收数据的速度,希望大家能够给我提一些更好的改进方案,提高我画图效率。(对另外两种画图方式,我还不是很了解,在此希望大家能够多多指教)

class CWBSpecView : public CFormView
{
CDC MemDC;
CBitmap MemBitmap;} //MemDC, MemBitmap为全局变量,
void CWBSpecView::OnInitialUpdate() //内存图层初始化
{

m_nScreenx=GetSystemMetrics(SM_CXSCREEN);
m_nScreeny=GetSystemMetrics(SM_CYSCREEN);
//内存图层初始化
CWnd *Specpic=this->GetDlgItem(IDC_PIC_SPEC);
CDC *SpecpicDC=Specpic->GetDC();
Specpic->GetClientRect(Rect2);
int w=Rect2.Width();
int h=Rect2.Height();
MemDC.CreateCompatibleDC(NULL);
MemBitmap.CreateCompatibleBitmap(SpecpicDC,m_nScreenx,m_nScreeny);
}
画图函数:
///////////////////////////////////////////////////////////////////
void drawpicSpec()
{ int count;
int nLevel;
count=4096;
CDrawpictureData* DrawpictureData=GetDrawpictureData();
ASSERT(DrawpictureData);
CMainFrame *pFrame=(CMainFrame *)AfxGetApp()->m_pMainWnd;
CWBSpecView *pView=(CWBSpecView *)(pFrame->m_pWBSpecview);
CWnd *Specpic=pView->GetDlgItem(IDC_PIC_SPEC);
CDC *SpecpicDC=Specpic->GetDC();
CRect Rect2;
Specpic->GetClientRect(Rect2);
int w=Rect2.Width();
int h=Rect2.Height();
CBitmap *poldBit=pView->MemDC.SelectObject(&pView->MemBitmap);
for(int i=0;i<count;i++)
{
MSG message;
while(::PeekMessage(&message,NULL,0,0,PM_REMOVE))
{
::TranslateMessage(&message);
::DispatchMessage(&message);
}
nLevel=ColorConf->Comppow(float(DrawpictureData->uiSonaData[i])); //此处计算色素索引值
pView->MemDC.SetPixelV(i*Rect2.right/count,Rect2.Height()-1,ColorConf->m_nColor[nLevel]); //根据色素索引值在最下一行画出
}
pView->MemDC.BitBlt(0,Rect2.top-1,w,h,&pView->MemDC,0,0,SRCCOPY); //将内存中图像上移一行
SpecpicDC->BitBlt(0,Rect2.top,w,h,&pView->MemDC,0,0,SRCCOPY);//将内存中图像显示
Specpic->ReleaseDC(SpecpicDC);
}

程序启动2个线程来工作,一个线程用来接收数据,令一个线程根据接收到的数据进行绘图。画图函数在线程中调用,目前我采用这种方法,每秒只能显示十几帧,根本不能将每秒全部接收的数据显示。请各路高手能帮我修改一下解决方法。在此多谢了。
...全文
1457 22 打赏 收藏 转发到动态 举报
写回复
用AI写文章
22 条回复
切换为时间正序
请发表友善的回复…
发表回复
chen2009zhou 2011-09-10
  • 打赏
  • 举报
回复
路过,来看看
clever101 2010-10-20
  • 打赏
  • 举报
回复
先做标记再学习。
bigdiesel 2009-04-05
  • 打赏
  • 举报
回复
多谢各位给我得修改意见,我试试直接写位图得方法
AliasKavin 2009-03-26
  • 打赏
  • 举报
回复
使用DX的平面绘图, 开硬件加速~!
aaaa3105563 2009-03-25
  • 打赏
  • 举报
回复
学习·····················
marine8086 2009-03-25
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 bigdiesel 的回复:]
如果直接改写位图,上移那一步,是不是会让效率更低呢
[/Quote]
这是最快的,想一想,你直接修改的是内存.
laviewpbt 2009-03-24
  • 打赏
  • 举报
回复
图像处理中用 setpixel就是 你在再好的机器配置也是白搭。

SetPixel要经过坐标系转化、剪裁区域判断、将颜色匹配为设备支持的最接近的,最后还要根据不同的颜色格式寻址、为将颜色写入其所在位进行位运算。经过这么多层处理,速度不慢才怪。

http://www.pcppc.cn/kaifa/VBjiaocheng/kaifa_18452.html
bigdiesel 2009-03-24
  • 打赏
  • 举报
回复
如果我只需要将原来图像上移一行后,在最下行按照计算出的色素值进行填充,除了在for循环中用setpixel()外,是否还有更好的解决方法呢?

现在可以确定是我的for循环占用时间太长,各位有没有些好的修改意见
Hiiishe 2009-03-24
  • 打赏
  • 举报
回复
我觉得速度瓶颈不在于GDI输出而在于你的逻辑
bigdiesel 2009-03-24
  • 打赏
  • 举报
回复
如果直接改写位图,上移那一步,是不是会让效率更低呢
marine8086 2009-03-24
  • 打赏
  • 举报
回复
setpixel 这样的函数是很慢的.
直接改写位图,然后一起BITBLT一下.
这样还不行的话,可以看一下用MMX指令,能提高几倍的速度.
bigdiesel 2009-03-24
  • 打赏
  • 举报
回复
如果我只需要将原来图像上移一行后,在最下行按照计算出的色素值进行填充,除了在for循环中用setpixel()外,是否还有更好的解决方法呢?
huojicha 2009-03-24
  • 打赏
  • 举报
回复
pView->MemDC.SetPixelV(i*Rect2.right/count,Rect2.Height()-1,ColorConf->m_nColor[nLevel]); //根据色素索引值在最下一行画出
你可以把参数在for循环外面算出来,省得他在for循环里面调用多次,还有for循环里面的参数能算出来的,就算出来,不要用函数来得到吧,省得函数调用栈时的开销
huojicha 2009-03-24
  • 打赏
  • 举报
回复
for(int i=0;i <count;i++)
{
MSG message;
while(::PeekMessage(&message,NULL,0,0,PM_REMOVE))
{
::TranslateMessage(&message);
::DispatchMessage(&message);
}
nLevel=ColorConf->Comppow(float(DrawpictureData->uiSonaData[i])); //此处计算色素索引值
pView->MemDC.SetPixelV(i*Rect2.right/count,Rect2.Height()-1,ColorConf->m_nColor[nLevel]); //根据色素索引值在最下一行画出
}

应该是这个for循环的问题,你可以用vs2005自带的性能分析工具测试一下,看在哪个函数哪里耗时最多.然后再那里优化他.
你在这个循环中要调用4096次里面的循环体,我相信这多半有问题,你把PeekMessage这段移到别的地方,然后这只是一个绘制的方法,做绘制的事情吧.

OGL中一般绘制的函数是这样调用的
while( msg.message != WM_QUIT )
{
if( PeedMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) ){
Translatemessage( &msg );
DispatchMessage( &msg );
}else
RenderScene( );
}
  • 打赏
  • 举报
回复
缓冲区可以设置得大一些,使用类似滑动窗口的方法处理
  • 打赏
  • 举报
回复
自己建一个缓冲区, 按 BITMAPHEADER自己建立位图格式数据, 在内存中完成操作,最后使用SetDIBBits显示
bigdiesel 2009-03-23
  • 打赏
  • 举报
回复
请教一下cqvoilet,用directx,该怎么修改我上面的代码呢,
我现在发现我的for循环里,setpixel,占用时间太长,
如果用directx,应该怎么修改
实达诚实 2009-03-18
  • 打赏
  • 举报
回复
Directx 或者GDI+
bigdiesel 2009-03-18
  • 打赏
  • 举报
回复
我的for循环,根据接收到的最新数据,来计算出每个数据需要表示的颜色值,并用setpixel()在最下一行画出
bigdiesel 2009-03-18
  • 打赏
  • 举报
回复
大家可不可以根据我的代码,用directx帮我优化一下
尤其bitmap上移,用directx该怎么解决
加载更多回复(2)

19,464

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 图形处理/算法
社区管理员
  • 图形处理/算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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