如何在不丢失阴影饱和度的情况下将带有阴影的 UIBezierpath 转换为 UIImage

Posted

技术标签:

【中文标题】如何在不丢失阴影饱和度的情况下将带有阴影的 UIBezierpath 转换为 UIImage【英文标题】:how to convert UIBezierpath with shadow to UIImage without losing the shadow saturation 【发布时间】:2020-07-14 09:01:50 【问题描述】:

我正在做一个绘图应用程序,它允许用户在视频帧上绘图,所以在 UIImageView 上绘图时,我将 Bezierpath 添加到 CAShapeLayer 并为其设置阴影路径,效果很好,事情是当我想将图层转换为最终将是 ciimage 的 cg 或 uiimage 时(合成到视频帧), UIGraphicContext 会降低阴影饱和度,例如, CAShapeLayer 中的线没有阴影路径,而只是一个简单的阴影饱和度低得多 这是用阴影绘制时的图像

这个图片是转换成图片后阴影相同的路径

我尝试了很多不同的方法,我可以在 SOF 或互联网上的任何其他地方找到,所以基本上有两种方法可以将路径转换为图像(ci,ui,cg),它们都使用相同的方式实践是 UIGraphicContext(如果有任何其他方式请告诉我),所以我尝试将图层转换为 uiimage(通过在 CGContext 上渲染)并尝试直接在上下文上绘制路径,直接给我绘制路径(只是) 比在上下文上渲染层有一点改进。 这是直接在上下文中绘制路径的代码:

    UIGraphicsBeginImageContextWithOptions(size, false, 0)
    let context = UIGraphicsGetCurrentContext()!
    //// Shadow Declarations
    let shadow = UIColor.yellow.withAlphaComponent(1)
    let shadowOffset = CGSize(width: 0, height: 0) //offset is the same as when drawing a path on CAShapeLayer
    let shadowBlurRadius: CGFloat = 20

    //// Bezier 2 Drawing
    context.saveGState()
    context.addPath(path.cgPath)
    context.setShadow(offset: shadowOffset, blur: shadowBlurRadius, color: (shadow as UIColor).cgColor)
    path.lineCapStyle = .round
    path.lineCapStyle = .round
    UIColor.white.setStroke()
    path.lineWidth = 10
    path.stroke(with: .color, alpha: 1.0)
    //context.strokePath()
    context.restoreGState()
    let image = UIGraphicsGetImageFromCurrentImageContext()!
    UIGraphicsEndImageContext()
    return image

如果我能在转换后获得相同的阴影结果,我将不胜感激。

更新

这是在图层上生成阴影的代码,在视图上可以正常工作(第一张图片) 渲染或绘制上下文后,我需要相同的结果。

private func setTheLayer(layer: CAShapeLayer, size: Int, path: CGPath, glowing: Bool, color: CGColor) 
    if glowing 
        layer.path = path
        layer.fillColor = nil
        layer.opacity = 1.0
        layer.lineWidth = CGFloat(size)
        layer.lineCap = .round
        layer.lineJoin = .round
        layer.strokeColor = UIColor.white.cgColor
        // drawing the glow shadow
        layer.shadowPath = path.copy(strokingWithWidth: CGFloat(size) * 4, lineCap: .round, lineJoin: .round, miterLimit: 0)
        layer.shadowOffset = CGSize(width: 0, height: 0)
        layer.shadowColor = color
        layer.shadowRadius = 5.0
        layer.shadowOpacity = 0.7
     else 
        layer.path = path
        layer.fillColor = nil
        layer.opacity = 1.0
        layer.lineWidth = CGFloat(size)
        layer.lineCap = .round
        layer.lineJoin = .round
        layer.strokeColor = color
    

【问题讨论】:

请包含您用于添加和配置形状图层及其阴影的代码。 我刚刚用阴影绘制代码更新了问题 【参考方案1】:

由于我不明白的原因,当您使用图层的 render(in:) 方法时,阴影无法正确渲染。

但是,如果您的图层被添加到视图中,您可以使用该视图的 drawHierarchy(in: afterScreenUpdates:),它将忠实地渲染阴影。

这个游乐场代码:

import UIKit
import PlaygroundSupport

let view = UIView(frame: CGRect(x: 0, y: 0, width: 200, height: 200))
view.backgroundColor = .black
PlaygroundPage.current.liveView = view

let layer = CAShapeLayer()
let path = UIBezierPath()
path.move(to: CGPoint(x: 20, y: 50))
path.addLine(to: CGPoint(x: 180, y: 50))
layer.path = path.cgPath
layer.lineCap = .round
layer.fillColor = nil
layer.lineWidth = 4
layer.strokeColor = UIColor.white.cgColor
layer.shadowPath = path.cgPath.copy(strokingWithWidth: 16, lineCap: .round, lineJoin: .round, miterLimit: 0)
layer.shadowOffset = .zero
layer.shadowColor = UIColor.yellow.cgColor
layer.shadowRadius = 5
layer.shadowOpacity = 0.7
layer.frame = CGRect(x:0, y: 0, width: 200, height: 100)
view.layer.addSublayer(layer)
layer.shouldRasterize = true
let renderer = UIGraphicsImageRenderer(bounds: layer.bounds)
let image = renderer.image  context in
    view.drawHierarchy(in: view.bounds, afterScreenUpdates: true)

let imageView = UIImageView(image: image)
view.addSubview(imageView)
imageView.frame.origin.y = 100

给你这个输出:

不过,我很想知道为什么阴影不能正确渲染。

【讨论】:

感谢您的回复,是的,我已经这样做了,正如我在问题中所说,在上下文中渲染是我的第一次尝试,但是直接在上下文中绘制阴影饱和度较低,我尝试了不同的阴影方法并且没有路径,并且在 ui 中还可以,只是在上下文中渲染时​​,它以某种方式被省略,如图所示 好的,我看到的和你一样,多么有趣。我会进一步调查

以上是关于如何在不丢失阴影饱和度的情况下将带有阴影的 UIBezierpath 转换为 UIImage的主要内容,如果未能解决你的问题,请参考以下文章

如何在不丢失信息的情况下将因子转换为整数\数字?

如何在不丢失 swift 精度的情况下将 String 转换为 Double [重复]

如何在不丢失 Xampp 中的数据的情况下将类型从 varchar 更改为 Date

如何在不丢失 exif 数据的情况下将 UIImage 转换为 JPEG?

如何在不丢失鼠标抓取的情况下将 QGraphicsItem 移动到另一个场景?

如何在不丢失 css 的情况下将模板从桌面发送到移动设备