Bitmap透明绘制的效率问题,难道没有高手吗? ( 积分: 300 )

  • 主题发起人 主题发起人 hyh.nj
  • 开始时间 开始时间
H

hyh.nj

Unregistered / Unconfirmed
GUEST, unregistred user!
我的程序中用到3个Bitmap,将B1和B2设置为透明,分别在B1和B2上绘制图形,最后将B1和B2
上的内容使用TBitmap.Canvas.Draw方法叠加显示到B3上。现在的问题是透明绘制有时速度很快,大约20ms,有时速度很慢,大约要几百ms,在有的机器上速度快,在有的机器上速度慢,bitmap小时速度快,bitmap大时速度慢,而且没有一个过渡,比如bitmap宽设为400时需20ms,设为401时就一下变为500ms,这是什么原因,有什么解决的办法?
 
我的程序中用到3个Bitmap,将B1和B2设置为透明,分别在B1和B2上绘制图形,最后将B1和B2
上的内容使用TBitmap.Canvas.Draw方法叠加显示到B3上。现在的问题是透明绘制有时速度很快,大约20ms,有时速度很慢,大约要几百ms,在有的机器上速度快,在有的机器上速度慢,bitmap小时速度快,bitmap大时速度慢,而且没有一个过渡,比如bitmap宽设为400时需20ms,设为401时就一下变为500ms,这是什么原因,有什么解决的办法?
 
楼主先去了解一下基本的GDI原理,用GDI直接画。

或者使用GDI+,GDI+处理透明位图快
 
谢谢建议,最好能给点更明确的指导
 
找一本windows编程的书,里面有
 
用FastBmp如何?
 
不能用FastBmp,我是在做一个非可视绘图控件,不可能使用其它控件的功能
 
下面是一个例子,请参考
制作一个透明的TPanel
unit MyPanel;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ExtCtrls;

type
TMyPanel = class(TPanel)
private
{ Private declarations }
protected
{ Protected declarations }
procedure Paint; override;
public
{ Public declarations }
published
{ Published declarations }
end;

procedure Register;

implementation
procedure DrawParentImage(Control: TControl; Dest: TCanvas);
var
SaveIndex: Integer;
DC: HDC;
Position: TPoint;
begin
with Control do
begin
if Parent = nil then
Exit;
DC := Dest.Handle;
SaveIndex := SaveDC(DC);
{$IFDEF DFS_COMPILER_2}
GetViewportOrgEx(DC, @Position);
{$ELSE}
GetViewportOrgEx(DC, Position);
{$ENDIF}
SetViewportOrgEx(DC, Position.X - Left, Position.Y - Top, nil);
IntersectClipRect(DC, 0, 0, Parent.ClientWidth, Parent.ClientHeight);
Parent.Perform(WM_ERASEBKGND, DC, 0);
Parent.Perform(WM_PAINT, DC, 0);
RestoreDC(DC, SaveIndex);
end;
end;

procedure Register;
begin
RegisterComponents('Samples', [TMyPanel]);
end;

procedure TMyPanel.Paint;
var
Bitmap: TBitmap;
begin

if not (csDesigning in ComponentState) then
exit;
Bitmap := TBitmap.Create;
try
Bitmap.Height := ClientRect.Bottom;
Bitmap.Width := ClientRect.Right;

DrawParentImage(Self, Bitmap.Canvas);


canvas.CopyRect(ClientRect, Bitmap.canvas, ClientRect);
finally
Bitmap.free;
end;
end;

end.
 
谢谢无泪的参与,但还请看清我的问题,我现在可以实现透明绘制,但只是效率不能得到保证,我想知道原因及解决的办法
 
用MMX或者SSE自己写混合算法,多图层带alpha叠加,p4 1.x 约可在640*480, 3层32bit叠加上用MMX得到22-24fps的结果,这是我们自己写的测试结果。用SSEx会更快
 
你将代码贴出来看看
 
章慧,能不能给个图层叠加的例程啊,分不够可以再加!!!!!!!
EMail:hyh@raysoft.com.cn 谢谢!!!!!
 
