I would like to stop a UIImageView from upscaling as it looks terrible. Unfortunately, I cannot control the UIImage content it is holding, so need to force it not to attempt the upscale on an iPhone 4 retina display.
What's the best advice here?
Set its frame manually, I think.
Unless you are always using 2x images (for retina display), then you can multiply the width/height with 0.5.
Related
I am trying to reduce the size (30+ MB) of my binary submission, and I sense that images acquire a sizable (>26 MB) part.
I also observed that if I remove retina images (#2x.png), iOS gracefully replaces them with 4-inch retina (-568h#2x.png) versions.
Are the retina images really redundant if I supply -568h#2x.png versions?
P.S.
Not that one image makes much of a difference, but if the answer is a Yes, does this also apply for default.png?
#2x images are for retina devices. They look much crisper and clean on retina devices (e.g. iPad3, iPhone 5) as compared to their non-retina counterpart images. Here are few suggestions to reduce size of your binary.
1) For background images check if they are really needed. If they are simple solid color images you can simply set the backgroundColor of the UIView.
2) Whenever possible use 9 patch (also called 9 scale) images for button or view backgrounds. They are generally 1 px wide images and you can use below method of UIImage to use them
- (UIImage *)resizableImageWithCapInsets:(UIEdgeInsets)capInsets resizingMode:(UIImageResizingMode)resizingMode
In general image#2x can be used as a stand in for image, but not the other way around (because they wouldn't look good). The side effect of doing this is that more memory will be used and on non-retina devices that could cause a problem. If you aren't supporting non-retina devices then you don't need any images.
Generally speaking you shouldn't have many image-568h#2x images other than the Default and other background images. Most of your content images will be the same size no matter what the screen size is. You do not need differently named images for a button of the same size on multiple different screen sizes.
I am using 2 images: image.png and image-hd.png and it works fine for retina and non-retina too.
But what I want to do now is to remove all non-retina images and leave only retina images. I heard that a non-retina device will scale the image down itself. I tried it but it didn't work :( How I do this? What name should I give to the image that it will show picture its actually size on retina and for non-retina will be scaled down?
No, Retina images are not scaled down automatically.
Only using Retina images and using them scaled down on standard resolution display devices is a bad idea.
Non-Retina devices have far less memory than Retina devices, but you're forcing them to load the Retina resolution images. In other words: device has half the memory, but is forced to load images that consume four times as much texture memory as need be.
Non-Retina devices have slower GPU & CPU. But you're forcing them to work on four times the number of pixels. Performance suffers.
You probably need to scale it down manually. I'm not sure if thats the best idea.
But I think you can just scale down the images to 0.5 if in retina device.
About images, its important to remember that each image is taking memory according to the size of the next power 2 dimensions. Which means that 20X20 pic will take the same memory as 32X32, and 130X260 will take 256X512.
So sometimes just handling your image sizes better or using something like Sprite Sheet.
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.
I have a UIImage, from either device's camera or downloaded from a URL. Say resolution is 800x600.
I want to display a scaled image in a UIImageView which is 200x150, and I have a proper image scaling code.
So, I just scale the UIImage to the UIImageView's frame.size (again, 200x150). On a non-retina display it looks OK, but on a retina display it looks bad, like a smaller picture was scaled up, because the actual frame in pixels is 400x300.
The question is - should I, manually multiply the frame.size.width/height by 2 when it's a retina display when I resize, so it'll be resized to 400x300, or is there a built in feature for that?
Since the UIImage is not a resource on the device, I don't have the #2x option.
Keep the frame size of the image view at 200x150 in all cases.
In case of non-retina display scale the image to 200x150. On retina display devices scale it to 400x300. Set the contentMode of the UIImageView to UIViewContentModeScaleAspectFit.
When you get the image in say 800x600, can't you make a UIImage that is scaled to 400x300 and save it temporarily with the #2x extension, maybe to the Documents folder or tmp folder, and then save another UIImage scaled to 200x150 and save it without the #2x in the same directory.
My app will download a image and display it into a UIImageView.
The image is quite large, say 600 * 600 and the UIImageView's size is 100 * 100.
So when the image is displayed, I set the UIImageView to scale it to fit.
My question is
For iPhone 3Gs, I understand the image is scaled to 100 * 100 directly and displayed in UIImageView.
But what about iPhone 4? When I do imageView.image = image, will iOS automatically scale the image to 200 * 200 first and then display it in 100 * 100 imageView?
I mean should I do anything extra to make sure that the Retina display is adapted?
Thanks
In this case, no, you needn't do anything particular. If your UIImageView is well configured (scale to fit, as it seems you've done), an iPhone4 will display your image scaled at 200x200 pixels in a 100x100 points UIImageView. No need either to download a different "whatever#2x.png" image.
You don't have to do anything specific here. Your image will be scaled appropriately by UIKit and in fact it's the UIImageView which will be affected by the Retina display, not your image. You specify a size of 100 x 100 which on non-Retina displays will hold true, but on Retina displays under the surface the physical size will actually be 200 x 200 because it'll take into account the scaleFactor.
Either way, the UIImageView will scale the image accordingly.
I have an experience that it works opposite way..so scale it for retina and iphone 3G or 3GS will display it correctly.