java.lang.OutOfMemoryError loading Images in Codename One - codenameone

This question refers to Codename One only.
I have a Form with a Tabs and each tab can contain an arbitrary number of images (taken from the Gallery).
Result: after few images (eight images from the gallery), on my Android device I get:
java.lang.OutOfMemoryError: Failed to allocate a 5683356 byte allocation with 1845080 free bytes and 1801KB until OOM
at dalvik.system.VMRuntime.newNonMovableArray(Native Method)
at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
at android.graphics.BitmapFactory.decodeStreamInternal(BitmapFactory.java:737)
at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:703)
at com.codename1.impl.android.c.b(AndroidImplementation.java:2037)
at com.codename1.r.z.a(Image.java:531)
at cool.teammate.apps.frontend.b.e.a$1.a(BasePageForm.java:208)
at com.codename1.r.l.b.a(EventDispatcher.java:349)
at com.codename1.impl.android.c.a(AndroidImplementation.java:7336)
at com.codename1.impl.android.CodenameOneActivity$6.run(CodenameOneActivity.java:527)
at com.codename1.r.r.n(Display.java:1298)
at com.codename1.r.r.l(Display.java:1242)
at com.codename1.r.r.k(Display.java:1130)
at com.codename1.r.aq.run(RunnableWrapper.java:120)
at com.codename1.impl.b$1.run(CodenameOneThread.java:60)
at java.lang.Thread.run(Thread.java:776)
Also iOS crashes, but I haven't the log.
Each image is scaled before showing (using the class FixedSizeButton, that I reported in this question). Any suggestion?
I guess that the dispose() method of Image can be useful, but it's written to "DO NOT CALL THIS METHOD UNLESS YOU KNOW WHAT YOU ARE DOING". Is it so problematic? For example, can it help if I dispose an Image after saving it to file and/or after scaling?
I also guess that System.gc() can be useful.
However, if few photos are so problematic... how can I make a photo gallery inside a Form without this kind of issues? Same problem to load hundreds of photo post inside an InfiniteContainer...
Note that the memory issue happens regardless if I insert the images as icon of a Button or as filled background of the Button.
Thank you for your suggestion.

You don't need to call dispose() or gc() for a proper application. You're trying to load a 5mb image which I'm assuming is a 5mb JPEG. That's probably from a 9+ mega pixel camera which means the decompressed size would be roughly 9 x 4 == 36MB!
So 36 x 8 = 288mb of RAM.
this.image = Image.createImage(this.imageWidth, this.imageHeight, 0xFFdddddd);
What's imageWidth/Height?
You might be taking a lot of RAM here...
this.setIcon(this.image);
EasyThread scalingThread = EasyThread.start("FixedSizeButton-ScalingImg-" + fileName);
Since you're creating multiple threads you might have all 8 images in RAM at once.
A better way is to use one image scaling thread. An even better approach is avoiding scaled altogether and using ImageIO to scale the image without loading it into RAM.

Related

What is the real weight of npm packages?

I want to add an image carousel to a profile page, and allow the user to view the images in fullscreen mode thanks to a modal. It means - if I'm not mistaken - that the carousel will be imported twice: once in the profile component, and another one on top of it when the modal opens.
It is a heavy process, and I'm afraid of performance issues. I thought about creating my own carousel, but there are already many packages that perfectly deal with hand gestures on mobile, etc. However, their weight is sometimes dreadful.
For instance, the library react-awesome-slider - which seems perfect - weights 666kb! However, on Bundlephobia, it is supposed to only weight 36.2kb or 8.2kb gzipped. Who is right?
Will react-awesome-slider weight 2*666kb, 2*36.2kb or 2*8.2kb in my final bundle? What is the maximum weight recommended to keep a high level of fluidity/performance?
This looks like premature optimization. Don't care about your bundle size in this manner - if 3kb gzip is a lot or not. Simply, if you need that library use it. You will understand that having library for summarizing of two numbers might not be necessary before any bundle size issue will appear.
Bundle size that you always care about is the gzipped value, that's what client receives and has to "download" - that takes time. But as you can imagine, downloading 30kb on your computer at home is not an issue. On old device in middle of Blairwitch forest it might be.
Also, it gets send to client once per page/application so if your modal has it and your page has it it won't be included twice. Imagine having some library like Lodash, which is big and used (if I exaggerate) in every function, do you think it be included 100 times?
Try to optimize the user experience in terms of ui/ux, that will be the first one user will quit your page for, not that he had to download 30kb of carousel, he will not even notice!

How to propery update an image in Nativescript?

I have the requirement to update an image in the App over and over again (displaying some generated data).
But after several intervals the app crashes with out of memory.
I'm updating the image with this line:
(that.detailImage.nativeElement).src = DummyImage.image1;
setting the image as base64-String. I already tried using res:// and external references and even local files. The problem stays: it keeps the memory.
Reducing the size of the image helps only to delay the crash, I even got the crash with an 1kb image, but it took some minutes.
You can find the "running" code at:
https://bitbucket.org/WarEagle/implementationproblems/src/944eedf10a14d60ec421e274760b3c2c3d9ae9a1/ImageTest/?at=master
I'm really interested in understanding what I'm doing wrong. Every solution I found so far said: "make the image smaller" but this only delays the problem.
Greetings
Torsten
p.s. don't wonder about the = undefined in the example-code, this is done because I'm setting the same image over and over again, than it works, but if I update the src-property with another image, it crashes, for this example I used = undefined to reproduce the problem without uploading thousands of images for changing them around.

