Obj-C, Using [button setImage:image]; how do I maximize the quality? - iphone

I'm about to resize some images, for use with buttons.
However, I think setImage will resize the images to the right size for the buttons.
My buttons are 72 x 72, according to IB.
I think I'm going to need to produce some retina size buttons too ?
What size should I create my images so that the iphone doesn't need to resize my images ?

Create 72x72px images for the normal iPhone screens and double the size for retina displays. So that would be 144x144px images for retina displays.
If your include the images in the resources folder of your project make sure to append #2x.png to the name of the retina version of your image. This way the iPhone will use this image automatically when the button is displayed on an iPhone with retina display.
For example name the 72x72px image: button.png
And name the 144x144px image button#2x.png.
Then select button.png in InterfaceBuilder or use [button setImage:[UIImage imageNamed:#"button.png"] forState:UIControlStateNormal] to set the image in code. The iPhone will automatically load the retina version when needed.

I think it would be better to create two images, One for iPhone 3 , iPad and other for iPhone 4. As per my information iPhone provides some naming convention for images in iPhone 3 and 4 device. Check out following.
http://useyourloaf.com/blog/2010/6/29/updating-for-the-iphone-4-retinal-display.html
if button is of 72X72 then for iphone 4 make image of 144X144
Hope it helps...

Related

UiTabbar Icon doesn't display correctly

I am trying to upgrade my app to display icons that look great on the retina screen of the iPhone 5. AS of right now I am not setting my icons using code, I'm simply selecting the image within xcode and it loads it on its own ( I don't know how to code in the icon so that's why I am doing it this way).
Anyways, when I set the icon I have to use a 24x24 icon or else it wont fit.
When I use my high-res icons 64x64 they do not fit correctly. My question is, how do I go about making it so my icons will be scaled to fit but still retain the high-res quality?
1) If your non-retina icon is 24x24, then your retina icon should be 48x48
2) You should set your icon to be the non-retina version in interface builder. The retina version will be swapped out automatically if its on a retina device, as long as you follow the standard naming scheme:
name.png (non-retina image)
name#2x.png (retina image)
Note also: if you do set an image in code, you can simply use [UIImage imageNamed:#"whatever"] and the retina image will be swapped out automatically for you too (you don't have to do if-else or anything like that).
just try to set this code in your .m file of your particular tabBar's parent view.. in viewDidLoad: method..
self.tabBarItem.image = [UIImage imageNamed:#"home#2x.png"];/// set your image name instead of home

Retina graphics

I'm using an image that fills the screen (like a background) to my app. The image is already in retina dimensions, but I scaled it to fit the simulator screen. Because it's already in retina dimensions, do I still need to add a copy of it with the #2x extension?
It's better to use separate images, normal & normal#2x. if you only use single image, small images will be distorted while bigger image will look squeezed.
don't forget the iphone 5 for background images for example.
3 images are required : Background-568h.png Background.png Background#2x.png
if ([UIScreen mainScreen].bounds.size.height > 480.0f) {
// for the iPhone 5
self.view.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"Background-568h.png"]];
} else {
// for iphone 3.5 inch retina /non retina.
self.view.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"Background.png"]];
}
the naming notation is required for compiler to detect your retina images.if you write image.png the compiler looks for image#2x.png and then image.png and if it can not find it(for retina displays).
So name all your images xxx#2x.png and provide also xxx.png for non retina devices.
On the other hand i would use exact image sizes for non-strechable images in you app.Resizing means extra time and naturally extra computation.On the other hand fractional image resolutions ends up with blurry images.
For iphone 5 images you should for instance include Iphone5BackgorundIamge#2x.png but call Iphone5BackgorundIamge.png in your code.
Iphone dont have to do with image dimension but it uses image name for checking whether it is to be used as ratina or normal image.You have to keep a normal size image with it's name like "image1.png" for normal display and ratina size image as "image1#2x.png" for ratina display.If your used image is already of ratina display then keep it with #2x format and put one half size image with normal name.

iOS not using -568h#2x.png

