从UIView蒙版剪切UIImage

时间:2019-07-04 08:49:58

标签: ios swift mask core-image

我有一个UIView,在特定点上具有一定半径的透明maskLayer。除此之外,我还有一个UIImageViewUIPanGesture的{​​{1}}。

现在,我可以拖动或缩放UIPinchGesture,使其适合UIImageView遮罩的一部分。完成后,我需要从UIView那里获得UIImage的透明部分。

我不知道该怎么实现。

masked image

以下是在UIImageView上使用指定的遮罩UIView和半径创建覆盖的代码。

CGRect

如有需要,我在这里存储func createOverlay(frame: CGRect, xOffset: CGFloat, yOffset: CGFloat, radius: CGFloat) -> UIView { // Step 1 let overlayView = UIView(frame: frame) overlayView.backgroundColor = UIColor.groupTableViewBackground.withAlphaComponent(0.8) // Step 2 let path = CGMutablePath() beizerPath = UIBezierPath(arcCenter: CGPoint(x: xOffset, y: yOffset + radius), radius: radius, startAngle: 0.0, endAngle: 2.0 * .pi, clockwise: false) path.addArc(center: CGPoint(x: xOffset, y: yOffset), radius: radius, startAngle: 0.0, endAngle: 2.0 * .pi, clockwise: false) path.addRect(CGRect(origin: .zero, size: overlayView.frame.size)) // Step 3 let maskLayer = CAShapeLayer() maskLayer.backgroundColor = UIColor.black.cgColor maskLayer.path = path maskLayer.fillRule = .evenOdd // Step 4 overlayView.layer.mask = maskLayer overlayView.clipsToBounds = true return overlayView }

然后,我尝试将UIBezierPath剪切到UIBezierPath上,但这是rect的问题。因为UIImage可以被拖动和缩放,所以它可以UIImageView进行更改。下面是我用来创建剪辑的代码。

CGRect

其他解决方案,我考虑拍摄完整视图的快照,然后从中删除extension UIImage { func imageByApplyingClippingBezierPath(_ path: UIBezierPath) -> UIImage { // Mask image using path let maskedImage = imageByApplyingMaskingBezierPath(path) // Crop image to frame of path let croppedImage = UIImage(cgImage: maskedImage.cgImage!.cropping(to: path.bounds)!) return croppedImage } func imageByApplyingMaskingBezierPath(_ path: UIBezierPath) -> UIImage { // Define graphic context (canvas) to paint on UIGraphicsBeginImageContext(size) let context = UIGraphicsGetCurrentContext()! context.saveGState() // Set the clipping mask path.addClip() draw(in: CGRect(x: 0, y: 0, width: size.width, height: size.height)) let maskedImage = UIGraphicsGetImageFromCurrentImageContext()! // Restore previous drawing context context.restoreGState() UIGraphicsEndImageContext() return maskedImage } } 。但是我不认为这是这样做的正确方法!

1 个答案:

答案 0 :(得分:1)

如果可能的话,最简单的方法是创建圆形视图并创建该视图的快照。检查以下解决方案:

func cutImageCircle(_ image: UIImage?, inFrame imageFrame: CGRect, contentMode: UIView.ContentMode = .scaleAspectFill, circle: (center: CGPoint, radius: CGFloat)) -> UIImage? {
    guard let image = image else { return nil }

    func generateSnapshotImage(ofView view: UIView, scale: CGFloat = 0.0) -> UIImage? {
        UIGraphicsBeginImageContextWithOptions(view.bounds.size, false, scale)

        defer { UIGraphicsEndImageContext() }

        view.drawHierarchy(in: view.bounds, afterScreenUpdates: true)
        return UIGraphicsGetImageFromCurrentImageContext()
    }

    let imageViewPanel = UIView(frame: CGRect(x: 0.0, y: 0.0, width: circle.radius*2.0, height: circle.radius*2.0))
    imageViewPanel.clipsToBounds = true
    imageViewPanel.layer.cornerRadius = circle.radius

    let imageView = UIImageView(frame: {
        var frame = imageFrame
        frame.origin.x -= circle.center.x-circle.radius
        frame.origin.y -= circle.center.y-circle.radius
        return frame
    }())
    imageView.contentMode = contentMode
    imageView.image = image

    imageViewPanel.addSubview(imageView)

    let cutImage = generateSnapshotImage(ofView: imageViewPanel, scale: 1.0)
    return cutImage
}

您只需要计算圆心在哪里以及它的大小。我在其中添加了调整帧的选项,因此您可以控制输出图像的大小。这样,您可以提高所拍摄图像的质量。