Take ARSCNView snapshot with subview - ios

I am using ARSCNView.snapshot() to take a snapshot in my iOS app with a picture as a frame. The picture frame is a UIImageView which is a subview to the ARSCNView. However, I can only get the scene in the taken picture without the image. I also tried to use this method (https://stackoverflow.com/a/45346555/10057340) to render the ARSCNView as an image but I only got the image frame with a white background rather than the image frame with the camera scene. Can anyone suggest a way for doing this? Thanks!!
Below is how I used snaphot():
var frameImageView: UIImageView!
var sceneView: ARSCNView!
func takeSnapShot() {
frameImageView.image = UIImage(named:"frame")
frameImageView.ishidden = false
sceneView.addSubView(frameImageView)
UIImageWriteToSavedPhotosAlbum(sceneView.snapshot(), nil, nil. nil)
}

I don't fully understand what you are asking specifically but you might find this video from the WWDC 2017 useful: https://www.youtube.com/watch?v=eBt1p799L3Q
Check out the project they make at 18 min.

Related

AVFoundation -> record camera video with animated overlay

In my app I am recording camera output with AVFoundation. I am trying to save not just camera output, but also GUI layout(overlay) presented over camera surface.
I am executing some basic animations on GUI layer( showing and hiding of UIView and UIProgressView animation).
So is it somehow possible to record camera output with animated overlay?
My research:
1.) https://www.raywenderlich.com/2734-avfoundation-tutorial-adding-overlays-and-animations-to-videos
Post processing is not an option. And this solution would not work for my problem.
2.) iPhone Watermark on recorded Video.
So it is possible to add watermark. Maybe it would be possible to capture frame from camera, capture frame from overlay then overlaying the captured camera frame with the captured overlay frame? :(
My solution (i am working on it right now) is create an object that subclass a CALayer and add it to your preview uiview.layer.
protocol VideoCameraLayer {
func playAnimation()
func stopAnimation()
}
class CircleFaceLayer: : CALayer,VideoCameraLayer{
init(){
//... add sublayers to this layer or whatever you need
}
func playAnimation(){
//Add animation/s to your layer/sublayers
}
func stopAnimation(){
//Pause animation/s to your layer/sublayers
}
}
You could use this object and sublayering in your avassetexportsession.animatioToll and in your preview layer in your UIView:
let animatedLayer:VideoCameraLayer = CircleFaceLayer()
self.view.layer.addSublayer(animatedLayer)

How to control multiple skeletal animations independently with SceneKit?

I am trying to control multiple skeletal animations at the same time with multiple inputs, each of which points to a different frame of an animation. Imagine the way you set weight for a morpher with setWeight(_:forTargetAt:), but with input as a frame which I want the animation to be in state of.
I achieved this for just one animation by doing something like
#IBOutlet weak var sceneView: SCNView!
var animationPlayer: SCNAnimationPlayer! = nil
override func viewDidLoad() {
super.viewDidLoad()
//add a node on the scene and give animationPlayer the node's animation player
animationPlayer.animation.usesSceneTimeBase = true
}
#IBAction func sliderChanged(_ sender: UISlider) {
sceneView.sceneTime = Double(sender.value) * animationPlayer.animation.duration
}
where a slider is put to change the sceneTime of sceneView. This could only work if the node has just one animation.
But what I want to achieve is controlling all the animations asynchronously but on one node. I cannot simply play with sceneTime because that will cause all the animations to be played on the same time base in sync.
Is there any way to play all the animations with different input time or any value that works as a pointer to a specific frame of the animation?
(e.g. at one point, first animation is playing the 5th frame while second is in state of 8th. At next frame of rendering, the first animation is playing 4th frame and the second is playing 12th frame.)
Thanks.

animate image once using SwiftGifOrigin swift4

I am trying to animate once using SwiftGifOrigin pod but it does not work, using .loadgif the image can animate unlimited times but I want to animate image once
image outlet
#IBOutlet weak var gifimage: UIImageView!
using this method image animate unlimited times
gifimage.loadGif(name: "1_splash1")
and using this method nothing happened it does not show any image
let animated_image = UIImage.gif(name: "1_splash1")
gifimage.animationImages = animated_image?.images
gifimage.animationDuration = (animated_image?.duration)!
gifimage.animationRepeatCount = 1
gifimage.startAnimating()

Xcode - Animating with PNG sequence

I have made an animation with After Effect and added it to my Xcode project as a PNG sequence. This leave me with a folder with 164 images, i am animating with a timer. How is that for the app performance? And could i add more animations like this without any problem?
if its images,
first get those images in an array
#IBOutlet weak var animatingImageView: UIImageView!
var imageList = [UIImage]()
now call function
func playAnimation() {
self.animatingImageView.animationImages = imageList
self.animatingImageView.animationDuration = 2.0
self.animatingImageView.startAnimating()
}
you can use
self.animatingImageView. animationRepeatCount
for repeat count,
and also, if you want to stop it after some time interval, do it with a timer, and on timer completion
self.animatingImageView.stopAnimating()
for better performance:
try using image of size close to the imageview
try using cached image
try making image opaque

ARSKView snapshot iOS

Has anyone had any luck with taking screenshots of the ARSKView in ARKit projects?
I tried something like this:
if let sc = view.snapshotView(afterScreenUpdates: true) {
DispatchQueue.main.async {
UIGraphicsBeginImageContextWithOptions(sc.bounds.size, true, 0.0)
sc.drawHierarchy(in: sc.bounds, afterScreenUpdates: true)
let screenshot = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
UIImageWriteToSavedPhotosAlbum(screenshot!, nil, nil, nil)
}
}
But the output is a black image.
On Apple's example, they are using ARSCNView, where they can call a snapshot function and it does everything automatically.
I'm using SpriteKit not SceneKit, so in spriteKit there is no snapshot method.
I also got the black screen when using drawHeirarchy(in:afterScreenUpdates:) on the ARSKView
Another approach that failed for me: Using the ARSession property (ARFrame *)currentFrame - converting the pixel buffer capturedImage to a UIImage but this just shows the image of the real world, it doesn't include the sprites.
What worked for me was just taking a screenshot from the View Controller view instead of the ARSKView.
It's still a possibility to just switch to SceneKit since you can still use SpriteKit as a material on an SCNNode. SceneKit comes with nice stuff like snapshot as well.
There are also open-source implementations like ARVideoKit https://github.com/AFathi/ARVideoKit as well

Resources