Using Images When Developing For iOS
This post will explain how to avoid blurred images on your iPhone and iPod touch with Retina display. It may contain nothing interesting for people that already have some knowledge of iOS development or have at least read some books or articles about it. If you just started developing for iOS though (using Delphi XE2), this may be useful.
Some weeks ago I made my first iPhone application (Fish Facts using RealThinClient; YouTube Video 1, Video 2) and I installed this App recently in my new iPhone 4S. Since I pay an extra attention to my UI’s, one thing that I noticed was the blurred images. To a certain point this was expected, because the iPhone 4 has a Retina display with a higher resolution and the images I used were based on the resolution of my iPhone 3GS. All the controls and texts had no problem, and we can thank the vector-based FireMonkey controls for this.
Shortly afterwards I asked myself two questions:
- How to use images and avoid them being blurred on devices with the Retina display?
- How does FireMonkey handle the different screen resolutions?
Currently, there are two iOS resolutions for iPhone and iPod touch:
- 320 x 480 (iPhone/iPod Touch)
- 640 x 960 (iPhone 4 and iPod with Retina display)
FireMonkey uses the same principle apple introduced with iOS 4. Starting in iOS 4, the dimensions are measured in points instead of pixels. We are used to measuring width and height in pixels, but the dimensions in a FireMonkey iOS application are measured in points. If you compare the width and height of an TImage that have the align property set to alClient, you notice that the result will be the same on iPhone and iPod touch with or without the Retina display. I mentioned to check the width and height using this method, because my first try was simply using form1.width and form1.height, but this always return height = 600 and width = 400 (Delphi XE2 Update 2) and don’t ask me why, because I couldn’t find a answer yet.
After spending some minutes reading some articles, I found a simple way to fix the problem with the blurry images.
- You should always load the images at runtime and not compile the program already with the images. People developing in Delphi may already add the images to a TImage components, but you should avoid that when developing for iOS. Loading sample:
image1.Bitmap.LoadFromFile(ExtractFilePath(paramstr(0)) + 'image.png');
- According to Josh Clark at global moxie
“For every image in your app, add a second version that’s twice the size, adding @2x to the name. For a low-resolution image named image.png, for example, you would add a second file named firstname.lastname@example.org. The new image will be picked up automatically by iPhone 4. Everywhere your code requests image.png (or even just plain old image), email@example.com will be used instead.”
- Set the size of your TImage to the normal image size (not 2x) and set the property WrapMode to iwStretch or iwFit.
To test you can simply use the iOS Simulator and change the hardware device between iPhone and iPhone Retina. You should be able to notice the difference, but you could also use two totally different images for image.png and firstname.lastname@example.org and compare.
Don’t forget to add the images to XCode project.
See the difference between the images below. In Delphi I added to a form two TImage components with dimensions 128×128. The image on the left side was loaded at designtime, because the iPhone searches and automatically loads the file with @2x (if existent). The dimension of image.png is 128×128 and email@example.com is 256×256.
An useful Mac application to check the content of your application (and not only for that) is iExplorer. Unfortunately the preview and export of a PNG image is not working (at least here), but you can open text files, rename files and view JPG images with it.
Some interesting links:
Apple Retina Display – http://www.apple.com/iphone/features/retina-display.html
Designing for iPhone 4’s Retina Display – http://globalmoxie.com/blog/designing-for-iphone4-retina-display.shtml