【问题标题】:XE7 FMX corrupted PNG thumbnailsXE7 FMX 损坏的 PNG 缩略图
【发布时间】:2015-02-22 02:27:43
【问题描述】:

在 XE7-Update1 FMX Windows7-64bit 中创建缩略图时遇到问题。 XE5 中不存在此问题。

我在 FMX HD 表单上有三个 TImage 组件,一个按钮和一个 TOpenDialog 组件。

使用 TOpenDialog,我选择了一个已经在 Photoshop/Corel 中测试过并且看起来不错的现有 PNG。图像在 Image1 中正确显示。

在运行时,我使用Image1.Bitmap.CreateThumbnail 创建两个缩略图,并将结果分配给 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;

任何关于如何解决这个问题的想法都会非常有帮助。

我们试过了:

  1. 无效
  2. 在分配缩略图之前设置 image2、image3 的大小
  3. 在分配缩略图之前清除 image2、image3

查看了 FMX.Graphics 中的 CreateThumbnail 代码,但我们发现没有什么可以更改以修补此问题。

【问题讨论】:

  • TBitmap.CreateThumbnail() 返回一个新的 TBitmap 对象。 TBitmap.Assign() 制作图像数据的副本,它不拥有原始数据的所有权。所以你正在泄漏那些TBitmap 对象。
  • @RemyLebeau 是的,非常正确。测试代码改变了,但结果是一样的。
  • try 应该紧跟在CreateThumbnail() 之后,而不是在Round() 之前。
  • 谢谢,你又是对的。如果尚未创建拇指,则代码不应尝试释放拇指,理论上,在我们创建拇指之前,Round 操作可能会失败。知道了。但这只是说明真正问题的测试代码。为什么大拇指坏了。你是说这是因为尝试不在正确的地方,还是因为我泄露了 TBitmaps(两者都是真的)?如果是这样,我想更详细地了解这一点。
  • 我认为 XE7 中存在问题,特别是因为即使泄漏的 TBitmap 版本也可以在 XE5 中使用。我们在一个更大的应用程序中发现了这个问题,并编写了这个“坏”代码来确定问题是否与我们的应用程序或 XE7 中的其他东西有关。也许有更好的方法来创建拇指?也许我的方法不正确?

标签: delphi png firemonkey delphi-xe7


【解决方案1】:

这当然是一个大错误。我拿了示例代码并自己尝试了。
结果:
1) Image2 不能很好地缩放,总是和 Image3 一样大小
2) 3 次尝试后 Image2 由两个重叠的图像组成:前面是第三次尝试的图像,后面是第一次尝试的图像。

这个过程是可重复的,图像的选择也不相关

【讨论】:

    【解决方案2】:

    由于这似乎是 XE7 的一个错误,我采用了另一种似乎在测试代码中有效的方法。我没有使用 TBitmap.CreateThumbnail 创建拇指,而是使用 TBitmap.LoadThumbnailFromFile 创建拇指,传递所需的拇指宽度和高度。我想在真正的应用程序中我们可以直接在可视组件中加载拇指,而不是在运行时创建 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;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-12-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-07-13
      • 1970-01-01
      • 2014-04-12
      相关资源
      最近更新 更多