I have been trying for several days without succeeding, as said in the title, to crop any images as 16:9 rectangles.
In fact, I want to create thumbnails, doing the following: cropping, resizing and compressing. In reality, it looks like this: PhotosPicker
-> selectedImage
-> selectedImageData
-> duplicated image data to selectedThumbData
-> cropping
function -> resizing
function -> compressing
function.
Here's an example to illustrate my point about what's a 16:9 rectangle:
About the function to resize and compress, I have no problem. I use .preparingThumbnail(of:)
and it works fine:
func createThumbnail() {
guard let selectedPhotoData, let image = UIImage(data: selectedPhotoData) else { return }
let scale = image.size.height / image.size.width
let width = UIScreen.main.bounds.width
let height = UIScreen.main.bounds.width * scale
let sizes = CGSize(width: width * 3, height: height * 3)
let thumbnail = image.preparingThumbnail(of: sizes)
selectedThumbData = thumbnail?.jpegData(compressionQuality: 0.80)
}
But about the function to crop it's different, I haven't found any other way than to use .cropping(to:)
(except draw(at:)
but it's too much complex) and in addition I can't do better than a square:
func cropImage() {
guard let selectedPhotoData, let image = UIImage(data: selectedPhotoData) else { return }
let sourceImage = image.size
let minSide = min(sourceImage.width, sourceImage.height)
let xOffset = (sourceImage.width - minSide) / 2
let yOffset = (sourceImage.height - minSide) / 2
var square = CGRect()
if sourceImage.width < sourceImage.height {
square = CGRect(x: yOffset, y: xOffset, width: minSide, height: minSide) // .integral
} else {
square = CGRect(x: xOffset, y: yOffset, width: minSide, height: minSide) // .integral
}
guard let croppedCGImage = image.cgImage?.cropping(to: square) else { return }
let croppedImage = UIImage(cgImage: croppedCGImage, scale: image.imageRendererFormat.scale, orientation: image.imageOrientation)
selectedThumbData = croppedImage.jpegData(compressionQuality: 0.80)
}
I think the problem is that I can't correctly set xOffset
and yOffset
. It's really tricky! Do you have any idea what should I change or replace to make it work as I want?
Thanks a lot, in advance!