Preparing graphic assets for a universal app - ios

From what I've read elsewhere, Apple recommends multiple versions of every graphical asset, so quality will be retained between pre-iPhone 4, iPhone 4 (with the retina display), and the iPad. But I'm using a technique that only requires one asset for all three cases.
I make each graphic the size I need for the iPhone 4 and the iPad, say a cat at 500x500 pixels. I name it myCat#2x.png. When I read it in for the iPhone:
CGRect catFrame = CGRectMake(0.0f, 0.0f, 250.0f, 250.0f);
UIImageView *theCat = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"myCat"]];
theCat.frame = catFrame;
[self.view addSubview:theCat];
[theCat release];
for the iPad, I do exactly the same thing, except for:
CGRect catFrame = CGRectMake(0.0f, 0.0f, 500.0f, 500.0f);
This seems to work fine in all three cases, and greatly reduces the number (and size) of graphic files. Is there anything wrong with this technique?

Check this: http://vimeo.com/30667638
We are releasing it soon. If you are interested in beta testing it drop me a lineEdit

This question has been a long time in circulation, so I will "answer" it based on my experience with the last couple of apps I've worked on.
I see no reason to have a separate image asset for retina display and non-retina display iPhones. The technique I outlined above seems to work just fine.
Probably, one will want a separate asset ("resource file") for the iPad, mostly for the change in aspect ratio of the screen. In my case (sprites for children's games) I was able to use many of the iPhone images on the iPad. The "look" was a little different, but I saved a lot of file space.
Whether this works for you will, of course, depend on the unique properties of your project.

Not all images scale well, even at 50%. dithering or patterns might get distorted. In general, scaling at factors of 1/2, 1/4 etc (dividing by two) will result in best results, but scaling down using an advanced algorithm like used in Photoshop will produce better results.
So, in most cases, this can produce acceptable results.

Related

Why do I need #1x, #2x and #3x iOS images?

Why do we need these 3 particular image types?
If I have a button on my app with a background image say, 50 pixels x 50 pixels, why do I need 3 versions of this image? What's stopping me from just making one image that's much higher in res, say, 700x700 so when it shrinks down on any iPhone it won't fall under the max res the device would want?
Only thing I can think of is it just takes up more space, but for simple apps / a simple button it seems like it wouldn't cause any issues. I've tried it on a few devices and see no difference between them when I simulate it and do this method. However, as I dive more into apps and stuff I'm sure there is substance behind this technique.
If you don't have the exact size, there are two things that can happen:
Upscaling
#3x or #2x can be upscaled from #1x but usually the visual result is blurry, with thick lines and doesn't look good. Upscaling #3x from #2x can be even worse because subpixels must be used.
Downscaling
In general, the results are much better than with upscaling, however, that doesn't apply for all the images. If you have a 1px border on a #3x image, after downscaling it to #1x the border won't be visible (0.33px). The same applies for any small objects in the image. Downscaling destroys all details.
In general - for an image to look perfect, you want to avoid both downscaling and upscaling. You can always go with only #2x or #3x images and add other scales only if you see visual problems. Using higher resolution won't improve downscaling. High resolutions are used only to avoid upscaling. Downscaling from a high scale (e.g. #100x) to #1x won't create better results than downscaling from #3x.
You need 3 kinds of images in Image Assets because in terms of Scaling or Pixels
There are 3 kinds of Apple Devices (iPhone and iPad) that is
Normal device which terms to 1 pixel = 1 point#1x (Older iPhone and iPad devices)
Retina device which terms to 4 pixels(2 x 2) = 1 point#2x (iPhone 4+)
Retina iPhone6 and iPad which terms to 9 pixels (3 x 3) = 1 point#3x (iPhone6+)
Thus for providing same image in 3 scales iOS decides which image to show for which devices.Hope could help you understand this.
EDIT
It is because if you provide one high resolution graphic it would be waste of space on a users' device. Thanks to app slicing the device will download (from App Store) only the parts that actually fits the device (so retina device won't download non retina graphics). This is why Apple created assets catalogs and this kind of rules to follow. They describe it in their sessions.
In short it is to decrease memory/disk usage so it is all about increasing performance and user experience
First of all, you need to know points vs. pixels behaviour. On non-retina devices, point vs pixels ratio is 1point=1pixel. On retina devices, there are two ratios: 1point = 2x2 pixels depending on screen size, and 1point=3x3 pixels, because of pixels density, that is quadrupled watching on non retina. That's why you need this 3 types of images, to be shown on its highest resolution.
Complementing what Sulthan said:
Because you didn't propitiated proper images for a specific device, it has to downscale or upscale. These processes will use up your memory and processing, resulting maybe in a decrease of performance, depending on how many images at a time you're doing it and the size of image.
If you provide only one big image you encounter several problems:
Downscaling leads to the loss of quality (even if it is not huge)
It takes more computational power to downscale the image than to display the already pre-rendered image
The size of your binary gets increased and you are not able to benefit from app thinning which is introduced with iOS 9.
As you can see, producing only one image will impact the performance and quality of your app and it will disproportionately hit those with older devices. This is because:
They need to downscale more. Also, the performance of their devices is not as good as that of the new ones, so they are much more likely to notice the lags with your app
They do not have as much storage space so you really want to be able to use app thinning to help them
The loss of quality will be the highest for them and considering the fact that the resolution of their devices is low, they will notice it.
Due to this users are likely to be unhappy and this is bad for you. Because, from my experience, unhappy users are 10 times more likely to rate your app than happy users. You don't want that, do you? :)

