【问题标题】:CAShapeLayer with CIFilters带有 CIFilter 的 CAShapeLayer
【发布时间】:2015-10-28 06:29:27
【问题描述】:

我想将 CIFilter 应用于 CAShapeLayer.filters。 这是正确的假设如何做到这一点:

  • 创建 CAShapeLayer
  • 从 CAShapeLayer 创建 CGImage 或 UIImage
  • 使用 CGImage 或 UIImage 创建 CIFilter
  • 将 CIFilter 添加到 CAShapeLayer.filters

为了从 CAShapeLayer 创建 CGImage,我使用了 CAShapeLayer.contents,但在我的情况下,contents 为 nil,如果我将 CAShapeLayer 渲染到图像上下文,我也无法获取图像。

override func layoutSubviews()
    {
        if(self.shapeLayer == nil && self.path != nil && self.pathOriginationSize != CGSizeZero)
        {
            let scaleFactor = self.scaleFactor(self.pathOriginationSize, targetSize: self.bounds.size)

            _scaledPath = UIBezierPath(CGPath: self.path.CGPath)
            _scaledPath.lineWidth = self.path.lineWidth
            _scaledPath.applyTransform(CGAffineTransformMakeScale(scaleFactor.x, scaleFactor.y))
            _scaledPath.lineCapStyle = CGLineCap.Round

            self.shapeLayer = CAShapeLayer()
            self.shapeLayer.path = _scaledPath.CGPath
            self.shapeLayer.strokeColor = UIColor.blackColor().CGColor
            self.shapeLayer.lineWidth = self.path.lineWidth

            let imageSize = CGPathGetBoundingBox(_scaledPath.CGPath).size

            UIGraphicsBeginImageContextWithOptions(imageSize, false, UIScreen.mainScreen().scale)
            let context = UIGraphicsGetCurrentContext()
            self.shapeLayer.renderInContext(context!)
            _ = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()

            let cgImage = self.shapeLayer.contents as! CGImageRef

            let inputImage = CIImage(CGImage: cgImage)

            let blurFilter = CIFilter(name: "CIZoomBlur")
            blurFilter?.setValue(inputImage, forKey: kCIInputImageKey)
            blurFilter?.setDefaults()
            self.shapeLayer.filters = [blurFilter!]
            self.shapeLayer.shouldRasterize = true

            self.layer.addSublayer(self.shapeLayer)
        }
    }

【问题讨论】:

    标签: ios swift uiimage cashapelayer cifilter


    【解决方案1】:

    CALayer.filters 未在 iOS 上实现。

    在这种情况下不需要使用CAShapeLayer(因为您不能使用filters)。您可以从UIBezierPath 创建一个CGImage(正如您所做的那样;只需stroke 和/或fill 路径,而不是调用renderInContext)。然后对结果使用apply CIFilter,创建一个CGImage 并将其分配给contents。 (从你上面的代码,你似乎明白了如何做所有这些事情,所以我不在这里写出来。)

    【讨论】:

    • 嘿,罗伯!您是否碰巧知道是否有一种有效的方法来过滤 CALayer,因为 CALayer.filters 在 iOS 上不起作用?
    • 我不确定你所说的“高效”是什么意思。但是,如果以上内容对您来说还不够快,那么您应该更深入地研究 Core Image。我将从最近的 WWDC developer.apple.com/videos/play/wwdc2017/510
    • 抱歉没有解释。我们正在开发一个视频处理应用程序。该应用程序的一部分正在对视频应用过滤器。使用更高级别的 AVFoundation API,我可以将视频帧作为 CALayer 对象访问。但是使用更复杂的 API,我可以通过 CIImage 对象访问视频帧。所以基本上我问的是使用这种方法是否比使用 CIImage 机制慢很多(具有复杂性的缺点)。你怎么看?
    • 我自己绝不会这样做视频;您想尽可能多地留在核心图像空间中,并尽可能晚且不频繁地(如果有的话)转换为核心图形。但是您必须对其进行测试才能知道这种方法是否真的很慢。我会留在 Core Image 进行控制,而不是性能本身(所以当你遇到性能问题时,你可以在不重新设计整个系统的情况下修复它)。 Apple 通常很好地在较低级别的框架之上构建其较高级别的框架,因此您无法猜测您会受到什么样的性能影响。你必须测试它。
    • 酷,谢谢!我会看看你发来的东西。祝你有美好的一天!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-17
    • 2014-01-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-23
    相关资源
    最近更新 更多