iOS Wrong Image Size when using my own image suffix - ios

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.

Related

What is the code when I want to show a #2x image in app

Today when I search some information about #1x #2x #3x
something confuses me
are these only used as app icon? Because most messages always give me the example of the icon.
and If it can be used in app view, how is the code?
like this?
self.view.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed: #"background.png"]];
Then, iOS will change #1x and #2x itself? OR I need to code like this:
#define deviceIsIPhone5 ([UIScreen mainScreen].applicationFrame.size.height == 568 ? YES : NO)
if (deviceIsIPhone5)
{
self.backgroundImage.image = [UIImage imageNamed:#"background#2x.png"];
}
else
{
self.backgroundImage.image = [UIImage imageNamed:#"background.png"];
}
You don't have to think about #2x #3x.iOS automatically handles it.
All you need to care about is to put right size image into the right box(.xcassets) if you want to show image properly in all iOS devices.
no need to care about 2x,3x and png.
just enter image name only. ios will automatically check image to use according to screen dimensions.
self.backgroundImage.image = [UIImage imageNamed:#"background"];

Loading a UIImage from xcassets

I'm trying to load a launch image from the Image.xcassets folder but to no avail. There are other answers (and this one) on SO that purport to answer it but their main solution, to simply load an image like so
UIImage *image = [UIImage imageNamed:#"Default#2x"];
returns nil for me.
The filename is named correctly and the project is setup to use the assets.
Does anyone have any idea how I do this or what I could be doing wrong?
Thanks in advance.
EDIT:
EDIT 2: my final code:
-(void) loadSplashImage{
if ([self isiPad]){
self.imageViewSplash.image = [UIImage imageNamed:#"Default-Portrait"];
}
else{
if (self.view.frame.size.height == 480){
self.imageViewSplash.image = [UIImage imageNamed:#"Default"];
}
else if (self.view.frame.size.height == 568){
self.imageViewSplash.image = [UIImage imageNamed:#"Default-568h"];
}
else if (self.view.frame.size.height == 667){
self.imageViewSplash.image = [UIImage imageNamed:#"Default-667h"];
}
}
}
Please note it works for Portrait only.
You dont have to specify the size of the image in your name. It will automatically load the size that best fits for the device that runs the app. So your code should be.
UIImage *image = [UIImage imageNamed:#"Default"];
where default is the name of the resource from xcassets, the one you see on the leftside list.
Here's the way to get LaunchImage name.
Xcode 5 & Asset Catalog: How to reference the LaunchImage?
Getting image name from info.plist ([[NSBundle mainBundle] infoDictionary])
You should have 2 files:
(1) Default.png (or any other image format) — Non retina
(2) Default#2x.png — Retina
Now, to get this image, you will not have to use #2x at the end of the file name. Use just name of that image asset.

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");

Retina image displayed too big in retina simulator

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"];

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