I need to resize UIImage proportionally by width, may be someone have a working code?
For ex.:
Input: Width: 900 Height: 675. Resize to width: 400 width
Result: Width: 400 Height: 300
Please help..
Check this blog post out. In particular, these two files:
UIImage+Resize.h
UIImage+Resize.m
Maybe this would work for you:
UIImage *image = [UIImage imageNamed:#"SomeImage-900x675"]; // SomeImage-900x675.png
CGFloat targetWidth = 400.0f;
CGFloat scaleFactor = targetWidth / image.size.width;
CGFloat targetHeight = image.size.height * scaleFactor;
CGSize targetSize = CGSizeMake(targetWidth, targetHeight);
UIImage *scaledImage = [image resizedImage:targetSize interpolationQuality:kCGInterpolationHigh];
Couldn't you just set the content mode? to .ScaleAspectFill? Then you can set the UIImageView size to any arbitrary size and the aspect ratio will be preserved.
https://developer.apple.com/reference/uikit/uiviewcontentmode/1622518-scaleaspectfill
Related
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.
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];
My current method of combining UIImages come from this answer on SO, as well as this popular question on resizing UIImage with aspect ratio. My current issue is the following:
I have an UIImage called pictureImage taken with the camera that comes out to the standard dimension 2448*3264. I also have a UIImageView called self.annotateView that has a frame of 320*568 where the user could draw and annotate the picture. When I present the pictureImage in a UIImageView, I set the image presentation as Aspect Fill so that it takes up the whole iPhone screen. Of course this means parts of pictureImage is cut off on both left and right (in fact 304 pixels on both sides), but this intended.
My problem is, when I combine the UIImages pictureImage and annotateView.image to a new dimension of 320*568, my combined image alters the original aspects of annotateView.image by stretching it horizontally. This is strange since the new dimensions are exactly that of annotateView.image's original dimensions.
Here is what the outcome looks like -
Before combining the UIImages
After combining the images
Note that the underlying picture is not stretched. However, annotateView.image is stretched only horizontally, not vertically.
Here is my code for merging the UIImages.
//Note: self.firstTakenImage is set to 320*568
CGSize newSize = CGSizeMake(self.firstTakenImage.frame.size.width, self.firstTakenImage.frame.size.height);
UIGraphicsBeginImageContext(newSize);
[self.firstTakenImage.image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
[self.drawView.image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
UIImage *combinedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
While doing the drawInRect, you have to redo the scaling and centering that the system did for you with AspectFill to make it match the original process. Something like this:
CGSize fullSize = self.pictureView.image.size;
CGSize newSize = self.outputView.frame.size;
CGFloat scale = newSize.height/fullSize.height;
CGFloat offset = (newSize.width - fullSize.width*scale)/2;
CGRect offsetRect = CGRectMake(offset, 0, newSize.width-offset*2, newSize.height);
NSLog(#"offset = %#",NSStringFromCGRect(offsetRect));
UIGraphicsBeginImageContext(newSize);
[self.pictureView.image drawInRect:offsetRect];
[self.annotateView.image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
UIImage *combImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
self.outputView.image = combImage;
Support Portrait and Landscape both type of image
Drawing and other subviews can be merged in my case I'm adding label to draw
{
CGSize fullSize = getImageForEdit.size;
CGSize sizeInView = AVMakeRectWithAspectRatioInsideRect(imgViewFake.image.size, imgViewFake.bounds).size;
CGFloat orgScale = orgScale = fullSize.width/sizeInView.width;
CGSize newSize = CGSizeMake(orgScale * img.image.size.width, orgScale * img.image.size.height);
if(newSize.width <= fullSize.width && newSize.height <= fullSize.height){
newSize = fullSize;
}
CGRect offsetRect;
if (getImageForEdit.size.height > getImageForEdit.size.width){
CGFloat scale = newSize.height/fullSize.height;
CGFloat offset = (newSize.width - fullSize.width*scale)/2;
offsetRect = CGRectMake(offset, 0, newSize.width-offset*2, newSize.height);
}
else{
CGFloat scale = newSize.width/fullSize.width;
CGFloat offset = (newSize.height - fullSize.height*scale)/2;
offsetRect = CGRectMake(0, offset, newSize.width, newSize.height-offset*2);
}
UIGraphicsBeginImageContextWithOptions(newSize, NO, getImageForEdit.scale);
[getImageForEdit drawAtPoint:offsetRect.origin];
// [img.image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
CGFloat oldScale = img.contentScaleFactor;
img.contentScaleFactor = getImageForEdit.scale;
[img drawViewHierarchyInRect:CGRectMake(0, 0, newSize.width, newSize.height) afterScreenUpdates:YES];
img.contentScaleFactor = oldScale;
UIImage *combImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
imageData = UIImageJPEGRepresentation(combImage, 1);
}
When you call [self.drawView.image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)]; you need to modify the frame to account for the difference in aspect ratio that you described (because you are chopping some of the image off on both sides).
That means modifying the x position and the width that you are drawing the annotation image.
The modification is based on the difference between the 2 rects when scaled to the same height. You say this is 304, so you can initially set x to 304 and the width to newSize.width - 608 to test. But really the difference should be calculated...
Mackworth's answer in Swift 3.x
let fullSize:CGSize = img.size
let newSize:CGSize = fullSize
let scale:CGFloat = newSize.height/fullSize.height
let offset:CGFloat = (newSize.width - fullSize.width*scale)/2
let offsetRect:CGRect = CGRect.init(x: offset, y: 0, width: newSize.width - offset*2, height: newSize.height)
print(NSStringFromCGRect(offsetRect))
UIGraphicsBeginImageContext(newSize);
self.pictureView.image.draw(in: offsetRect)
self.annotateView.image.draw(in: CGRect.init(x: 0, y: 0, width: waterMarkImage.size.width, height: waterMarkImage.size.height))
let combImage:UIImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext();
return combImage;
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