Feeling weird while picking an image and cropping in Swift?
Keep reading, and you will find a nice solution to the question above. And if you know a better way, please write your thoughts in comments.
Initial steps —
Step 1: Create your Xcode project.
Step 2: Design storyboard and create outlets and properties in ViewController class.
let picker = UIImagePickerController()
var circlePath = UIBezierPath()
@IBOutlet weak var crop: CropView!
@IBOutlet weak var imageView: UIImageView!
@IBOutlet weak var scroll: UIScrollView!
The property crop has a custom UIView class. Add the below delegate function in it.
func point(inside point: CGPoint, with event: UIEvent?) -> Bool{
return false
}
Step 3: Create an extension for UIImage and UIImageView — refer. For zooming image, use delegate function viewForZooming, then add UIScrollViewDelegate to class as the subtype and return imageView.
Pick an image from the gallery —
Step 4: Create IBAction, to pick an image from Album and set the picker source type as photo library use the code below:
picker.sourceType = .photoLibrary
present(picker, animated: true, completion: nil)
and add UIImagePickerControllerDelegate to class as sub type. In viewDidLoad:
picker.delegate = self
Use didFinishPickingMediaWithInfo —UIImagePickerControllerDelegate function to set the image to the view after picking image from the album.
let chosenImage = info[UIImagePickerControllerOriginalImage] as! UIImage
imageView.image = chosenImage.resizeImage()
dismiss(animated:true, completion: nil)
To dismiss the photo album when you did cancel, use imagePickerControllerDidCancel delegate.
Shoot a picture from the camera —
Create IBAction to shoot an image from the camera. First, check whether SourceTypeAvailable in the device. If it is set picker camera capture mode as a photo. Else handle the action. Then set source type as camera and camera capture mode as the photo.
if UIImagePickerController.isSourceTypeAvailable(.camera){
picker.sourceType = UIImagePickerControllerSourceType.camera
picker.cameraCaptureMode = UIImagePickerControllerCameraCaptureMode.photo
picker.modalPresentationStyle = .custom
present(picker,animated: true,completion: nil)
}else{
//action performed if there is no camera in device.
}
That’s it!
Now you can pick an image from the album, as well as from the camera to display in your app for further action.
Cropping —
Add sublayer:
Add subLayer to the picked image — this layer provides an area to fix crop frame.
let path = UIBezierPath(roundedRect: CGRect(x: 0, y: 0, width: self.view.bounds.size.width, height: self.view.bounds.size.height), cornerRadius: 0)
Assign the path to the circle path property as of type UIBezierPath. Using BezierPath, you can change the crop frame into different shapes.
circlePath = UIBezierPath(roundedRect: CGRect(x: (self.view.frame.size.width / 2) - (size/2), y: (self.view.frame.size.height / 2) - (size / 2), width: size, height: size, cornerRadius: 0)
path.append(circlePath)
The CAShapeLayer that draws a cubic Bezier spline in its coordinate space.
let fillLayer = CAShapeLayer()
fillLayer.path = path.cgPath
Finally, add the layer to view:
view.layer.addSublayer(fillLayer)
Add crop area:
Create a crop area. For that we need to set factor, dividing the imageView image width by view frame width set scale:
let factor = imageView.image!.size.width/view.frame.width
for zooming as scroll zoomScale:
let scale = 1/scroll.zoomScale
Then set crop area frame(x, y, width, height).
let x = (scroll.contentOffset.x + circlePath.bounds.origin.x - imageFrame.origin.x) * scale * factor
let y = (scroll.contentOffset.y + circlePath.bounds.origin.y - imageFrame.origin.y) * scale * factor
let width = circlePath.bounds.width * scale * factor
let height = circlePath.bounds.height * scale * factor
Finally, create a IBAction to crop the image.
let croppedCGImage = imageView.image?.cgImage?.cropping(to: croparea)
let croppedImage = UIImage(cgImage: croppedCGImage!)
Screenshot:
That’s all!!!
Check out the sample project on my Github repo:
“We tend to steer our lives in the direction of the lessons we need to learn.”
- Don Campbell