你的代码有几个bug:
if( Value.Graphic is TPngImage ) then
如果调用者的 TPicture
中没有包含 TPNGImage
,则您根本不返回任何内容。 Result
是未定义的。
实际上,您根本不应该检查 Graphic
的类型。各种 TGraphic
类可以相互赋值,从一个格式转换为另一种格式,因此应尽可能让此转换发生。
AnImage.Assign( TPngImage( Value ) );
您正在对
TPicture
本身进行类型转换。您需要对其
Graphic
进行类型转换。
Result := AnImage;
//AnImage.Free();
这要求调用者接管
TPNGImage
并释放它,这通常是一个不好的设计。
Image2.Picture.Assign( Effect( Image1.Picture ) );
比如说,调用者没有对返回的 TPngImage
进行所有权控制,导致它泄漏了。
如果你想要返回一个新的 TPNGImage
,请尝试下面这种方式:
function Effect(Value : TPicture) : TPngImage;
begin
Result := TPngImage.Create;
try
if (Value.Graphic <> nil) and (not Value.Graphic.Empty) then
begin
Result.Assign(Value.Graphic);
end;
except
Result.Free;
raise;
end;
end;
或者
function Effect(Value : TPicture) : TPngImage;
begin
Result := nil;
if (Value.Graphic <> nil) and (not Value.Graphic.Empty) then
begin
Result := TPngImage.Create;
try
Result.Assign(Value.Graphic);
except
Result.Free;
raise;
end;
end;
end;
无论哪种方式,你都可以这样做:
procedure TForm11.Button1Click(Sender : TObject);
var
AImage: TPngImage;
begin
AImage := Effect(Image1.Picture);
try
Image2.Picture.Assign(AImage);
finally
AImage.Free;
end;
end;
然而,更好的设计是根本不返回新的TPngImage
。传入2个TPicture
对象,让Effect()
根据需要进行操作:
procedure Effect(Input, Output : TPicture);
var
AnImage : TPngImage;
begin
AnImage := TPngImage.Create;
try
if (Input.Graphic <> nil) and (not Input.Graphic.Empty) then
begin
AnImage.Assign(Input.Graphic);
end;
Output.Assign(AnImage);
finally
AnImage.Free;
end;
end;
或者
procedure Effect(Input, Output : TPicture);
var
AnImage : TPngImage;
begin
if (Input.Graphic <> nil) and (not Input.Graphic.Empty) then
begin
AnImage := TPngImage.Create.Create;
try
AnImage.Assign(Input.Graphic);
Output.Assign(AnImage);
finally
AnImage.Free;
end;
end else
Output.Assign(nil);
end;
然后你可以这样做:
procedure TForm11.Button1Click(Sender : TObject);
begin
Effect(Image1.Picture, Image2.Picture);
end;
FastMM
(适用于此类目的的免费工具之一)。 - Josef Švejk