How to get image without resizing? - ios

first of all i need to describe what i gonna to do:
i need to display a header image with full screen width for all devices.
there for i should provide multiple pictures with different sizes, and not just 2x and 3x.
so i would have these images:
header_width_1242.png for iphone 6 plus.
header_width_1125.png for iphone 6 plus display zoom
header_width_640.png for iphone 5,6
...
so i shouldn't choose image according to the scale, rather i should choose image according to the width:
let image_name = "header_width_" + String(UIScreen.mainScreen().scale * UIScreen.mainScreen().bounds.width)
let image = UIImage(named:image_name)
the problem, that ios scale the image automatically again. so if the device with scale 2x. then it return the image * 2 size.
e.g : for iphone 5 which has width 320 and scale 2, i need the header_width_640.png , but it seems that the system scale the image to 1280 (640 * 2).
How could i tell the system, to return image UIImage(named:image_name) without scaling ?thanks

You could declare a screenSize property on your viewController.
// Determine screen size
let screenSize: CGRect = UIScreen.mainScreen().bounds
Then, when you need to set an image, you could do the following:
if screenSize.width < 641 {
// set your imageView to the image for 640 screen width
} else if screenSize.width < 1126 {
// set your imageView to the image for 1125 screen width
} else if screenSize.width < 1243 {
// set your imageView to the image for 1242 screen width
}

You should not constraint assets by screen size, is better if you do by using size classes if available. Image assets directory make this possible in the inspector panel, by choosing the size classes for each image.
I do understand that sometimes is a need, but try to think in a relative perspective. If the image is something like a logo aligned by left or right you can use slicing to create stretchable end/beginning on the image.
If the image is center with a solid color or something drawable by code you can draw it at run time.
Here is a snippet in ObjC that use in an app of mine you can easily convert in SWIFT:
-(UIImage*) createNavBarBackgroundWithImage:(UIImage*) image {
CGSize screenSize = ((CGRect)[[UIScreen mainScreen] bounds]).size;
CGFloat width = screenSize.width;
CGFloat height = 64.0;
UIGraphicsBeginImageContextWithOptions(CGSizeMake(width, height), NO, 0.0);
//Draw background
UIColor * backGroundColor = [UIColor colorWithRed:27.f/255.f green:142.f/255.f blue:138.f/255.f alpha:1.0];
[backGroundColor setFill];
UIRectFill(CGRectMake(0, 0, width, height));
//Draw the image at the center
CGPoint point = CGPointMake(width/2 - image.size.width/2, 0);
[image drawAtPoint:point];;
UIImage *newBGImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newBGImage;
}

Use Image Asset
https://developer.apple.com/library/ios/recipes/xcode_help-image_catalog-1.0/chapters/AddingImageSets.html
header_width_1242.png for iphone 6 plus. Name it header_width_414.png drag to 3x
header_width_1125.png name it header_width_375.png drag to 3x
header_width_640.png name it header_width_320.png drag to 2x
let image_name = "header_width_" + UIScreen.mainScreen().bounds.width)
let image = UIImage(named:image_name)

Related

Resize image and maintain its aspect ratio in iOS

