У меня проблемы с обрезкой снимков, сделанных с точным размером в широкоформатном формате. Например, я делаю снимок с фронтальной камерой iPad, которая имеет разрешение 960 Вт, 1280 ч, и мне нужно кадрировать, чтобы получить ровно 875 Вт, 570 ч. Я попробовал некоторые методы в здесь , но все они растягивают изображение или не получают желаемый размер.
Вот первый метод, который я попробовал:
func cropToBounds(image: UIImage, width: Double, height: Double) -> UIImage {
let cgimage = image.cgImage!
let contextImage: UIImage = UIImage(cgImage: cgimage)
guard let newCgImage = contextImage.cgImage else { return contextImage }
let contextSize: CGSize = contextImage.size
var posX: CGFloat = 0.0
var posY: CGFloat = 0.0
let cropAspect: CGFloat = CGFloat(width / height)
var cropWidth: CGFloat = CGFloat(width)
var cropHeight: CGFloat = CGFloat(height)
if width > height { //Landscape
cropWidth = contextSize.width
cropHeight = contextSize.width / cropAspect
posY = (contextSize.height - cropHeight) / 2
} else if width < height { //Portrait
cropHeight = contextSize.height
cropWidth = contextSize.height * cropAspect
posX = (contextSize.width - cropWidth) / 2
} else { //Square
if contextSize.width >= contextSize.height { //Square on landscape (or square)
cropHeight = contextSize.height
cropWidth = contextSize.height * cropAspect
posX = (contextSize.width - cropWidth) / 2
}else{ //Square on portrait
cropWidth = contextSize.width
cropHeight = contextSize.width / cropAspect
posY = (contextSize.height - cropHeight) / 2
}
}
let rect: CGRect = CGRect(x: posX, y: posY, width: cropWidth, height: cropHeight)
// Create bitmap image from context using the rect
guard let imageRef: CGImage = newCgImage.cropping(to: rect) else { return contextImage}
// Create a new image based on the imageRef and rotate back to the original orientation
let cropped: UIImage = UIImage(cgImage: imageRef, scale: image.scale, orientation: image.imageOrientation)
print(image.scale)
UIGraphicsBeginImageContextWithOptions(CGSize(width: width, height: height), false, 0.0)
cropped.draw(in: CGRect(x: 0, y: 0, width: width, height: height))
let resized = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return resized ?? image
}
Это всегда растягивает изображение.
Я думал о попытке обрезать нужный размер, поэтому я попробовал это:
func cropImage(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 recWidth : CGFloat = CGFloat(width)
var recHeight : CGFloat = CGFloat(height)
if width > height { //Landscape
posY = (contextSize.height - recHeight) / 2
}
else { //Square
posX = (contextSize.width - recWidth) / 2
}
let rect: CGRect = CGRect(x: posX, y: posY, width: recWidth, height: recHeight)
let imageRef:CGImage = cgimage.cropping(to: rect)!
print(imageRef.width)
print(imageRef.height)
let croppedimage:UIImage = UIImage(cgImage: imageRef, scale: image.scale, orientation: image.imageOrientation)
print(croppedimage.size)
return croppedimage
}
Но это привело к изображению с противоположность того, что я хочу, 570 Вт, 875 ч. Поэтому я подумал об инверсии значений, но если я это сделаю, то получу 605 Вт, 570 ч. Может быть, проблема в том, как я получаю координаты X и Y изображения?
РЕДАКТИРОВАТЬ
Вот что я делаю сейчас после помощи Лео Дабуса:
extension UIImage {
func cropped(to size: CGSize) -> UIImage? {
guard let cgImage = cgImage?
.cropping(to: .init(origin: .init(x: (self.size.width-size.width)/2,
y: (self.size.height-size.height)/2),
size: size)) else { return nil }
let format = imageRendererFormat
return UIGraphicsImageRenderer(size: size, format: format).image {
_ in
UIImage(cgImage: cgImage, scale: 1, orientation: imageOrientation)
.draw(in: .init(origin: .zero, size: size))
}
}
}
Вот как я это называю:
let foto = UIImage(data: imageData)!
let size = CGSize(width: 875.0, height: 570.0)
let cropedPhoto = foto.cropped(to: size)
imageData поступает из захвата фронтальной камеры.
И это мой код захвата:
@objc func takePhoto(_ sender: Any?) {
let videoOrientation = AVCaptureVideoOrientation.portrait
stillImageOutput!.connection(with: .video)?.videoOrientation = videoOrientation
let settings = AVCapturePhotoSettings(format: [AVVideoCodecKey: AVVideoCodecType.jpeg])
let gesture = previewView.gestureRecognizers
previewView.removeGestureRecognizer(gesture![0])
}
func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {
guard let imageData = photo.fileDataRepresentation()
else { return }
}