Matplotlib image show in PyQt GUI stops with Memory Error - memory

Problem:
I've got a PyQt4 GUI application which has to import 16-bit grayscale image data and do some calculations on the image. The Gui has some control elements and a QTabWidget() element with two tabs, where one displays the image and the other represents the calculation results in a table. The image representation is done using Matplotlib.
In my applications I should be able to open images of up to 10000x12500 pixels which corresponds to 250MB of image data. Unfotunately, with my application I am only able to open images of about the size of 130MB. When importing and displaying data bigger than 8000x8000 pixels, my application stops showing Memory Error. Although the image itself is 128MB of size, the windows task manager shows 694MB of used memory for the python task. Images of the size 8000x9000 pixels can't be displayed any more.
My computer has 4GB of RAM memory. I don't think that the problem occurs due to insuffiecient memory.
Question:
How can I enable my application to display images of sizes up to 10000x12500 pixels grayscale 16-bit? Is there a Matplotlib internal limitation I can modify?
I searched the net but didn't find any answer. The closest problem description to the one I have can be seen in Excessive memory usage in Matplotlib imshow. But changing the display command from show() to draw() didn't help.
Thank you VERY MUCH for any help.

mapplotlib is not efficient with memory with images, there are multiple internal copies of the data.
Unless you have a gargantuan screen (at 300ppi, your image is 33in x 42in), your images are going to be down-sampled when they are displayed. I would suggest down-sampling your images to a size that is closer to the pixel count of the area it will actually be. You probably will want to write something do to adaptive down sampling based on what the user can actually see.
related question and answer

Related

iOS app crashes because images use too much ram

I know this is a stupid problem, but this is my first real app that I have to make, I have no one to ask and I looked up this problem and found no other similar problems.
My app crashes on real devices with no exception. I saw in the simulator that uses too much RAM and after a while I got to the conclusion that the pictures I am using are to blame.
The app is structured in this way: it has 8 viewControllers for different things: for example, it starts with one which lets the user select the avatar with which he/she will play and here I have two pictures, next is a viewController which shows the stats for that avatar and here it is another picture and so on. The problem is that each picture uses 40MB of RAM to be displayed and things add up so the app uses more than 300MB of RAM when the user gets to the gameviewCOntroller where the game is. Because of this, on devices like iPAD 2 or iphone 4 it crashes, but not on iphone 5.
I tried to set the images both from "images.xcassets" and from a ".atlas" folder, but the result is exactly the same. The pictures have a dimension of no more than 1500x1999px, they are in png format.
Also, I saw that if the app were to start directly into the gaveViewController it would use 180MB so the other viewController remain in memory or something like that. Should I "clear" them or something similar?
//-------update-------
This is what I got from Instruments:
Memory is a big deal on mobile devices, there is not a clear answer to you question, but I can give you some advices:
If your images are plain colors or have symmetric axes use resizable images. You can just use one line of pixel multiplied by with or height to cover the entire screen using a small amount of memory
Image compression doens't have effects when the image is decompressed. So if you have a png that is 600kb and you are thinking that converting in a 300kb will lower memory usage is only true for "disk space" when an image is decompressed in memory the size is widthXheightXNumber_of_channelXbit_for_channel
resize images: if are loading a 2000px square image into memory and you show it inside an image view of 800 px square, resize before adding it.You will have just a peak while resizing, but later it will use less memory
If you need to use big images, use tiling techniques such as CATiledLayer
If you don't need an image anymore get rid of it. It's ok to have an array of path to images, but not an array of full uncompressed images
Avoid -imageNamed it caches images and even if Apple says that this cache is released under memory pressure, you don't have a lot of control on it and it could be too late to avoid a crash
Those are general advices, it's up to you if they fit your requirements.
You should definitely follow Andrea's advices.
Additionally you should consider setting the image size to exactly what your need is. You're saying that you've tried to set them from xcassets so you have full control over the images you're loading, which is great (compared to downloading an image that you cannot modify).
I highly suggest you read some documentation on using Asset catalog files. This will allow you to have high-resolution image for bigger screens that also have more memory, and smaller ones for older devices, which is what you want here.
Also, note that 1500x1999px is still a very big size for most mobile devices.
More links about screen-size:
https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/MobileHIG/IconMatrix.html
http://www.paintcodeapp.com/news/iphone-6-screens-demystified

