Retina image displayed too big in retina simulator - ios

I display a retina image (with #2x.png extension) using:
myImage = [UIImage imageNamed:#"iPhoneBackground#2x.jpg"];
UIGraphicsBeginImageContext(myImage.size);
[myImage drawAtPoint: CGPointZero];
myImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
imageView = [[UIImageView alloc] initWithImage:myImage];
NSLog(#"Dimension:%f x %f",myImage.size.width,myImage.size.height);
[self.view addSubview:imageView];
However the image is displayed twice its size on the retina simulation. Image and simulator both have 640 x 960 resolution, so I would expect the image filling the screen.
I know there are other ways than CGContext to display an image, but that's the way I would need to other purposes in my code.
Any idea why I have this definition issue ?

Don't use #2x suffix
From apple documentation:
The UIImage class handles all of the work needed to load
high-resolution images into your app. When creating new image objects,
you use the same name to request both the standard and the
high-resolution versions of your image. For example, if you have two
image files, named Button.png and Button#2x.png, you would use the
following code to request your button image:
UIImage *anImage = [UIImage imageNamed:#"Button"];

You do not need to explicitly load a retina image, #2x will be automatically appended to the image name if the device has a retina display.
Change your UIImage code to: myImage = [UIImage imageNamed:#"iPhoneBackground.jpg"];

Related

Reading a image at 2x or 3x in iOS

I am fetching a image from my server based on the scale so I fetch something like :
http://myserver.com/image1.png
or http://myserver.com/image1#2x.png
However what I see is that once I initialize a image with the contents of http://myserver.com/image1#2x.png the scale on the UIImage says it is 1x and it gets rendered badly where I want it to be rendered, it renders it in full size.. instead of 1/2 the size with double the pixels.. how do I make this work correctly?
You can create a new UIImage with a scale factor of 2 using the code below:
UIImage * img = [UIImage imageNamed:#"myimagename"];
img = [UIImage imageWithCGImage:img.CGImage scale:2 orientation:img.imageOrientation];
To make the code device-independent, you should get the scale factor of the current device using the code below and replace the number 2 with it.
[UIScreen mainScreen].scale

Specify asset image for UIImageView for all devices

Is there a way I can say for a particular UIImageView:
UIImageView *imageView = <#instantiate#>
imageView.image = #"someImageFromImageAsset";
and based on the device it's rendering on, it sets the right image. Obviously I need to set the image for a particular device but I am unsure how you do it.
iOS will automatically choose the correct sized image if you just use the name of the image. Use #2x in the image file name for retina display.
Objective-C
imageView.image = [UIImage imageNamed: #"someImageName"];
Swift
imageView.image = UIImage(named: "someImageName");

iOS Wrong Image Size when using my own image suffix

I use bg.png for iPhone, bg#2x for both iPhone retina and iPad, bg#4x for iPad retina.
Here is the code i wrote: (in Helper.m)
+ (UIImage *) imageNamed:(NSString *)name
{
name = [name stringByReplacingOccurrencesOfString:#".png" withString:#""];
UIImage *image;
if (IS_IPAD) {
if (IS_RETINA) {
image = [UIImage imageNamed:[NSString stringWithFormat:#"%##4x.png", name]];
if (image) {
return image;
}
}
return [UIImage imageNamed:[NSString stringWithFormat:#"%##2x.png", name]];
}
else {
if (IS_RETINA) {
image = [UIImage imageNamed:[NSString stringWithFormat:#"%##2x.png", name]];
if (image) {
return image;
}
}
return [UIImage imageNamed:name];
}
}
The file is correct, but the size of image is wrong.
If the file is automatically picked by the system (use [UIImage imageNamed:#"bg.png"]), then on iPhone retina, the size is still 320x480 (1 point = 4 pixels).
but if i use [Helper imageNamed:#"bg.png"], the size is 640x960. (1 point = 1 pixel)
So anyway to correct the size?
On a retina device
[UIImage imageNamed:#"bg.png"]
searches for bg#2x.png first. If that image exists, it is loaded and the scale property
of the image is automatically set to 2.0. On the other hand,
[UIImage imageNamed:#"bg#2x.png"]
also loads that image, but uses the default scale = 1.0.
If you have to use a custom loading mechanism, you have to adjust the scale factor.
Since scale is a read-only property of UIImage it cannot be set directly. One method
I know of is
UIImage *tmpImage = [UIImage imageNamed:#"bg#2x.png"];
UIImage *properlyScaledImage = [UIImage imageWithCGImage:[tmpImage CGImage]
scale:2.0
orientation:UIImageOrientationUp];
Why reinvent what Apple already provides? The imageNamed: method already supports the ability to load iPhone or iPad specific images by using the ~iphone and ~ipad suffixes.
To get an iPad specific retina image you just name it bg#2x~ipad.png.
To get an iPad specific non-retina image you name it bg~ipad.png.
The problem you have with your code is due to the non-standard naming conventions, the image is loaded with the wrong scale.
Update: based on additional information in the comments, a better approach to solve this issue is to replace the use of the UIImage imageNamed: method with calls to the UIImage imageWithData:scale: method. This provides better memory management as well as the ability to specify the proper scale for the custom naming conventions and image sharing between iPhone retina and iPad non-retina.

Subclass UIImage imageNamed:?

I am on my voyage to supporting the iPhone 5. I am well aware that there is iOS 6's auto layout feature in Interface Builder. This is great however, sometimes I want to load my own images if its an iPhone 5.
So some of the images in my game for iPhones are exactly the screen's size either (320x480) or (640 x 960). So if I am on an iPhone 5 those images will not cover the entire screen. So I am going to make (640 x 1136) images for those full screen images.
Now I know that if I simply name the image: MyImage-568h#2x.png it won't load. So, how would I subclass UIImage so that it will load the -568h#2x image thats not the default image?
Thanks!
The lazy way:
UIImage * img = [UIScreen mainScreen].bounds.size.height > 500 ? [UIImage imageNamed:#"Default-568h.png"] : [UIImage imageNamed:#"Default.png"];
I've done this in an app where the main screen on devices without a camera is Default.png; it doesn't seem too hacky because we would need to change Default.png to support new devices anyway.
The less lazy way: Condition on the space you need to fill, not the screen size.
The solution you asked for isn't really generic enough to warrant a class, but here it is anyway:
#implementation MyImage
+(UIImage)imageNamed:(NSString*)name {
if ([UIScreen mainScreen].bounds.size.height > 500) {
UIImage * img = [UIImage imageNamed:[name stringByAppendingString:#"-iPhone5"];
if (img) { return img; }
}
return [UIImage imageNamed:name];
}
#end
There's really no need to subclass UIImage. If you're feeling really hacky, you can patch/swizzle/otherwise +[UIImage imageNamed:] to point to a custom method, but I really don't recommend that except for debugging.

Graphic for retina display not working for IPAD

I am going to update my app for retina display.For this purpose I have set image name with #2x suffix.But iPad 3 not load hd graphic. I also try with suffix #2x~ipad but no any luck.
How can I set retina graphic for IPad3?.
#2x~ipad postfix should do the trick, there might be something else wrong.
When you load the image, leave off the suffix. For example, do
UIImage *image = [UIImage imageNamed:#"myImage"];
and not
UIImage *image = [UIImage imageNamed:#"myImage.png"];

Resources