Resize UIImage without squashing - ios

I would like to resize a UIImage to be able to upload it to parse.com. I would like to resize it without squashing it. How can I make sure that it is small enough to upload to parse.com (10485760 bytes) but not squash it to a set size.
This is the code I tried below but obviously sets the image size exactly.
Any ideas?
var newSize:CGSize = CGSize(width: 600,height: 600)
let rect = CGRectMake(0,0, newSize.width, newSize.height)
UIGraphicsBeginImageContextWithOptions(newSize, false, 0.0)
// image is a variable of type UIImage
profileImage?.drawInRect(rect)
profileImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()

Try using this method to scale your image while maintaining the aspect ratio:
func scaleImage(image: UIImage, maxDimension: CGFloat) -> UIImage {
var scaledSize = CGSize(width: maxDimension, height: maxDimension)
var scaleFactor: CGFloat
if image.size.width > image.size.height {
scaleFactor = image.size.height / image.size.width
scaledSize.width = maxDimension
scaledSize.height = scaledSize.width * scaleFactor
} else {
scaleFactor = image.size.width / image.size.height
scaledSize.height = maxDimension
scaledSize.width = scaledSize.height * scaleFactor
}
UIGraphicsBeginImageContext(scaledSize)
image.drawInRect(CGRectMake(0, 0, scaledSize.width, scaledSize.height))
let scaledImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return scaledImage
}
In this case, you would call it like so:
profileImage = scaleImage(profileImage, newSize: CGSizeMake(600, 600))

Related

White line appears on image when image is converted to data using jpegData?

When I convert UIImage to data using jpegData compression it will add a thin line on top of the image, why is that so?
Also I'm using this func for resizing image.
After resizing Im converting to jpegData.
func resizeImage(image: UIImage, targetSize: CGSize , percentage:Double) -> UIImage {
let size = image.size
let widthRatio = targetSize.width / size.width
let heightRatio = targetSize.height / size.height
// Figure out what our orientation is, and use that to form the rectangle
var newSize: CGSize
if(widthRatio > heightRatio) {
newSize = CGSize(width: size.width * heightRatio, height: size.height * heightRatio)
} else {
newSize = CGSize(width: size.width * widthRatio, height: size.height * widthRatio)
}
// This is the rect that we've calculated out and this is what is actually used below
let rect = CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height)
// Actually do the resizing to the rect using the ImageContext stuff
UIGraphicsBeginImageContextWithOptions(newSize, false, percentage)
// UIGraphicsBeginImageContextWithOptions(newSize , false , )
image.draw(in: rect)
let newImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
return newImage
}
let image = resizeImage.jpegData(compressionQuality: 0.60)!

Resizing the image to Aspect Fit

