UIImagePNGRepresentation() and scale (iPhone 4 screen) - iphone

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.

Related

UIImageView memory usage

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

Use a single photo for both 1x and 2x graphics on iPhone

I'm working on a comic viewer app that downloads the latest content from a server. It downloads a single file regardless of the screen scale. What I'd like to do is make this file work correctly on both screens.
What's the procedure for this and how should I size the photos to fit? The trouble I'm having is that the graphics are retina screen size, but the iPhone doesn't interpret them as such. That means they're displayed twice as large as they should be.
CGImageRef cgImage = [myImage cgImage];
UIImage *retinaImage = [UIImage imageWithCGImage:cgImage scale:2.0 orientation:UIImageOrientationUp];
You could also change your image's dpi value in an image editor to make UIImage recognize the scale automatically.
Generally though, you should use lower-resolution images on devices that don't have a retina display because otherwise you're wasting precious memory.
For normal screen, you can resize them programmatically, by adding a scale category to the UIImage class by example, there are many code samples on stackoverflow like :
UIImage resize (Scale proportion)
For retina, you need to set the scale of the UIImage to let the ios know for what screen size it is used (you can set this with the initWithCGImage:scale:orientation: method of UIImage).

Retina images from server display incorrectly in table cells

I have a table where the cells' image views are being populated by images that have been previously pulled down off a server. So:
[[cell imageView] setImage:[[[UIImage alloc] initWithContentsOfFile:filePath] autorelease]];
Where "filePath" is the location of these images. Working beautifully, until I decided to be clever and add retina display images to my server. These images (double-sized, obviously) are being displayed, but are shrunk. I had labelled them image#2x.png, hoping that the iPhone would just know what to do with them, but obviously that doesn't work in this context.
I've looked at the discussions, and am guessing I need to do something with the contentsScale of the cell's imageView, like matching it to the screen scale, but I'm not sure exactly how to do this. Any help appreciated.
From server you cannot download automatically retina images.
You need a control like
if (iphone == 4) image=img#2x.png
else image=img.png
to get correct images.
You would need to set the scale factor of the image correctly. Please check the scale property in UIImage
If you load an image from a file whose
name includes the #2x modifier, the
scale is set to 2.0. If the filename
does not include the modifier but is
in the PNG or JPEG format and has an
associated DPI value, a corresponding
scale factor is computed and reflected
in this property. You can also specify
an explicit scale factor when
initializing an image from a Core
Graphics image. All other images are
assumed to have a scale factor of 1.0.
So you can read your image as above, get the CGImage from it and create a new UIImage using + (UIImage *)imageWithCGImage:(CGImageRef)imageRef scale:(CGFloat)scale orientation:(UIImageOrientation)orientation.
A nicer way could be to check the DPI of your retina image and make it 144dpi with a graphics program. According to the scale property documentation this might work, too.

iPhone - Resizing an UIImage in less than a second on an iPhone 4

I have a 5MP image coming from the back camera. I want to downsize it to put it into an ImageView without having to wait too long (it take a logn time to the UIImageView to display a 5 MP picture). So I tried many methods to resize / resample the image to make it fit a just-screen resolution (retina one). But it take around 1 sec to downsize the image.
Would you know any optimised way to be able to resize this 5MP image to the retina 960 x 640 resolution as fast as possible, and at least at less that 0.7 sec on an iPhone 4 ?
This is my favorite blog post and code to resize images. I haven't benchmarked it but I know of no faster way.
http://vocaro.com/trevor/blog/2009/10/12/resize-a-uiimage-the-right-way/
You're displaying an image in an UIImageView. I understand you want a version that is equal to the size of the screen. The way I would do it: display the original image in the UIImageView directly, this shouldn't take any noticeable amount of time.
Then in a background thread resize the same image down to the size you want and update the UIImageView as soon as that is done.
This gives you something on screen immediately while you generate an optimized version at the same time.
I don't know if you are using the original image for something else, but if you really only want the screen sized image it might be an idea to use an AVCaptureSession with a preset of AVCaptureSessionPresetHigh (see AVCaptureSession sessionPreset). This setting results in a more reasonably sized image, which might better suit your needs.

What's the fastest way to load big image on iPhone?

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