When to use double size images

I was thinking to write some quiz app where questions are represented as images.
My question is, for each quiz question (question.jpg), and thus a jpg file, do I have to create
a double sized question#2x.jpg file?
Is it necessary?
Doing this seems will increase size of my program so I was thinking when/if this is necessary to do?
PS. And in case I have to do it, I will just have to double in size each image manually and add to the project right (both original and double sized image)?
PPS. Just to add more info. The questions are located on the web site, I have to download them and add to my project manually (like resources). On web site there are no different versions of the same image. So, I have whatever is on the web site. Some images I noticed are 800x600 in dimensions but some are also in dimentions 500x400. So after I download these images, how shall I name them? Just with original names? and forget about the #2x extension? What's the best practice?
(if this will help my image view will probably be smth .like 310 in width). Do I have to modify them in size? What to do?
Apple's naming conventions of high resolution images can be found here:
Apple doc naming conventions
If you are developing in the way that you want to support old screen as well as retina screens. You can use xxxx.jpg for old devices as iPhone 3gs and iPad 1, and use xxxx#2x.jpg for retina displays. Where the aspect ratio needs to be the same but the #2x image needs to be twice as big.
In your case "my image view will probably be smth .like 310 in width", then the #2x image needs to be 620px in width and normal revolution 310px.
There is actually no need to have both image sizes in the app as you can use the same image and just scale it(If you really really need to have the old resolution supported).
Even if you add just a #2x, it will scale itself if someone on an old device installs your app. It may become a bit blurry but will still be quite ok.
If you are planning to use a lot of images in your app I suggest using some sort of web service where the user can download content that is to be shown. But that's just me. As the app will quite quickly become very large as images takes up quite a bit of space. Of course this all comes down to how many images you will have.
The drawback of using a web service is that the user much have an internet connection to be able to play. And download your content.(Most quiz apps I know of does use a web service for this.) This is a matter of taste.
If you do need to support normal and #2x here us a method you can use. This method will return the scaled image so you just need the normal one or the #2x one and then scale to the other size. This will at least help you a bit when it comes to getting either your app size down or your clients download time down.
If you are using .jpg's and scaling them upwards you can quite easily get a pixalated image as it is a lossy format. But if that's what you still want to do and maintain aspect ratio, this is one way to do it:
-(UIImage*)resizeImage: (UIImage *)imageToScale withScale:(CGFloat)theScale{
UIImage *image = [UIImage imageWithCGImage:[imageToScale CGImage]
scale:(imageToScale.scale * theScale)
orientation:(imageToScale.imageOrientation)];
return image;
}
Usage
[self resizeImage:[UIImage imageNamed:#"question.jpg"] withScale:0.5];
0.5 would double the size and 2.0 results in an image half the size as the original.
If you want a more complex method to set for instance set a specific target size just say so and I'll edit this answer.

iOS apps - why include both #2x and low-res images?

This has been bugging me for a while. I don't understand why one should include low-res images. If a 3GS, for example, can't find the low-res image, it just uses the #2x version anyway and displays it at it's native resolution. So why add to the filesize of your app by including all the half-res images?
Halley had it right. The system does not automatically downsample #2x images to non-retina size, and it shouldn't. The 3Gs does not have enough memory to load retina images. It will likely choke your app and cause it to exit with an out of memory error.
The problem gets even worse with the iPad 1. The iPad 1 has very low memory relative to it's screen size, and if you tried to make it load retina sized images, it would choke and die very quickly.
To scale an image the system has to load it at full size and do a complex scaling operation each time it draws it. It's the worst of all possible worlds - slower, 4x as much memory, and the images don't look as good.
In most cases, you can make an icon look better when created at the low-res resolution, instead of having the system scale it. If you don't care too much about how your icons look when scaled, then using the #2x version only is probably fine.
The other posters mentioned some excellent points, but here's one more for posterity: as mentioned several times in http://developer.apple.com/library/ios/#DOCUMENTATION/UserExperience/Conceptual/MobileHIG/IconsImages/IconsImages.html#//apple_ref/doc/uid/TP40006556-CH14-SW1, a 2x image may be more detailed. In other words, the low-res image isn't simply a scaled-down version of the 2x image; the 2x image may contain details not present in the smaller image.
#2x filenames are intended for Retina Display enabled devices.
If you intend to use them for display on the iPhone 3GS make sure to properly test that they look as acceptable as the low-res image Apple wants you to use.
The reason being, is when images are scaled up if there is no #2x available, they can become pixelated and blurry, so you would prob think that making the original image twice as big would solve the problem.
But no, because the retina devices would still scale it up (in my experience) and non retina devices would display the image incorrectly.
It's got a lot to do with the quality standards Apple wants for the Apps on their app store

Make Flixel (iOS port) support retina graphics

In case you are familiar with the Flixel game engine, open sourced here:
https://github.com/ericjohnson/canabalt-ios/tree/master/flixel-ios
How would you go about adding support for retina graphics? Like retina sized textures.
I tried adding #2x atlas pngs and they seem to load, however I guess the offsets will be incorrect as specified in the atlas plist. Changing the plist (load retina atlases for retina devices) with correct offsets surely loads the graphics correctly, but the textures themselves generally shows up too big, and other problems seem to occur.
Progress update:
As noted above I'm creating separate texture atlases for high res graphics - I guess this would mean I would need to have a complete set of high res graphics (or none at all) to make things simple. This makes the graphics load correctly (or the offsets are incorrect of course if using lowres atlas plist)
When creating FlxSprite:s, I don't use the shorthand static creators, but the init* constructors, specifying the modelScale parameter using the device's scale (will be 2.0 for retina devices, 1.0 for other). With this the graphics also show up with correct size on screen no matter retina screen or not.
What's left is make the retina versions use the correct resolution because somewhere the texture itself seems shrunk, then sized up again producing a blurry, incorrect effect - not the original high res image. I'm guessing the last culprit is somewhere in SemiSecretTexture class...
Progress update again:
I was likely just wrong above. I think I found out how to do it. No need to set modelScale to 2.0... I might sort out the details and provide the answer later :-)
I guess there's no straight forward way to do this, but when you instantiate your class derived from FlxGame, don't use YES in the zoom parameter. For starters. Then you'll have to load different atlases for retina and non-retina. Not sure what happens with iPad support from there however. Then when loading textures for FlxSprites, you need to specify the "device scale", which would be 2.0 for retina devices - get it from [UIScreen scale]. This would make retina and non-retina work good for FlxSprite. Then FlxTileblock (and possibly other classes) is another story which I haven't solved yet.

What is the point of the #2x for Retina display apps?

I understand that the Retina display has 2x as many pixels as the non retina displays, but what is difference between using the #2x version and taking and taking the 512 x 512 image and constraining it via the size of the frame ?
To Clarify:
if I have a button that is 72 x 72 The proper way to display that on an iPhone is to have a
image.png = 72x72
image#2x.png = 144 x 144 <---Fixed :) TY
But why not just use 1 image:
image.png = 512x512
and do something like this:
UIImageView *myImage = [[UIImageView alloc] init ];
[myImage setImage:[UIImage imageNamed:#"image.png"]];
[myImage setFrame:CGRectMake(50, 50, 72, 72)];
I am sure there is a good reason, I just dont know what it is, other then possibly a smaller app file size?
Thanks for the education!
There are several good reasons for sizing your images correctly, but the main one would have to be image clarity: When resizing images, you often end up w/ artifacts that make a picture look muddy or pixelated. By creating the images at the correct size, you'll know exactly what the end user will see on his or her screen.
Another reason would simply be to cut down on the overall file size of your binary: a 16x16 icon takes up orders of magnitude fewer bytes than a 512x512 image.
And if you need a third reason: Convenience methods such as [UIImage imageWithName:#"xxxx"] produce images of actual size and usually do not need additional frame/bounds code to go along with them. If you know the size, you can save yourself a lot of headache.
Because images may not be displayed correctly when resized. Also because larger images use more memory. But if both these are not issues for you, you can use one image for both retina and non retina displays.
Because large images consume a lot of memory and CPU/GPU cycles. Another reason is that scaling down an image causes pixel-level quality issues.
Besides the extra memory and CPU, downsampling an image is inherently lossy. Nice crisply rendered lines turn to crud.
The #2x naming convention exists in case the source image is exactly the same size as the displayed image. Then you can have a 57x57 app icon for non-retina iPhone, and 114x114 app icon for retina display iPhones.
The main advantage of using 2 images is, that both pictures can be handcrafted from the designers so everything looks fine and no up- or downscaling code needed, which cost energy, slows performance and may contains bugs.

Resources