视频像素化文本上的 CATextLayer
CATextLayer on video pixelated text
我正在从图像创建视频并向它们添加叠加层。问题是当我尝试将 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 基本上是三种动画,一种是将隐藏参数设置为 true 或 false,另一种是添加 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 可能的结果并尝试了很多东西,但结果仍然相同。
尝试使用 .contentsScale 属性。我认为视频以 videoComposition 的比例呈现,而不是 UIScreen.main.scale
所以为了在生成视频的时候得到高质量的图片或者文字,一定要注意将contentScale设置为1。
我遇到的其他问题是某些帧的问题,其中 UIImageView 或 UITextField 可以缩放所有内容以看起来清晰,而 contentMode 将处理所有内容,而使用视频逻辑生成视频开发人员必须特别注意这个
我的意思是当图层框架中的 iff 图像更大时,图像将按比例缩小但看起来会像素化。为图层提供与图像相同的框架将使图像看起来不错。这在水印图像上尤其明显,我们将图像放入 1x、2x 和 3x 维度的资产中。在使用 UIImage(named: "my_watermark") 获取此图像后,它将加载 3x 维度,而我们需要 1x 维度的视频,因为视频比例 == 1。删除 2x 和 3x 维度解决了这个问题。
当我们发现这一点时,我们对 CATextLayer 进行了相同的测试,因此将 contentScale 设置为 1,并处理框架,就达到了目的。
按此逻辑生成的视频,无论是文字还是图片,质量都不错。最大的问题实际上是设置播放后需要时间检查输出结果,其中生成视频需要一些时间,然后将其转移到更大的屏幕上检查一切都非常耗时。
希望这个回答对大家有所帮助!
我正在从图像创建视频并向它们添加叠加层。问题是当我尝试将 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 基本上是三种动画,一种是将隐藏参数设置为 true 或 false,另一种是添加 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 可能的结果并尝试了很多东西,但结果仍然相同。
尝试使用 .contentsScale 属性。我认为视频以 videoComposition 的比例呈现,而不是 UIScreen.main.scale
所以为了在生成视频的时候得到高质量的图片或者文字,一定要注意将contentScale设置为1。 我遇到的其他问题是某些帧的问题,其中 UIImageView 或 UITextField 可以缩放所有内容以看起来清晰,而 contentMode 将处理所有内容,而使用视频逻辑生成视频开发人员必须特别注意这个
我的意思是当图层框架中的 iff 图像更大时,图像将按比例缩小但看起来会像素化。为图层提供与图像相同的框架将使图像看起来不错。这在水印图像上尤其明显,我们将图像放入 1x、2x 和 3x 维度的资产中。在使用 UIImage(named: "my_watermark") 获取此图像后,它将加载 3x 维度,而我们需要 1x 维度的视频,因为视频比例 == 1。删除 2x 和 3x 维度解决了这个问题。
当我们发现这一点时,我们对 CATextLayer 进行了相同的测试,因此将 contentScale 设置为 1,并处理框架,就达到了目的。
按此逻辑生成的视频,无论是文字还是图片,质量都不错。最大的问题实际上是设置播放后需要时间检查输出结果,其中生成视频需要一些时间,然后将其转移到更大的屏幕上检查一切都非常耗时。
希望这个回答对大家有所帮助!