好长的一段,南京的?雷软?没听过
。。
function DrawBmp(SrcBmp, DetBmp: TBitmap; SrcRect: TRect; DetPoint: TPoint; DrawStyle: Integer; Alpha:Byte; CPUCodeStyle: Integer; NeedEMMS: Boolean):Integer;
var
// DetWidth, DetHeight, SrcWidth, SrcHeight: Integer;
BytePerRowDet, BytePerRowSrc: Integer;
// SrcRect, ReginDet: TRect;
DetRect: TRect;
ReginWidth, ReginHeight: Integer;
。。。。。。
procedure Draw_MixAlpha_MMX;
label
NextLine, NextPixel, Finish, L1, L2, L3, L4, L5;
var
pDet, pSrc: PByteArray;
iReginWidth, iReginHeight: Integer;
iSubBytesDet, iSubBytesSrc: Integer;
iAlpha: Byte;
begin
if Alpha=0 then Exit;
pDet:=DetBmp.ScanLine[DetRect.Top];
Integer(pDet):=Integer(pDet)+(DetRect.Left)*4;
pSrc:=SrcBmp.ScanLine[SrcRect.Top];
Integer(pSrc):=Integer(pSrc)+(SrcRect.Left)*4;
iReginWidth:=ReginWidth;
iReginHeight:=ReginHeight;
iSubBytesDet:=BytePerRowDet;//+iReginWidth*4;
iSubBytesSrc:=BytePerRowSrc;//+iReginWidth*4;
iAlpha:=Alpha;
asm
//mm7=0
pxor mm7, mm7
//mm6=Mask($00ff000000000000)
mov eax, $FF000000
movd mm6, eax
punpcklbw mm6, mm7
//mm4=Alpha
mov dl, byte ptr iAlpha
movd mm4, edx;
PSLLQ mm4,48
punpckhwd mm4,mm4
punpckhwd mm4,mm4
//ecx=Det[y][x]
mov eax, dword ptr [pDet]
mov ecx, eax
//edx=Src[y][x]
mov eax, dword ptr [pSrc]
mov edx, eax
//for Y:=0 to iReginHeight-1
xor ebx, ebx
NextLine:
xor eax, eax
//for X:=0 to iReginWidth-1
NextPixel:
//mm0=Det
movd mm0, dword ptr [ecx+eax*4]
punpcklbw mm0, mm7
//mm1=Src
movd mm1, dword ptr [edx+eax*4]
punpcklbw mm1, mm7
//mm1*Alpha/256
pmullw mm1,mm4
psrlw mm1,8
//判断SrcAlpha和DetAlpha,避免255/256误差 //再议
// Push eax
// //check DetAlpha
// movq mm5, mm0
// packuswb mm5, mm5
// movd eax, mm5
// and eax, $FF000000
// jnz L1
// pxor mm0, mm0
// L1:
// //Check SrcAlpha
// movq mm5, mm1
// packuswb mm5, mm5
// movd eax, mm5
// and eax, $FF000000
// jnz L2
// pxor mm1, mm1
// L2:
// Pop eax
//MM2=(A2,A2,A2,A2);
movq mm2,mm1
punpckhwd mm2,mm2
punpckhdq mm2,mm2
//MM3=(255-A2,255-A2,255-A2,255-A2);
movq MM3,mm1
PXOR mm3,mm6
punpckhwd mm3,mm3
punpckhdq mm3,mm3
//MM1=(255,R2,G2,B2);
por mm1,mm6;
//(1)*(255-a2);
pmullw mm0, mm3
//(2)*(a2)
pmullw mm1, mm2
//(1)/255
psrlw mm0,8
//(2)/255
psrlw mm1,8
//(1)+(2)
paddusw mm0,mm1
Finish:
//64bit->32bit
packuswb mm0,mm0
//Save
movd dword ptr [ecx+eax*4],mm0

//for
Inc eax
cmp eax, iReginWidth
jnz NextPixel
//End Fro X
sub ecx, iSubBytesDet;
sub edx, iSubBytesSrc;
//for
Inc ebx
cmp ebx, iReginHeight
jnz NextLine;
//End Fro Y
end;
end;
。。主程序分块调他
 
呵呵,不过MMX还是没SSE快,但是好处就是Pentium机器就能用,没有指令不兼容问题。[:D]

嗯,南京的。哈哈,雇我做个兼职吧,或者分包也可以。正好在南京[:)]
 
