Android Question Downsampling image due to lack of memory

AlpVir

Well-Known Member
Licensed User
Longtime User
I have over 200 JPG images (all around 8000 pixels wide and 600 pixels high) that I see is (one at a time) with a complex system of sliding (they are 360 degree panoramas) and a scale factor of 1:1.

B4X:
BMP.Initialize (File.DirRootExternal, filename)
DestRect.Initialize (CurrentX, CurrentY, BMP.Width-CurrentX, BMP.Height-CurrentY)
SrcRect.Initialize (0, 0, BMP.Width, BMP.Height)
Gestures1.SetOnTouchListener (Panel1, "Handle_Touch")

Everything is working very well but two JPG files (about 14,000 pixels wide and 600 pixels high) appear very very small (about 400x15 pixels) and in the log window shows the message

Downsampling image due to lack of memory

How to fix it ?
In case of lack of memory I read that you should use LoadBitmapSample

I tried with BMP.InitializeSample but the image remains reduced (8000x300 pixels approx)
Thanks in advance
 

socialnetis

Active Member
Licensed User
Longtime User
Every image is loaded into memory without compressing, so you will have height*width*4 bytes per image.
So, an 8000x600 image is ~ 18mb, and 14000x600 ~ 32mb.

If you say you don't have problems with 8000x600 images, you could try LoadBitmapSample with MaxWidth 10000, and so the 14000x600 images will be about 10000x428 which is about ~ 16mb. And try to not have more than one image in memory at time.
 
Upvote 0

AlpVir

Well-Known Member
Licensed User
Longtime User
Why do you need to load the whole image?

I do not know how to not load the whole image, is a unique JPG files.
The standard image viewer has no problems with these great pictures !

Propose again below the code that should be concerned :
B4X:
If BMP.IsInitialized Then
  Dim Obj1 As Reflector
  Obj1.Target = BMP
  Obj1.RunMethod("recycle")
  BMP = Null     
End If   
Panel1.Initialize("")
Activity.AddView(Panel1, 0, 0, Main.LargSchermo , Main.AltSchermo )
Canvas1.Initialize(Panel1)
BMP.Initialize(File.DirRootExternal , Main.NomeFileCompleto)
DestRect.Initialize(CurrentX, CurrentY, BMP.Width-CurrentX, BMP.Height-CurrentY)
SrcRect.Initialize(0, 0, BMP.Width, BMP.Height)
Gestures1.SetOnTouchListener(Panel1, "Handle_Touch")

As an alternative, could I have a suggestion to make it appear, in these rare cases, a message "The image is not displayed correctly !"?
That is, how to catch the error that does not cause a shutdown of the app?

In a few days I will send this app in the forum "Share Your Creations" and then maybe the situation will be clearer.
Thanks
 
Upvote 0

CitizenGokuMauricio

Member
Licensed User
Longtime User
Hi there,
did you find a solution??...I have a very similar problem(too many .jpgs and .gif), my app going well in galaxys(phones and tablets) and other devices but in Xperia appears lack of memory and then crash,i see you use this code:
B4X:
If BMP.IsInitialized Then
  Dim Obj1 As Reflector
  Obj1.Target = BMP
  Obj1.RunMethod("recycle")
  BMP = Null    
End If
is this a better way to free ram than just BMP=Null?
Thanks.
 
Upvote 0

Informatix

Expert
Licensed User
Longtime User
When you deal with very large bitmaps and don't want to resize them, you have two solutions: load your images as textures with the libGDX library (they are not stored in the Java heap memory but in the native memory of your device) or set LargeHeap to true in the manifest if your app runs only with Android v3+.

About "recycle":
With a little demo and the monitor tool, I showed to one of my ULV donator that "recycle" is absolutely useless since Honeycomb. It was useful with Gingerbread and before because the garbage collector was unable to know the amount of memory that could be freed for each bitmap and it was split in two processes (and one of them could not be triggered before an OOM). It's completely different since Honeycomb.
 
Upvote 0

RonC.

Member
Licensed User
Longtime User
I must be loading my layouts wrong, not keeping the images in memory, or something. I'm having issues with 7 200x200 8-bit transparent PNG's with a file size of less than 20KB each. The program has only one string and one byte array of 7 as globals. I load the layout like this:

B4X:
If Activity.Width > Activity.Height Then
  Activity.LoadLayout("landscapelayout.bal")
Else
  Activity.LoadLayout("portraitlayout.bal")
End If

When I close out and change orientation multiple times (about 20~30 times) plus back & home screen twice, the program starts Downscaling. I know the normal user wouldn't do this, but I don't want such an error to show up... Note: this is happening in Debug (Rapid) Mode...

Is there garbage collection that I need to do at Activity.Pause or Activity.Resume, or is there a way to make the images used in the Layout stay in memory (as a process global), Make a new panel variable or should I set the LargeHeap to True in the manifest? This app is planned to be used by Android v3+... Confused and tried using Activity.RemoveAllViews and Activity.Initialize (I know, you're not supposed to do that. ;) ). Confused.

BTW: 24KB .otf is loaded as well in Activity_Create...
 
Last edited:
Upvote 0
Top