我正在构建一个具有“虚拟窗口”的应用程序。输出为TImage
对象。
1)应用程序将窗口外观文件加载到TPNGObject
:
2)然后,应用程序必须创建一个新的空白TPNGObject
,并将皮肤文件的大小调整为所需的大小,并在该空白图像上绘制它们。应该看起来像这样:
3)TImage
上的最终输出:
问题是我确实知道如何创建一个完全空白的屏幕外图像。当然,我每次都可以简单地将皮肤文件渲染到TImage
,但是调整皮肤文件的大小并创建窗口一次更容易也更好。
我正在使用Gustavo Daud的PNG图书馆,版本1。1564(2006年7月31日)。
答案 0 :(得分:5)
下面使用了Martijn Sally的'pngfunctions.pas'的CreatePNG
程序,从扩展库(pngcomponents)到pngimage。
var
Bmp, Mask: TBitmap;
PNG: TPNGObject;
begin
Bmp := TBitmap.Create;
Bmp.PixelFormat := pf24bit;
Bmp.SetSize(64, 64);
Bmp.Canvas.Brush.Color := clBtnFace;
Bmp.Canvas.Font.Color := clRed;
Bmp.Canvas.Font.Size := 24;
Bmp.Canvas.TextOut(4, 10, 'text');
Mask := TBitmap.Create;
Mask.PixelFormat := pf24bit;
Mask.Canvas.Brush.Color := clBlack;
Mask.SetSize(64, 64);
Mask.Canvas.Font.Color := clWhite;
Mask.Canvas.Font.Size := 24;
Mask.Canvas.TextOut(4, 10, 'text');
PNG := TPNGObject.Create;
CreatePNG(Bmp, Mask, PNG, False);
PNG.Draw(Canvas, Rect(10, 10, 74, 74));
// finally, free etc...
这是输出(黑色,白色方块是TS形状):
答案 1 :(得分:2)
我的另一个答案是我建议的另一种选择。但是你的问题仍然存在问题:PNG库必须有一个错误,它阻止任何画布绘图可见(使用带有COLOR_RGBALPHA作为颜色类型的CreateBlank构造函数)或者我们都遗漏了一些东西。
看起来我能看到的唯一解决方法是(正如您在编辑中提到的那样)使用位图来代替您的绘图。使用此位图的透明属性(Transparent: Bool
和TransparentColor: TColor
)设置图像的透明区域,然后在需要透明PNG时,只需将该位图复制到新的PNG对象即可。
BMP.Width:= 100;
BMP.Height:= 100;
BMP.Transparent:= True;
BMP.TransparentColor:= clWhite;
BMP.Canvas.Brush.Style:= bsSolid;
BMP.Canvas.Brush.Color:= clWhite;
BMP.Canvas.FillRect(BMP.Canvas.ClipRect);
BMP.Canvas.Brush.Color:= clBlue;
BMP.Canvas.Ellipse(10, 10, 90, 90);
PNG.Assign(BMP);
图像的白色区域应该是透明的。还有其他方法可以完成透明区域,但这是另一个主题。
图片:强>
这是你想要做的吗?
答案 2 :(得分:2)
事实证明CreateBlank
可以正常工作。问题是我在PNG画布上绘制了PNG(PNG.Canvas.Draw
)。 Canvas
并不真正支持透明度。要在另一个PNG上绘制半透明PNG,您需要一个将这两个层合并在一起的过程/函数。通过一些谷歌搜索,我最终得到了这个程序:
procedure MergePNGLayer(Layer1, Layer2: TPNGObject; Const aLeft, aTop: Integer);
var
x, y: Integer;
SL1, SL2, SLBlended: pRGBLine;
aSL1, aSL2, aSLBlended: PByteArray;
blendCoeff: single;
blendedPNG, Lay2buff: TPNGObject;
begin
blendedPNG := TPNGObject.Create;
blendedPNG.Assign(Layer1);
Lay2buff:=TPNGObject.Create;
Lay2buff.Assign(Layer2);
SetPNGCanvasSize(Layer2, Layer1.Width, Layer1.Height, aLeft, aTop);
for y := 0 to Layer1.Height - 1 do
begin
SL1 := Layer1.Scanline[y];
SL2 := Layer2.Scanline[y];
aSL1 := Layer1.AlphaScanline[y];
aSL2 := Layer2.AlphaScanline[y];
SLBlended := blendedPNG.Scanline[y];
aSLBlended := blendedPNG.AlphaScanline[y];
for x := 0 to Layer1.Width - 1 do
begin
blendCoeff:=aSL1[x] * 100/255/100;
aSLBlended[x] := round(aSL2[x] + (aSL1[x]-aSL2[x]) * blendCoeff);
SLBlended[x].rgbtRed := round(SL2[x].rgbtRed + (SL1[x].rgbtRed-SL2[x].rgbtRed) * blendCoeff);
SLBlended[x].rgbtGreen := round(SL2[x].rgbtGreen + (SL1[x].rgbtGreen-SL2[x].rgbtGreen) * blendCoeff);
SLBlended[x].rgbtBlue := round(SL2[x].rgbtBlue + (SL1[x].rgbtBlue-SL2[x].rgbtBlue) * blendCoeff);
end;
end;
Layer1.Assign(blendedPNG);
Layer2.Assign(Lay2buff);
blendedPNG.Free;
Lay2buff.Free;
end;
用法:
var
PNG1, PNG2: TPNGObject;
begin
PNG1 := TPNGObject.CreateBlank(COLOR_RGBALPHA, 16, 500, 500);
PNG2 := TPNGObject.Create;
PNG2.LoadFromFile('...*.png');
MergePNGLayer(PNG1, PNG2, 0, 0);
// PNG1 is the output
而且,对于想要提供帮助的用户,我感到非常抱歉,但由于不了解我,我感到非常抱歉。