高手来~关于画图的效率问题(500FPS)

高手来~关于画图的效率问题(500FPS) Delphi / Windows SDK/API
http://www.delphi2007.net/DelphiMultimedia/html/delphi_20061018141036227.html
Timer_GetWave.Enabled:=false;  
                  timestart:=now();  
                  self.GroupBox_Draw.DoubleBuffered:=true;  
                  for   i:=0   to   500   do  
                  begin  
                                  getdata();  
                                  drawdata();  
                        //           PB.Canvas.Draw(0,0,_DrawMap);  
                  end;  
                  timeend:=now();  
                  self.LabelFPS.Caption:=inttostr(milliSecondsBetween(timestart,timeend));  
   
  -------------------------------------------------------------------------  
   
  用了双缓冲,以上代码的执行结果是1100毫秒.  
   
  如果我把PB.Canvas.Draw(0,0,_DrawMap);加上去,执行结果要9900毫秒,效率差了十倍.  
   
  请问有什么方法可以加上这句后效率不变化那么大~?  
   
  给个思路也好~~

对于占用大量计算时间的画图操作不能使用直接在PictureBox上画图的办法的,这样效率很低的,好久不做这方面的程序了,具体方法我说不清楚,你自己查,给你个思路。  
  第一步,计算需要的画图数据  
  第二步,在内存页(一般是bitmap对象)画出图形(这两步花费比较长的时间)  
  第三步,直接用显示组件(例如PictureBox)把画好的内存页直接调入,显示出来。  
  根据需要使用内存页的数量。  
  如果图形的计算与绘制本身就是要花很多时间,这个画图程序是没有办法降低画图时间的,但是使用上边的方法,可以消除绘画的过程(至少用户看不到),不会产生图形的闪烁。而且内存页的绘制时间本身也要比直接绘制显示还是要快。

好像要用到bitblt函数,如果组件不提供类似方法,就要用Windows   API了。

我就是用TBitmap在内存画的啊~~然后发觉贴出来的时候,  
    PB.Canvas.Draw(0,0,_DrawMap);  
  特别耗时间~~~  
   
  不执行   PB.Canvas.Draw(0,0,_DrawMap);的话比执行快很多~

_DrawMap就是个Tbitmap

显示本来就耗时间啊,需要从内存到显存复制,就是直接用BitBlt也快不了多少。  
  如果不需要动画效果,全部画完之后再更新显示就可以了,否则单独用一个线程(定时器也可以)来更新,每秒更新个15-30次就够了,完全不需要象你现在这样每秒50几帧。  
 

问题是公司需要.....  
   
   
  因为从波形采样频率很高....要是帧数低了就有可能错过某些采集来的重要信息.....  
 

你不是都保存了吗?不显示也不会丢失吧。  
 

不怕丢失,但得实时显示....

30FPS就是实时显示了。  
  你非要50FPS以上,没啥意义。  
 

for   i:=0   to   500   do  
                  begin  
                                  getdata();  
                                  drawdata();  
                        //           PB.Canvas.Draw(0,0,_DrawMap);  
                  end;  
  要求太高了,什么软件,如果真的是要求高效的制图,请使用DirectX,不要用原始方法。

DirectX~~~用不用装多什么开发工具~~~  
   
  没用过~~~~  
   
  能给个小例子看看吗~~?

要装DirectX开发包,例子我现在拿不出来,入门肯定也不容易,这个一般只有做3D游戏才需要,首先你弄清楚你的需求,不要乱来。

不知道你的具体需求,我只是讨论一下:  
  1)如果你采样的数据是历史增量数据,只需要在上面更新新的数据,而不需要整幅图重画吧。也就是你的DRAWDATA应该直接向PB的CANVAS上画,我想,如果新数据量应该不会很大吧。  
  2)如果新数据真的很大,就只能是使用DIRECTX了。  
  3)如果如你的程序给出的思路,那么也可以在显示的时候将一组合并成一帧来画吧。

opengl   可以看   nehe   入门例子做简单   还是可以的  
  另外teechart控件包有   封装   opengl   chart

netfly(支点)说得对,可以考虑只重画变化了的部分,不用全部重画。

只是简单绘制2D图,用什么速度都差不多。并不是你用DirectX(准确地讲是用DirectX中的DirectDraw)或者OpenGL就能快多少。  
  如果你是显示一个连续变化的波形(因为你有Timer_GetWave这种命名),那么可以使用ScrollDC把前一幅图卷动一下(左到右或者右到左之类的),然后画上更新的部分就可以了。  
 