I am trying to resize images using the following popular code and it is resizing the image but it is resizing the image as Scale to Fill, I would like to resize them as Aspect Fit. How do I do that?
func resizeImage(image: UIImage, newSize: CGSize) -> (UIImage) {
let newRect = CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height).integral
UIGraphicsBeginImageContextWithOptions(newSize, true, 0)
let context = UIGraphicsGetCurrentContext()
// Set the quality level to use when rescaling
context!.interpolationQuality = CGInterpolationQuality.default
let flipVertical = CGAffineTransform(a: 1, b: 0, c: 0, d: -1, tx: 0, ty: newSize.height )
context!.concatenate(flipVertical)
// Draw into the context; this scales the image
context?.draw(image.cgImage!, in: CGRect(x: 0.0,y: 0.0, width: newRect.width, height: newRect.height))
let newImageRef = context!.makeImage()! as CGImage
let newImage = UIImage(cgImage: newImageRef)
// Get the resized image from the context and a UIImage
UIGraphicsEndImageContext()
return newImage
}
I have already set the content mode of image to Aspect Fit but still it is not working.
This is how I called the above code in my collection view controller
cell.imageView.image = UIImage(named: dogImages[indexPath.row])?.resizeImage(image: UIImage(named: dogImages[indexPath.row])
I manually selected my image in storyboard and set its content mode to apsect fit
Did you tried setting the newSize in aspect ratio of original Image size. If you want width fix calculate the height as per width and if you want height fix then calculate width as per height
Calculate height when width is fix:
let fixedWidth: CGFloat = 200
let newHeight = fixedWidth * image.size.height / image.size.width
let convertedImage = resizeImage(image: image, newSize: CGSize(width: fixedWidth, height: newHeight))
Calculate width when height is fix:
let fixedheight: CGFloat = 200
let newWidth = fixedheight * image.size.width / image.size.height
let convertedImage = resizeImage(image: image, newSize: CGSize(width: newWidth, height: fixedheight))
You can use this resized image with aspect fit ratio.
also check the answer: https://stackoverflow.com/a/8858464/2677551, that may help
func scaleImageAspectFit(newSize: CGSize) -> UIImage? {
var scaledImageRect: CGRect = CGRect.zero
let aspectWidth: CGFloat = newSize.width / size.width
let aspectHeight: CGFloat = newSize.height / size.height
let aspectRatio: CGFloat = min(aspectWidth, aspectHeight)
scaledImageRect.size.width = size.width * aspectRatio
scaledImageRect.size.height = size.height * aspectRatio
scaledImageRect.origin.x = (newSize.width - scaledImageRect.size.width) / 2.0
scaledImageRect.origin.y = (newSize.height - scaledImageRect.size.height) / 2.0
UIGraphicsBeginImageContextWithOptions(newSize, false, 0)
if UIGraphicsGetCurrentContext() != nil {
draw(in: scaledImageRect)
let scaledImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return scaledImage
}
return nil
}
Usage :
let resizedImage = oldImage.scaleImageAspectFit(newSize: CGSize(width: nexSize.width, height: nexSize.height))

iOS Swift: How to properly scale down an image?

I'm using AlamofireImage to download and set my UIImage:
backdrop.af_setImageWithURL(downloadURL)
The image is substantially larger than what I will be displaying and so I have an issue with aliasing. How can I resize this image properly?
Results:
You can resize the image with any size once you have a valid UIImage:
func resizedImageWith(image: UIImage, targetSize: CGSize) -> UIImage {
let imageSize = image.size
let newWidth = targetSize.width / image.size.width
let newHeight = targetSize.height / image.size.height
var newSize: CGSize
if(newWidth > newHeight) {
newSize = CGSizeMake(imageSize.width * newHeight, imageSize.height * newHeight)
} else {
newSize = CGSizeMake(imageSize.width * newWidth, imageSize.height * newWidth)
}
let rect = CGRectMake(0, 0, newSize.width, newSize.height)
UIGraphicsBeginImageContextWithOptions(newSize, false, 0.0)
image.drawInRect(rect)
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage
}
For any other queries/modifications you have, refer this NShipster
Here is #Santosh's answer in ObjC:
- (UIImage*) scaleImage:(UIImage*)image toSize:(CGSize)newSize {
CGSize imageSize = image.size;
CGFloat newWidth = newSize.width / image.size.width;
CGFloat newHeight = newSize.height / image.size.height;
CGSize newImgSize;
if(newWidth > newHeight) {
newImgSize = CGSizeMake(imageSize.width * newHeight, imageSize.height * newHeight);
} else {
newImgSize = CGSizeMake(imageSize.width * newWidth, imageSize.height * newWidth);
}
CGRect rect = CGRectMake(0, 0, newImgSize.width, newImgSize.height);
UIGraphicsBeginImageContextWithOptions(newImgSize, false, 0.0);
[image drawInRect:rect];;
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}

iOS: Get displayed image size in pixels

In my app, I'm displaying an image of a rectangle from the assets library. The image is 100x100 pixels. I'm only using the 1x slot for this asset.
I want to display this image at 300x300 pixels. Doing this using points is quite simple but I can't figure out how to get UIImageView to set the size in pixels.
Alternatively, if I can't set the size in pixels to display, I'd like to get the size in pixels that the image is being displayed.
I have tried using .scale on the UIImageView and UIImage instances, but it's always 1. Even though I have set constraints to 150 and 300.
To get size in pixels of UIImageView:
let widthInPixels = imageView.frame.width * UIScreen.mainScreen().scale
let heightInPixels = imageView.frame.height * UIScreen.mainScreen().scale
To get size in pixels of UIImage:
let widthInPixels = image.size.width * image.scale
let heightInPixels = image.size.height * image.scale
Swift 5
Take a Look here
// This extension to save ImageView as UImage
extension UIView {
func asImage() -> UIImage {
let renderer = UIGraphicsImageRenderer(bounds: bounds)
return renderer.image { rendererContext in
layer.render(in: rendererContext.cgContext)
}
}
}
// this extension to resize image
extension UIImage {
func resizeImage(targetSize: CGSize) -> UIImage {
let size = self.size
let widthRatio = targetSize.width / size.width
let heightRatio = targetSize.height / size.height
let newSize = widthRatio > heightRatio ? CGSize(width: size.width * heightRatio, height: size.height * heightRatio) : CGSize(width: size.width * widthRatio, height: size.height * widthRatio)
let rect = CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height)
UIGraphicsBeginImageContextWithOptions(newSize, false, 1.0)
self.draw(in: rect)
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage!
}
}
// This extension will display image with 300X300 pixels
extension UIImage {
func Size300X300() -> UIImage? {
let imageView = UIImageView()
imageView.contentMode = .scaleAspectFit
imageView.frame = CGRect(x: 0, y: 0, width: 300, height: 300)
let image = imageView.asImage()
let newImage = image.resizeImage(targetSize: CGSize(width:300, height: 300))
return newImage
}
}
let image = YOURIMAGE.Size300X300()
imageView.image = image!

