gpt4 book ai didi

delphi - 将 ImgView32 透明图层保存为 PNG

转载 作者:行者123 更新时间:2023-12-03 15:26:45 29 4
gpt4 key购买 nike

我在将 ImgView32 图层保存为透明 PNG 时遇到问题。我使用 this question 中的代码进行储蓄。但是,图像以白色背景保存。

以下是我如何初始化 ImgView32,在其上创建一个图层,然后在其上画一条线:

procedure TputLine.FormCreate(Sender: TObject);
var
P: TPoint;
W, H: Single;
imwidth: integer;
imheight: integer;
begin
imwidth := Iv1.Width;
imheight := Iv1.Height;
with iv1 do
begin
Selection := nil;
Layers.Clear;
Scale := 1;
Scaled := True;
Bitmap.DrawMode := dmTransparent;
Bitmap.SetSize(imwidth, imheight);
Bitmap.Canvas.Pen.Width := 4;
end;
BL := TBitmapLayer.Create(iv1.Layers);
try
BL.Bitmap.DrawMode := dmTransparent;
BL.Bitmap.SetSize(imwidth,imheight);
BL.Bitmap.Canvas.Pen.Width := penwidth;
BL.Bitmap.Canvas.Pen.Color := pencolor;
BL.Location := GR32.FloatRect(0, 0, imwidth, imheight);
BL.Scaled := False;
except
BL.Free;
raise;
end;
end;

所以 iv1 是我的 ImgView32 的名称。然后我使用以下代码在其上画一条线:

var 
bm32:TBitmapLayer;
...
begin
bm32:=(iv1.Layers[0] as TBitmapLayer).Bitmap;
bm32.canvas.pen.color:=clwhite;
bm32.canvas.brush.color:=clwhite;
bm32.canvas.rectangle(0,0,bm32.width-1, bm32.height-1);

bm32.canvas.Pen.Color:=WinColor(ColorPickerGTK1.SelectedColor);
bm32.canvas.brush.color:=clWhite;
bm32.Canvas.Pen.Width:=3;
bm32.Canvas.MoveTo(0,bm32.Height);
bm32.Canvas.LineTo(0+150,bm32.Height-250);
end;

如果我在绘制矩形时使用 clWhite32 作为上述代码,那么在保存 PNG 时,imgView 的背景会变成黑色......所以我真的不明白这个问题。

我这样保存:

procedure TputLine.Button2Click(Sender: TObject);
var
myLay:TBitmapLayer;
begin
mylay := iv1.Layers.Items[0] as TBitmapLayer;
SavePNGTransparentX(mylay.Bitmap);
end;

以及实际的保存代码(来自上述链接)

procedure TPutLine.SavePNGTransparentX(bm32:TBitmap32);
var
Y: Integer;
X: Integer;
Png: TPortableNetworkGraphic32;

function IsWhite(Color32: TColor32): Boolean;
begin
Result:= (TColor32Entry(Color32).B = 255) and
(TColor32Entry(Color32).G = 255) and
(TColor32Entry(Color32).R = 255);
end;

begin
bm32.ResetAlpha;
for Y := 0 to bm32.Height-1 do
for X := 0 to bm32.Width-1 do
begin
if IsWhite(bm32.Pixel[X, Y]) then
bm32.Pixel[X,Y]:=Color32(255,255,255,0);
end;
Png:= TPortableNetworkGraphic32.Create;
Png.Assign(bm32);
Png.SaveToFile('C:\ThisShouldBeTransparent.png');
Png.Free;
end;

我不明白为什么它不将图层保存为透明PNG。我该如何修复它?欢迎任何想法。

您可以使用上面的代码复制我的问题。它使用 GR32_PNG 和 GR32_PortableNetworkGraphic。您只需将 TImgView32 控件添加到表单并添加上面列出的代码即可。

最佳答案

