1

我正在尝试截取我的 UIView 并裁剪它,将其保存到我的照片库中。当我试图这样做时,有3个冲突。

(1) - 我想拍摄带有模糊的屏幕截图,因为模糊滤镜永远不会保存在屏幕截图中。

(2) - 图像质量非常低。

(3) - 我无法裁剪图像。

这是我的代码 -

@IBAction func Screenshot(_ sender: UIButton) {

    // Declare the snapshot boundaries
    let top: CGFloat = 70
    let bottom: CGFloat = 400

    // The size of the cropped image
    let size = CGSize(width: view.frame.size.width, height: view.frame.size.height - top - bottom)

    // Start the context
    UIGraphicsBeginImageContext(size)

    // we are going to use context in a couple of places
    let context = UIGraphicsGetCurrentContext()!

    // Transform the context so that anything drawn into it is displaced "top" pixels up
    // Something drawn at coordinate (0, 0) will now be drawn at (0, -top)
    // This will result in the "top" pixels being cut off
    // The bottom pixels are cut off because the size of the of the context
    context.translateBy(x: 0, y: -top)

    // Draw the view into the context (this is the snapshot)
    view.drawHierarchy(in: view.bounds, afterScreenUpdates: true)
    let snapshot = UIGraphicsGetImageFromCurrentImageContext()

    // End the context (this is required to not leak resources)
    UIGraphicsEndImageContext()

    // Save to photos
    UIImageWriteToSavedPhotosAlbum(snapshot!, nil, nil, nil)

}
4

2 回答 2

0

我无法以正确的方式裁剪图像,因为导航栏和状态栏显示为空白(白色)背景。(图像的其余部分裁剪良好)。

这是代码 -

让顶部:CGFloat = 70 让底部:CGFloat = 280

    // The size of the cropped image
    let size = CGSize(width: view.frame.size.width, height: view.frame.size.height - top - bottom)

    // Start the context
    UIGraphicsBeginImageContext(size)

    // we are going to use context in a couple of places
    let context = UIGraphicsGetCurrentContext()!

    // Transform the context so that anything drawn into it is displaced "top" pixels up
    // Something drawn at coordinate (0, 0) will now be drawn at (0, -top)
    // This will result in the "top" pixels being cut off
    // The bottom pixels are cut off because the size of the of the context
    context.translateBy(x: 0, y: 0)

    // Draw the view into the context (this is the snapshot)
    UIGraphicsBeginImageContextWithOptions(size,view.isOpaque, 0)
    self.view.drawHierarchy(in: view.bounds, afterScreenUpdates: true)
    let snapshot = UIGraphicsGetImageFromCurrentImageContext()
于 2016-10-08T04:42:47.570 回答
0

你说:

  1. 我想拍摄带有模糊的屏幕截图,因为模糊滤镜永远不会保存在屏幕截图中。

我想知道被快照的视图是否可能不是UIVisualEffectView作为子视图的视图。因为当我在答案末尾使用代码时,fractionCompleted会捕获模糊效果(以及更改 的影响)。

  1. 图像质量非常低。

如果您使用UIGraphicsBeginImageContextWithOptions零比例,它应该以设备的分辨率捕获图像:

UIGraphicsBeginImageContextWithOptions(size, isOpaque, 0)
  1. 我无法裁剪图像。

我个人捕捉整个视图,然后根据需要进行裁剪。请参阅UIView下面的扩展。

在斯威夫特 3 中:

class ViewController: UIViewController {

        var animator: UIViewPropertyAnimator?
        @IBOutlet weak var imageView: UIImageView!

        override func viewDidAppear(_ animated: Bool) {
            super.viewDidAppear(animated)

            let blur = UIBlurEffect(style: .light)
            let effectView = UIVisualEffectView(effect: blur)
            view.addSubview(effectView)
            effectView.translatesAutoresizingMaskIntoConstraints = false
            NSLayoutConstraint.activate([
                effectView.leadingAnchor.constraint(equalTo: imageView.leadingAnchor),
                effectView.trailingAnchor.constraint(equalTo: imageView.trailingAnchor),
                effectView.topAnchor.constraint(equalTo: imageView.topAnchor),
                effectView.bottomAnchor.constraint(equalTo: imageView.bottomAnchor)
            ])

            animator = UIViewPropertyAnimator(duration: 0, curve: .linear) { effectView.effect = nil }
        }