Resize an image with drawInRect while maintaining the aspect ratio like Scale Aspect Fill?

I would like to resize an image with drawInRect method, but I would also like to maintain the right aspect ratio, while filling completely the given frame (as .ScaleAspectFill does for UIViewContentMode).
Anyone has a ready answer for this?
Here is my code (pretty straightforward...):
func scaled100Image() -> UIImage {
let newSize = CGSize(width: 100, height: 100)
UIGraphicsBeginImageContext(newSize)
self.pictures[0].drawInRect(CGRect(x: 0, y: 0, width: 100, height: 100))
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage
}
OK, so no ready-made answer... I wrote a swift extension for UIImage, feel free to use it if you need it.
Here it is:
extension UIImage {
func drawInRectAspectFill(rect: CGRect) {
let targetSize = rect.size
if targetSize == .zero {
self.draw(in: rect)
}
let widthRatio = targetSize.width / self.size.width
let heightRatio = targetSize.height / self.size.height
let scalingFactor = max(widthRatio, heightRatio)
let newSize = CGSize(width: self.size.width * scalingFactor,
height: self.size.height * scalingFactor)
UIGraphicsBeginImageContext(targetSize)
let origin = CGPoint(x: (targetSize.width - newSize.width) / 2,
y: (targetSize.height - newSize.height) / 2)
self.draw(in: CGRect(origin: origin, size: newSize))
let scaledImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
scaledImage?.draw(in: rect)
}
}
So in the example above, you use it like that:
self.pictures[0].drawInRectAspectFill(CGRect(x: 0, y: 0, width: 100, height: 100))
The Objective-C version, if someone need it(Paste this code inside a UIIMage category):
- (void) drawInRectAspectFill:(CGRect) recto {
CGSize targetSize = recto.size;
if (targetSize.width <= CGSizeZero.width && targetSize.height <= CGSizeZero.height ) {
return [self drawInRect:recto];
}
float widthRatio = targetSize.width / self.size.width;
float heightRatio = targetSize.height / self.size.height;
float scalingFactor = fmax(widthRatio, heightRatio);
CGSize newSize = CGSizeMake(self.size.width * scalingFactor, self.size.height * scalingFactor);
UIGraphicsBeginImageContext(targetSize);
CGPoint origin = CGPointMake((targetSize.width-newSize.width)/2,(targetSize.height - newSize.height) / 2);
[self drawInRect:CGRectMake(origin.x, origin.y, newSize.width, newSize.height)];
UIImage* scaledImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[scaledImage drawInRect:recto];
}

Resources