问题的原因似乎有两个。

  • 首先,当您在 GR32_PNG 单元中调用 Png.Assign(bm32); 时,它会尝试找出存储图像的最小格式。如果图像的不同颜色少于 256 种,它会创建调色板格式,并且根据找到的颜色数量,位深度可以变为 1、2、4 或 8。据我所知,只有具有 TrueColor 和Alpha 可以保存为可变透明度 png 图像。
  • 其次,您只使用一种颜色进行绘制,这会引发上述问题。这当然不是你的错,IMO 上述分析应该可以绕过。

TPortableNetworkGraphic32 类有两个属性,BitDepthColorType,它们控制 png 图像的格式,如果它们是可设置的,那就很有用了!尝试在代码中将它们设置为:

Png.BitDepth := 8;
Png.ColorType := ctTrueColorAlpha;

导致异常

EPngError with message 'Bit depth may not be specified directly yet!
EPngError with message 'Color Type may not be specified directly yet!

从措辞中我们可以假设 future 会有一些进一步的发展。

治疗

要绕过上述图像分析,您可以更改 GR32_PNG.pas 中的第 459 行。

procedure TPortableNetworkGraphic32.AssignPropertiesFromBitmap32()
var
...
begin
...
IsPalette := True; // <--- change to False
...

这将负责位深度分析并防止调色板创建(如果颜色少于 256 种)。在此 hack 之后,您可以使用 SavePNGTransparentX() 过程将 TBitmap32 保存到 .png 文件并保留透明度。

然后,还有一项您可能感兴趣的更改,涉及 SavePNGTransparentX() 过程。正如您所看到的,它要求绘图表面的背景为白色,因为它专门将所有白色像素的 Alpha channel 设置为零。然而,TBitmapLayer 初始化时所有像素 (RGBA) 均为零,因此每个像素的颜色分量组成黑色(由于 Alpha channel 为零,因此不可见)。因此,您需要用白色填充绘图层,使其不透明,从而再次覆盖所有较低层(绘图层下方)。

要对此进行更正,您可以

  • 去掉绘图层的初始化为全白
  • IsWhite 函数更改为 IsBlack 函数
  • 更改透明像素的分配

代码将变成

procedure TForm8.SavePNGTransparentX(bm32:TBitmap32);
var
Y: Integer;
X: Integer;
Png: TPortableNetworkGraphic32;

function IsBlack(Color32: TColor32): Boolean;
begin
Result:= (TColor32Entry(Color32).B = 0) and
(TColor32Entry(Color32).G = 0) and
(TColor32Entry(Color32).R = 0);
end;

function IsWhite(Color32: TColor32): Boolean;
begin
Result:= (TColor32Entry(Color32).B = 255) and
(TColor32Entry(Color32).G = 255) and
(TColor32Entry(Color32).R = 255);
end;

begin
bm32.ResetAlpha;
for Y := 0 to bm32.Height-1 do
for X := 0 to bm32.Width-1 do
begin
// if IsWhite(bm32.Pixel[X, Y]) then
// bm32.Pixel[X,Y]:=Color32(255,255,255, 0);
if IsBlack(bm32.Pixel[X, Y]) then
bm32.Pixel[X,Y]:=Color32( 0, 0, 0, 0);
end;

Png:= TPortableNetworkGraphic32.Create;
Png.Assign(bm32);
Png.SaveToFile('C:\tmp\imgs\ThisShouldBeTransparent3.png');
Png.Free;
end;

通过此更改,您可以看到绘图图层下方的图层,并且绘图图层的生成文件将使所有非绘制像素透明。然而,上述过程总体上仍然存在一个问题,那就是部分透明的像素失去了透明度,但这将在以后的练习中保留。

这里有一些图像,首先是在底层加载了位图的 ImageView:

enter image description here

然后,我基本上使用 Button1Click() 中的代码在 BL 层(引用您的代码)上绘制一个蓝色十字,但没有白色矩形。

enter image description here

然后,我将 BL 图层保存到 .png 文件中,并使用 Windows 资源管理器“预览”查看它:

enter image description here

关于delphi - 将 ImgView32 透明图层保存为 PNG,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29582157/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com