        @IBAction func didChangeValueForSlider(_ sender: UISlider) {
            animator?.fractionComplete = CGFloat(sender.value)
        }

        @IBAction func didTapSnapshotButton(_ sender: AnyObject) {
            if let snapshot = view.snapshot(of: imageView.frame) {
                UIImageWriteToSavedPhotosAlbum(snapshot, nil, nil, nil)
            }
        }

    }

    extension UIView {

        /// Create snapshot
        ///
        /// - parameter rect: The `CGRect` of the portion of the view to return. If `nil` (or omitted),
        ///                 return snapshot of the whole view.
        ///
        /// - returns: Returns `UIImage` of the specified portion of the view.

        func snapshot(of rect: CGRect? = nil) -> UIImage? {
            // snapshot entire view

            UIGraphicsBeginImageContextWithOptions(bounds.size, isOpaque, 0)
            drawHierarchy(in: bounds, afterScreenUpdates: true)
            let wholeImage = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()

            // if no `rect` provided, return image of whole view

            guard let image = wholeImage, let rect = rect else { return wholeImage }

            // otherwise, grab specified `rect` of image

            let scale = image.scale
            let scaledRect = CGRect(x: rect.origin.x * scale, y: rect.origin.y * scale, width: rect.size.width * scale, height: rect.size.height * scale)
            guard let cgImage = image.cgImage?.cropping(to: scaledRect) else { return nil }
            return UIImage(cgImage: cgImage, scale: scale, orientation: .up)
        }

    }
}

或者在 Swift 2 中:

class ViewController: UIViewController {

    var animator: UIViewPropertyAnimator?
    @IBOutlet weak var imageView: UIImageView!

    override func viewDidAppear(animated: Bool) {
        super.viewDidAppear(animated)

        let blur = UIBlurEffect(style: .Light)
        let effectView = UIVisualEffectView(effect: blur)
        view.addSubview(effectView)
        effectView.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activateConstraints([
            effectView.leadingAnchor.constraintEqualToAnchor(imageView.leadingAnchor),
            effectView.trailingAnchor.constraintEqualToAnchor(imageView.trailingAnchor),
            effectView.topAnchor.constraintEqualToAnchor(imageView.topAnchor),
            effectView.bottomAnchor.constraintEqualToAnchor(imageView.bottomAnchor)
        ])

        animator = UIViewPropertyAnimator(duration: 0, curve: .Linear) { effectView.effect = nil }
    }

    @IBAction func didChangeValueForSlider(sender: UISlider) {
        animator?.fractionComplete = CGFloat(sender.value)
    }

    @IBAction func didTapSnapshotButton(sender: AnyObject) {
        if let snapshot = view.snapshot(of: imageView.frame) {
            UIImageWriteToSavedPhotosAlbum(snapshot, nil, nil, nil)
        }
    }

}

extension UIView {

    /// Create snapshot
    ///
    /// - parameter rect: The `CGRect` of the portion of the view to return. If `nil` (or omitted),
    ///                 return snapshot of the whole view.
    ///
    /// - returns: Returns `UIImage` of the specified portion of the view.

    func snapshot(of rect: CGRect? = nil) -> UIImage? {
        // snapshot entire view

        UIGraphicsBeginImageContextWithOptions(bounds.size, opaque, 0)
        drawViewHierarchyInRect(bounds, afterScreenUpdates: true)
        let wholeImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

        // if no `rect` provided, return image of whole view

        guard let rect = rect, let image = wholeImage else { return wholeImage }

        // otherwise, grab specified `rect` of image

        let scale = image.scale
        let scaledRect = CGRect(x: rect.origin.x * scale, y: rect.origin.y * scale, width: rect.size.width * scale, height: rect.size.height * scale)
        guard let cgImage = CGImageCreateWithImageInRect(image.CGImage!, scaledRect) else { return nil }
        return UIImage(CGImage: cgImage, scale: scale, orientation: .Up)
    }

}

因此,当我在四个不同的滑块位置捕获四个图像时,会产生:

在此处输入图像描述

于 2016-10-07T18:53:13.930 回答