2
votes

Community,

my problem is the following:

I have written a XE7 FMX application for my Kindle Fire where I want to work with TBitmaps. The problem is, I'm unable to create a TBitmap from the storage of my device. If I run the application as a Win32-app on my computer all works, but if I run it as an android-app, it throws the exception from the title.

Here is my code:

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;

This code has no sense but this is only a test program. If this works I can use it in my main program but it already fails at this point. (And I have already checked that he used the FMX.Graphics.TBitmap and not the VCL)

Here is my stack:

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

Where is the error? Is it my fault or did delphi something wrong?

3
How big is the image? If it's very large, it may be exceeding the memory limits for the app. Can you tell us its dimensions and file size, please?David
Btw nice work for providing a short demo program - many people don't. It's great to see someone put in the debugging effort like this, especially for reproducing in a small test / demo. Nice work, and +1.David
My test image is very small. The file size is 8 KB and the image size is 290p*250p. I have only drawn with paint a casual black "A". There is no transparency or something special. I don't know why this test image can't be loaded.Adam
And if I put all these things together, I'm starting to believe that's a Delphi internal bug and not my fault. And if it is so, I have a big problem, because I need this for work...Adam
Try posting on the Google+ group, Delphi iOS and Android developers, with a link to the complete example project including the problematic image. Someone may be able to help you. Bitmaps do work on Android, I'm sure, so...David

3 Answers

1
votes

I seemed to have partly found a solution for images with known dimensions, this could very well be a delphi XE6/XE7 bug with android as it works with IOS and Win32/64?

My App worked with Min-SDK 10 set, as i changed it to sdk 15 or higher, i kept getting the same error as above, and in XE7, an exception string "Bitmap too large." If I specified the dimensions at exactly the file dimensions, it would work, yet dynamically if i loaded the png and it was a different size (smaller or bigger) would get "Bitmap too large." With SDK 10 it seems I could create a bitmap with no dimensions, if you try with no dimensions 15 > it doesn't load.

This works with any sized image file as long as you know the exact dimensions of the file:

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

Edit: After much testing and research (and weeping), I have found 2 things which have solved my problem.

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

This creates the bitmap according to the size of the file. The second solution which seems to be the main problem is the fact I was trying to create and load the bitmap from within a thread. To solve I put the load into a thread queue or synchronize

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

I imagine the TBitmap library is not thread safe on the android platform.

0
votes

Does it work if you create the bitmap first and loaf the file afterwards: TBitmap.Create(dimensions) and then LoadFromFile?

0
votes

I solved the same issue by changing the option "largeHeap" in the "Version Info" section from "False" into "True".

No more OutOfMemoryError after that.