【问题标题】:Bitmap creation gets all-black when generating lots of them生成大量位图时,位图创建全黑
【发布时间】:2012-12-04 10:53:02
【问题描述】:

我正在使用 Delphi 7,我必须从嵌入在我的 Delphi 应用程序中的 FlashMovie 生成大量位图。 图片清晰度为1010x720。

当我生成超过 6000 张图片时(数量每次都不一样),我得到一个 EOutOfResources 异常。 我环顾四周,似乎它可能来自缺少可用的句柄。

代码如下:

var
FFlashPlayerControlExport:TFlashPlayerControl;
Bmp:TBitmap;
pPNG:TPNGObject;

begin
Bmp := FFlashPlayerControlExport.CreateFrameBitmap;
Bmp.Width := StrToInt(aArgs[5]);
Bmp.Height := StrToInt(aArgs[6]);

pPNG := TPNGObject.Create;
pPNG.Assign(Bmp);
pPNG.SaveToFile(sFileName);
pPNG.Free;

DeleteObject(Bmp.Handle);
Bmp.Free;
end;

我在 Bmp.Free 之前尝试过 CloseHandle(Bmp.Handle),但我得到了 EExternalException。

感谢大家的帮助!


2012 年 12 月 6 日更新:

感谢Arioch'The的回答,我尝试直接设置FFlashPlayerControlExport的Width和Height,而不是使用Bmp.Width和Bmp.Height 它有帮助,因为现在我没有收到 EOutOfResources 异常,但 CreateFrameBitmap 会在一段时间后保存全黑图片。

FlashPlayerControl 仍在运行,因为我在屏幕上看到了图片。

代码更新:

var
FFlashPlayerControlExport:TFlashPlayerControl;
Bmp:TBitmap;
pPNG:TPNGObject;

begin
FFlashPlayerControlExport.Width := StrToInt(aArgs[5]);
FFlashPlayerControlExport.Height := StrToInt(aArgs[6]);

Bmp := FFlashPlayerControlExport.CreateFrameBitmap;

pPNG := TPNGObject.Create;
pPNG.Assign(Bmp);
pPNG.SaveToFile(sFileName);
pPNG.Free;

Bmp.Free;
end;

2012 年 12 月 20 日更新:

在联系 FlashPlayerControl 开发团队后,我发现当应用程序达到 10.000 个 GDI 对象时,位图会变黑。 他们为我的问题提供了有效的帮助,与他们联系很有效:)

我最终发现 GDI 对象泄漏来自我代码的另一个并行部分。 这个主题很接近:)

【问题讨论】:

  • 您可以尝试在引发异常之前添加ReportMemoryLeaksOnShutdown...您关闭应用程序并检查是否有任何内存泄漏以及哪种对象不是免费的...
  • 对于句柄泄漏,请参考这个问题:stackoverflow.com/questions/2180345/…
  • 该代码看起来很干净。你当然应该使用 try/finally。不要打电话给DeleteObject。让它在TBitmap 析构函数中发生。其他东西正在泄漏。
  • 您尝试过原始支持论坛吗?对于 300 美元的价格标签,他们应该为您提供支持,并且他们在那里非常活跃。 f-in-box.com/forum/viewforum.php?f=1
  • Bmp.Width := StrToInt(aArgs[5]); 这一行似乎也很奇怪。你真的做了6000次? 1:在循环之前执行一次 StrToInt。为什么在创建位图后调用它? 2:在一行中进行大小调整docwiki.embarcadero.com/Libraries/XE3/en/… 3:在创建位图之前,您不能在 F-In-BOX 组件上设置导出的大小吗?我不会下载 20MB 的演示,但我认为应该有一种方法,它应该是不同的顺序

标签: flash delphi bitmap delphi-7


【解决方案1】:

当错误代码使用由 TBitmap 创建的句柄时,可能无法正确清理句柄。此句柄泄漏累积并在几次此类泄漏后GetDC 开始失败。

EOutOfResource 异常的另一个原因是位图的尺寸错误。 VCL 单元 Graphics 中的 CopyBitmap 函数调用 GDICheck,它总是引发 EOutOfResource 异常,但也调用 GetLastError 以给出更合适的错误消息。

根据TPNGObject.Assign 的工作方式,您应该在释放位图之前调用ReleaseHandleFreeImage

http://docwiki.embarcadero.com/Libraries/XE3/en/Vcl.Graphics.TBitmap.ReleaseHandle

http://docwiki.embarcadero.com/Libraries/XE3/en/Vcl.Graphics.TBitmap.FreeImage

编辑:

调用ReleaseHandle 可能会使事情变得更糟,因为当没有人负责位图句柄时,它会导致句柄泄漏。

通常不需要致电FreeImage,但在类似情况下只帮助过我一次。

【讨论】:

  • @DavidHeffernan 我有一个非常相似的案例。当您不断创建和销毁位图时,它会导致 EOutOfResources。在我的情况下,我将位图添加到 TImageList。
  • 我不怀疑您遇到过类似的问题。只是这个提议的解决方案看起来不像一个解决方案。如果它真的是一个解决方案,也许你可以解释为什么 Q 中的代码泄漏位图句柄。就目前而言,这看起来像是试错法编程。
  • @DavidHeffernan 你是对的,我无法真正解释解决方案。失败的操作是 Vcl.Graphics CopyBitmap 中的 GetDC。 GetDC 和 ReleaseDC 之间一定存在不匹配,这是由FreeImage“治愈”的。我不知道为什么/没有时间调查。
  • @Jens - 你能切换到一个独立于 VCL 的库吗?喜欢 Graphics32.org 或 Vampyre Imaging 吗?深入到 GDI 上下文中只是为了将一个内存中的图像复制到另一个对我来说似乎太过分了!
  • 我想知道这是否仅适用于香草 Delphi 7.0。看起来他们在 Delphi 7 Update 1 中修复了非常相似的问题:edn.embarcadero.com/article/32337qc.embarcadero.com/wc/qcmain.aspx?d=2511 - 或者 TPngImage.Assign 中可能存在类似的泄漏?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-09
  • 2012-06-19
  • 2012-04-18
  • 2013-08-07
  • 2011-04-30
  • 1970-01-01
相关资源
最近更新 更多