裁剪(到:CGRect)没有正确裁剪
cropping(to: CGRect) doesn't crop correctly
我正在为我的应用制作扫描仪,但当我裁剪图像时,它总是裁剪错误。
图像上的裁剪矩形-
裁剪后的图像-
我的裁剪矩形的代码...
func croppedImage(rect: CGRect) -> UIImage {
print("rect: \(rect)")
UIGraphicsBeginImageContextWithOptions(rect.size, false, self.scale)
let context = UIGraphicsGetCurrentContext()! as CGContext
let drawRect : CGRect = CGRect(x: -rect.origin.x, y: -rect.origin.y, width: self.size.width, height: self.size.height)
context.clip(to: CGRect(x:0, y:0, width: rect.size.width, height: rect.size.height))
self.draw(in: drawRect)
let croppedImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
return croppedImage
}
我尝试了无数不同的代码片段来正确裁剪图像,它们都得到了相同的结果。
docVC.croppedImage = pdfImage.croppedImage(rect: croppingRect)
docVC 是我将图像传递到其中的视图控制器
pdfImage 是您在第一张图片中看到的整个图像
croppingRect 是应该没问题的矩形
我真的需要这方面的帮助,我花了最后 2 个小时试图裁剪一张图片。
您是否在图像视图中使用其中一种缩放内容模式?如果是这样,图像的尺寸与图像视图的尺寸不同,你有两个选择:
您可以在尝试裁剪之前调整图像大小以匹配图像视图的尺寸。然后一个标准的裁剪程序就会起作用。但这会导致分辨率下降或出现像素化。
更好的解决方案是在裁剪前将裁剪矩形转换为图像尺寸的坐标。
例如:
extension UIImageView {
func image(at rect: CGRect) -> UIImage? {
guard
let image = image,
let rect = convertToImageCoordinates(rect)
else {
return nil
}
return image.cropped(to: rect)
}
func convertToImageCoordinates(_ rect: CGRect) -> CGRect? {
guard let image = image else { return nil }
let imageSize = CGSize(width: image.size.width, height: image.size.height)
let imageCenter = CGPoint(x: imageSize.width / 2, y: imageSize.height / 2)
let imageViewRatio = bounds.width / bounds.height
let imageRatio = imageSize.width / imageSize.height
let scale: CGPoint
switch contentMode {
case .scaleToFill:
scale = CGPoint(x: imageSize.width / bounds.width, y: imageSize.height / bounds.height)
case .scaleAspectFit:
let value: CGFloat
if imageRatio < imageViewRatio {
value = imageSize.height / bounds.height
} else {
value = imageSize.width / bounds.width
}
scale = CGPoint(x: value, y: value)
case .scaleAspectFill:
let value: CGFloat
if imageRatio > imageViewRatio {
value = imageSize.height / bounds.height
} else {
value = imageSize.width / bounds.width
}
scale = CGPoint(x: value, y: value)
case .center:
scale = CGPoint(x: 1, y: 1)
// unhandled cases include
// case .redraw:
// case .top:
// case .bottom:
// case .left:
// case .right:
// case .topLeft:
// case .topRight:
// case .bottomLeft:
// case .bottomRight:
default:
fatalError("Unexpected contentMode")
}
var rect = rect
if rect.width < 0 {
rect.origin.x += rect.width
rect.size.width = -rect.width
}
if rect.height < 0 {
rect.origin.y += rect.height
rect.size.height = -rect.height
}
return CGRect(x: (rect.minX - bounds.midX) * scale.x + imageCenter.x,
y: (rect.minY - bounds.midY) * scale.y + imageCenter.y,
width: rect.width * scale.x,
height: rect.height * scale.y)
}
}
现在,我只处理四种可能的内容模式,如果您想处理更多,则必须自己实现。但希望这能说明模式,即在尝试裁剪之前将选择 CGRect
转换为图像内的坐标。
FWIW,这是我使用的裁剪方法,cropped(to:)
来自 ,使用更现代的 UIGraphicsImageRenderer
,如果可以的话使用 CoreGraphics 裁剪,等等。但是使用任何裁剪你想要的例程,但只要确保将坐标转换为适合图像的坐标即可。
我正在为我的应用制作扫描仪,但当我裁剪图像时,它总是裁剪错误。
图像上的裁剪矩形-
裁剪后的图像-
我的裁剪矩形的代码...
func croppedImage(rect: CGRect) -> UIImage {
print("rect: \(rect)")
UIGraphicsBeginImageContextWithOptions(rect.size, false, self.scale)
let context = UIGraphicsGetCurrentContext()! as CGContext
let drawRect : CGRect = CGRect(x: -rect.origin.x, y: -rect.origin.y, width: self.size.width, height: self.size.height)
context.clip(to: CGRect(x:0, y:0, width: rect.size.width, height: rect.size.height))
self.draw(in: drawRect)
let croppedImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
return croppedImage
}
我尝试了无数不同的代码片段来正确裁剪图像,它们都得到了相同的结果。
docVC.croppedImage = pdfImage.croppedImage(rect: croppingRect)
docVC 是我将图像传递到其中的视图控制器 pdfImage 是您在第一张图片中看到的整个图像 croppingRect 是应该没问题的矩形
我真的需要这方面的帮助,我花了最后 2 个小时试图裁剪一张图片。
您是否在图像视图中使用其中一种缩放内容模式?如果是这样,图像的尺寸与图像视图的尺寸不同,你有两个选择:
您可以在尝试裁剪之前调整图像大小以匹配图像视图的尺寸。然后一个标准的裁剪程序就会起作用。但这会导致分辨率下降或出现像素化。
更好的解决方案是在裁剪前将裁剪矩形转换为图像尺寸的坐标。
例如:
extension UIImageView {
func image(at rect: CGRect) -> UIImage? {
guard
let image = image,
let rect = convertToImageCoordinates(rect)
else {
return nil
}
return image.cropped(to: rect)
}
func convertToImageCoordinates(_ rect: CGRect) -> CGRect? {
guard let image = image else { return nil }
let imageSize = CGSize(width: image.size.width, height: image.size.height)
let imageCenter = CGPoint(x: imageSize.width / 2, y: imageSize.height / 2)
let imageViewRatio = bounds.width / bounds.height
let imageRatio = imageSize.width / imageSize.height
let scale: CGPoint
switch contentMode {
case .scaleToFill:
scale = CGPoint(x: imageSize.width / bounds.width, y: imageSize.height / bounds.height)
case .scaleAspectFit:
let value: CGFloat
if imageRatio < imageViewRatio {
value = imageSize.height / bounds.height
} else {
value = imageSize.width / bounds.width
}
scale = CGPoint(x: value, y: value)
case .scaleAspectFill:
let value: CGFloat
if imageRatio > imageViewRatio {
value = imageSize.height / bounds.height
} else {
value = imageSize.width / bounds.width
}
scale = CGPoint(x: value, y: value)
case .center:
scale = CGPoint(x: 1, y: 1)
// unhandled cases include
// case .redraw:
// case .top:
// case .bottom:
// case .left:
// case .right:
// case .topLeft:
// case .topRight:
// case .bottomLeft:
// case .bottomRight:
default:
fatalError("Unexpected contentMode")
}
var rect = rect
if rect.width < 0 {
rect.origin.x += rect.width
rect.size.width = -rect.width
}
if rect.height < 0 {
rect.origin.y += rect.height
rect.size.height = -rect.height
}
return CGRect(x: (rect.minX - bounds.midX) * scale.x + imageCenter.x,
y: (rect.minY - bounds.midY) * scale.y + imageCenter.y,
width: rect.width * scale.x,
height: rect.height * scale.y)
}
}
现在,我只处理四种可能的内容模式,如果您想处理更多,则必须自己实现。但希望这能说明模式,即在尝试裁剪之前将选择 CGRect
转换为图像内的坐标。
FWIW,这是我使用的裁剪方法,cropped(to:)
来自 UIGraphicsImageRenderer
,如果可以的话使用 CoreGraphics 裁剪,等等。但是使用任何裁剪你想要的例程,但只要确保将坐标转换为适合图像的坐标即可。