I have 3 images:
test.png
test#2x.png
test-568#2x.png
In IBOutlet, a UIImageView is set to display test.png.
On iPhone 3.5in without retina, it's displaying test.png
On iPhone 3.5in with retina, it's displaying test#2x.png
But on iPhone 4in with retina, it's displaying test#2x.png!!!
What's going on?
Thanks!
The -568#2x suffix only applies to the Default.png launch images. There is no special suffix used by UIImage imageNamed: (or the other UIImage methods). If you need a special image on the 4" screen, you need to add code to get the desired image yourself.
The following works for the iPhone. For the iPad, you would need additional images.
For the three versions of the background image, use the following names:
background-480h.png (320x480)
background-480h#2x.png (640x960)
background-568h#2x.png (640x1136)
(You don't need a "-568h.png" image because there's no 320x568 iPhone screen.)
When you set the background image, simply append the screen height to the image name:
NSString* imageName = [NSString stringWithFormat: #"background-%ih", (int)[[UIScreen mainScreen] bounds].size.height];
[view setBackgroundColor: [UIColor colorWithPatternImage: [UIImage imageNamed: imageName]]];
iOS automtically appends the "#2x" if applicable.
You could omit the "h" after the height in the image names, but I think it's nice to emulate the iOS convention for the default image.
I know it's an old thread but I was having trouble with the new screen sizes for iPhone 6/6+.
What I did is to use this naming convention for different image files:
none if #1x small old phones
#2x for iPhone 4
-568h#2x for iPhone 5
-667h#2x for iPhone 6
#3x for iPhone 6 Plus
And then to automatically generate (full size) images just by including the code from this Gist in the project:
https://gist.github.com/kevindelord/fe2e691d06ab745fbb00
You have nothing else to do. When you instantiate an image in your code:
[UIImage imageNamed:#"background.png”];
The categorised class from the Gist will automatically create an image corresponding to the current device.
There is a Pod for it UIImage+Autoresize documented on CocoaDocs.

iPhone: Do I have to have images for both retina and non-retina for all image?

I heard that you need to create images for both retina and non-retina.
And you need to name them like image#2x.png for retina and image.png for non-retina.
But I want use image.png for both retina and non-retina.
And scale it down in program because it is easier to adjust size of image by code than by recreating images with paint tool.
It is possible to do so using this code:
[button setImage:[UIImage imageNamed:#"image.png"] forState:UIControlStateNormal];
UIImageView *imageView = [[UIImageView alloc] init];
imageView.frame = CGRectMake(20, 20, 40, 40);
imageView.image = [UIImage imageNamed:#"image.png"];
image.png is scaled down to button size or image view size.
Is this a common way?
Does this way have any disadvantages?
Does apple reject if application does't have both image.png and image#2x.png?
[EDIT1 - SPECIAL CASE]
There is a SPECIAL case however to this problem. Since Apple' current 2x algorithm is essentially a pixel doubling (in each direction), if you images are made of of only vertical and horizontal lines, then I would go about providing those images as the 1x and let the API auto upscale those, an example would be an image for a button that looks like this
As this will have zero problems upscaling and still looking very crisp!!! (Tested on both iPhones, as well as both iPads)
[ORIGINAL]
If you are simply doing it for display, then one way would be to simply provide the image as it should be for the retina only, and allow the UIImageView to scale down the image automatically for the non-retina displays. It WILL do this and will NOT be rejected by apple.
For the retina display, the UIImageView will naturally take up the space of 2x the pixels in each direction, thus when the image is read in for display on a retina display, the API will recognize that no scaling needs to occur!!!
Be careful though!!! Downscaling images lets say for buttons can have effects that make your images or buttons come out looking unclean / pixelated. This is why it is "recommended" to provide both, is with lets say a vector based image, you would be able to generate the highest quality image for a given resolution. Kinda depends on how you want to use the images.
As a side note. I would recommend that if you do choose the resizing option, that you try to recognize the device' screen resolution up front and resize the images (if necessary in my case for the SMALLER resolutions) only once at initialization into the button or UIImageView etc... so that you won't suffer the slower performance each time it needs to be rendered to screen.
Well, you may not want to hear this but it is best to use a paint tool. If you have the device resize the images each time, it'll slow down your app - depending on how frequently you perform this task. I don't think apple will reject you for not including #2x images. I've forgotten them before with no issues.
If you don't want to include #2x images then your app will work both for retina and non-retina iphones. Apple is not going to reject your binary for this.
The only disadvantage is that instead of good quality images for retina you will be displaying normal images.

iOS Retina display: images double size

For testing not/retina display I've created an UIView with size 100x100.
I've create 2 images:
- normal size (100x100)
- retina size (200x200)
I have two situations:
1) Non-Retina display + Normal Size image in background
2) Retina display + Retina Size image in background
The 1st scenario is ok.
In the 2nd scenario the image is double size and in my UIView I can see only 1/4 of the total image.
The same happens when I try to assign a background image to my UIViewController navigation bar as following:
if (IS_RETINA()) {
[self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:IMG_NAVIGATION_BAR_BACKGROUND_RETINA] forBarMetrics:UIBarMetricsDefault];
}
else {
[self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:IMG_NAVIGATION_BAR_BACKGROUND] forBarMetrics:UIBarMetricsDefault];
}
There's a much easier way to do this. Give the retina version of the image the same name as the non-retina version, except with a "#2x" at the end. For example, if your regular image was named foo.png, then the retina version should be named foo#2x.png.
Then, just refer to the regular version of the filename (e.g., foo.png) at all times. When your app is running on non-retina hardware the regular image will be used, but whenever you're on retina hardware the higher-resolution image will be used automatically. It's easier than having to write an if statement for every image you use, plus it'll actually work.
You don't need to code the IS_RETINA test, just add the #2x suffix to the name of the file containing the image you want to use for the retina display, and iOS will automagically use that in preference.
Bundle 2 image files, prettyNavBarBackground.png and prettyNavBarBackground#2x.png
#define IMG_NAVIGATION_BAR_BACKGROUND prettyNavBarBackground
Then you can just use this single call, and iOS will select the appropriate option
[self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:IMG_NAVIGATION_BAR_BACKGROUND] forBarMetrics:UIBarMetricsDefault];
U don't have to write any sought of code to distinguish between retina and normal hardware. U just need to add a "#2x" image . This will work fine as perfect.
U don't have to call these images individually, but just write the filename.