谢谢各位!  
   
  现在问题解决了!说出来笑死人,郁闷了我好多天.....原来是给我用的那个笔记本电脑没显卡驱动  
  ......  
   
  我写的东西是用在工业超声探伤上的波形显示.  
   
   
   
  procedure   TForm1.Button1Click(Sender:   TObject);  
  var  
                  c1,t1,t2:int64;  
                  t3:double;  
  begin  
                  self.Button1.Enabled:=false;  
                  QueryPerformanceFrequency(c1);  
                  DrawCount:=0;  
                  self.Button1.Enabled:=false;  
                  QueryPerformanceCounter(t1);  
                  while   true   do  
                  begin  
                                  GetPoints;  
                                  Draw;  
                                  DrawCount:=DrawCount+1;  
                                  Form1.Edit1.Text:=IntToStr(DrawCount);  
                                  Application.ProcessMessages;  
                                  if   DrawCount=500   then  
                                  begin  
                                                  break;  
                                  end;  
                  end;  
                  QueryPerformanceCounter(t2);  
                  t3:=(t2-t1)/c1*1000;  
                  ShowMessage('实际经过时间'+FloatToStr(t3)+'毫秒');  
                  self.Button1.Enabled:=true;  
  end;  
   
   
   
   
  //取得模拟数据  
  procedure   GetPoints;  
  var  
                  x:integer;  
  begin  
  //取得数据  
                  for   x:=0   to   511   do  
                  begin  
                                  DrawPoints[x].X:=x;  
                                  DrawPoints[x].Y:=random(300);  
                  end;  
  end;  
  //画图  
  procedure   Draw;  
  begin  
                  //画背景入缓存  
                  Form1.Image1.Canvas.Brush.Color:=clBlack;  
                  Form1.Image1.Canvas.FillRect(Rect(0,0,512,300));  
                  //画波形入缓存  
                  Form1.Image1.Canvas.Pen.Style:=psSolid;  
                  Form1.Image1.Canvas.Pen.Color:=clGreen;  
                  Form1.Image1.Canvas.Polyline(DrawPoints);  
                  //画网格入缓存  
                  Form1.Image1.Canvas.Pen.Style:=psDot;  
                  Form1.Image1.Canvas.Pen.Color:=clRed;  
                  Form1.Image1.Canvas.MoveTo(0,30);  
                  Form1.Image1.Canvas.LineTo(511,30);  
                  Form1.Image1.Canvas.MoveTo(0,60);  
                  Form1.Image1.Canvas.LineTo(511,60);  
                  Form1.Image1.Canvas.MoveTo(0,90);  
                  Form1.Image1.Canvas.LineTo(511,90);  
                  Form1.Image1.Canvas.MoveTo(0,120);  
                  Form1.Image1.Canvas.LineTo(511,120);  
                  Form1.Image1.Canvas.MoveTo(0,150);  
                  Form1.Image1.Canvas.LineTo(511,150);  
                  Form1.Image1.Canvas.MoveTo(0,180);  
                  Form1.Image1.Canvas.LineTo(511,180);  
                  Form1.Image1.Canvas.MoveTo(0,210);  
                  Form1.Image1.Canvas.LineTo(511,210);  
                  Form1.Image1.Canvas.MoveTo(0,240);  
                  Form1.Image1.Canvas.LineTo(511,240);  
                  Form1.Image1.Canvas.MoveTo(0,270);  
                  Form1.Image1.Canvas.LineTo(511,270);  
                  Form1.Image1.Canvas.MoveTo(51,0);  
                  Form1.Image1.Canvas.LineTo(51,300);  
                  Form1.Image1.Canvas.MoveTo(102,0);  
                  Form1.Image1.Canvas.LineTo(102,300);  
                  Form1.Image1.Canvas.MoveTo(153,0);  
                  Form1.Image1.Canvas.LineTo(153,300);  
                  Form1.Image1.Canvas.MoveTo(204,0);  
                  Form1.Image1.Canvas.LineTo(204,300);  
                  Form1.Image1.Canvas.MoveTo(255,0);  
                  Form1.Image1.Canvas.LineTo(255,300);  
                  Form1.Image1.Canvas.MoveTo(306,0);  
                  Form1.Image1.Canvas.LineTo(306,300);  
                  Form1.Image1.Canvas.MoveTo(357,0);  
                  Form1.Image1.Canvas.LineTo(357,300);  
                  Form1.Image1.Canvas.MoveTo(408,0);  
                  Form1.Image1.Canvas.LineTo(408,300);  
                  Form1.Image1.Canvas.MoveTo(459,0);  
                  Form1.Image1.Canvas.LineTo(459,300);  
                  Form1.Image1.Canvas.MoveTo(510,0);  
                  Form1.Image1.Canvas.LineTo(510,300);  
                  //画边框  
                  Form1.Image1.Canvas.Pen.Style:=psSolid;  
                  Form1.Image1.Canvas.MoveTo(0,0);  
                  Form1.Image1.Canvas.LineTo(511,0);  
                  Form1.Image1.Canvas.MoveTo(0,299);  
                  Form1.Image1.Canvas.LineTo(511,299);  
                  Form1.Image1.Canvas.MoveTo(0,0);  
                  Form1.Image1.Canvas.LineTo(0,300);  
                  Form1.Image1.Canvas.MoveTo(511,0);  
                  Form1.Image1.Canvas.LineTo(511,300);  
                  bitblt(Form1.Canvas.Handle,Form1.Image1.Left,Form1.Image1.Top,512,300,Form1.Image1.canvas.handle,0,0,srccopy);  
   
  end;  
   
   
  在公司我用的机器上运行是8000多毫秒,在同事的机器上是1000多...  
   
  另外发现一个问题,同样的这个程序,我在家里用delphi7编译的时候,不用用到btiblt,image1直接画直接显示画面不会闪烁,拿到公司这部机器编译后运行就很闪,得加上btiblt才不会闪,公司的环境是delphi6.....  
   
  不知是不是跟delphi的版本有关~~~~~  
   
  现在试不了~回家再重新试试~!

感觉用btiblt的速度比在Form里面开双缓冲速度快一半.

开心~~~~~知道是电脑的问题....不是我能力问题......  
   
  一开始还很郁闷和我一起新进公司的那个同事很轻松就能达到500FPS....早上才发觉是因为没显卡驱动的原因~~~松了口气~!

posted on 2008-12-19 10:00  delphi2007  阅读(467)  评论(0编辑  收藏  举报