谁能将下面DirectDraw画图速度提高10倍? ( 积分: 100 )

  • 主题发起人 主题发起人 czw6296
  • 开始时间 开始时间
C

czw6296

Unregistered / Unconfirmed
GUEST, unregistred user!
以下程序是将屏幕分成3*3的小格子,每个格子填充颜色,当填充整个屏幕时,速度较慢,一秒钟只能进行2次。
有谁知道媒体播放器是如何填充颜色的,没有感觉到有停顿现象,不会使用setpixel吧,那样速度会更慢。
deltaw=3;
deltah=3;
void TForm1::Draw(void)//如何提高速度
{
HDC DC;
if (lpDDSPrimary->IsLost() == DDERR_SURFACELOST)
lpDDSPrimary->Restore();
if (lpDDSBack->GetDC(&DC) == DD_OK)
{
Canvas->Handle = DC;//能否不用Canvas,直接写缓存,加快速度?
if(phase)
{
top=1;
//填充方格颜色,当方格数量较多时,速度较慢
for(int i=0;i<Canvas->ClipRect.Bottom;i+=deltah)
{
left=1;
for(int j=0;j<Canvas->ClipRect.Right;j+=deltaw)
{
Canvas->Brush->Color=(TColor)RGB(255-i,255-j,255-i*j);
Canvas->FillRect(Rect(left,top,left+deltaw,top+deltah));
left+=deltaw;
}
top+=deltah;
}
Canvas->TextOutA(50,100,&quot;Front&quot;);
phase = 0;
}
else

{
top=1;
for(int i=0;i<Canvas->ClipRect.Bottom;i+=deltah)
{
left=1;
for(int j=0;j<Canvas->ClipRect.Right;j+=deltaw)
{
Canvas->Brush->Color=(TColor)RGB(255-i*j,255-j,255-i);
Canvas->FillRect(Rect(left,top,left+deltaw,top+deltah));
left+=deltaw;
}
top+=deltah;
}
Canvas->TextOutA(50,150,&quot;Back&quot;);
phase = 1;
}
lpDDSBack->ReleaseDC(DC);
}
}
以上程序来自c++builder的例子,我做了修改,如果有朋友想要源代码,请留下email共同探讨
 
以下程序是将屏幕分成3*3的小格子,每个格子填充颜色,当填充整个屏幕时,速度较慢,一秒钟只能进行2次。
有谁知道媒体播放器是如何填充颜色的,没有感觉到有停顿现象,不会使用setpixel吧,那样速度会更慢。
deltaw=3;
deltah=3;
void TForm1::Draw(void)//如何提高速度
{
HDC DC;
if (lpDDSPrimary->IsLost() == DDERR_SURFACELOST)
lpDDSPrimary->Restore();
if (lpDDSBack->GetDC(&amp;DC) == DD_OK)
{
Canvas->Handle = DC;//能否不用Canvas,直接写缓存,加快速度?
if(phase)
{
top=1;
//填充方格颜色,当方格数量较多时,速度较慢
for(int i=0;i<Canvas->ClipRect.Bottom;i+=deltah)
{
left=1;
for(int j=0;j<Canvas->ClipRect.Right;j+=deltaw)
{
Canvas->Brush->Color=(TColor)RGB(255-i,255-j,255-i*j);
Canvas->FillRect(Rect(left,top,left+deltaw,top+deltah));
left+=deltaw;
}
top+=deltah;
}
Canvas->TextOutA(50,100,&quot;Front&quot;);
phase = 0;
}
else

{
top=1;
for(int i=0;i<Canvas->ClipRect.Bottom;i+=deltah)
{
left=1;
for(int j=0;j<Canvas->ClipRect.Right;j+=deltaw)
{
Canvas->Brush->Color=(TColor)RGB(255-i*j,255-j,255-i);
Canvas->FillRect(Rect(left,top,left+deltaw,top+deltah));
left+=deltaw;
}
top+=deltah;
}
Canvas->TextOutA(50,150,&quot;Back&quot;);
phase = 1;
}
lpDDSBack->ReleaseDC(DC);
}
}
以上程序来自c++builder的例子,我做了修改,如果有朋友想要源代码,请留下email共同探讨
 
email : ak_20042008@163.com
发我一份吧
 
要一份研究一下
songyx0@126.com
谢谢
 
1、觉得可能是 FillRect 的问题。你每次就贴窄窄的一条,能快么?
后来创建一个 Bitmap,先用他的 ScanLine 方法进行填充,然后用 BitBlt 将 Bitmap 贴到画面上。由于 ScanLine 可以操作设备无关位图(Device Independent Bitmap),速度还是跟得上去的。至于速度提高 10 倍我没有概念,换个好显卡应该没问题。
2、你可以把要求说明,现写一个都不难。
 
你这是用gui 函数画图,不是用 dshow画图
 
如果用 想快 就得先把图画好 再贴过去
 
To vvyang :需求是这样的,我模拟大屏幕播放动画,大屏幕上的每个像素对应屏幕上的一个方格,每个像素的颜色值RGB存放在文件中,每播放一帧需要从文件中读取一帧数据的RGB值,把颜色值填入相应的方格内。要求每秒播放20帧左右,ScanLine如何处理?
To workshop:如何用dshow画图?是直接用API函数吗?能否给个例子?
 
DIRECTDRAW+MMX加速
 
FillRect是GDI方法,速度自然很慢,可以使用Blt的颜色填充,速度可以提高10倍以上.
ddbltfx.dwFillColor =(TColor)RGB(255-i,255-j,255-i*j);
rect=Rect(left,top,left+deltaw,top+deltah);
lpDDSBack->Blt(&amp;rect, NULL, NULL, DDBLT_COLORFILL, &amp;ddbltfx);
 
