Retina display for an image from URL - objective-c

I have some images I need to get from the web. Just using data from a URL.
They need to show correctly on Retina Display.
When I get the images from the web, they still look pixelated. I need to set the images' scale to retina display (2.0), but I must be missing something.
Here's what I did so far.
UIImage *img = [UIImage imageWithData:[NSData dataWithContentsOfURL:#"http://www.msdomains.com/tmp/test.png"];
CGRect labelFrame = CGRectMake(0,0,64,64);
UIImageView *imageView = [[UIImageView alloc] initWithFrame:labelFrame];
imageView.contentScaleFactor = [UIScreen mainScreen].scale;
[imageView setImage:img];
[self addSubview:imageView];
[imageView release];

Try adding ##2x.png at the end of your URL. That wont change the URL, but the image will be recognized as a retina #2x image. It worked for me, but I used this method with SDWebImage.
e.g. using http://www.msdomains.com/tmp/test.png##2x.png.

Your code should work pretty much as-is. I don't know what the original dimensions of your image were, but I'd guess they were 64x64 px. In order to scale down correctly, the original image would need to be 128x128 px.
As a test, the following code correctly displayed my photo in Retina resolution on the Simulator, and on my iPhone 4:
UIImage *img = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:#"http://www.seenobjects.org/images/mediumlarge/2006-08-19-native-lilac.jpg"]]];
CGRect labelFrame = CGRectMake(0, 0, 375, 249.5);
UIImageView *imageView = [[UIImageView alloc] initWithFrame:labelFrame];
[imageView setImage:img];
[self.view addSubview:imageView];
Note that the UIImageView is 375x249.5 points, which is half of the original (pixel) dimensions of the photo. Also, setting the contentScaleFactor didn't seem to be necessary.
(As an aside, I can't see that specifying #2x on the URL will help, in this case, as the call to dataWithContentsOfURL: will return an opaque blob of data, with no trace of the filename left. It's that opaque data that's then passed to imageWithData: to load the image.)

when you directly assign the image URL to imageView, it will not take it as retina.
imageView.imageURL = [NSURL URLWithString:#"http://example.com/image.png"];
will not give you a retina image.
So, inspite your image is 200x200 but if your imageView is 100x100 then it will take 100x100 from the downloaded image and show pixelated image on retina devices.
Solution would be to use the image property of imageView instead of imageURL.
imageView.image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:#"http://example.com/image.png"]]];
This will assign 200x200 image to the imageView of 100x100 and hence the image will not be pixelated.

For retina display, add the same image with the resolution which is exactly the double of the original image. dont forget to add "#2x"at the end of this image name... e.g. "image_header.png" is an image 320x100 then another image with name "image_header#2x.png" (dimension 640x200) will be selected for the retina display automatically by the OS...
hope it helps

Related

Render play image over existing image in objective c

I have collection view with some videos and images
Using AVFoundation able to capture video from iPhone and generated thumbnail using AVAssetImageGenerator. When shown in gallery image should distinguish it's of video thumbnail. So i need to transform exact image by drawing video symbol(like play icon) over it.
Is it possible?
You could use CoreGraphics to edit the image.
First, create a UIImage with the image you would like to edit. Then, do something like this:
UIImage *oldThumbnail; //set this to the original thumbnail image
UIGraphicsBeginImageContext(oldThumbnail.size);
[oldThumbnail drawInRect:CGRectMake(0, 0, oldThumbnail.size.width, oldThumbnail.size.height)];
/*Now there are two ways to draw the play symbol.
One would be to have a pre-rendered play symbol that you load into a UIImage and draw with drawInRect */
UIImage *playSymbol = [UIImage imageNamed:"PlaySymbol.png"];
CGRect playSymbolRect; //I'll let you figure out calculating where you should draw the play symbol
[playSymbol drawInRect: playSymbolRect];
//The other way would be to draw the play symbol directly using CoreGraphics calls. Start with this:
CGContextRef context = UIGraphicsGetCurrentContext();
//now use CoreGraphics calls. I won't go over it here, butthe second answer to this questionmay be helpful.
//Once you have finished drawing your image, you can put it in a UIImage.
UIImage *newThumbnail = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext(); //make sure you remember to do this :)
Now you can use the newly generated thumbnail in a UIImageView, cache it so you don't need to re-render it every time, etc.
This should work (you may have to play with positions and sizes):
-(UIImage*)drawPlayButton:(UIImage*)image
{
UIImage *playButton = [UIImage imageNamed:#"playbutton.png"];
UIGraphicsBeginImageContext(image.size);
[image drawInRect:CGRectMake(0, 0, image.size.width, image.size.height)];
[playButton drawInRect:CGRectMake(image.size.width/2-playButton.size.width/2, image.size.height/2-playButton.size.height/2, playButton.size.width, playButton.size.height)];
UIImage *result = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return result;
}

How to correctly show #2x retina images

  I'm using Xcode 4.5.2, the app is targeting iOS 6.0.
In my application, I am having trouble with showing iPad Retina images. I know I have to use the #2x~ipad.png extension in order to get them to properly show and I do that. My images are named according so they are all named the same besides the extension for each device.
Here is how I named it.
However,
NSString *name=#"appearanceConnection.png";
//NSString *name=#"appearanceConnection"; //I did check this
//I did check the target
UIImage *image = [UIImage imageNamed:name];
NSLog(#"%f",image.size.width);
shows me the width of #1x image.
If i try to set proper image name manually:
if ([[UIScreen mainScreen] respondsToSelector:#selector(displayLinkWithTarget:selector:)] &&
([UIScreen mainScreen].scale == 2.0)) {
// Retina display
name=#"appearanceConnection#2x~ipad.png";
NSLog(#"retina");
}
else
{
name=#"appearanceConnection.png";
NSLog(#"non-retina");
}
UIImage *image = [UIImage imageNamed:name];
NSLog(#"%f",image.size.width);
proper #2x picked and then it scaled by 2.0 when I'm adding it to view.
I cleaned/rebuild my project many times, I reset IOS simulator settings, no result.
What am I doing wrong?
update:
non-retina
retina:
NSLog(#"%f", image.scale)
after imageNamed method gives me 1.0
UPDATE 2:
I'm trying to optimize my animation appearance, so I want to load one big image once and cut it by frames.
Firstly, I load big image (#2x or 1#x), then using cycle
for (int i = 0; i<numberOfFrames; i++)
{
CGImageRef imageRef = CGImageCreateWithImageInRect(image.CGImage,
CGRectMake(i*width, 0.0f, width, height));
UIImage *animationImage = [UIImage imageWithCGImage:imageRef];
if (isFlip)
{
[animationImages insertObject:animationImage atIndex:0];
}
else
{
[animationImages addObject:animationImage];
}
CGImageRelease(imageRef);
}
i cut this big image and create animation.
width and height are multiplied by 2 if it is retina display.
Maybe here is a caveat?
UIImage *animationImage = [UIImage imageWithCGImage:imageRef];
returns me image scaled twice?
however, if I scale (0.5,0.5) UIImageView which is initialized by this image it fits. Have any idea why scaled twice?
the retina and non retina images will have the same width and height when used as a UIImage or something similar, think of it as on retina displays the DPI of the image is doubled, and not the width or height.
this is to keep things transparent when coding for retina and non retina.

set UIImageView to display middle section of an image

I've got an image view that I want to show a central slice of the user's profile picture. I want to scale the picture so that the width matches the width of the screen while maintaining the aspect ratio, center the image, and then have any extra on the top/bottom to not appear at all.
I've tried setting the imageView.contentMode to UIViewContentModeScaleAspectFill, UIViewContentModeScaleAspectFit, UIViewContentModeCenter and a few others, but it either resizes my UIImageView, changes the aspect ratio, or doesn't fill the area.
"but it either resizes my UIImageView"
I guess you see the cropped parts.
Maybe you forgot the "clipsToBounds" property?
UIImageView *view1 = [[UIImageView alloc] initWithFrame: ___ ];
view1.clipsToBounds = YES;
UIImage * img = [UIImage imageNamed:#" ___ "];
view1.image = img;
view1.contentMode = UIViewContentModeScaleAspectFill;

Downloading images from a web server for the retina display iOS

I am downloading images from a webserver for display in a table view in my iOS application using the following code:
NSURL *url = [NSURL URLWithString:[imageArray objectAtIndex:indexPath.row]];
UIImage *myImage = [UIImage imageWithData:[NSData dataWithContentsOfURL:url]];
cell.imageView.image = myImage;
The image view is a 60x60 placeholder and 120x120 for the retina display. I am going to assume the user has an iPhone 4. However, if I size the image to 120x120 it does not correct the issue, it just becomes too big for the the imageview. If I size the image to 60x60, on the webserver that is, then the image fits fine but its a little fuzzy. Anyone know how to fix this issue?
Thanks!
Let's first agree that your UIImageView is 60x60 points, meaning 60x60 pixels for a standard display and 120x120 pixels for a retina display.
For a UIImageView at 60x60 points, the image should be 60x60 pixels at scale 1.0 for a standard display and 120x120 pixels at scale 2.0 for a retina display. This means that your UIImage should always have a size of 60x60 points, but should have a different scale depending on the display resolution.
When getting the image data from your server, you should first check the scale of the device's screen and then request the appropriate image size (in pixels), like so:
if ([UIScreen mainScreen].scale == 1.0) {
// Build URL for 60x60 pixels image
}
else {
// Build URL for 120x120 pixels image
}
Then you should put the image data in a UIImage of size 60x60 points, at the appropriate scale:
NSData *imageData = [NSData dataWithContentsOfURL:url];
CFDataRef cfdata = CFDataCreate(NULL, [imageData bytes], [imageData length]);
CGDataProviderRef imageDataProvider = CGDataProviderCreateWithCFData (cfdata);
CGImageRef imageRef = CGImageCreateWithJPEGDataProvider(imageDataProvider, NULL, true, kCGRenderingIntentDefault);
UIImage *image = [[UIImage alloc] initWithCGImage:imageRef
scale:[UIScreen mainScreen].scale
orientation:UIImageOrientationUp];
CFRelease (imageRef);
CFRelease (imageDataProvider);
CFRelease(cfdata);
Hope this helps.
If your downloaded image have a size 2X from your UIImageView dimension size. It's look fine for retina display in iPhone4.
see also there: http://mobile.tutsplus.com/tutorials/iphone/preparing-your-iphone-app-for-higher-resolutions/
Images downloaded from the web are not formatted for Retina Display the same way images bundled with your app (using the "#2x" suffix) are.
You can get/set the scale of any UIView with the aptly named scale: and setScale: methods to help you better display content from the web if you know it's intended for Retina Display devices.
Well the answer is as simple as it can be:
I would recommend always downloading the double density images from the server (as users with non retina display are very few) and setting in the imageview.
What you didn't do correctly is you didn't set the imageView to automatically fit the content.
You can do this either in IB by selecting the ImageView and setting the contentMode (mode) to scale to Fill, or by code:
imageView.contentMode = UIViewContentModeScaleToFill;

Does anyone know how I can get the "real" size of the UIImageView instead of creating a frame

I was hoping there was some sort of function that could take the real size of my picture
CGRect myImageRect = CGRectMake(0.0f, 0.0f, 320.0, 210.0f); // 234
UIImageView *myImage = [[UIImageView alloc] initWithFrame:myImageRect];
[myImage setImage:[UIImage imageNamed:#"start.png"]];
And with CGRectMake which does something like this ..( imageViewHeight ,
CGFloat imageViewHeight = [myImage frame].size.height;
So that I could get the real size instead of having to define it like you can seen above.
I don't really get what you're asking, but here's a shot:
If you have a UIImage, and you want to know its size, you can ask it for its -[UIImage size] property.
However, if you want to create a UIImageView that's the same size as a UIImage, then you can just use -[UIImageView initWithImage:], which will automatically set the frame of the UIImageView to correspond to the dimensions of the image.
If, however, you're just looking to change the dimensions of a currently existing view, there's really no easy way to do that without messing around with the view's frame. You could maybe apply an affine transform to scale it, but it's easier to manipulate the frame.
It looks like you're asking to add the image to the imageview without first creating a frame. If this is the case, you can do the following:
UIImageView *myImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"start.png"]];
As far as I understood, you are looking for the size of the image used in UIImageView object. To do that, there is not a function built in UIImageView but you can do it this way:
NSString* image= [myImage image].accessibilityIdentifier; // Get the image's name
UIImage *img = [UIImage imageNamed:image]; // Create an image object with that name
CGSize size = img.size; // Get the size of image
Hope this helps your question.