In Swift programming , how do you crop an image and put it on the center afterwards?
This is what I\'ve got so far ... I\'ve successfully crop the image but I want t
You can also, very simply, put the concerned ImageView in "Aspect Fill" mode from the Storyboard, and add this in the code :
imageView.layer.masksToBounds = true
imageView.clipsToBounds = true
I came up with a code that will give a desired cropped aspect ratio, regardless of original video frame size (adapted from @Cole's answer):
func cropImage(uncroppedImage: UIImage, cropWidth: CGFloat, cropHeight: CGFloat) -> UIImage {
let contextImage: UIImage = UIImage(cgImage: uncroppedImage.cgImage!)
let contextSize: CGSize = contextImage.size
var cropX: CGFloat = 0.0
var cropY: CGFloat = 0.0
var cropRatio: CGFloat = CGFloat(cropWidth/cropHeight)
var originalRatio: CGFloat = contextSize.width/contextSize.height
var scaledCropHeight: CGFloat = 0.0
var scaledCropWidth: CGFloat = 0.0
// See what size is longer and set crop rect parameters
if originalRatio > cropRatio {
scaledCropHeight = contextSize.height
scaledCropWidth = (contextSize.height/cropHeight) * cropWidth
cropX = (contextSize.width - scaledCropWidth) / 2
cropY = 0
} else {
scaledCropWidth = contextSize.width
scaledCropHeight = (contextSize.width/cropWidth) * cropHeight
cropY = (contextSize.height / scaledCropHeight) / 2
cropX = 0
}
let rect: CGRect = CGRect(x: cropX, y: cropY, width: scaledCropWidth, height: scaledCropHeight)
// Create bitmap image from context using the rect
let imageRef: CGImage = contextImage.cgImage!.cropping(to: rect)!
// Create a new image based on the imageRef and rotate back to the original orientation
let croppedImage: UIImage = UIImage(cgImage: imageRef, scale: uncroppedImage.scale, orientation: uncroppedImage.imageOrientation)
return croppedImage
}
Hope it helps!
In swift 4.1 I would do simply:
imageView.clipsToBounds = true
imageView.contentMode = .scaleAspectFill
imageView.layer.cornerRadius = 20
Credits to Stretching, Redrawing and Positioning with contentMode
you can also use Alamofire and AlamofireImage to crop your image.
https://github.com/Alamofire/AlamofireImage
Installing using CocoaPods
pod 'AlamofireImage'
Usage:
let image = UIImage(named: "unicorn")!
let size = CGSize(width: 100.0, height: 100.0)
// Scale image to size disregarding aspect ratio
let scaledImage = image.af_imageScaled(to: size)
let aspectScaledToFitImage = image.af_imageAspectScaled(toFit: size)
// Scale image to fill specified size while maintaining aspect ratio
let aspectScaledToFillImage = image.af_imageAspectScaled(toFill: size)
Accepted answer did not work for me, so I tried wrote my own. Here is an effect of my work:
import UIKit
extension UIImage {
func cropedToRatio(ratio: CGFloat) -> UIImage? {
let newImageWidth = size.height * ratio
let cropRect = CGRect(x: ((size.width - newImageWidth) / 2.0) * scale,
y: 0.0,
width: newImageWidth * scale,
height: size.height * scale)
guard let cgImage = cgImage else {
return nil
}
guard let newCgImage = cgImage.cropping(to: cropRect) else {
return nil
}
return UIImage(cgImage: newCgImage, scale: scale, orientation: imageOrientation)
}
}
This function crop image to given ratio. It keeps image scale. Cropped image is always center of original image.
To get a centered position for your crop, you can halve the difference of the height and width. Then you can assign the bounds for the new width and height after checking the orientation of the image (which part is longer)
func cropToBounds(image: UIImage, width: Double, height: Double) -> UIImage {
let contextImage: UIImage = UIImage(CGImage: image.CGImage)!
let contextSize: CGSize = contextImage.size
var posX: CGFloat = 0.0
var posY: CGFloat = 0.0
var cgwidth: CGFloat = CGFloat(width)
var cgheight: CGFloat = CGFloat(height)
// See what size is longer and create the center off of that
if contextSize.width > contextSize.height {
posX = ((contextSize.width - contextSize.height) / 2)
posY = 0
cgwidth = contextSize.height
cgheight = contextSize.height
} else {
posX = 0
posY = ((contextSize.height - contextSize.width) / 2)
cgwidth = contextSize.width
cgheight = contextSize.width
}
let rect: CGRect = CGRectMake(posX, posY, cgwidth, cgheight)
// Create bitmap image from context using the rect
let imageRef: CGImageRef = CGImageCreateWithImageInRect(contextImage.CGImage, rect)
// Create a new image based on the imageRef and rotate back to the original orientation
let image: UIImage = UIImage(CGImage: imageRef, scale: image.scale, orientation: image.imageOrientation)!
return image
}
I found most of this info over at this website in case you wanted to read further.
Updated for Swift 4
func cropToBounds(image: UIImage, width: Double, height: Double) -> UIImage {
let cgimage = image.cgImage!
let contextImage: UIImage = UIImage(cgImage: cgimage)
let contextSize: CGSize = contextImage.size
var posX: CGFloat = 0.0
var posY: CGFloat = 0.0
var cgwidth: CGFloat = CGFloat(width)
var cgheight: CGFloat = CGFloat(height)
// See what size is longer and create the center off of that
if contextSize.width > contextSize.height {
posX = ((contextSize.width - contextSize.height) / 2)
posY = 0
cgwidth = contextSize.height
cgheight = contextSize.height
} else {
posX = 0
posY = ((contextSize.height - contextSize.width) / 2)
cgwidth = contextSize.width
cgheight = contextSize.width
}
let rect: CGRect = CGRect(x: posX, y: posY, width: cgwidth, height: cgheight)
// Create bitmap image from context using the rect
let imageRef: CGImage = cgimage.cropping(to: rect)!
// Create a new image based on the imageRef and rotate back to the original orientation
let image: UIImage = UIImage(cgImage: imageRef, scale: image.scale, orientation: image.imageOrientation)
return image
}