WHAT I AM TRYING TO DO
我正在尝试将多个图形绘制到Timage中,我绘制的这些图形由带有Foodfills和线条的有序图层组成 . 我使用多个缓冲区来确保订购和双缓冲 .
WHAT I AM DOING
procedure DrawScene();
var
ObjLength,LineLength,Filllength,Obj,lin,angle,i:integer;
Npoints : array[0..1] of Tpoint;
Objmap:TBitmap;
wholemap:TBitmap;
begin
wholemap := TBitmap.Create;
wholemap.Width:=area;
wholemap.height:=area;
ObjLength:=length(Objects);
for Obj:=0 to (ObjLength-1) do
if objects[Obj].Visible then
begin
// create object bitmap
if Objects[obj].Tag='FBOX' then
begin
Objmap := TBitmap.Create;
Objmap.Width:=area;
Objmap.height:=area;
Objmap.Transparent:=true;
Objmap.Canvas.Rectangle((objects[obj].Boundleft-4)+objects[obj].Position.x,area-((objects[obj].boundtop+4)+objects[obj].Position.y),(objects[obj].boundright+4)+objects[obj].Position.x,area-((objects[obj].boundbottom-4)+objects[obj].Position.y));
end;
//draw object
LineLength:=length(objects[Obj].Lines)-1;
angle:=objects[Obj].Rotation;
for lin:=0 to (LineLength) do
begin
for i:=0 to 1 do
begin
Npoints[i] := PointAddition(RotatePoint(objects[obj].Lines[lin].Point[i],angle),objects[obj].Position,false);
end;
Objmap:=DrawLine(Npoints[0].x,Npoints[0].y,Npoints[1].x,Npoints[1].y,objects[obj].Lines[lin].Color,Objmap);
end;
Filllength:=length(objects[Obj].Fills)-1;
for i:=0 to Filllength do
begin
Npoints[0]:=PointAddition(RotatePoint(objects[Obj].Fills[i].Point,objects[Obj].Rotation),objects[Obj].Position,false);
Objmap:=fillpoint( Npoints[0].x, Npoints[0].y,objects[Obj].Fills[i].color,Objmap);
end;
//write object to step frame
wholemap.Canvas.Draw(0,0,Objmap);
Objmap.Free;
end;
// write step frame to Visible Canvas
mainwindow.bufferim.Canvas.Draw(0,0,wholemap);
mainwindow.RobotArea.Picture.Graphic:=mainwindow.bufferim.Picture.Graphic;
wholemap.Free;
end;
WHAT I EXPECT
我期望看到每个图像对象彼此叠加,每个图像层都是该图层的完整图像 . 我的例子是它背后有一面旗帜的机器人 . 首先绘制标志然后绘制机器人 .
WHAT I GET(on a pc)
在电脑上,我得到了我所期待的,一切似乎都是正确的 .
WHAT I GET(on a laptop)
在几乎每台笔记本电脑和一些电脑上我只能看到机器人 . 我提出了一些判断,看它是否正在绘制旗帜,它确实如此 . 游戏甚至可以以正确的方式与旗帜互动 . 进一步的调查显示,它只显示最后一幅图像绘制了我的“drawcene”,并且当图像被直接绘制到wholecanvas everthing apeared时(这不能用于重叠填充层的原因)
WHAT I THINK IS HAPPENING
所以我推断出Timage的Timage.transparent属性不起作用或在某些机器上的计算方式不同 .
我做了一个测试,以证明这一点,并使帆布红色 . 然后到画布我画了0,0 i Timage,属性transparent = true,红色画布中间只有一个点 . 那件商品是一块白色的帆布,中间有一个圆点 .
我假设并且发现表明具有非常基本的图形驱动程序的机器似乎将null或透明视为白色,而更强大的机器似乎将null或透明视为透明 .
由于Timage.Transparent属性为true,这似乎有点失败 .
编辑:更新!!!似乎在ATI显卡上,如果颜色为“空”,那么它将以PF24bit的格式进行解释,因此没有alpha通道,也没有透明度 .
在Nvidia卡上它将它作为PF32bit并将null视为透明 .
解决这个问题的明显方法是将位图类型设置为PF32bit,但这仍然不起作用 . 我假设可能这还不够,我应该确保背景设置为透明而不是保留为空...但是在Timage中没有工具(我可以看到)用alpha设置颜色 . 所有画布绘图功能都需要一个RGB 24位的Tcolor和一个带有RGBA 32位的TcolorRef ....有没有用alpha 0绘制的方法?
WHAT I THINK I NEED TO KNOW
如何强制Transparent属性在所有机器上工作或者使笔记本电脑不以透明方式粘贴为白色或者达到相同结果的方法 .
任何人有任何解决方案或想法?
3 回答
我在过去(几年前)在不同的机器上看到了类似的行为 .
它们是由不同的视频卡和驱动程序引起的 . 无论是NVideo还是ATI都得到了错误的结果,但我忘记了哪些 .
它可以在笔记本电脑和普通PC上重现 .
那么:你使用什么视频卡和驱动程序?
--jeroen
我会为您创建的每个位图显式设置位图格式为pf32bit,以确保问题不会将颜色从32位转换为16位(如果这是位图的本机视频分辨率被创建),这可能会干扰透明度的工作方式 . 另外,我有更好的运气,专门设置过去的透明度颜色 .
另一种选择 - 从长远来看可能是更好的选择 - 是在图像上设置Alpha通道(即使用PNG文件),并使用GDI函数AlphaBlend()绘制图形 .
我一直在使用图形库(AggPas)来帮助绘制图形,我注意到的一件事是我总是需要一行
Bitmap.PixelFormat = pf32bit
才能让它画出透明度 .话虽如此,我使用AggPas库中的TransformImage将具有透明背景的Image复制到另一个,而AggPas仅接受pf24bit或pf32bits作为Pixel格式(否则它不会附加到位图)