简体   繁体   English

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

[英]how to convert UIBezierpath with shadow to UIImage without losing the shadow saturation

I'm doing a drawing app, which allows users to draw on video frames, so when drawing on the UIImageView, i add the Bezierpath to a CAShapeLayer and set a shadow path to it, and it works great, the thing is when i want to convert the layer to a cg or uiimage which will be eventually ciimage(to compose to a video frame), UIGraphicContext drops the shadow saturation, like, the line in CAShapeLayer doesn't have shadow path, but just a simple shadow with much less saturation this is the image while drawing with shadow我正在做一个绘图应用程序,它允许用户在视频帧上绘图,所以在 UIImageView 上绘图时,我将 Bezierpath 添加到 CAShapeLayer 并为其设置阴影路径,效果很好,事情就是当我想要要将图层转换为 cg 或 uiimage 最终将是 ciimage(合成到视频帧),UIGraphicContext 会降低阴影饱和度,就像 CAShapeLayer 中的线没有阴影路径,而只是一个简单的阴影,少得多饱和度 这是使用阴影绘制时的图像

在此处输入图像描述

this image is the path with the same shadow after converting to image此图为转成image后阴影相同的路径

在此处输入图像描述

i have tried lots of different methods that i could find in SOF or any other place on the internet, so basically there are two ways to convert a path to image(ci,ui,cg) which all of them using somehow same practice which is UIGraphicContext(if there is any other way PLEASE tell me), so i tried to convert a layer to uiimage(by rendering it on CGContext) and also tried to draw path directly on the context, drawing path directly gave me (just)a little improvement than rendering layer on the context.我尝试了很多不同的方法,我可以在 SOF 或互联网上的任何其他地方找到,所以基本上有两种方法可以将路径转换为图像(ci,ui,cg),它们都使用相同的做法,即UIGraphicContext(如果有任何其他方式请告诉我),所以我尝试将图层转换为 uiimage(通过在 CGContext 上渲染它)并且还尝试直接在上下文上绘制路径,直接绘制路径给了我(只是)一点比在上下文上渲染层的改进。 this is the code for directly drawing the path on the context:这是直接在上下文中绘制路径的代码:

    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

i would really appreciate any help or hint that i could get the same shadow result after converting.我真的很感激任何帮助或提示,我可以在转换后得到相同的阴影结果。

Updated :更新

here is the code which generates the shadow on layer which works fine on the view (the first picture) I need the same result after rendering or drawing on the context.这是在图层上生成阴影的代码,它在视图(第一张图片)上运行良好,在渲染或绘制上下文后我需要相同的结果。

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
    }
}

For reasons I don't understand, shadows are not rendered correctly when you use a layer's render(in:) method.由于我不明白的原因,当您使用图层的render(in:)方法时,阴影不会正确渲染。

However, if your layers are added to a view, you can use that view's drawHierarchy(in: afterScreenUpdates:) , which will faithfully render the shadow.但是,如果您的图层被添加到视图中,您可以使用该视图的drawHierarchy(in: afterScreenUpdates:) ,它将忠实地渲染阴影。

This playground code:这个游乐场代码:

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

Gives you this output:给你这个output:

在此处输入图像描述

I'd love to know why shadows don't render properly, though.不过,我很想知道为什么阴影不能正确渲染。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM