Delphi XE7 FMX损坏的PNG缩略图
在XE7-Update1 FMX Windows7-64位中创建缩略图时遇到问题。XE5中不存在此问题 我有三个TImage组件,一个按钮和FMX HD表单上的TopEndDialog组件 使用TOpenDialog,我选择了一个已经在Photoshop/Corel中测试过的、看起来不错的现有PNG。图像在图像1中正确显示 在运行时,我使用Delphi XE7 FMX损坏的PNG缩略图,delphi,png,firemonkey,delphi-xe7,Delphi,Png,Firemonkey,Delphi Xe7,在XE7-Update1 FMX Windows7-64位中创建缩略图时遇到问题。XE5中不存在此问题 我有三个TImage组件,一个按钮和FMX HD表单上的TopEndDialog组件 使用TOpenDialog,我选择了一个已经在Photoshop/Corel中测试过的、看起来不错的现有PNG。图像在图像1中正确显示 在运行时,我使用Image1.Bitmap.create缩略图创建两个缩略图,并将结果分配给Image2和Image3。在XE7上,Image2和Image3的背景已损坏,表
Image1.Bitmap.create缩略图创建两个缩略图,并将结果分配给Image2和Image3。在XE7上,Image2和Image3的背景已损坏,表单的随机部分已损坏。使用XE5,一切都很好
当我重复这个过程(在Image1中加载PNG…创建缩略图并显示)时,损坏会增加
保存到文件时存在损坏的背景
代码如下:
procedure TForm1.Button1Click(Sender: TObject);
begin
FormShow(nil);
end;
procedure TForm1.FormShow(Sender: TObject);
var
thumbX, thumbY : Integer;
SaveParams: TBitmapCodecSaveParams;
thumb1, thumb2 : TBitmap;
begin
if OpenDialog1.Execute then
begin
Image1.Bitmap.LoadFromFile(OpenDialog1.FileName);
try
thumbX := Round(Image1.Width / 4);
thumbY := Round(Image1.Height / 4);
thumb1 := Image1.Bitmap.CreateThumbnail(thumbX, thumbY);
Image2.Bitmap.SetSize(thumbX, thumbY); //this has no impact
Image2.Bitmap.Assign(thumb1);
finally
thumb1.free;
end;
try
thumbX := Round(Image1.Width / 2);
thumbY := Round(Image1.Height /2);
thumb2 := Image1.Bitmap.CreateThumbnail(thumbX, thumbY);
Image3.Bitmap.SetSize(thumbX, thumbY); //this has no impact
Image3.Bitmap.Assign(thumb2);
finally
thumb2.Free;
end;
SaveParams.Quality := 100;
Image2.Bitmap.SaveToFile('c:\blackdot\image_quarter.png', @SaveParams);
Image3.Bitmap.SaveToFile('c:\blackdot\image_half.png', @SaveParams);
end;
end;
任何关于如何解决这个问题的想法都将非常有用
我们尝试:
使无效
在指定缩略图之前,设置image2、image3的大小
在指定缩略图之前清除image2、image3
查看了FMX.Graphics中的CreateThumbnail
代码,但是我们看到的没有什么可以改变的来修补这个问题。这肯定是一个大错误。我使用了示例代码,并亲自进行了尝试。
结果:
1) 图像2的缩放效果不好,并且始终与图像3的大小相同
2) 3次尝试后,图像2由两个重叠图像组成:前面是第三次尝试的图像,后面是第一次尝试的图像
该过程是可重复的,图像的选择也不相关,因为这似乎是XE7的一个缺陷,我采用了另一种方法,似乎在测试代码中也能起作用。我没有使用TBitmap.CreateThumbnail创建拇指,而是使用传递所需拇指宽度和高度的TBitmap.LoadThumbnailFromFile创建拇指。我想在真正的应用程序中,我们可以直接在可视化组件中加载thumb,而不必在运行时创建TBitmaps
尽管这种方法反复从磁盘加载文件,但它允许我们继续应用程序开发。使用测试代码,我可以反复加载图像,这些图像既直观又正确地保存到文件中
var
thumbX, thumbY : Integer;
SaveParams: TBitmapCodecSaveParams;
thumb1, thumb2 : TBitmap;
begin
if OpenDialog1.Execute then
begin
Image1.Bitmap.LoadFromFile(OpenDialog1.FileName);
thumbX := Round(Image1.Width / 4);
thumbY := Round(Image1.Height / 4);
//thumb1 := Image1.Bitmap.CreateThumbnail(thumbX, thumbY);
thumb1 := TBitmap.Create;
try
thumb1.LoadThumbnailFromFile(OpenDialog1.FileName, thumbX, thumbY);
thumb1.SaveToFile('c:\blackdot\thumb1.png'); //just to compare with our visual components
Image2.Bitmap.SetSize(thumbX, thumbY);
Image2.Bitmap.Assign(thumb1);
finally
thumb1.Free;
end;
thumbX := Round(Image1.Width / 2);
thumbY := Round(Image1.Height /2);
//thumb2 := Image1.Bitmap.CreateThumbnail(thumbX, thumbY);
thumb2 := TBitmap.Create;
try
thumb2.LoadThumbnailFromFile(OpenDialog1.FileName, thumbX, thumbY);
thumb2.SaveToFile('c:\blackdot\thumb2.png'); //just to compare with our visual components
Image3.Bitmap.SetSize(thumbX, thumbY);
Image3.Bitmap.Assign(thumb2);
finally
thumb2.Free;
end;
SaveParams.Quality := 100;
Image2.Bitmap.SaveToFile('c:\blackdot\image_quarter.png', @SaveParams);
Image3.Bitmap.SaveToFile('c:\blackdot\image_half.png', @SaveParams);
end;
end;
TBitmap.create缩略图()
返回一个新的TBitmap
对象TBitmap.Assign()
创建图像数据的副本,但不获取原始数据的所有权。所以你正在泄漏那些TBitmap
对象。@RemyLebeau是的,非常正确。测试代码已更改,但结果相同。try
应该紧跟在CreateThumbnail()
之后,而不是在Round()
之前。谢谢,你说得对。如果没有创建拇指,代码不应该尝试释放拇指,理论上,在我们创建拇指之前,Round操作可能会失败。知道了。但这只是说明实际问题的测试代码。为什么拇指被损坏了。你是说这是因为尝试不在正确的地方,还是我泄露了TBitmaps(都是真的)?如果是这样的话,我想更详细地了解这一点。我认为XE7中存在一个问题,特别是因为即使是泄漏的TBitmap版本也可以在XE5中工作。我们在一个大得多的应用程序中发现了这个问题,并编写了这个“坏”代码,以确定问题是否与我们的应用程序或XE7中的其他内容有关。也许有更好的方法来创造拇指?也许我的方法不正确?