Crop an image to a square in iOS - ios

In my app I import an image from either the camera or the photo library using a UIImagePickerController. Than I save the imported image to the app documents directory. This all works fine, however I would like to save the image cropped as a square(like on instagram) instead of it's original size.The square should be the size of either the width of the image or the height of it(depending on which is the smaller one). I figured that maybe a CGRect would be useful here, but I have no idea how to crop a CGRect out of an image..I have looked at countless tutorials but none of them seemed to work or they were all too complicated..

-(UIImage *)squareImage:(UIImage *)image
{
if (image.size.width>=image.size.height)
{
image=[self imageWithImage:image scaledToHeight:100];
}
else
{
image=[self imageWithImage:image scaledToWidth:100];
}
return image;
}
-(UIImage*)imageWithImage:(UIImage*)sourceImage scaledToWidth:(float)width
{
float oldWidth = sourceImage.size.width;
float scaleFactor = width / oldWidth;
float newHeight = sourceImage.size.height * scaleFactor;
float newWidth = oldWidth * scaleFactor;
UIGraphicsBeginImageContext(CGSizeMake(newWidth, newWidth));
[sourceImage drawInRect:CGRectMake(0, 0, newWidth, newHeight)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
-(UIImage*)imageWithImage:(UIImage*)sourceImage scaledToHeight:(float)height
{
float oldHeight = sourceImage.size.height;
float scaleFactor = height / oldHeight;
float newWidth = sourceImage.size.width * scaleFactor;
float newHeight = oldHeight * scaleFactor;
UIGraphicsBeginImageContext(CGSizeMake(newHeight, newHeight));
[sourceImage drawInRect:CGRectMake(0, 0, newWidth, newHeight)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
above method will help you to scale image proportionately and scaling image in square..for rotation you can search on google.

Related

how to fit the image in tableview based on size and Aspect ration?

I am developing the project like Instagram upload the image and display the all feeds in home page.But image not fitting in image view. In Instagram table view cell automatically fit based on image size please provide me suggestions.
[_imageView setImage:[ViewController imageWithContentMode:[UIImage imageNamed:#"howwehelp_bg.png"] withScaledSize:_imageView.bounds.size]];
_imageView.contentMode = UIViewContentModeScaleToFill;
+(UIImage *)imageWithContentMode:(UIImage *)image withScaledSize:(CGSize)newSize{
UIGraphicsBeginImageContextWithOptions(newSize, NO, 0.0);
[image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
UIImage *imageNew = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return imageNew;
}
You can apply this code for fit images.
+(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;
}

issue with cropImage method on image in UIScrollView yields wrong image

I am using the following crop method to crop a uiimage that's sitting in a UIImageView which is then sitting in a UIScrollView.
-(UIImage *)cropImage:(UIImage *)image
{
float scale = 1.0f/_scrollView.zoomScale;
NSLog(#"Oh and heres that zoomScale: %f", _scrollView.zoomScale);
CGRect visibleRect;
visibleRect.origin.x = _scrollView.contentOffset.x * scale;
visibleRect.origin.y = _scrollView.contentOffset.y * scale;
visibleRect.size.width = _scrollView.bounds.size.width * scale;
visibleRect.size.height = _scrollView.bounds.size.height * scale;
NSLog(#"Oh and here's that CGRect: %f", visibleRect.origin.x);
NSLog(#"Oh and here's that CGRect: %f", visibleRect.origin.y);
NSLog(#"Oh and here's that CGRect: %f", visibleRect.size.width);
NSLog(#"Oh and here's that CGRect: %f", visibleRect.size.height);
CGImageRef imageRef = CGImageCreateWithImageInRect([image CGImage], visibleRect);
UIImage *croppedImage = [[UIImage alloc] initWithCGImage:imageRef];
CGImageRelease(imageRef);
return croppedImage;
}
I need the image to be cropped to a CGSize of (321,115). Upon cropping the image and seeing the print results, I can see that visibleRect is (0,0,321,115) - what it is supposed to be, the croppedImage UIImage then has width:321 and height:115. for some reason however the image appears to be zoomed in entirely too far (the method cropped a smaller portion of the original image to a size of 321x115).
Why is this method not correctly cropping my image?
-As a side note: When I call this method, I am calling like so _croppedImage = [self cropImage:_imageView.image]; which sets a UIImage property of a custom UIView class to the cropped image.
Please try this function. It may help you.
Parameters:
UIImage
CGSize (321,115) or any size
// crop image - image will crop from full image
- (UIImage *)cropImageWithImage:(UIImage *)image scaledToSize:(CGSize)newSize {
double ratio;
double delta;
CGPoint offset;
//make a new square size, that is the resized imaged width
CGSize sz = CGSizeMake(newSize.width, newSize.width);
//figure out if the picture is landscape or portrait, then
//calculate scale factor and offset
if (image.size.width > image.size.height) {
ratio = newSize.width / image.size.width;
delta = (ratio*image.size.width - ratio*image.size.height);
offset = CGPointMake(delta/2, 0);
}
else {
ratio = newSize.width / image.size.height;
delta = (ratio*image.size.height - ratio*image.size.width);
offset = CGPointMake(0, delta/2);
}
//make the final clipping rect based on the calculated values
CGRect clipRect = CGRectMake(-offset.x,
-offset.y,
(ratio * image.size.width) + delta,
(ratio * image.size.height) + delta);
//start a new context, with scale factor 0.0 so retina displays get
//high quality image
if ([[UIScreen mainScreen] respondsToSelector:#selector(scale)]) {
UIGraphicsBeginImageContextWithOptions(sz, YES, 0.0);
} else {
UIGraphicsBeginImageContext(sz);
}
UIRectClip(clipRect);
[image drawInRect:clipRect];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
To crop only selected portion of image
Please check this link

How to resize the UIImageView after AspectFit ratio

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

How can I resize the UIImage to specific size

In my app, I am taking picture with camera and displaying it in 320*320 UIView. But as the image resolution is more than that of UIView its kinda look squeezed. Is there any way I can resize that image?
Here's how you can resize the image while preserving its aspect ratio. The code below is from a category for UIImage:
+ (UIImage*)imageWithImage:(UIImage *)image
scaledToSize:(CGSize)newSize
{
float heightToWidthRatio = image.size.height / image.size.width;
float scaleFactor = 1;
if(heightToWidthRatio > 0) {
scaleFactor = newSize.height / image.size.height;
} else {
scaleFactor = newSize.width / image.size.width;
}
CGSize newSize2 = newSize;
newSize2.width = image.size.width * scaleFactor;
newSize2.height = image.size.height * scaleFactor;
UIGraphicsBeginImageContext(newSize2);
[image drawInRect:CGRectMake(0,0,newSize2.width,newSize2.height)];
UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
I do this, but first I enable the photo picker to editable so it is default 1:1 aspect, like so:
imgPicker.allowsImageEditing = YES; //I think this is what you're really looking for
then I resize the image using this method:
-(UIImage*)resizeImage:(UIImage*)image{
CGSize newSize = CGSizeMake(480.0, 480.0);
UIGraphicsBeginImageContext(newSize);
[image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}

How to resize an UIImage while maintaining its Aspect Ratio

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

Resources