将裁剪后的 UIImage 保存到 CGPath
Saving a UIImage cropped to a CGPath
我正在尝试屏蔽 UIImage
然后保存屏蔽的图像。到目前为止,当在 UIImageView
预览中显示时,我已经可以正常工作了,如下所示:
let maskLayer = CAShapeLayer()
let maskPath = shape.cgPath
maskLayer.path = maskPath.resized(to: imageView.frame)
maskLayer.fillRule = .evenOdd
imageView.layer.mask = maskLayer
let picture = UIImage(named: "1")!
imageView.contentMode = .scaleAspectFit
imageView.image = picture
其中 shape
是 UIBezierPath()
.
resized
函数是:
extension CGPath {
func resized(to rect: CGRect) -> CGPath {
let boundingBox = self.boundingBox
let boundingBoxAspectRatio = boundingBox.width / boundingBox.height
let viewAspectRatio = rect.width / rect.height
let scaleFactor = boundingBoxAspectRatio > viewAspectRatio ?
rect.width / boundingBox.width :
rect.height / boundingBox.height
let scaledSize = boundingBox.size.applying(CGAffineTransform(scaleX: scaleFactor, y: scaleFactor))
let centerOffset = CGSize(
width: (rect.width - scaledSize.width) / (scaleFactor * 2),
height: (rect.height - scaledSize.height) / (scaleFactor * 2)
)
var transform = CGAffineTransform.identity
.scaledBy(x: scaleFactor, y: scaleFactor)
.translatedBy(x: -boundingBox.minX + centerOffset.width, y: -boundingBox.minY + centerOffset.height)
return copy(using: &transform)!
}
}
所以这在预览我想要的结果方面是有效的。我现在想将这个修改后的 UIImage
以原始大小保存到用户的相册中(因此基本上再次生成它但不要调整图像大小以适合 UIImageView
- 保持原样 -是并在上面涂上面具)。
我试过了,但它只保存了原始图像 - 没有应用 path/mask:
func getMaskedImage(path: CGPath) {
let picture = UIImage(named: "1")!
UIGraphicsBeginImageContext(picture.size)
if let context = UIGraphicsGetCurrentContext() {
let pathNew = path.resized(to: CGRect(x: 0, y: 0, width: picture.size.width, height: picture.size.height))
context.addPath(pathNew)
context.clip()
picture.draw(in: CGRect(x: 0.0, y: 0.0, width: picture.size.width, height: picture.size.height))
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
UIImageWriteToSavedPhotosAlbum(newImage!, nil, nil, nil)
}
}
我做错了什么?谢谢。
不要放弃基于图层的方法!在图形上下文中绘图时,您仍然可以使用它。
示例:
func getMaskedImage(path: CGPath) -> UIImage? {
let picture = UIImage(named: "my_image")!
let imageLayer = CALayer()
imageLayer.frame = CGRect(origin: .zero, size: picture.size)
imageLayer.contents = picture.cgImage
let maskLayer = CAShapeLayer()
let maskPath = path.resized(to: CGRect(origin: .zero, size: picture.size))
maskLayer.path = maskPath
maskLayer.fillRule = .evenOdd
imageLayer.mask = maskLayer
UIGraphicsBeginImageContext(picture.size)
defer { UIGraphicsEndImageContext() }
if let context = UIGraphicsGetCurrentContext() {
imageLayer.render(in: context)
let newImage = UIGraphicsGetImageFromCurrentImageContext()
return newImage
}
return nil
}
请注意,这实际上并没有调整图像的大小。如果你想调整图像的大小,你应该得到调整后的路径的 boundingBox
。然后改为这样做:
// create a context as big as the bounding box
UIGraphicsBeginImageContext(boundingBox.size)
defer { UIGraphicsEndImageContext() }
if let context = UIGraphicsGetCurrentContext() {
// move the context to the top left of the path
context.translateBy(x: -boundingBox.origin.x, y: -boundingBox.origin.y)
imageLayer.render(in: context)
let newImage = UIGraphicsGetImageFromCurrentImageContext()
return newImage
}
我正在尝试屏蔽 UIImage
然后保存屏蔽的图像。到目前为止,当在 UIImageView
预览中显示时,我已经可以正常工作了,如下所示:
let maskLayer = CAShapeLayer()
let maskPath = shape.cgPath
maskLayer.path = maskPath.resized(to: imageView.frame)
maskLayer.fillRule = .evenOdd
imageView.layer.mask = maskLayer
let picture = UIImage(named: "1")!
imageView.contentMode = .scaleAspectFit
imageView.image = picture
其中 shape
是 UIBezierPath()
.
resized
函数是:
extension CGPath {
func resized(to rect: CGRect) -> CGPath {
let boundingBox = self.boundingBox
let boundingBoxAspectRatio = boundingBox.width / boundingBox.height
let viewAspectRatio = rect.width / rect.height
let scaleFactor = boundingBoxAspectRatio > viewAspectRatio ?
rect.width / boundingBox.width :
rect.height / boundingBox.height
let scaledSize = boundingBox.size.applying(CGAffineTransform(scaleX: scaleFactor, y: scaleFactor))
let centerOffset = CGSize(
width: (rect.width - scaledSize.width) / (scaleFactor * 2),
height: (rect.height - scaledSize.height) / (scaleFactor * 2)
)
var transform = CGAffineTransform.identity
.scaledBy(x: scaleFactor, y: scaleFactor)
.translatedBy(x: -boundingBox.minX + centerOffset.width, y: -boundingBox.minY + centerOffset.height)
return copy(using: &transform)!
}
}
所以这在预览我想要的结果方面是有效的。我现在想将这个修改后的 UIImage
以原始大小保存到用户的相册中(因此基本上再次生成它但不要调整图像大小以适合 UIImageView
- 保持原样 -是并在上面涂上面具)。
我试过了,但它只保存了原始图像 - 没有应用 path/mask:
func getMaskedImage(path: CGPath) {
let picture = UIImage(named: "1")!
UIGraphicsBeginImageContext(picture.size)
if let context = UIGraphicsGetCurrentContext() {
let pathNew = path.resized(to: CGRect(x: 0, y: 0, width: picture.size.width, height: picture.size.height))
context.addPath(pathNew)
context.clip()
picture.draw(in: CGRect(x: 0.0, y: 0.0, width: picture.size.width, height: picture.size.height))
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
UIImageWriteToSavedPhotosAlbum(newImage!, nil, nil, nil)
}
}
我做错了什么?谢谢。
不要放弃基于图层的方法!在图形上下文中绘图时,您仍然可以使用它。
示例:
func getMaskedImage(path: CGPath) -> UIImage? {
let picture = UIImage(named: "my_image")!
let imageLayer = CALayer()
imageLayer.frame = CGRect(origin: .zero, size: picture.size)
imageLayer.contents = picture.cgImage
let maskLayer = CAShapeLayer()
let maskPath = path.resized(to: CGRect(origin: .zero, size: picture.size))
maskLayer.path = maskPath
maskLayer.fillRule = .evenOdd
imageLayer.mask = maskLayer
UIGraphicsBeginImageContext(picture.size)
defer { UIGraphicsEndImageContext() }
if let context = UIGraphicsGetCurrentContext() {
imageLayer.render(in: context)
let newImage = UIGraphicsGetImageFromCurrentImageContext()
return newImage
}
return nil
}
请注意,这实际上并没有调整图像的大小。如果你想调整图像的大小,你应该得到调整后的路径的 boundingBox
。然后改为这样做:
// create a context as big as the bounding box
UIGraphicsBeginImageContext(boundingBox.size)
defer { UIGraphicsEndImageContext() }
if let context = UIGraphicsGetCurrentContext() {
// move the context to the top left of the path
context.translateBy(x: -boundingBox.origin.x, y: -boundingBox.origin.y)
imageLayer.render(in: context)
let newImage = UIGraphicsGetImageFromCurrentImageContext()
return newImage
}