Gro*_*rMD 3 delphi graphics png
我有一个函数,它将TPicture作为参数并返回一个TPngImage.为了保留原始图像,我创建了一个TPngImage并将TPicture复制到TPngImage,应用效果并返回TPngImage.就是这样.
function Effect( const Value : TPicture ) : TPngImage;
var
AnImage : TPngImage;
begin
if( Value.Graphic is TPngImage ) then
begin
AnImage := TPngImage.Create();
AnImage.Assign( TPngImage( Value ) );
//Apply effect
Result := AnImage;
//AnImage.Free(); //error
end;
end;
procedure TForm11.Button1Click( Sender : TObject );
begin
Image2.Picture.Assign( Effect( Image1.Picture ) );
end;
Run Code Online (Sandbox Code Playgroud)
在创建对象时,何时释放创建的对象.我不能在函数中调用TPngImage.Free(),因为它会在赋值之前销毁对象.那么如何释放创建的对象呢?当对象超出范围时,TPngImage是否调用其析构函数?据我所知,不释放对象会导致内存泄漏.
您的代码中有几个错误:
Run Code Online (Sandbox Code Playgroud)if( Value.Graphic is TPngImage ) then
如果调用者TPicture
尚未包含a TPNGImage
,则根本不返回任何内容.这Result
是未定义的.
事实上,你根本不应该检查它Graphic
的类型.TGraphic
可以为彼此分配各种类,将其图像数据从一种格式转换为另一种格式,因此您应该尽可能地进行转换.
Run Code Online (Sandbox Code Playgroud)AnImage.Assign( TPngImage( Value ) );
你是TPicture
自己的类型.你需要对它进行类型转换Graphic
.
Run Code Online (Sandbox Code Playgroud)Result := AnImage; //AnImage.Free();
这需要调用者获取TPNGImage
并释放它,这通常是一个糟糕的设计.
Run Code Online (Sandbox Code Playgroud)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);
//Apply effect
end;
except
Result.Free;
raise;
end;
end;
Run Code Online (Sandbox Code Playgroud)
要么
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);
//Apply effect
except
Result.Free;
raise;
end;
end;
end;
Run Code Online (Sandbox Code Playgroud)
无论哪种方式,您都可以这样做:
procedure TForm11.Button1Click(Sender : TObject);
var
AImage: TPngImage;
begin
AImage := Effect(Image1.Picture);
try
Image2.Picture.Assign(AImage);
finally
AImage.Free;
end;
end;
Run Code Online (Sandbox Code Playgroud)
但是,更好的设计是不返回新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);
//Apply effect
end;
Output.Assign(AnImage);
finally
AnImage.Free;
end;
end;
Run Code Online (Sandbox Code Playgroud)
要么
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);
//Apply effect
Output.Assign(AnImage);
finally
AnImage.Free;
end;
end else
Output.Assign(nil);
end;
Run Code Online (Sandbox Code Playgroud)
然后你可以这样做:
procedure TForm11.Button1Click(Sender : TObject);
begin
Effect(Image1.Picture, Image2.Picture);
end;
Run Code Online (Sandbox Code Playgroud)