av_read_frame reads frames from cache

I want to detect an object with my camera. For performance reason, i like to keep the connection to my camera alive and read new images on demand.
The function to read images calls av_read_frame till the frame is complete and then does some calculation.
My problem now is, that the frames "chain-up". If i stop frequently asking for new frames, i get old-images and not the current, because they're not yet readed (even i don't need them). If possible, i don't want to read the images with an additional thread because i don't want to waste resources on my RaspberryPi. Any ideas how to disable this "cache" or other ideas?

How do you make sure WPF releases large BitmapSource from Memory?

System: Windows XP SP3, .NET 3.5, 4GB RAM, Dual 1.6gHz
I have a WPF application that loads and transitions (using Storyboard animations) extremely large PNGs. These PNGs are 8190x1080 in resolution. As the application runs it appears to cache the images and the system Memory slowly creeps up. Eventually it chokes the system and throws the OutOfMemoryException.
Here are the steps I am currently taking to try to solve this:
1)I am removing the BitmapSource objects from the app
2)I am setting the BitmapSource BitmapCacheOption to None when I load the BitmapSource
3)I am Freezing the BitmapSource once it's loaded.
4)I am deleting all references to the Image that uses the source as well as any references to the source itself.
5)Manually calling GC.Collect() after above steps have completed.
Hoping to figure out why WPF is hanging onto memory for these images and a possible solution to ensure that the memory used to load them is properly recovered.
You certainly have put in a lot of work on this. I think the main problem is that BitmapCacheOption.None doesn't prevent the underlying BitmapDecoder(s) from being cached.
There are several tricky solutions to this such as doing a GC.Collect(), loading 300 small images from 300 different Uris, and calling GC.Collect() again, but the simple one is straightforward:
Instead of loading from a Uri, just construct a Stream and pass it to BitmapFrame's constructor:
var source = new BitmapImage();
using(Stream stream = ...)
{
source.BeginInit();
source.StreamSource = stream;
source.CacheOption = BitmapCacheOption.OnLoad; // not a mistake - see below
source.EndInit();
}
The reason this should work is that loading from a stream completely disables the cache. Not only is the top-level source not cached, but none of the internal decoders are cached either.
Why BitmapCacheOption.OnLoad? It seems counterintuitive, but this flag has two effects: It enables caching if caching is possible, and it causes the load to happen at EndInit(). In our case caching is impossible, so all it does it cause the load to happen immediately.
Obviously you'll want to run this code off your UI thread, then freeze the BitmapSource so you can move it over.
You may also wonder why I didn't use BitmapCreateOptions.IgnoreImageCache. Other than the fact that caching is impossible any with no URI given, the IgnoreImageCache doesn't completely ignore the image cache: It only ignores it for reading. So even if IgnoreImageCache is set, the loaded image is still inserted into the cache. The difference is that the existing image in the cache is ignored.

Using Silverlight 2 for short audio caching

I'm attempting to use a large number of short sound samples in a game I'm creating in Silverlight 2. The samples are less than 2 seconds long.
I would prefer to load all the audio samples onto the canvas during the initualization. I have been adding the media element to the canvas and a generic list to manage it. So far, it appears to work.
When I play the sample the first time, it plays perfectly. If it has finished playing and I want to re-use the same element, it cuts off the first part of the sound. To play the sample again, I stop and play the media element.
Is there another method I should use the samples so that the audio is not clipped and good performance is obtained?
Also, it's probably a good idea to make sure that all of your audio samples are brought down to the client side initially. Depending on how you set it up, it's possible that the MediaElements are using their progressive download functionality to get the media files from the server. While there's nothing wrong with this per se (browser caching should be helping you out after the initial download), it does mean that you have to deal with the browser cache, and there are some potential issues there.
Possible steps to try:
Mark your audio files as "Content". This will get them balled up in the .xap.
Load your audio files into MemoryStreams (see Application.GetResourceStream method) and call MediaElement.SetSource().
HTH,
Erik
Some comments:
From MSDN:
Try to limit the number of MediaElement objects you have in your application at once. If you have over one hundred MediaElement objects in your application tree, regardless of whether they are playing concurrently or not, MediaFailed events may be raised. The way to work around this is to add MediaElement objects to the tree as they are needed and remove them when they are not.
You could try to seek to the start of the sample to reset the point currently being played before re-using it with:
mediaelement.Position = new TimeSpan();
See also MSDNs MediaElement.Position.
One techique you can use, although I'm not sure how well it will work in Silverlight, is create one large file with all of your samples joined together (probably with a half-second or so of silence between each). Figure out the timecode for each sample and seek the media element to that position and play. You'll only need as many media elements as simultaneous sounds you want to play.

Resources