谢谢楼上,按照您的方法使用颜色填充速度只能提高2倍左右。继续努力,如果不使用Canvas,如何使用DirectDraw直接画园等图形?
 
3*3的大小.我提供两个方法实现....
1.只画1*1,再放大3倍....

2.3*3中其实是由9幅相同的图形构成的...你可只出一幅,其它8份BIT
(使用DIRECTDRAW的直接写屏技术,会快很多的,我用P4 2.4G的电脑,FPS 可达到70左右)
(对了.你图形的颜色数为多少的)
qq:112981347
 
to:wlong01
我使用DirectDraw每秒只有5次左右(在全屏方式下),每一屏要画1024*768/9=87381个小矩形,使用DirectDraw的colorfill。
显示器分辨率1024*768*32,一幅图像的颜色数最多可能87381,因为每个方格颜色都可以不同(也可能更多,方格可以更小)。
 
感兴趣的可以在QQ交流,QQ:178744902
 
关注中。。。
可以事先把每一帧图像画好,压缩存储,播放时解压,把整幅图像Blt到视频内存中,这样速度就很快。缺点是文件较大,媒体播放器好像就是这样处理的。
 
一个方法是按照vvyang说的,不过记住要操作的是dib位图,而不是普通的位图,效率没有试过。
另一个方法就是直接写表面了,大致代码贴出来,用的是网上封装好的ddraw单元,不过大概应该都可以看出来,初始化时是32位色的。
Type
TXX = packed record
R: Byte;
G: Byte;
B: Byte;
A: Byte;
end;

Axx = array [0..0] of TXX;
PAXX = ^AXX;

procedure TForm1.Button1Click(Sender: TObject);
var
i, j, K: Integer;
P: PAXX;
tick: cardinal;
DD: TDDSurfaceDesc2;
R: TRect;
begin

tick := GetTickCount;
for K := 1 to 50do

begin

R := ClientRect;
FillChar(DD, Sizeof(DD), #0);
DD.dwSize := Sizeof(DD);
Disp.GetBackBuffer.Lock(@R, dd, DDLOCK_WAIT or DDLOCK_WRITEONLY, 0);
P := DD.lpSurface;
for i := 0 to ClientHeight-1 do

begin

for j := 0 to ClientWidth-1do

begin

with p^[j]do

begin

R := 255-i*j;
G := 255-j;
B := 255-i;
A := 0;
end;

end;

P := PAXX(Pchar(P)+dd.lPitch);
end;

Disp.GetBackBuffer.Unlock(@R);
Disp.Flip;
end;

Caption := inttostr(GetTickCount-tick);
end;

在我的机器上50次也用不了1秒。
关键函数是lock和unlock,关键结构是_DDSURFACEDESC2,这些都可以从相关的文档中查到。
Over.
:Delphi的代码优化很有意思,如果把里面的A := 0去掉,那么速度会慢3倍,呵呵
 
DoubleWood提供了解决问题的另一个途径,方法很好。我不懂Delphi,但意思我明白,就是用一个像素颜色矩阵对应屏幕,最后就整个颜色矩阵放到屏幕上,避免了一次填充一个个小矩形,从而提高速度。
用C语言如何实现?在C中如何填写一个屏幕区域的RGB值
 
问题快解决了,谢谢大伙,继续努力。
有对directshow熟悉的吗,使用其中的DMO或者Filter速度是不是会更快?看了两天DirectX9.0头晕。
 
来晚了。写了一个简单的类,它的 Draw 方法采用 ScanLine 来实现同样的效果,每次贴图只用 20 ms。
unit DrawUtils;

interface

uses Windows, Graphics;

const
deltaw = 3;
deltah = 3;
deltaw2 = deltaw * 3;

type
TMemoryBitmap = class(TBitmap)
public
constructor Create;
override;
procedure CopyTo(hdcDest: HDC);
procedure Draw;
reintroduce;
end;


implementation

uses SysUtils;

{ TMemoryBitmap }

constructor TMemoryBitmap.Create;
begin

inherited Create;
PixelFormat := pf24bit;
end;


procedure TMemoryBitmap.CopyTo(hdcDest: HDC);
begin

BitBlt(hdcDest, 0, 0, Width, Height, Canvas.Handle, 0, 0, SRCCOPY);
end;


procedure TMemoryBitmap.Draw;
var
i, j: Longint;
p: PByteArray;
begin

for i := 0 to Height - 1do

begin

p := ScanLine;
j := 0;
while j < Width * 3do

begin

p[j] := 255 - (i div deltah * deltah) * (j div deltaw2 * deltaw);
p[j + 1] := 255 - j div deltaw2 * deltaw;
p[j + 2] := 255 - i div deltah * deltah;
Inc(j, 3);
end;

end;

end;


用起来很简单:
procedure TForm1.FormCreate(Sender: TObject);
begin

FbmpBuf := TMemoryBitmap.Create;
FbmpBuf.Width := Width;
FbmpBuf.Height := Height;
end;


procedure TForm1.FormDestroy(Sender: TObject);
begin

FbmpBuf.Free;
end;


procedure TForm1.Button1Click(Sender: TObject);
begin

FbmpBuf.Draw;
FbmpBuf.CopyTo(GetDC(Handle));
end;
 
估计提高不了这么多,填充一个BMp,然后放大3×3倍
 

Similar threads

I
回复
0
查看
612
import
I
I
回复
0
查看
774
import
I
I
回复
0
查看
516
import
I
I
回复
0
查看
582
import
I
后退
顶部