I have an iPhone application that downloads images from the internet and saves them for display later.
The user can select the images to view from a UITableView, the table view has custom cells which display thumbnails of the original images in varying sizes.
When the large image is first downloaded it is scaled to thumbnail size and the thumbnail is saved using UIImagePNGRepresentation.
What I would like to do is save the thumbnail in the optimized iPhone PNG format. How can I do that? does it happen magically just by loading the original large image into memory and saving it? Do I have to do any further processing on the thumbnail before saving?
Chances are the UIImagePNGRepresentation does not create the images, as they are non-comformant PNGs, and can't be read by anything else. If they API generated PNGs that could not be read I think it would document that, and anyone who uploads PNGs from the phone would notice that they did not work.
The optimization is useful, but most of the optimized PNGs are part of the UI where the optimization is done as part of the build process. Chances are the cost of performing the optimization will offset any gains you get from it.
So it turns out that the RGB565 colorspace used in the optimized format is simply not available in a CGGraphicsContext, which is the rendering class used by all the UIwhatever components.
So if I DID write some code to change the color space of the image before saving it, I couldn't get the texture back into a UI class. The only way to use it is to load it directly into the OpenGL innards and use OpenGL in my app.
Don't worry about the "optimized PNG" format, as it isn't making any significant difference.
It does not affect rendering speed at all, and loading speed is dictated by file size more than file format.
So simply save it in a format that will give you smallest files. If you're not using transparency, then it might be JPEG.
If you need transparency, and can spend more CPU time when saving images, then include pngquant in your program (it's under BSD-like license) and shrink those PNGs to 8-bit palette.
Related
I need to create a very short background animation for the entire iPhone screen. I am trying to figure out whether I should use a video or animate a series of PNG files.
Does anybody know the advantage of using video as an app background instead of the series of PNG files being animated inside UIImageView? I heard that video can be compressed to really small size and will look better that animated PNGs.
Thanks in advance.
I really don't think using a video rather than a series of PNG is a good idea. You'll make your life more complicated for a few kilobytes saved, if you even save any.
It is of course highly dependent on what exactly you are trying to animate, and where you try to save space. For example, if you try to save memory in the binary and if you have your PNGs (already well compressed format) in a zip that you unzip on the fly, most similarities will be factored out by the zip algorithm. If you're trying to save space in memory during the game itself (not in the binary), then this doesn't count. However, loading up the video library binaries has a serious chance to clutter your memory more than the few PNGs will.
This project does the job with JPG, it should be very easy to change that with PNG ;)
I've read many of the png vs. jpg threads here and elsewhere. I didn't find this aspect covered for small images that are downloaded from a server.
A short recap:
Xcode optimizes png images that are delivered with the app bundle in a way that they are optimized for the iOS hardware ("png magic")
png images support transparency (which I don't need)
png is the better choice from graphics, jpg for pictures (we have pictures)
I'm building an app that periodically downloads feeds that contain links to thumbnail images (size 80x80). These images are presented side by side the text content in a tableview. I can influence which format is used (jpg, png) on the server side.
If I use an uncompressed png format, it will have about 17k size for one image. This is quite large. And since this png doesn't use the "png magic" of Xcode, the iPhone still might need quite some cpu to get them into the table view compared to an "Xcode prepared" png.
The same image as a compressed jpg is only 3k which is great.
Question: are there lab comparisons that show the real world performance of these 2 formats?
Another one: has anyone used jpgs of a similar size (80x80, 3k) successfully in a table-view?
Many thanks in advance
What do you mean "lab comparisons"? PNG is going to do better with flat colors -- it uses variations on run-length and dictionary encoding as I understand. JPEG will be better with images containing subtle gradients, and loses data mostly in jumps in luminosity which are hard for the human eye to see. "Better" here refers only to file size. It sounds like you would want JPEGs here.
I have an app that will display a bunch of images in a slideshow. Those images will be part of the bundle, thus distributed with the app.
All the images are photographs or photographic, etc.
I've read that it's preferred to use PNG as the image format, but seeing that the JPG version will be much smaller, I'd rather be using that.
Are there any guidelines which format to use and in which case?
PNG's are pixel perfect (non-lossy), and require very little extra CPU energy to display. However, large PNGs may take longer to read from storage than more compressed image formats, and thus be slower to display.
JPG's are smaller to store, but lossy (amount depends on compression level), and to display them requires a much more complicated decoding algorithm. But the typical compression and image quality is usually quite sufficient for photos.
Use JPG's for photos and for anything large, and PNG's for anything small and/or designed to be displayed "pixel perfect" (e.g. small icons) or as a part of a composited transparent overlay, etc.
Apple optimizes PNG images that are included in your iPhone app bundle. In fact, the iPhone uses a special encoding in which the color bytes are optimized for the hardware. XCode handles this special encoding for you when you build your project. So, you do see additional benefits to using PNG's on an iPhone other than their size consideration. For this reason it is definitely recommended to use PNG's for any images that appear as part of the interface (in a table view, labels, etc).
As for displaying a full screen image such as a photograph you may still reap benefits with PNG's since they are non-lossy and the visual quality should be better than a JPG not to mention resource usage with decoding the image. You may need to decrease the quality of your JPG's in order to see a real benefit in file size but then you are displaying non-optimal images.
File size is certainly a factor but there are other considerations at play as well when choosing an image format.
There is one important thing to think about with PNGs. If a PNG is included in your Xcode build it will be optimized for iOS. This is called PNG crush. If your PNG is downloaded at run time it will not be crushed. Crushed PNGs run about the same as 100% JPGs. Lower quality JPGs run better than higher quality JPGs. So from a performance standpoint from fastest to slowest it would go low quality JPG, high quality JPG, PNG Crushed, PNG.
If you need to download PNGs you should consider crushing the PNGs on the server before the download.
http://www.cocoanetics.com/2011/10/avoiding-image-decompression-sickness/
The Cocoanetics blog published a nice iOS performance benchmark of JPGs at various quality levels, and PNGs, with and without crushing.
From his conclusion:
If you absolutely need an alpha channel or have to go with PNGs then
it is advisable to install the pngcrush tool on your web server and
have it process all your PNGs. In almost all other cases high quality
JPEGs combine smaller file sizes (i.e. faster transmission) with
faster compression and rendering.
It turns out that PNGs are great for small images that you would use
for UI elements, but they are not reasonable to use for any full
screen applications like catalogues or magazines. There you would want
to choose a compression quality between 60 and 80% depending on your
source material.
In terms of getting it all to display you will want to hang onto
UIImage instances from which you have drawn once because those have a
cached uncompressed version of the file in them. And where you don’t
the visual pause for a large image to appear on screen you will have
to force decompression for a couple of images in advance. But bear in
mind that these will take large amounts of RAM and if you are
overdoing it that might cause your app to be terminated. NSCache is a
great place to place frequently used images because this automatically
takes care of evicting the images when RAM becomes scarce.
It is unfortunate that we don’t have any way to know whether or not an
image still needs decompressing or not. Also an image might have
evicted the uncompressed version without informing us as to this
effect. That might be a good Radar to raise at Apple’s bug reporting
site. But fortunately accessing the image as shown above takes no time
if the image is already decompressed. So you could just do that not
only “just in time” but also “just in case”.
Just thought I'd share a bit of decompression performance data...
I'm doing some prototyping of a 360 degree viewer - a carousel where the user can spin through a series of photos taken from different angles, to give the impression of being able to smoothly rotate an object.
I have loaded the image data into an array of NSData's to take file i/o out of the equation, but create NSImage's on the fly. Testing at near max frame rate (~25 fps) and watching in Instruments I see the app is clearly CPU-bound and there's an approximately 10% increase in CPU load showing ~275 kb png's vs. ~75 kb jpg's.
I can't say for sure but my guess is the CPU limit is just from general program execution and moving all the data around in memory, but that image decompression is done on the GPU. Either way and the JPG vs. PNG performance argument looks to favour JPG, especially when the smaller file sizes (and therefore smaller sizes of objects in memory at least in some parts of the chain) is taken into consideration.
Of course every situation is different, there's no substitute for testing...
I have found massive differences in animation performance when using jpegs vs png. For example placing three screen-sized jpegs side by side in a UIScrollView and scrolling horizontally on an iPhone4 results in lag and a thoroughly unpleasant jerky animation. With non-transparent pngs of the same dimensions the scrolling is smooth. I never use jpegs, even if the image is large.
I think if you want to use transparent, you have no choice except PNG. But, if your background is opaque already, then you may use JPG. That is the only difference I can see
'Use JPEG for photos' as mentioned in Human Interface Guidelines under section Produce artwork in the appropriate format.
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.