将一个UIBezierPath变成一个掩模?

问题描述 投票:0回答:1

不知道我问的这个问题是否正确,但我有两个组件,一个是 CIImage 和一个 UIBezierPath. 理想情况下,我想创建一个 CGRect 囊括了我 UIBezierPath;路径内的所有东西都将是 白色径外的一切都将是 黑色. 这样一来,我就可以呈现这个 CGRect 变成某种图像,然后我可以将其用作其他用途的遮罩。

我正在苦苦思索如何做到这一点。注重业绩. 我的测试,如下文所述,使用的杠杆是 UIGraphicsImageRenderer 这对我的需求来说太慢了(我将在相机的采样缓冲区上做这件事)。 因此,我想坚持在 CoreImage. 这是我的尝试。

// Path
let path = UIBezierPath()
// ... define the path's shape and close it

// My source image
let image = CIImage(cgImage: UIImage(named: "test.jpg")!.cgImage!)

// Renderer
let renderer = UIGraphicsImageRenderer(size: image.extent.size)

// Render path as mask
let img = renderer.image { ctx in
   ctx.cgContext.setFillColor(UIColor.black.cgColor)
   ctx.cgContext.fill(CGRect(x: 0, y: 0, width: image.extent.size.width, height: image.extent.size.height))
   ctx.cgContext.setFillColor(UIColor.white.cgColor)
   ctx.cgContext.addPath(path.cgPath)
   ctx.cgContext.drawPath(using: .fill)
}

// Put a filter on the image
let imageFiltered = image.applyingFilter("CIPhotoEffectNoir")

// Blend with mask
let maskFilter = CIFilter.blendWithMask()
maskFilter.inputImage = imageFiltered
maskFilter.backgroundImage = image
maskFilter.maskImage = CIImage(cgImage: img.cgImage!)

// Output
if let output = maskFilter.outputImage {
   ... use CIContext() to render back to CVPixelBuffer for preview on MTKView.
}

总的来说,我们的目标是有一个定义的图像部分(这将不符合传统的形状,如一个正方形或圆形),这将是一个CIFilter过滤,然后合成回原来的。 如果有更好的方法(比如将原始图像进行过滤,裁剪到路径上(让路径外的所有东西都是透明的),然后再进行合成,这可能会有更好的表现。

要注意的是,上面的示例代码会导致崩溃,因为它的 UIGraphicsImageRenderer 不能足够快地渲染遮罩。

swift image-processing uibezierpath core-image
1个回答
0
投票

到目前为止,你的方法看起来不错。我认为慢的部分是用Core Graphics生成蒙版图像。不幸的是,没有直接的方法可以直接用Core Image做同样的事情(在GPU上)。不过,你可以尝试以下方法。

(根据你之前的问题假设路径总是有一定的形状) 你可以生成一个包含路径的蒙版图像: 曾经 为您选择的某个参考尺寸。确保该路径不会 "触及 "边界,然后,当你想使用它作为遮罩时,使用变换将形状图像移动并缩放到正确的位置,让它的边缘无限延伸(覆盖整个底层图像)。

然后,当你想把它用作蒙版时,使用变换将形状图像移动和缩放到正确的位置,并让它的边缘无限延伸(以覆盖整个底层图像;这就是为什么形状不应该接触边缘)。类似这样。

let pathImage = CIImage(cgImage: img.cgImage!)
// scale path to the size of the area you want to mask
var mask = pathImage.transformed(by: CGAffineTransform(scaleX: scaleX, y: scaleY))
// move path to the place you want to cover
mask = mask.transformed(by: CGAffineTransform(translationX: offsetX, y: offsetY))
// let mask fill the rest of the area
mask = mask.clampedToExtent()

// use mask as maskImage...

你应该能够回收 pathImage 每一帧都是如此,从而避免了Core Graphics和CPU-GPU的同步。

© www.soinside.com 2019 - 2024. All rights reserved.