When animating a number of frames using UIImageView how does iOS map them into memory, is it simply image resolution x bit depth (i.e. a 200x200 24bit TGA will be the same as a 200x200 24bit JPG) or does iOS take into account unused alpha pixels in the image. Also how does this work with images loaded into the Xcode project (and maybe not used) and those that are directly loaded into memory (i.e. using UIImage imageNamed: from within the app)?
I think that even if the image is 24 bit it will decompress to 32bit, because the default color space is 4channels, the size usually is the number_of_pixel_in_row*number_of_pixel_in_height*byte_for_pixels. In my tests I always saw the same memory consumption even for different formats. Images are loaded lazily at the time they need to be drawn in a context, after that if not released they keep the memory pressure.That means that even if you create an UIImage object it won't be decompressed until it needs to be drawn . Methods such as -imageNamed caches the images in memory, I usually use it only for repetitive images.
Hope this helps
Related
I have a lot of png images in my app which is causing my app to overload the real memory usage of my iPad2 device. My whole app folder with lots of sound files and png images is only about 50-60 MB precompiled, 90 MB on device, but still I'm easily going up to 300MB++ at run time.. ViewControllers on top of former ViewControllers etc.. which I'm also trying to fix..
What I find strange is that by just displaying one background .png image I'm adding 12 MB onto real memory usage(seen in instrument). The image that I used to fill a ImageView image in the storyboard is only 700 KB in my project folder. Taking it out or leaving the image field empty saves me 12 MB of memory...
I'm using a lot of these background images as well as other foreground images in the app which is eating up way to much space.
Any suggestions or help is appreciated
Thanks.
Well, 700kb image on disk space doesn't mean 700kb image in memory. It is compressed while stored on disk, but when it is taken into memory - it will grow in size.
If you are using a lot of images in your project, I would recommend using [UIImage imageWithContentsOfFile:] method. It doesn't cache images internally and you have more control over the memory than using [UIImage imageNamed:].
For me, the general rule of thumb is this. If the image is huge and used once in the app -> [UIImage imageWithContentsOfFile:], but if the image is reused in many places over the app -> [UIImage imageNamed:].
In addition, if you have to use .png format because it has transparency, then you might try giving .webp a chance. This format is not supported officially in ios, however there is a custom implementation on github you can take a loot at.
UPDATE:
I personally don't use interface builder in my apps at all, as I find it extremely time consuming and slow. Instead I create all views programmatically, that gives me more flexibility like choosing between [UIImage imageWithContentsOfFile:] or [UIImage imageNamed:]. You can just set an Outlet to your UIImageView and then set the actual image in code.
As for pngs, there is no such thing as the preferred type of images in iOS. It really depends on your case. If you need transparency -> png, need just a plane image -> jpg. This is just a simple example.
And as for .webp, this format, as I have already mentioned, is not officially supported in iOS, but you can add your own support for it. Basically, .webp will let you replace .png and reduce the size of project folder without loosing transparency in your images.
Hope this helps, cheers!
I'm loading 100s 4k-8k png files(768*768 resolution), total less than 1mg.
Although I do convert them to UIImage and resize/combine images occasionaly,
I was surprised to see ipad device die because of memory warning due to the image loadings.
Is converting to UIImage takes up much more memory than actual byte size of the file?
Thank you.
That's because png's are decompressed into memory, taking more memory. And each decompressed image will take up to 768*768*4 = 2.25 MByte of memory.
You might want to consider how you load images if they aren't all for simultaneous display. There are lots of threads about this here and elsewhere, such as this thread.
UIImage imageNamed will cache the image (and sometimes Apple's caching is slightly buggy, not releasing properly) whilst UIImage imageWithData won't, so once no longer displayed, the memory will be released. There are advantages and disadvantages to both depending on your circumstances, so try to get a good understanding of the differences.
I've got some image generating code that uses UIGraphicsBeginImageContext(), UIGraphicsGetImageFromCurrentImageContext() and UIImagePNGRepresentation() to do some drawing, then save it to disk as a PNG for later use.
Does UIImagePNGRepresentation() take into account scale? As in, if I have an image that is 20 points wide, will the resultant PNG be 20 pixels or 40 pixels?
Also, when I display these images, I use [UIImage imageWithContentsOfFile:] and [image drawInRect:]. Is there a way to hint to those methods to use higher resolution drawing?
Per the iPhone Application Programming Guide you should use UIGraphicsBeginImageContextWithOptions with a scale of 2.0 to create a properly scaled context for the iPhone 4.
As for the second part of your question, I believe you should save the resulting png with the #2x suffix on the base name (e.g., myImage#2x.png). Then when you load it back in using UIImage, its size and scale will be correctly set. Otherwise your image will be loaded at scale 1.0 and be twice as large (in points) as you expect it to be. This section of the same document goes into a bit of detail regarding high-resolution images for devices with high-resolution displays.
Should I use UIImage or CGImage ? Png or Jpg ?
I've read the doc and tried different things but did not notice significant improvement.
Loading an image can take 1 good second which seems slow
UIImage is just an ObjC wrapper of CGImage, so they're the same.
From the SDK doc:
You should avoid creating UIImage objects that are greater than 1024 x 1024 in size. Besides the large amount of memory such an image would consume, you may run into problems when using the image as a texture in OpenGL ES or when drawing the image to a view or layer. This size restriction does not apply if you are performing code-based manipulations, such as resizing an image larger than 1024 x 1024 pixels by drawing it to a bitmap-backed graphics context. In fact, you may need to resize an image in this manner (or break it into several smaller images) in order to draw it to one of your views.
If you have a huge image, you could try to use a UIWebView to reduce memory consumption.
The time to load an image has 2 parts: the time to decompress the image (relevant to choosing JPG or PNG) and the time to render the image.
For decompressing, I'd suggest you profile the simple statement
[UIImage imageWithContentsOfFile:#"/path/to/your/image.jpg"];
It is faster for the iPhone to load PNGs than JPGs because PNGs are optimized when bundled in your application (although, not loaded from remote).
An except from Addison Wesley's iPhone Cookbook:
"Xcode automatically optimizes your PNG images using the pngcrush utility shipped with the SDK. (You'll find the program in the iPhoneOS platform folders in /Developer. Run it from the command line with the –iphoneswitch to convert standard PNG files to iPhone- formatted ones.) For this reason, use PNG images in your iPhone apps where possible as your preferred image format."
Also, PNG is a lossless format, and JPGs are lossy. Apple chose this format for these reasons.
-Kevin
I am grabbing an image from the camera roll and then using it for a while as well as save it to disk as a PNG on the iPhone. I am getting the odd crash, presumably due to out of memory.
Does it make a difference if I save it as PNG or JPG (assuming I choose note to degrade the quality in the JPG case)? Specifically:
is more memory then used by the UIImage after I reload it off of disk if I saved it as a PNG?
is it possible the act of saving as PNG uses up more memory transiently during the saving process?
I had been assuming the UIImage was a format neutral representation and it shouldn't matter, but I thought I should verify.
I am getting the odd crash, presumably due to out of memory
Then STOP WHAT YOU ARE DOING RIGHT NOW and first figure out if that's actually the cause of the crash. Otherwise there's a very good chance that you're chasing the wrong problem here, fixing a memory problem that doesn't exist while ignoring the real cause of the crash. If you want to fix a crash, start by figuring out what caused the crash. Following up on what's "presumably" the problem is a recipe for wasted time and effort.
I have an application on the store that needs to save intermediate versions of an image as it's being edited. In the original version, I used PNG format for saving, to avoid quality loss from loading and saving JPEG multiple times.
Sometime around the 2.2 software release, Apple introduced a change into the PNG writing code, such that it takes many times longer to save PNG data from some images. I ended up having to change to saving in JPEG format, because my application was timing out when trying to save images on exit.
Also, you'll run into issues because saving in PNG format doesn't preserve the "orientation" information in the UIImage, so a picture taken in Portrait orientation with the built-in camera will appear rotated after you save and reload it.
It depends on what type of images you're dealing with. If you're dealing with photographic images, JPEGs will almost always be smaller than PNGs, with no discernable loss of detail as can be seen by the human eye.
Conversely, if you're dealing with highly non-photographic images such as GUI elements or images with large blocks of solid colors, then PNGs and JPEGs will be comparable in size, but the PNG will save losslessly whereas the JPEG will be lossy and have very visible artifacts. If you have a really simple image (very large blocks of constant colors, e.g.), then a PNG will very likely be much smaller than a JPEG, and again will not have any compression artifacts.
The act of saving an image as a PNG or JPEG should not take up very much transient memory. When an image is in memory, it is typically stored uncompressed in memory so that it can be drawn to the screen very quickly, as opposed to having to decompress it every time you want to render it. Compared to the size of the uncompressed image, the amount of extra temporary storage you need to compress it is very small. If you can fit the uncompressed image in memory, you don't have to worry about the memory used while compressing it.
And of course, once you write the image to the file system in non-volatile storage and free the in-memory image, it really doesn't matter how big the compressed image is, because it doesn't take up main memory any more. The size of the compressed image only affects how much flash storage it's using, which can be an issue, but it does not affect high likely your app is to run out of memory.
Your crashes may be from a known memory leak in the UIImagePickerController.
This should help you fix that.
I don't have any hard data, but I'd assume that PNGs are preferable because Apple seems to use PNGs virtually everywhere in iPhone OS.
However, if you've already got the code set up for writing PNGs, it shouldn't be too hard to change it to write JPEGs, should it? Just try both methods and see which works better.
Use PNG wherever possible. As part of the compilation XCode runs all PNG files through a utility (pngcrush) to compress and optimize them.
is more memory then used by the UIImage after I reload it off of
disk if I saved it as a PNG?
=> No, it's the same memory size if you import from 2 images that have same resolution and same number of channels. (such as RGBA)
is it possible the act of saving as PNG uses up more memory transiently during the saving process?
=> No, it only effect your disk memory.