What's the best way to use big textures (2048*1536) in Unity3d with NGUI on ios?

I'm using Unity3d (4.3.1) and NGUI for creating an 2d iOS (iPad) app. Also I need to use a lot of full screen images (about 100 images with size 2048x1536), for Gallery for example.
Now I'm using them with GUI type, override for iPhone with max size 2048 and compression quality: normal. And I'm using a UITexture with Unlit/Transparent shader to show them.
However, after about 40 images in the project XCode returns the terminated due to memory error. So the question is, what type of images do I need, and with which preferences to make them work?
I'm using iPad 3 as a test device with XCode 5.1.1. I'll be thankful for any help!
Also I need to use a lot of full screen images (about 100 images with size 2048x1536), for Gallery for example.
I think your 2048x2048 size images use a very huge memory area. Basically, 2048 image use 16MB memory. So, this case need to use about a 1600MB memory! Normal application don't over about 200 MB.
So, I think you need to be reduce using a memory:
Remember that this texture is going to be expand 2048x2048 by unity.( http://www.opengl.org/wiki/NPOT_Texture ) So, if you are going to reduce file size to 1500x1000, your application still use 2048x2048 image. But if you can reduce file size to 1024x1024, do it. 1024 image just use 4 MB memory.
If you can use texture compression. Use it. PVRTC 4 bit ( https://docs.unity3d.com/Documentation/Manual/ReducingFilesize.html ) compression is make file size 1/8 than true color. Also memory size is going to reduce.(maybe reduced to half)
If your application don't display all images, load image dynamically. Use thumb nail.
Good luck:D
If you want to make a gallery-like app to render photos maybe you can try a different approach:
create two large editable textures and fill texels with image data (it must be editable otherwise you will no have access to write directly image data into them).
if you still have memory issues or if you want to use lower memory you can use several smaller textures as tiles. You can render then image parts to each smaller texture. Remember to configurate correctly the texture borders or so not use border texels to avoid wrapping problems.
Best way is to use a smaller texture. In an ipad you will need a magnifying glass to really appreciate the difference between 1024x1024 and larger textures. Remember an ipad screen is smaller (7"~10") than a computer one and with filtering enabled is really hard to tell the difference.
If you still need manager such a large texture for some other reason (zooming or similar) I recommend you one of the following approaches:
split the texture into layers with alpha channel (transparency): usually backgrounds can be rendered with lower resolutions.
split also the texture into blocks: usually most textures have repeating patterns.
use compression.
Always avoid use such large textures if possible.

High memory usage in the app

I have an app that has 12 images contained in an array. All these images are displayed at the same time on the screen. (1 view - 12 much wider and higher images (UIImageView's) one on another. When user does something, app moves the images, thus the view displays different scenes)
The images themselves are not too heavy (it is about 2500x5000 in size, but the whole folder with images is around 3.5 MB).
After loading, the app consumes 355 MB.
When I put breakpoint in viewDidLoad (and all images are loaded at that time), xcode shows that the app consumes only 9 MB, but in viewDidAppear it is 355 MB.
What is the reason of it? And how can I store images compactly? (As I assume that the problem is in the images).
Thank you for any help!
An image open will occupy something like : H x W x number of channel x number of bit for channel, the file size is another thing, because images are compressed according to their type. Your images are 50Mb each one in memory.
The only way is to resize the image before displaing them. There are plenty of image resizing categories online, just google a little bit.
The other suggestion is to not load all the images togheter, just bring in the array the file path, and instantiate the image lazily.
If you need to use hires images you should look for CATiledLayer and tiling techniques.
These images probably cannot be displayed all at the same time onscreen, so you may want to load them only when necessary.
If you still need to display them all together onscreen, think about reducing their size.
Still, 355Mb is huge. Are you doing anything else in that application, that might use up all of that memory?
In Xcode go to Product->Profile. You will find there a lot of useful instruments which will help you to find problems with memory, CPU or battery usage. However, check it if you haven't seen it before.

Display large images on iOS without precut tiles

I'm building a camera application that saves the image data to a single JPEG file in the sandbox. The images average at about 2mb in size.
Problem : I cannot display the images in a photo viewer because having a few images in memory throws memory warnings and makes scrolling through the images very slow.
I cannot split the image into tiles and save them to disk because that's even more expensive than displaying the single image. I tried splitting the image up into tiles upon capture, but on the 5S it took, on average, 5 1/2 seconds to save all the tiles to disk. It will only get worse from there as the app is executed on older devices. This is very bad because what if the user exists the app in the middle of the save? I will have missing tiles and no uncompressed original file to find missing tiles later.
Question : what's the best way to show a full sized image without causing memory issues and keeping the scrolling fast? Tons of camera applications on the App Store do this and the Photos app does this, there has to be a good solution.
Note : I'm currently showing a thumbnail of the image and then loading the full size image from disk in another thread. Once the full size image loading has finished, I present the full size image on the main thread. This removes the memory issues because I only have one full size image in memory at once, with two thumbnails, but still causes lagging on the scrollview because drawing the full size image in the main thread is still pretty expensive.
I would greatly appreciate any input!
you could..
create a down sized thumb nail..
create a smaller image and save that in a different "sandbox" folder.. and read that for browsing.. then after that load the image if the user wants to look at it full size.
One way to deal with this is to tile the image.
You can save the large decompressed image to "disk" as a series of tiles, and as the user pans around pull out only the tiles you need to actually display. You only ever need 1 tile in memory at a time because you draw it to the screen, then throw it out and load the next tile. (You'll probably want to cache the visible tiles in memory, but that's an implementation detail. Even having the whole image as tiles may relieve memory pressure as you don't need one large contiguous block.)
This is how applications like Photoshop deal with this situation.
Second way which I suggest you is to
check the example from Apple for processing large images called PhotoScroller. The images have already been tiled. If you need an example of tiling an image in Cocoa check out cimgf.com
Hope this will helps you.

Image size limitations in mobile safari?

I'm working on an iOS app using PhoneGap. I ran into an annoying problem where some of my images weren't loading. Thinking it was a cache issue I played around swapping images.
I finally discovered that the issue had to do with the height of my image. After a whole bunch of trial and error I discovered that an image taller than 7864px will not load in the iPad simulator or the iPad itself. It will load fine in Safari. It's not a file size limitation as these are only 45k in size and I'm loading images that are 700k in size elsewhere without a problem.
Has anyone run into this? I can't find any documented restrictions on image dimensions within mobile Safari. If there are restrictions, knowing them would be handy.
For native apps, Apple says images larger than 2048x2048 1024x1024 are to be avoided and should be broken down into smaller ones. The problem here is not the file size on disk, but the size in memory: the image has to be decoded and turned into a "flat" representation.
So let's do some math: assume an image 5000x5000 pixels, with 8-bit RGB. This means each pixel occupies 3 bytes:
5,000 * 5,000 * 3 = 75,000,000 (roughly 71.5 MiB)
So you see your seemingly small image really fills up the memory very fast. iOS now cannot throw parts away if it's under memory pressure, it's the whole image or nothing.
Your only solution is break down the image into smaller parts. iOS can then remove images that aren't visible any more from memory (I doubt with such a huge image that all parts are visible all the time).

Resources