I am trying to create an iOS app using Swift to capture images and let the user save a selected portion of the image. In many cam based apps, I noticed that a rectangular frame is offered to let the users choose the desired portion. This involves either sliding the edges of the rectangle or moving the corners to fit the required area.
Could you please guide me on how to implement that moveable rectangle and how to save only that piece of the image?
Using Swift 3
Image cropping can be done using CGImages from CoreGraphics.
Get the CGImage version of a UIImage like this:
// cgImage is an attribute of UIImage
let cgImage = image.cgImage
CGImage objects have a method cropping(to: CGRect) that does the cropping:
let croppedCGImage: CGImage = cgImage.cropping(to: toRect)
Finally, convert back from CGImage to UIImage:
let uiImage = UIImage(cgImage: croppedCGImage)
Example function:
func cropImage(image: UIImage, toRect: CGRect) -> UIImage? {
// Cropping is available trhough CGGraphics
let cgImage :CGImage! = image.cgImage
let croppedCGImage: CGImage! = cgImage.cropping(to: toRect)
return UIImage(cgImage: croppedCGImage)
}
The CGRect attribute of cropping defines the 'crop rectangle' inside the image that will be cropped.
Found one more solution. This time it is in Swift. The solution looks elegant and the code relative to other such solutions is written in fewer number of lines.
Here it is..
https://github.com/DuncanMC/CropImg
Thanks to Duncan Champney for making his work available on github.
https://github.com/myang-git/iOS-Image-Crop-View does something like what you are looking for..
Hope this helps.
If you getting issue like rotating 90 after cropping image try this.
Store the original image scale and orientation property for later Use
let imgOrientation = image?.imageOrientation
let imgScale = image?.scale
Get the CGImage from UIImage:
let cgImage = image.cgImage
Pass the cropArea(CGRect) area you want to crop (incase you are using imageView.image you have find the scale and do maths to find cgRect) adding that code below if needed
let croppedCGImage = cgImage.cropping(to: cropArea)
let coreImage = CIImage(cgImage: croppedCGImage!)
Need context for rendering image (its a heavy process do check https://developer.apple.com/documentation/coreimage/cicontext if you are doing multiple times ) using this you can set the scale and orientation we created in first line so image don't rotate 90
let ciContext = CIContext(options: nil)
let filteredImageRef = ciContext.createCGImage(coreImage, from: coreImage.extent)
let finalImage = UIImage(cgImage:filteredImageRef!, scale:imgScale!, orientation:imgOrientation!)
imageView.image = finalImage