I am trying to select an image from photo library, this is the photo which I have downloaded from net and is stored in my photo lib.
So now I want to give user an option to select an image from photo lib and apply as a backgroundImage throught my app, but when I do it, I get the image this way on my iphone screen
Actually the image has been filled the screen, because the content mode specified is "scaleToFill".
1) I want to know how to make this image maintain its aspect ratio and also fill the screen?
Regards
Ranjit
check this blog. use these two files
UIImage+Resize.h
UIImage+Resize.m
UIImage *image = [UIImage imageNamed:#"SomeImage-900x675"]; // SomeImage-900x675.png
CGFloat targetWidth = 320.0;
CGFloat scaleFactor = targetWidth / image.size.width;
CGFloat targetHeight = image.size.height * scaleFactor;
CGSize targetSize = CGSizeMake(targetWidth, targetHeight);
UIImage *scaledImage = [image resizedImage:targetSize interpolationQuality:kCGInterpolationHigh];
though your image is taking all the screen size, Your image size is biger...You will try by scaling image with following resolutions
320*480,
640*960,
1240*2208

UIImageView with fixed width: how to set its height to keep its aspect?

I have a view where I need to place an UIImageView, and I was told to place it inside a rectangle that takes the screen width and its height is smaller than width (fixed size). However, the images I've been given are more or less square jpeg images, so the idea is to fill the width of the rectangle that should contain the image and set the height of the image in a way that its aspect ratio is kept. Then, I should be able to let the user scroll the image vertically to see the complete image.
How could I do this?
Thanks in advance
EDIT: I need to do this for several images that have different sizes, but that should fit the same rectangular area size within the view
You can set imageview content mode.
imageView.contentMode = UIViewContentModeScaleAspectFit;
This will make sure that the image is displayed by keeping original aspect ratio.
Edit:
I think this is what you wanted:
UIImage *originalImage = [UIImage imageNamed:[picArr objectAtIndex:a]];
double width = originalImage.size.width;
double height = originalImage.size.height;
double apect = width/height;
double nHeight = 320.f/ apect;
self.img.frame = CGRectMake(0, 0, 320, nHeight);
self.img.center = self.view.center;
self.img.image = originalImage;
Hope this helps.. :)

Trying to crop my UIImage to a 1:1 aspect ratio (square) but it keeps enlarging the image causing it to be blurry. Why?