救命啊:(
我把代码试了,好象不行耶!一些变量不知道该赋什么值。
汇编语言七八年没碰了,硬着头皮分析了一下,不太懂,
如mov dl, byte ptr iAlpha,但dl下面好象没用到啊?
烦请章大侠把完整的drawbmp函数发给我,最好有一个简单的例程。

至于兼职的事,好说好说,不知道你是哪个学校的,擅长什么?
 
发了email.
这么说来, ASP一直写,JSP给前一家公司写,PHP在自己公司写;
虽然MSSQLServer和Access也用,还是Oracle相对熟一些

通信也做,3层平台开发大型项目经验也有。
主要是Oracle+Tuxedo+WebLogic/SQLServer+MSDAC+自行搭建WebServer+客户端
Oracle+DOA+自行搭建WebServer+客户端的经验。

银行缴费/对帐接口,套打控件,收银机驱动,DirectX,嗯,这样看来
似乎没有什么擅长的。。
擅长delphi吧,98年开始用delphi的。
 
运行老会报错,我发了Email给你,请帮忙看看
 
宽度为width的图片只有 0 - width-1, -___-b。不能用width
不要犯这种错误啊
 
但透明叠加效果为什么出不来啊
 
指望用透明色去画是不成的。算了,再贴一段。
Procedure DrawBMPtoDC(Var SourceBMP: TBitmap; DC: HDC; Rect: TRect; WithAlpha: Boolean);
Type
TPixelLine = Array [Word] of TRGBQuad;
pPixelLine = ^TPixelLine;

Const
BitmapInfoHeader: TBitmapInfoHeader =
(biSize: sizeof(TBitmapInfoHeader);
biWidth: 100;
biHeight: 100;
biPlanes: 1;
biBitCount: 32;
biCompression: BI_RGB;
biSizeImage: 0;
biXPelsPerMeter: 0;
biYPelsPerMeter: 0;
biClrUsed: 0;
biClrImportant: 0);

Var
BitmapInfo : TBitmapInfo;
BufferDC : HDC;
BufferBits : Pointer;
OldBitmap,
BufferBitmap: HBitmap;
BytesPerRowDest: Integer;
ImageSource : Pointer;
ImageData : pPixelLine;
i, j : Integer;
z: ^Byte;
y: Byte;
w: Array [0..3] Of Byte;
Begin
FillChar(BitmapInfo, SizeOf(BitmapInfo), #0);
BitmapInfo.bmiHeader := BitmapInfoHeader;
BitmapInfo.bmiHeader.biWidth := SourceBMP.Width;
BitmapInfo.bmiHeader.biHeight := -1 * SourceBMP.Height;

BufferDC := CreateCompatibleDC(0);
If BufferDC = 0 Then Exit;
BufferBitmap := CreateDIBSection(BufferDC, BitmapInfo, DIB_RGB_COLORS, BufferBits, 0, 0);
If (BufferBitmap = 0) Or (BufferBits = Nil) Then
Begin
If BufferBitmap <> 0 Then DeleteObject(BufferBitmap);
DeleteDC(BufferDC);
Exit;
End;
OldBitmap := SelectObject(BufferDC, BufferBitmap);
StretchBlt(BufferDC, 0, 0, SourceBMP.Width, SourceBMP.Height, DC, Rect.Left, Rect.Top, SourceBMP.Width, SourceBMP.Height, SRCCOPY);

BytesPerRowDest := (((BitmapInfo.bmiHeader.biBitCount * SourceBMP.Width) + 31) And Not 31) Div 8;
ImageData := BufferBits;

For j := 0 to SourceBMP.Height - 1 Do
Begin
ImageSource := SourceBMP.ScanLine[j];
z := ImageSource;
For i := 0 to SourceBMP.Width - 1 Do
Begin
Move(z^, w, 4);
y := 255 - w[3];
With ImageData Do
Begin
rgbRed := (255 + w[2] * w[3] + rgbRed * y) Shr 8;
rgbGreen := (255 + w[1] * w[3] + rgbGreen * y) Shr 8;
rgbBlue := (255 + w[0] * w[3] + rgbBlue * y) Shr 8;
If WithAlpha Then rgbReserved := AlphaPlus(rgbReserved, w[3]);
End;
Inc(z, 4);
End;
LongInt(ImageData) := LongInt(ImageData) + BytesPerRowDest;
End;

StretchBlt(DC, Rect.Left, Rect.Top, SourceBMP.Width, SourceBMP.Height, BufferDC, 0, 0, SourceBMP.Width, SourceBMP.Height, SRCCOPY);
SelectObject(BufferDC, OldBitmap);
DeleteObject(BufferBitmap);
DeleteDC(BufferDC);
End;
 
后退
顶部