【问题标题】:CATextLayer on video pixelated text视频像素化文本上的 CATextLayer
【发布时间】:2020-07-30 00:26:03
【问题描述】:

我正在从图像创建视频并向它们添加叠加层。问题是当我尝试将 CATextLayer 添加到视频时。文字像素化了,看图吧

这是用于生成 CATextLayer 的代码:

private func generateTextLayer(for text: String, at frame: CGRect, in layer: CALayer) -> CATextLayer {
    let textLayer = CATextLayer()

    textLayer.frame = frame.integral
    textLayer.contentsScale = UIScreen.main.scale

    textLayer.isWrapped = true
    textLayer.isHidden = true

    textLayer.foregroundColor = UIColor.white.cgColor
    textLayer.backgroundColor = UIColor.clear.cgColor

    let fontHeight = resolution.fontHeight
    textLayer.font = UIFont.systemFont(ofSize: fontHeight)
    textLayer.fontSize = fontHeight

    textLayer.string = text

    textLayer.truncationMode = .end
    textLayer.alignmentMode = .center

    textLayer.contentsScale = UIScreen.main.scale

    layer.addSublayer(textLayer)

    return textLayer
}

而这段代码是用来生成带有图片的CALayer:

private func generateImageLayer(for image: CGImage?, at frame: CGRect, in layer: CALayer) -> CALayer {
    let imageLayer = CALayer()
    imageLayer.frame = frame.integral

    imageLayer.contents = image
    imageLayer.contentsGravity = .resizeAspectFill

    imageLayer.isHidden = true

    imageLayer.backgroundColor = UIColor.clear.cgColor

    layer.addSublayer(imageLayer)

    return imageLayer
}

由于生成的视频中不同图像层的动画,图像层被隐藏。这是用于层生成的代码:

    let size = backgroundTrack.naturalSize.applying(backgroundTrack.preferredTransform)

    let parentlayer = CALayer()
    parentlayer.frame = CGRect(origin: .zero, size: size).integral
    parentlayer.backgroundColor = UIColor.black.cgColor
    parentlayer.isOpaque = true

    let backgroundVideoLayer = CALayer()
    backgroundVideoLayer.frame = parentlayer.bounds
    backgroundVideoLayer.backgroundColor = UIColor.black.cgColor
    backgroundVideoLayer.isOpaque = true

    parentlayer.addSublayer(backgroundVideoLayer)

    var currentTime: Double = 0
    for source in videoSources {

        // This will generate blurred background layer
        let blurrLayer = generateImageLayer(for: source.blurredImage, at: backgroundVideoLayer.bounds, in: backgroundVideoLayer)
        blurrLayer.contentsGravity = .resizeAspectFill

        // Adds image to blurrLayer
        if let image = source.image { 
            let frame = calculateFrame(for: image.size)
            let imageLayer = generateImageLayer(for: image.cgImage, at: frame, in: blurrLayer)
            imageLayer.isHidden = false

            Animations.fadeInOut(layer: blurrLayer, beginTime: currentTime, duration: duration.value)
        }

        // Adds CATextLayer 
        if let text = source.title {
            let frame = parentlayer.bounds.offsetBy(dx: 0, dy: 100)

            let titleLayer = generateTextLayer(for: text, at: frame, in: parentlayer)

            Animations.fadeInOut(layer: titleLayer, beginTime: currentTime, duration: duration.value)
        }

        currentTime += duration.value
    }

我尝试将 rasterizationScale 设置为 UIScreen.main.scale,shouldRasterize 设置为 true,contentsScale 设置为 UIScreen.main.scale,各种不同的选项,甚至尝试拍摄 UILabel 并将其设置为图像(甚至在本地保存图像并检查它,质量很好),但结果又是像素化的写作。

Animate fadeInOut 基本上是三个动画,一个是设置隐藏参数为真或假,另一个是添加 CATransition 显示动画,用于层之间的进入和退出过渡。

    static func fadeInOut(layer: CALayer, beginTime: Double, duration: Double, skipEntry: Bool = false) {
    let t = beginTime < 1 ? -0.0001 : beginTime
    let d = beginTime < 1 ? duration + 0.0001 : duration - 0.0001

    if !skipEntry {
        let entryTransition = CATransition()

        entryTransition.beginTime = t
        entryTransition.duration = 0.5

        entryTransition.type = CATransitionType.reveal
        entryTransition.subtype = CATransitionSubtype.fromTop

        entryTransition.isRemovedOnCompletion = false
        layer.add(entryTransition, forKey: "entry")
    }

    let exitTransition = CATransition()

    exitTransition.beginTime = d - 0.5
    exitTransition.duration = 0.5

    exitTransition.startProgress = 1
    exitTransition.endProgress = 0

    exitTransition.type = CATransitionType.reveal
    exitTransition.subtype = CATransitionSubtype.fromTop

    exitTransition.isRemovedOnCompletion = false
    layer.add(exitTransition, forKey: "exit")

    let fadeInOutAnimation = CABasicAnimation(keyPath: "hidden")
    fadeInOutAnimation.fromValue = false
    fadeInOutAnimation.toValue = false

    fadeInOutAnimation.beginTime = t
    fadeInOutAnimation.duration = d

    fadeInOutAnimation.isRemovedOnCompletion = false
    layer.add(fadeInOutAnimation, forKey: "opacity")
}

在将我的问题标记为已查看并已回答之前,我花了很多时间尝试在 Google 上搜索可能的结果并尝试了很多方法,但结果仍然相同。

【问题讨论】:

  • 我还尝试为父层设置一大堆选项,但都没有成功
  • 尝试将 textLayer.backgroundColor 设置为黑色而不是清晰。由于透明度,像素化可能会成为问题。
  • 也试过了,没用

标签: swift calayer avkit catextlayer avvideocomposition


【解决方案1】:

尝试使用 .contentsScale 属性。我认为视频以 videoComposition 的比例呈现,而不是 UIScreen.main.scale

【讨论】:

    【解决方案2】:

    因此,为了在生成视频时获得高质量的图像或文本,必须注意 contentScale 将其设置为 1。 我遇到的其他问题是某些帧的问题,其中 UIImageView 或 UITextField 可以缩放所有内容以看起来清晰,而 contentMode 会处理所有内容,而使用视频逻辑生成视频开发人员必须特别注意这一点

    我的意思是如果图像比图层框架更大,图像会按比例缩小,但看起来会像素化。为图层提供与图像相同的帧将使图像看起来不错。这在水印图像上尤其明显,我们将图像放置到具有 1x、2x 和 3x 尺寸的资产中。使用 UIImage(named: "my_watermark") 获取此图像后,它将加载 3x 尺寸,由于视频比例 == 1,我们需要 1x 尺寸的视频。删除 2x 和 3x 尺寸可以解决此问题。

    当我们发现这一点时,我们对 CATextLayer 进行了相同的测试,因此将 contentScale 设置为 1,并处理好帧,就可以了。

    按照这个逻辑生成的视频,里面的文字和图片质量都很好。最大的问题实际上是在播放设置后检查输出结果需要时间,其中生成视频需要一些时间,然后将其转移到更大的屏幕上检查所有内容非常耗时。

    希望这个答案对某人有所帮助!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-11-05
      • 2012-05-23
      • 2013-04-13
      • 1970-01-01
      • 1970-01-01
      • 2015-10-25
      • 1970-01-01
      相关资源
      最近更新 更多