【问题标题】:I don't want to extent in CIGaussianBlur of CIFilter我不想在 CIFilter 的 CIGaussianBlur 中扩展
【发布时间】:2017-03-26 07:47:13
【问题描述】:

当我应用 GaussianBlur 时,边缘仍然像这样case

我知道图像大小的问题。模糊效果变得比源图像大。但我不知道如何应用原始图像大小:(

这是我的代码:

func applyBlurEffect(image: UIImage) -> UIImage {
    let imageToBlur = CIImage(image: image)
    let blurfilter = CIFilter(name: "CIGaussianBlur")
    blurfilter!.setValue(imageToBlur, forKey: "inputImage")
    let resultImage = blurfilter!.value(forKey: "outputImage") as! CIImage
    let croppedImage: CIImage = resultImage.cropping(to: CGRect(x: 0, y: 0, width: imageToBlur!.extent.size.width, height: imageToBlur!.extent.size.height))
    let context = CIContext(options: nil)
    let blurredImage = UIImage(cgImage: context.createCGImage(croppedImage, from: croppedImage.extent)!)
    return blurredImage
}

我想应用在 func 中输入的图像大小。有人知道吗?

【问题讨论】:

  • 基于这个问题(基于 Obj-C)stackoverflow.com/questions/12839729/… 您可能只需要更改使用 resultImage 的方式...直接在 createCGImage 中使用,并使用 imageToBlur.extent 为要使用的矩形。如果这不起作用,还有其他方法可以尝试,但听起来确实可行。
  • @dfd 感谢您的评论。我试过了,但图像变成空白.. :(

标签: ios swift image-processing uiimage


【解决方案1】:

1. 我不知道这是否能满足您的需求,但您可以像 Apple 在通知中心所做的那样尝试UIBlurEffect(深色、浅色或非常浅色):

func applyBlurEffectTo(imageView: UIImageView) {
    guard !UIAccessibilityIsReduceTransparencyEnabled() else {
        return
    }

    imageView.backgroundColor = .clear

    let blurEffect = UIBlurEffect(style: .light)
    let blurEffectView = UIVisualEffectView(effect: blurEffect)
    blurEffectView.frame = imageView.bounds
    blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]

    imageView.addSubview(blurEffectView)
}

(我认为它太亮了,.dark 选项的效果太暗了 :) 你会想要去除色调。)

2. 或者使用这个UIImage extension(有点矫枉过正,但可以 100% 工作,这部分是第一个案例在后台实现的方式):

import UIKit
import Accelerate

class ViewController: UIViewController {

    @IBOutlet weak var imageView: UIImageView!

    override func viewDidLoad() {
        super.viewDidLoad()

        imageView.image = imageView.image?.applyBlurWithRadius(5)
    }
}

extension UIImage {
    func applyBlurWithRadius(_ blurRadius: CGFloat) -> UIImage? {
        if (size.width < 1 || size.height < 1) { return nil }
        guard let cgImage = self.cgImage else {  return nil }

        let __FLT_EPSILON__ = CGFloat(FLT_EPSILON)
        let screenScale = UIScreen.main.scale
        let imageRect = CGRect(origin: CGPoint.zero, size: size)
        var effectImage = self

        let hasBlur = blurRadius > __FLT_EPSILON__

        if hasBlur {
            UIGraphicsBeginImageContextWithOptions(size, false, screenScale)
            guard let effectInContext = UIGraphicsGetCurrentContext() else { return  nil }

            effectInContext.scaleBy(x: 1.0, y: -1.0)
            effectInContext.translateBy(x: 0, y: -size.height)
            effectInContext.draw(cgImage, in: imageRect)

            var effectInBuffer = createEffectBuffer(effectInContext)

            UIGraphicsBeginImageContextWithOptions(size, false, screenScale)

            guard let effectOutContext = UIGraphicsGetCurrentContext() else { return  nil }
            var effectOutBuffer = createEffectBuffer(effectOutContext)

            if hasBlur {
                let inputRadius = blurRadius * screenScale
                let d = floor(inputRadius * 3.0 * CGFloat(sqrt(2 * M_PI) / 4 + 0.5))
                var radius = UInt32(d)
                if radius % 2 != 1 {
                    radius += 1
                }

                let imageEdgeExtendFlags = vImage_Flags(kvImageEdgeExtend)
                vImageBoxConvolve_ARGB8888(&effectInBuffer, &effectOutBuffer, nil, 0, 0, radius, radius, nil, imageEdgeExtendFlags)
                vImageBoxConvolve_ARGB8888(&effectOutBuffer, &effectInBuffer, nil, 0, 0, radius, radius, nil, imageEdgeExtendFlags)
                vImageBoxConvolve_ARGB8888(&effectInBuffer, &effectOutBuffer, nil, 0, 0, radius, radius, nil, imageEdgeExtendFlags)
            }

            effectImage = UIGraphicsGetImageFromCurrentImageContext()!
            UIGraphicsEndImageContext()
        }

        UIGraphicsBeginImageContextWithOptions(size, false, screenScale)

        guard let outputContext = UIGraphicsGetCurrentContext() else { return nil }

        outputContext.scaleBy(x: 1.0, y: -1.0)
        outputContext.translateBy(x: 0, y: -size.height)
        outputContext.draw(cgImage, in: imageRect)

        if hasBlur {
            outputContext.saveGState()
            outputContext.draw(effectImage.cgImage!, in: imageRect)
            outputContext.restoreGState()
        }

        let outputImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

        return outputImage
    }

    private func createEffectBuffer(_ context: CGContext) -> vImage_Buffer {
        let data = context.data
        let width = vImagePixelCount(context.width)
        let height = vImagePixelCount(context.height)
        let rowBytes = context.bytesPerRow
        return vImage_Buffer(data: data, height: height, width: width, rowBytes: rowBytes)
    }
}

第二个选项结果:

【讨论】:

  • 感谢您的回答。我不想模糊效果,因为我必须绘制图像。模糊效果无法绘制图像:(
  • 如果您想要一个可靠的模糊示例并更好地控制半径,则很难找到解决方案 2
猜你喜欢
  • 1970-01-01
  • 2021-08-15
  • 2021-12-13
  • 2016-01-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多