How do I resize UIImageView after setting its contentmode to UIViewContentModeScaleAspectFit so that i can remove the white spaces from top & below.
Please see the attached image
Thanks in advance:)
Hope this will help some others as well ,please do comment if it will break in some condition :)
- (CGRect)frameForImageattribute:(CGSize)image inImageViewAspectFit:(UIImageView *)imageView {
float imageRatio = image.width / image.height;
float viewRatio = imageView.frame.size.width / imageView.frame.size.height;
if (imageRatio < viewRatio) {
float scale = imageView.frame.size.height / image.height;
float width = scale * image.width;
return CGRectMake(kLeftPading, kTopPading, width, imageView.frame.size.height);
}
else {
float scale = imageView.frame.size.width / image.width;
float height = scale * image.height;
return CGRectMake(kLeftPading, kTopPading, imageView.frame.size.width, height);
}
}
You need to get the scale factor of the image view. it can be obtained by
float scaleFactor = MAX(image.size.width/imageView.bounds.size.width, image.size.height/imageView.bounds.size.height);
Then do
CGRect ivFrame = imageView.frame;
ivframe.size.height = image.size.height/scalefactor;
ivFrame.size.width = image.size.width/scalefactor;
imageView.frame = ivFrame;
theres probably a category out there that does this automagically.
EDIT: Heres one for the scalefactor calculation, and it even respects the content mode of the mageView:
how can I get the scale factor of a UIImageView who's mode is AspectFit?
If you know only the width of the imageview and when the height of the image is dynamic then you need to scale the image's height according to the given width to remove the white spaces above and below your image in UIViewContentModeScaleAspectFit mode. Use the following method from here to scale the height of the image according to the standard width of your screen.
-(UIImage*)imageWithImage: (UIImage*) sourceImage scaledToWidth: (float) i_width
{
float oldWidth = sourceImage.size.width;
float scaleFactor = i_width / oldWidth;
float newHeight = sourceImage.size.height * scaleFactor;
float newWidth = oldWidth * scaleFactor;
UIGraphicsBeginImageContext(CGSizeMake(newWidth, newHeight));
[sourceImage drawInRect:CGRectMake(0, 0, newWidth, newHeight)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
And call it from your cellForRowAtIndexPath: method like this:
UIImage *img = [dictImages objectForKey:yourImageKey]; // loaded the image
cell.imgView.image = [self imageWithImage:img scaledToWidth:self.view.frame.size.width];
Related
I am using the code below first to create an image thumb (using a category) and then tailor the thumb to the VC in question, for example, make it round.
Somehow, the aspect ratio of images is not getting preserved with some getting squashed vertically...so a face looks like a sideways oval while others get squashed horizontally, so a round ball looks like an upright football. In the code for individual VCs, I am using UIViewContentModeScaleAspectFill and setting clip to bounds to yes but to no avail. Also tried checking these in Storybord but still no luck.
Can anyone see what might be wrong with code below?
//code in viewDidLoad
UIImage *thumbnail = [selectedImage createThumbnailToFillSize:CGSizeMake(side, side)];
//see createThumbNail method below
self.contactImage.image = thumbnail;
//image has been selected and trimmed to thumb. Now format it
CGSize itemSize = CGSizeMake(64, 64);
UIGraphicsBeginImageContextWithOptions(itemSize, NO, UIScreen.mainScreen.scale);
CGRect imageRect = CGRectMake(0.0, 0.0, itemSize.width, itemSize.height);
self.contactImage.contentMode = UIViewContentModeScaleAspectFill;
self.contactImage.clipsToBounds = YES;
[self.contactImage.image drawInRect:imageRect];
self.contactImage.image = UIGraphicsGetImageFromCurrentImageContext();
self.contactImage.layer.cornerRadius=60.0;
UIGraphicsEndImageContext();
//Generic category to create thumb
-(UIImage *) createThumbnailToFillSize:(CGSize)size
{
CGSize mainImageSize = size;
UIImage *thumb;
CGFloat widthScaler = size.width / mainImageSize.width;
CGFloat heightScaler = size.height / mainImageSize.height;
CGSize repositionedMainImageSize = mainImageSize;
CGFloat scaleFactor;
// Determine if we should shrink based on width or hight
if(widthScaler > heightScaler)
{
// calculate based on width scaler
scaleFactor = widthScaler;
repositionedMainImageSize.height = ceil(size.height / scaleFactor);
}
else {
// calculate based on height scaler
scaleFactor = heightScaler;
repositionedMainImageSize.width = ceil(size.width / heightScaler);
}
UIGraphicsBeginImageContext(size);
CGFloat xInc = ((repositionedMainImageSize.width-mainImageSize.width) / 2.f) *scaleFactor;
CGFloat yInc = ((repositionedMainImageSize.height-mainImageSize.height) / 2.f) *scaleFactor;
[self drawInRect:CGRectMake(xInc, yInc, mainImageSize.width * scaleFactor, mainImageSize.height * scaleFactor)];
thumb = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return thumb;
}
I need to set the UIImageView size aspectfit according to height .
means my requirement is that my height of image should be fix but the width of image should be change according to height i know that in UIViewContentModeScaleAspectFit it will take width and hieght automatically but what if i need fix height and dynamic width like aspectfit according to height.
UIImage *originalImage = [UIImage imageNamed:#"image.png"];
double width = originalImage.size.width;
double height = originalImage.size.height;
double apect = width/height;
double nWidth = 320.f/ apect;
self.img.frame = CGRectMake(0, 0, nWidth, 320.f);
self.img.center = self.view.center;
self.img.image = originalImage;
-(CGSize)resizeImage:(CGSize)imageSize toTargetedHeight:(float)height {
NSLog(#"actualImageSize : %#", NSStringFromCGSize(imageSize));
float scaleFactor = height / imageSize.height;
float newHeight = imageSize.height * scaleFactor;
float newWidth = imageSize.width * scaleFactor;
CGSize newSize = CGSizeMake(newWidth, newHeight);
NSLog(#"convertedImageSize : %#", NSStringFromCGSize(newSize));
return newSize;
}
This will create your image with specific height with maintaining its aspect ratio.
I have a UIImage and I want to adjust what is shown on the device based on a UIImageView.
The UIImage is:
UIImage *image = // a PNG I have
// width = 1200
CGFloat width = image.size.width;
// height = 900
CGFloat height = image.size.height;
And I have an UIImageView
UIImageView *iview = [[UIImageView alloc] initWithFrame:CGRectMake(0.0, 0.0, 675.0, 900.0)];
How do I get my UIImage into the UIImageView without adjust the aspect ratio? I want the UIImage to be cropped off the edges?
hope this helps
-(UIImage*)crop:(CGRect)frame
{
// Find the scalefactors UIImageView's widht and height / UIImage width and height
CGFloat widthScale = self.bounds.size.width / self.image.size.width;
CGFloat heightScale = self.bounds.size.height / self.image.size.height;
// Calculate the right crop rectangle
frame.origin.x = frame.origin.x * (1 / widthScale);
frame.origin.y = frame.origin.y * (1 / heightScale);
frame.size.width = frame.size.width * (1 / widthScale);
frame.size.height = frame.size.height * (1 / heightScale);
// Create a new UIImage
CGImageRef imageRef = CGImageCreateWithImageInRect(self.image.CGImage, frame);
UIImage *croppedImage = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
return croppedImage;//(return value is uiimage)
}
and then add it to uiimageview
If u want to crop off the edges and center the position of ur image then
Set the Imageview properties to AspectFill
myImageView.contentMode = UIViewContentModeScaleAspectFill;
myImageView.clipsToBounds = YES;
Hope this helps
Try setting the contentMode property of your UIImageView to UIViewContentModeScaleAspectFill, which according to the documentation is:
The option to scale the content to fill the size of the view. Some portion of the
content may be clipped to fill the view’s bounds.
You can see the other options in the UIView documentation.
I am developing an app where in users click images and upload them. There is a button in my app and on clicking it, the camera mode opens. User can click image and see preview. In preview the image looks good and it occupies whole screen. Later I have to display this image in a UIImageView of width 110 and height 111. When I display it in this, the image is getting distorted and cropped at edges. My main objective is to maintain aspect ratio.
I tried doing this.
- (void)displayCapturedImage
{
//[self.imageView setImage:self.capturedImage];
CGSize smallSize = CGSizeMake(110, 111);
[self.imageView setImage:[self imageWithImage:self.capturedImage scaledToSize:smallSize]];
}
- (UIImage*)imageWithImage:(UIImage*)image
scaledToSize:(CGSize)newSize;
{
UIGraphicsBeginImageContext( newSize );
[image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
but this didn't work for me. Image is still distorted.
You need to calculate the scale ratio yourself. Determine how much smaller the image needs to be and apply that to both the width and height.
Something like
float widthFactor = targetWidth / width;
float heightFactor = targetHeight / height;
if ( widthFactor < heightFactor )
scaleFactor = widthFactor;
else
scaleFactor = heightFactor;
scaledWidth = width * scaleFactor;
scaledHeight = height * scaleFactor;
if ( widthFactor < heightFactor )
thumbnailPoint.y = (targetHeight - scaledHeight) * 0.5;
else if ( widthFactor > heightFactor )
thumbnailPoint.x = (targetWidth - scaledWidth) * 0.5;
I want to resize a UIImage with maintaining its Aspect Ratio. I have written the following code, but it is not working as expected.
Code
-(UIImage * ) scaleImage: (UIImage * ) image toSize: (CGSize) targetSize {
CGFloat scaleFactor = 1.0;
if (image.size.width > targetSize.width || image.size.height > targetSize.height)
if (!((scaleFactor = (targetSize.width / image.size.width)) > (targetSize.height / image.size.height))) //scale to fit width, or
scaleFactor = targetSize.height / image.size.height; // scale to fit heigth.
UIGraphicsBeginImageContext(targetSize);
CGRect rect = CGRectMake((targetSize.width - image.size.width * scaleFactor) / 2, (targetSize.height - image.size.height * scaleFactor) / 2,
image.size.width * scaleFactor, image.size.height * scaleFactor);
[image drawInRect: rect];
UIImage * scaledImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return scaledImage;
}
What exactly is wrong here?
I'm using something similar to this in a few projects:
- (UIImage*) scaleImage:(UIImage*)image toSize:(CGSize)newSize {
CGSize scaledSize = newSize;
float scaleFactor = 1.0;
if( image.size.width > image.size.height ) {
scaleFactor = image.size.width / image.size.height;
scaledSize.width = newSize.width;
scaledSize.height = newSize.height / scaleFactor;
}
else {
scaleFactor = image.size.height / image.size.width;
scaledSize.height = newSize.height;
scaledSize.width = newSize.width / scaleFactor;
}
UIGraphicsBeginImageContextWithOptions( scaledSize, NO, 0.0 );
CGRect scaledImageRect = CGRectMake( 0.0, 0.0, scaledSize.width, scaledSize.height );
[image drawInRect:scaledImageRect];
UIImage* scaledImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return scaledImage;
}
If this is for displaying in a UI, you can use Interface Builder and specify the "Aspect Fit" property.
You can also do this in code by setting the content mode to UIViewContentModeScaleAspectFit:
imageView.contentMode = UIViewContentModeScaleAspectFit;
This method takes an image and a max dimension. If the max original image dimension is less than the specified max dimension, you get the original back so it won't get blown up. Otherwise, you get a new image having a max dimension of the one specified and the other determined by the original aspect ratio. So as an example, if you give it a 1024x768 image and max dimension of 640 you get back a 640x480 version, if you give it a 768x1024 image and max dimension of 640 you get back a 480x640 version.
- (UIImage *)resizeImage:(UIImage *)image
withMaxDimension:(CGFloat)maxDimension
{
if (fmax(image.size.width, image.size.height) <= maxDimension) {
return image;
}
CGFloat aspect = image.size.width / image.size.height;
CGSize newSize;
if (image.size.width > image.size.height) {
newSize = CGSizeMake(maxDimension, maxDimension / aspect);
} else {
newSize = CGSizeMake(maxDimension * aspect, maxDimension);
}
UIGraphicsBeginImageContextWithOptions(newSize, NO, 1.0);
CGRect newImageRect = CGRectMake(0.0, 0.0, newSize.width, newSize.height);
[image drawInRect:newImageRect];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
In my case (I wanted to have an image in a UIView) and keep the ratio with auto layout the way described here was great. The most important part of the article for me was (almost quoting):
constraint = [NSLayoutConstraint constraintWithItem:self.imageView
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:self.imageView
attribute:NSLayoutAttributeWidth
multiplier:ration
constant:0.0f];
[self.imageView addConstraint:constraint];
the only thing is to calculate the ratio according to the actual width and height of image. I found this way easy and elegant.
- (UIImage *)imageWithImage:(UIImage*)image scaledToSize:(CGSize)newSize {
UIGraphicsBeginImageContext(newSize);
float ratio = newSize.width/image.size.width;
[image drawInRect:CGRectMake(0, 0, newSize.width, ratio * image.size.height)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
NSLog(#"New Image Size : (%f, %f)", newImage.size.width, newImage.size.height);
UIGraphicsEndImageContext();
return newImage;
}
In Swift 5 you can use scaleAspectFit on the contentMode attribute.
let photo = UIImage(imageLiteralResourceName: "your_img_name")
let photoImageView = UIImageView(image: photo)
photoImageView.contentMode = .scaleAspectFit