【问题标题】:Delphi XE7 Firemonkey - Creating a TBitmap form file throws EJNIException java.lang.OutOfMemoryErrorDelphi XE7 Firemonkey - 创建 TBitmap 表单文件抛出 EJNIException java.lang.OutOfMemoryError
【发布时间】:2015-01-04 11:28:53
【问题描述】:

社区,

我的问题如下:

我为我的 Kindle Fire 编写了一个 XE7 FMX 应用程序,我想在其中使用 TBitmaps。 问题是,我无法从设备的存储中创建 TBitmap。 如果我在我的计算机上将应用程序作为 Win32 应用程序运行,则一切正常,但如果我将其作为 android 应用程序运行,则会引发标题中的异常。

这是我的代码:

procedure TForm1.Button1Click(Sender: TObject);
var
  MyImage: TBitmap;
  Path: String;
begin
  Path := TPath.GetDocumentsPath + TPath.DirectorySeparatorChar + 'test.png';
  if TFile.Exists(path, true) then
  begin
    MyImage := TBitmap.CreateFromFile(path);        //<- Here it fails
  end;
end;

这段代码没有意义,但这只是一个测试程序。如果这可行,我可以在我的主程序中使用它,但此时它已经失败了。 (而且我已经检查过他使用的是 FMX.Graphics.TBitmap 而不是 VCL)

这是我的堆栈:

System._DbgExcNotify(86,0x11fc0b0,0x5bf3b0dd,0x11fc0b0,0x5bf3b0dd)
System.NotifyReRaise(0x11fc0b0,0x5bf3b0dd)
System._RaiseAtExcept(0x11fc0b0,0x5bf3b0dd)
System._RaiseExcept(0x11fc0b0)
System.Internal.Excutils.DoRaiseJNIExceptionCallBack('class java.lang.OutOfMemoryError','java.lang.OutOfMemoryError')
Androidapi.Jni.HandleJNIException(0xbe42f8)
Androidapi.Jnimarshal.ExecJNI(0x5d226490,0x125e998)
:5C8B8A14 DispatchToImport
:5C8C4FA8 dispatch_first_stage_intercept
Fmx.Graphics.Android.TBitmapCodecAndroid.LoadFromFile(0x127e7f8,'/data/data/com.embarcadero.Project1/files/test.png',0x1297040,4096)
Fmx.Graphics.TBitmapCodecManager.LoadFromFile(0x5cbab65c,'/data/data/com.embarcadero.Project1/files/test.png',0x1297040,4096)
Fmx.Graphics.TBitmap.LoadFromFile(0x127e788,'/data/data/com.embarcadero.Project1/files/test.png')
Fmx.Graphics.TBitmap.TBitmap(0x127e788,1,'/data/data/com.embarcadero.Project1/files/test.png')
Unit1.TForm1.Button1Click(0xad1c48,0x103dbd8)
[...] rest is unneccessary

错误在哪里? 是我的错还是delphi出了什么问题?

【问题讨论】:

  • 图片有多大?如果它非常大,它可能会超出应用程序的内存限制。请告诉我们它的尺寸和文件大小?
  • 顺便说一句,提供一个简短的演示程序做得很好——很多人不这样做。很高兴看到有人像这样投入调试工作,尤其是在小型测试/演示中重现。干得好,+1。
  • 我的测试图像非常小。文件大小为 8 KB,图像大小为 290p*250p。我只用颜料画了一个随意的黑色“A”。没有透明度或特殊的东西。不知道为什么这个测试图加载不出来。
  • 如果我把所有这些东西放在一起,我开始相信这是一个 Delphi 内部错误,而不是我的错。如果是这样,我有一个大问题,因为我需要这个来工作......
  • 尝试在 Google+ 组、Delphi iOS 和 Android 开发人员上发帖,并附上包含问题图像的完整示例项目的链接。有人可能会帮助你。位图确实可以在 Android 上运行,我敢肯定,所以...

标签: android delphi firemonkey delphi-xe7 tbitmap


【解决方案1】:

我似乎找到了部分解决已知尺寸图像的方法,这很可能是 android 的 delphi XE6/XE7 错误,因为它适用于 IOS 和 Win32/64?

我的应用程序使用 Min-SDK 10 集,当我将其更改为 sdk 15 或更高版本时,我一直收到与上述相同的错误,并且在 XE7 中,出现异常字符串“位图太大”。如果我在文件尺寸上指定尺寸,它会工作,但如果我加载 png 并且它是不同的尺寸(更小或更大)会动态地得到“位图太大”。 使用 SDK 10,我似乎可以创建一个没有尺寸的位图,如果你尝试没有尺寸 15 > 它不会加载。

只要您知道文件的确切尺寸,这适用于任何大小的图像文件:

 bmpscale:=1024;
try
    tb := TBitmap.Create(bmpscale,bmpscale);
    tb.LoadFromFile('img.png');
finally
    freeandnil(tb)
end;

编辑:经过大量测试和研究(和哭泣),我发现了两件事解决了我的问题。

tb:=TBitmap.CreateFromFile('img.png');

这将根据文件的大小创建位图。似乎是主要问题的第二个解决方案是我试图从线程中创建和加载位图。 为了解决我将负载放入线程队列或同步

TThread.queue(nil,
 procedure
      begin
          tb:=TBitmap.CreateFromFile('img.png');
      end);

我想 TBitmap 库在 android 平台上不是线程安全的。

【讨论】:

    【解决方案2】:

    如果你先创建位图然后再放文件,它是否有效:TBitmap.Create(dimensions) 然后是 LoadFromFile?

    【讨论】:

    • 由于这不是问题的实际答案,因此最好将其作为对原始帖子的评论发布。答案应保留给更明确的答复。
    • 我知道,但我没有足够的声誉来发表评论。如果可以,请随意移动它
    【解决方案3】:

    我通过将“版本信息”部分中的“largeHeap”选项从“False”更改为“True”解决了同样的问题。

    之后不再出现 OutOfMemoryError。

    【讨论】:

      猜你喜欢
      • 2016-12-11
      • 2011-12-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多