Two apparently identical .png files display at different resolutions on iPhone - iphone

I have a .png file that I am using for a UIButton
[bookmarkButton setImage:[UIImage imageNamed:#"Bookmark.png"] forState:UIControlStateNormal];
It looks fine, but I'd like to be able to change its appearance in Photoshop.
As a test, I open the .png in Photoshop, then save it as a "Bookmark copy.png" without making any other changes or edits.
Then I change the code to:
[bookmarkButton setImage:[UIImage imageNamed:#"Bookmark copy.png"] forState:UIControlStateNormal];
Now when I run the app on the iPhone the same icon appears at a lower resolution.
When I examine the two different .pngs both appear to have the same resolution and appear identical in other applications.
Does anyone have any idea why this could be happening??
Thanks!

You have to save it for 3 different device resolution. like 1x-2x and 3x.
https://developer.apple.com/library/safari/documentation/UserExperience/Conceptual/MobileHIG/IconMatrix.html
you can find information from this link.

Related

jpg images in iphone and 2x images

I am working on an iphone app and targeting iOS 4.0 or later. I am trying to add an image to UIImageView, and image is in jpeg format. This is what I have done so far..
UIImageView *bgImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 246.0)];
bgImageView.image = [UIImage imageNamed:#"background"];
[self.view addSubview:bgImageView];
[bgImageView release];
I have added two images,
background.jpg (as normal 1x image)
background#2x.jpg (for 2x / retina
display).
But when I build and run, everything runs fine, except there is no background. All my other widgets are there, but there is a white background and image is not showing.
Next I created two png images for my background, added it to the project and ran. This time my background was shown. I was perplexed because according to documentation jpg image can be used in iphone with UIImage.
I tried again with my jpg images and changed the code above to this
UIImageView *bgImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 246.0)];
bgImageView.image = [UIImage imageNamed:#"background.jpg"]; //added extension
[self.view addSubview:bgImageView];
[bgImageView release];
When I run the above code, background image is showing, but 2x images are not loaded. That shows my jpg image is fine, and it is not the culprit. So when I just give image name without extension, png files (both 1x and 2x)are loaded on respective devices, jpg files are not loaded at all.
Looks like a bug (either in sdk or documentation). iOS 4 is here for a good year. why no one noticed it? Also is there any option for me other than to convert all my images to png?
EDIT :
Well, two days in to the question, zero answers. I have already converted all my images to png, and that part of my project is done (as my project couldn't wait..). Still, for my own sake and for sake of everyone who faces this in future, I would like to know more about this problem. At least someone can confirm that this is indeed an apple bug. I am starting a bounty so that more people can see this thread.
EDIT AGAIN
2 days remaining for this bounty to end. Thanks for everyone who responded. But let me clarify one thing. I have already said that I have converted all my images to png and I moved along. I just wanted some confirmation that imageNamed treats jpg and png files same way. Documentation certainly says it will(unless Apple has written it somewhere other than UIImage documentation). If documentation is correct then my code failed me because of two possible reasons
It is a bug in imageNamed. If this is the reason, then I dont have too much option other than file a bug report, change my images to png or write a wrapper(like Chandan has said in his answer) and move on..
There is some problem with the jpeg image I used. Well I am not a photoshop guy. But I used
RGBA jpg image. If image does matter I am ready to ask my designer
friend and provide more info.
One more thing. This post also just tells about this problem. But he dont know the reason behind. So I am not alone.
EDIT : THE END
Well it is something related to the image itself. I googled and downloaded some sample jpeg images and played with it. Some of them shown up correctly and some doesn't. Since the boundy time is up, I am giving the boundy to PengOne who tried to reproduce the bug and successfully loaded jpg image without extension, there by making me to work with more images. Thanks for everyone who tried to help.
According to the UIImage Class Reference:
Discussion
This method looks in the system caches for an image object with the
specified name and returns that object if it exists. If a matching
image object is not already in the cache, this method loads the image
data from the specified file, caches it, and then returns the
resulting object.
On a device running iOS 4 or later, the behavior is identical if the
device’s screen has a scale of 1.0. If the screen has a scale of 2.0,
this method first searches for an image file with the same filename
with an #2x suffix appended to it. For example, if the file’s name is
button, it first searches for button#2x. If it finds a 2x, it loads
that image and sets the scale property of the returned UIImage object
to 2.0. Otherwise, it loads the unmodified filename and sets the scale
property to 1.0. See iOS Application Programming Guide for more
information on supporting images with different scale factors. Special
Considerations
On iOS 4 and later, the name of the file is not required to specify
the filename extension. Prior to iOS 4, you must specify the filename
extension.
Since you're targeting iOS 4.0 and later, you should not need the filename extension. I tried to reproduce this potential bug, but it worked as expected for me without the filename extensions.
Here are some ideas for what may have gone wrong to create this effect in your app:
It's possible that the problem comes from the cache if you changed your images at some point.
If you choose not to use the filename extensions, and you have both "background.jpg" and "background.png" as options, the preference appears to be to use the ".png" file.
If you set the target to iOS 4.0 and later after first running the app, then the filename extension would have been required and the image may have been cached blank, which leads back to theory 1.
That's the best I can make of this.
Write a wrapper to get the image like
-(UIImage*) getImage:(NSString*)imageName{
UIImage *image;
if ([[UIScreen mainScreen] respondsToSelector:#selector(scale)] == YES && [[UIScreen mainScreen] scale] == 2.00) {
// RETINA DISPLAY
NSString *jpegFile = [imageName stringByAppendingString:#"#2x.jpg"];
image = [UIImage imageNamed:jpegFile];
}
else{
NSString *jpegFile = [imageName stringByAppendingString:#".jpg"];
image = [UIImage imageNamed:jpegFile];
}
return image;
}
And from your code call
bgImageView.image = getImage(#"background");
With the dawn of Xcode 6 I have found that JPG images might not render at all on certain iOS7 devices (they may work on some but not on others, or they may not work on any, and you may see a different result on a different developers machine, there doesn't seem to be any consistency). This is regardless of whether the image is just referenced in UIImageView in a XIB or programmatically with [UIImage imageNamed:] (which returns nil).
After scratching my head for a long time, the solution was to rename the *.jpg file extension to *.png (whilst obviously leaving the file contents as JPG data).
HTH
You just need to provide the full name of image.
bgImageView.image = [UIImage imageNamed:#"background.jpg"];
don't leave off the extension.
As for the #2x, it is not necessary to call it out anywhere in the code. If you code correctly there is no need to test for a retina display as some here have suggested.
You can use jpgs, just tried it myself and it worked. Only suggestion is how you are instantiating it.
Try it this way:
stockImage = [[UIImageView alloc]initWithImage:[UIImage imageNamed:#"Morbo.jpg"]];
stockImage.frame = CGRectMake(0,0, self.view.bounds.size.width, self.view.bounds.size.height) ;
[self.view addSubview:stockImage];
This is the image I used:
http://futurama.wikia.com/wiki/File:Morbo.jpg

Button images not working on device

so, I made my app and everything, and it has a few UI buttons with background images, which worked fine when it was on the computer and i was testing in iphone sim.
now, when i test on a real iphone, the buttons just show up as standard UICustomWhiteRect or whatever it is called.
here is the code i use to make them:
filepath = [[NSBundle mainBundle]
pathForResource:#"button-half#2x"
ofType:#"png"];
[sendAsOneSMSButton setBackgroundImage:[UIImage imageWithContentsOfFile:filepath] forState:UIControlStateNormal];
i also have one for when it is pressed, which i set just like that. and just so no one asks me, the images for the buttons are both in my main folder the same folder my .xcodeproj file is in.
what could i be doing wrong?
SO:
they work in iPhone Simulator,
they show up as normal buttons without images on a real iPhone.
The first thing to check in a case like this is whether your images are really named "button-half#2x.png", or if they are in fact "button-half#2x.PNG", "button-half#2X.png", or the like. The usual filesystem on OS X (and therefore on the simulator) is case-insensitive, while the filesystem on the device is case-sensitive.
Make sure the image file is included in the Bundle Resources folder.

Substituting flash in a iphone app

I have some .swf files I want to use in an iphone app for menu changes etc.
I have tried to loop through the images(200) to get the same effect, but it doesnt seem to be to my benefit.
What are the best ways to achieve this?
Edit
I currently use the following code
[A1 setImage:[UIImage imageNamed:#"m1.10001.png"] forState:UIControlStateNormal];
[A1 setImage:[UIImage imageNamed:#"m1.10002.png"] forState:UIControlStateNormal];
[A1 setImage:[UIImage imageNamed:#"m1.10003.png"] forState:UIControlStateNormal];
[A1 setImage:[UIImage imageNamed:#"m1.10004.png"] forState:UIControlStateNormal];
[A1 setImage:[UIImage imageNamed:#"m1.10005.png"] forState:UIControlStateNormal];
I wanted to add something like
[self performSelector:#selector(somecode to set image) withObject:A1 afterDelay:1.0];
This feels completely wrong, especially when I have around 200 images.
I need to types of animations.
Firstly I am trying to have a my menus which are png files covering the screen, which has buttons layered on top of that. I want the background to animate.
Secondly I have UIButtons which I need to change image as well, a series of about 5 images to disply, these 5 images are xported from a small swf file.
The buttons seem more difficult to do, but still I am not sure on achieving either of these.
Thanks
Looping does nothing in an event driven UI such as Cocoa Touch, you just block the main thread.
Try your animation using an NSTimer to call back into your animation step-and-display routine at your desired frame rate.
Why not animate the menu changes programatically? Are the .swf files that complicated that they can't be done in the iphone app?
Is there a was to covert the files to iPhone supported video files?
First of all, using UIAnimation with a plist of image names and some parser code is your best bet.
However, a new technology on the horizon may make your original idea possible. A new iPhone native Flash Animation parser called hiramkei is coming soon. You can add SWF file animations directly into Xcode projects.
Here's the link http://flash-on-iphone.com/demo/

Hi-Res #2x image not being picked up for tab bar item

I have a TabBarController that sets the image for the tab like so, in the -init method:
self.tabBarItem.image = [UIImage imageNamed:#"tabImage.png"];
I have a tabImage#2x.png file in the resource. In the iPhone 4 simulator or the phone, the hi-res image isn't being picked up - the low res version is simply being scaled up.
Any ideas why this might be?
EDIT: Some more info:
If I try and explicitly use tabImage#2x.png (or just tabImage#2x) then the tab image I see is extremely large and blown up beyond the bounds of the tab, as if it's being scaled from 60px to 120px. So it looks like whatever name is supply is being treated as a scale=1.0 image.
Note that the simulator is not case-sensitive, but the device is. Make sure case matches EXACTLY. If you've changed the case of the filename at some point, you'll need to clean and rebuild. Sometimes, for the simulator, I've had to actually blow away the folder in Library/Application Support/iPhone Simulator/4.3/Applications/ to get the rebuild to pick up the renamed image.
Always use
[UIImage imageNamed:#"foo.png"]
This will work on 3.x and 4.x devices, and on the 4.x Simulator. Devices with Retina Displays (and the 4.x simulator) will magically pick up the #2x versions of your images; iOS has been modified to be smart about this function and #2x.png files.
Make sure you have both the #2x.png and the normal.png added to the project file, and do a full clean & build. As others have mentioned, verify the size of the images, too; apparently if they're not exactly 2x the dimensions it won't work (I haven't verified this myself).
If you leave the .png off, it will only work on iOS 4.0. So if you're building a 4.0+ only app, you can ask for:
[UIImage imageNamed:#"foo"]
If you have only one hi-res image and want to use it on both Retina and non-Retina devices, then you'll have to change view.contentMode to scale to fit.
I had the same problem. It turned out that my png was not square. Solution: make it square and it will work.
Are you sure the file has been added to the XCode project and is visible in the project explorer?
I had this problem as well.
Make 2 images:
30x30 pixels
60x60 pixels
Suffix the 60x60pixel image with #2x. For example, tabBarImage#2x.png. Then, in your storyboard or code, you can specify the regular one, tabBarImage.png, and iOS will choose the #2x version at its discretion.
You can leave the .png off now. I believe it will still work, but you may try that.
I just went through a few hours of redoing art in The Gimp and trying to get it recognized and loaded by my app on an iPhone 4.
I ran into the problem described with certain images with a #2x extension not being recognized and loaded.
I was not able to discern any pattern. My images are all loaded using [UIImage imageNamed:#"<name>.png"] into a singleton. I inspected the image scale settings post-startup and some were 1.0 (the old art) and some were 2.0 (the new art).
The only way I was able to resolve this problem was to delete and re-add the high resolution images that were not being recognized.
Two silly mistakes (both of which I've made before) that can cause this problem:
Accidentally naming the small
versions #2x instead of the large
ones
Having the large versions be
slightly missized (by one pixel)
you need 2 versions of your images and both ned to be at the same location in the project folder and added to the project
image.png 60x60
image#2.png 120x120
then simply use [UIImage imageNamed:#"image.png"]
did it this way with selfmade buttons and it worked for me (iOS 4.1)
Another thing to look out for is having two images with the same name.
I had the same issue. The #2x image had the wrong build target checked (ServiceTests instead of MyProject).
I had exactly the same problem.
Make two images: im1.png and im1#2x.png
Call imageNamed: with the first one.
Note, imageNamed: doesn't initialize UIImage, hence use it as transient [[UIImageView new] initWithImage:[UIImage imageNamed: #"im1.png"]] or initialize UIImage yourself.

iphone - not loading ~ipad image

I have 3 images on the same place on my app's bundle: "image~iphone.png", "image#2x~iphone.png" and "image~ipad.png".
when I do
UIImage *imageU = [UIImage imageNamed:[[NSBundle mainBundle] pathForResource:#"image"
ofType:#"png"]];
BOth, the iPhone and iPhone 4 hires versions load fine, but not the ipad image. When I run on iPad, I get nil on imageU.
Yes, the image is there, the name is correct (iphone~ipad.png).
Why is that? any clues?
thanks.
I discovered that the solution for that is: do not use any extension on the iPad images. This tilde trick is not working for iPad. One more buggy stuff that makes us waste time.
Possible daft attempt, but is the ipad image copied into the correct target when you add it as a resource? By that, I mean - of you right click the image and get info, does it have the iPad ticked as it's target?
I ran into the same problem with launch images. Despite what the docs say, naming a file with a ~ipad suffix doesn't do anything. You need to set the UILaunchImageFile~ipad key and use a separate name for your launch images on iPad, e.g., DefaultiPad.png and DefaultiPad-Landscape.png, then make sure to just set UILaunchImageFile~ipad to DefaultiPad (no .png suffix) and it will pick up the variants correctly.
image "image~ipad.png" will show HD quality on iPad because in ios 5.1 "~ipad.png" is used to show HD quality image of resolution 2048*2048.Test this naming conservation on iPad,it will work.