Given a UIImage, I'm trying to make it into a square. Just chop some of the largest dimension off to make it 1:1 in aspect ratio.
UIImage *pic = [UIImage imageNamed:#"pic"];
CGFloat originalWidth = pic.size.width;
CGFloat originalHeight = pic.size.height;
float smallestDimension = fminf(originalWidth, originalHeight);
CGRect square = CGRectMake(0, 0, smallestDimension, smallestDimension);
CGImageRef imageRef = CGImageCreateWithImageInRect([pic CGImage], square);
UIImage *squareImage = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
UIImageView *imageView = [[UIImageView alloc] initWithImage:squareImage];
imageView.frame = CGRectMake(100, 100, imageView.bounds.size.width, imageView.bounds.size.height);
[self.view addSubview:imageView];
But this is what it results in:
When it should look like this, but just a little narrower.
Why is this? The images are pic(150x114) / pic#2x(300x228).
The problem is you're mixing up logical and pixel sizes. On non retina devices these two are the same, but on retina devices (like in your case) the pixel size is actually double the logical size.
Usually, when designing your GUI, you can always just think in logical sizes and coordinates, and iOS (or OS X) will make sure, that everything is doubled on retina screens. However, in some cases, especially when creating images yourself, you have to explicitly specify what size you mean.
UIImage's size method returns the logical size. That is the resolution on non-retina screens for instance. This is why CGImageCreateWithImageInRect will only create an new image, from the upper left half of the image.
Multiply your logical size with the scale of the image (1 on non-retina devices, 2 on retina devices):
CGFloat originalWidth = pic.size.width * pic.scale;
CGFloat originalHeight = pic.size.height * pic.scale;
This will make sure, that the new image is created from the full height (or width) of the original image. Now, one remaining problem is, that when you create a new UIImage using
UIImage *squareImage = [UIImage imageWithCGImage:imageRef];
iOS will think, this is a regular, non-retina image and it will display it twice as large as you would expect. To fix this, you have to specify the scale when you create the UIImage:
UIImage *squareImage = [UIImage imageWithCGImage:imageRef
scale:pic.scale
orientation:pic.imageOrientation];

How to make UIImageView automatically resize to the size of the image loaded

I have put an UIImageView control on my view with IB.
The size of the control is just something I decided upon, pretty random size really
What I want to do is the control to resize automatically whenever I set the image property to a new image. I want it to actually resize to the size of the image.
Can it be done automatically ? without any code intervention ?
If not - what will the best approach be in this case ?
What happens today is strange. I load images into the ImageView and I see the images getting displayed properly even though the size of the ImageView is not changed. This interferes with my intention of grabbing users touches over the ImageView. The user touches the actual image, but since some parts of the image are outside ( and this is the strange part ) of the ImageView - point mapping goes crazy
Can someone think of any explanation to this ?
thanks
The size of an image has no bearing on how large the UIImageView actually is, rather the size of the UIImageView solely depends on the size given to it in Interface Builder (or that you assigned to it). Else the images would be all whacky when you use the #2x images for Retina displays for example.
If you want to fix this, you must change the frame when setting the image as well. If you're doing this now:
[imageView setImage:[UIImage imageNamed:#"myImage.jpg"]];
change it to:
UIImage img = [UIImage imageNamed:#"myImage.jpg"];
[imageView setImage:img];
imageView.frame = CGRectMake(imageView.frame.origin.x, imageView.frame.origin.y,
img.size.width, img.size.height);
This will however not change the layout of view it is contained within, you can make it change the sizes of the other views automatically under iOS 6 using Layout Constraints. If you are an Apple Developer you can watch the WWDC instruction videos, they explain how that system works quite well.
If you're fine with the view not growing, and the problem is just how the image overflows it's bounds when you change it to one that does not match the dimension of the containing view, you can set the "Clip Subviews" checkbox in Interface Builder for the image view. This will make it so that the view will not draw anything outside it's own bounding box, if you also set the scaling mode to "Aspect Fill" or "Scale To Fill", the image will always fill up the entire bounds of the containing view.
Here is the code snippet I cut and paste often, using the same method as Hampus Nilsson above -
Example
func demo(x0:CGFloat, y0:CGFloat) {
let imgView = UIImageView(image: UIImage(named: "someImg.png"));
imgView.sizeToImage();
imgView.center = CGPoint(x:x0, y:y0);
}
UIImageView Extension
extension UIImageView {
/******************************************************************************/
/** #fcn sizeToImage()
* #brief size view to image
* ##assum (image!=nil)
*/
/******************************************************************************/
func sizeToImage() {
//Grab loc
let xC = self.center.x;
let yC = self.center.y;
//Size to fit
self.frame = CGRect (x: 0, y: 0, width: (self.image?.size.width)!/2, height: (self.image?.size.height)!/2);
//Move to loc
self.center = CGPoint(x:xC, y:yC);
return;
}
A wonderful cut & paste, use if needed!
let containerView = UIView(frame: CGRect(x:0,y:0,width:320,height:500))
let imageView = UIImageView()
if let image = UIImage(named: "Image_Name_Here") {
let ratio = image.size.width / image.size.height
if containerView.frame.width > containerView.frame.height {
let newHeight = containerView.frame.width / ratio
imageView.frame.size = CGSize(width: containerView.frame.width, height: newHeight)
}
else{
let newWidth = containerView.frame.height * ratio
imageView.frame.size = CGSize(width: newWidth, height: containerView.frame.height)
}
}

Using one image png file for retina and normal screen in UIImageView

Say there is cool.png file with dimension 200 X 100 pixels and I'd like to use it for both retina and normal devices.
I need to get size of UIImageView 100 X 50 points.
I tried to decrease the size of UIImageView according to image dimensions and visually I don't see any difference whether I prepare two file with and without scale modifier #2x or use UIImageView to scale it by contentMode property.
BOOL retina = [[UIScreen mainScreen] scale] == 2.0 ? YES : NO;
UIImage *img = [UIImage imageNamed:#"cool.png"];
UIImageView *imgView = [[UIImageView alloc] initWithImage:img];
imgView.contentMode = UIViewContentModeScaleToFill;
CGFloat width = img.size.width;
CGFloat height = img.size.height;
if (!retina) {
width = width/2.0;
height = height/2.0;
}
imgView.frame = CGRectMake (somePoint.x, somePoint.y, width, height);
Is there something wrong in the approach?
You are taking the wrong approach here..
CGRect,Point and Size aren't measured in pixels.. They are points.. Points are iOSes coordinate system and will be scaled to the device... So for example if you make a UIView 320 points wide then it will fill the width on both a retina iPhone or iPad...
so if you want your cool.png to display at 100x50 points on all devices then you can simply set the frame to be 100x50, set the image to cool.png then set the imgView.contentView to UIViewContentModeScaleAspectFit... This will then rescale the 200x100 image to fit of its a non retina device... Then if it was a retina device it would be at full resolution (200x100) but in the 100x50 points...
However the #2x system was made for a reason as having to scale the images down increases loading times as it has to be scaled but if you can't use #2x images then you can still do the above

Resources