как преобразовать UIBezierpath с тенью в UIImage без потери насыщенности тени - PullRequest
1 голос
/ 14 июля 2020

Я делаю приложение для рисования, которое позволяет пользователям рисовать на видеокадрах, поэтому при рисовании в UIImageView я добавляю Bezierpath в CAShapeLayer и устанавливаю к нему теневой путь, и он отлично работает, дело в том, что когда я хочу преобразовать слой в cg или uiimage, который в конечном итоге будет ciimage (чтобы составить видеокадр), UIGraphicContext отбрасывает насыщенность тени, например, линия в CAShapeLayer не имеет теневого пути, а просто простая тень с гораздо меньшей насыщенностью это изображение при рисовании с тенью

enter image description here

this image is the path with the same shadow after converting to image

введите описание изображения здесь

Я пробовал множество разных методов, которые я мог найти в SOF или любом другом месте на inte rnet, поэтому в основном есть два способа преобразовать путь в изображение (ci, ui, cg), и все они используют ту же практику, которая является UIGraphicContext (если есть какой-либо другой способ, ПОЖАЛУЙСТА, сообщите мне), поэтому я попытался преобразовать слой в uiimage (путем рендеринга его в CGContext), а также попытался нарисовать путь непосредственно на 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

Я был бы очень признателен за любую помощь или подсказку, что я могу получить тот же результат тени после преобразования.

Обновлено :

вот код, который генерирует тень на слое, который отлично работает на виде (первое изображение). Мне нужен тот же результат после рендеринга или рисования в контексте.

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 Ответ

0 голосов
/ 14 июля 2020

По непонятным мне причинам тени не отображаются правильно, когда вы используете метод слоя 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

Дает вам следующий результат:

введите описание изображения здесь

Я бы хотел знать, почему тени не отображаются должным образом.

...