Reputation: 478
I have a problem with CALayer. The point is that I want to save few UIViews on the movie. Basically I am trying to do it by CALayer. Everything is okay, the app export movie with layers but the layers with views are smaller than video frame.
I tried to scale layer manually but at all it is not look like on the screen. If I move UIView higher on movie it is going much higher.
Video has FullHd frame and layers of UIView depends of it how user place it on the screen.
The questions are: - How to render UIView Context with better retina quality?
There is the code:
VideoSaver.saveVideo(videoAsset!) { (composition, size) in
////////////////
//Parent Layer//
////////////////
let parentLayer = CALayer()
parentLayer.frame = CGRectMake(0, 0, size.width, size.height)
/////////
//Sizes//
/////////
let xScaleValue = CGRectGetWidth(parentLayer.frame)/CGRectGetWidth(self.view.frame)
let yScaleValue = CGRectGetHeight(parentLayer.frame)/CGRectGetHeight(self.view.frame)
///////////////
//Video Layer//
///////////////
let videoLayer = CALayer()
videoLayer.frame = CGRectMake(0, 0, size.width, size.height)
//////////////////
//Captions Layer//
//////////////////
//Creating UIImage from Captions
UIGraphicsBeginImageContext(CGSizeMake(self.captionsTextView.bounds.size.width, self.captionsTextView.bounds.size.height+20))
let currentContext = UIGraphicsGetCurrentContext()
CGContextTranslateCTM(currentContext, 0, 16)
self.captionsTextView.layer.renderInContext(currentContext!)
let captionTextViewImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
let captionsOverlayLayer = CALayer()
captionsOverlayLayer.contents = captionTextViewImage.CGImage
captionsOverlayLayer.frame = CGRectMake(self.captionsTextView.frame.origin.x * xScaleValue,
(size.height - ((self.captionsTextView.frame.origin.y - 20) * yScaleValue)),
CGRectGetWidth(self.captionsTextView.frame) * xScaleValue,
(CGRectGetHeight(self.captionsTextView.frame)+20) * yScaleValue)
captionsOverlayLayer.masksToBounds = true
///////////////////
//TagFilter Layer//
///////////////////
UIGraphicsBeginImageContext(self.tagView.bounds.size)
self.tagView.layer.renderInContext(UIGraphicsGetCurrentContext()!)
let tagViewImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
let tagOverlayLayer = CALayer()
tagOverlayLayer.contents = tagViewImage.CGImage
tagOverlayLayer.frame = CGRectMake(self.tagView.frame.origin.x * xScaleValue,
(size.height - ((self.tagView.frame.origin.y) * yScaleValue)),
CGRectGetWidth(self.tagView.frame) * xScaleValue,
(CGRectGetHeight(self.tagView.frame)) * yScaleValue)
///////////////////////////////////////////////
parentLayer.addSublayer(videoLayer)
parentLayer.addSublayer(captionsOverlayLayer)
parentLayer.addSublayer(tagOverlayLayer)
///////////////
//Composition//
///////////////
composition.animationTool = AVVideoCompositionCoreAnimationTool.init(postProcessingAsVideoLayer: videoLayer, inLayer: parentLayer)
}
I will be glad for help :)
Upvotes: 3
Views: 2764
Reputation: 478
At the end all UIViews
that I want to have on the video I put to one UIView
. From that UIView
I am creating the layer and scaling it to video size. There is a code if someone will have the same problem:
VideoSaver.saveVideo(videoAsset!)
{
(composition, size) in
////////////////
//Parent Layer//
////////////////
let parentLayer = CALayer()
parentLayer.frame = CGRectMake(0, 0, size.width, size.height)
///////////////
//Video Layer//
///////////////
let videoLayer = CALayer()
videoLayer.frame = CGRectMake(0, 0, size.width, size.height)
///////////////////////
//Effect Layout Layer//
///////////////////////
UIGraphicsBeginImageContextWithOptions(self.effectLayoutView.bounds.size, false, 0.0)
self.effectLayoutView.layer.renderInContext(UIGraphicsGetCurrentContext()!)
let effectLayoutViewImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
let effectOverlayLayer = CALayer()
effectOverlayLayer.contents = effectLayoutViewImage.CGImage
effectOverlayLayer.frame = CGRectMake(0, 0, size.width, size.height)
effectOverlayLayer.masksToBounds = true
///////////////////////////////////////////////
parentLayer.addSublayer(videoLayer)
parentLayer.addSublayer(effectOverlayLayer)
///////////////
//Composition//
///////////////
composition.animationTool = AVVideoCompositionCoreAnimationTool.init(postProcessingAsVideoLayer: videoLayer, inLayer: parentLayer)
}
Upvotes: 1
Reputation: 535138
If the problem is the resolution of the image as displayed by the layer, then:
This is your first mistake: UIGraphicsBeginImageContext
. Always call UIGraphicsBeginImageContextWithOptions
and a third argument of 0
, or an explicit resolution.
Your second mistake is that you never set the CALayer's contentsScale
.
Upvotes: 1