frosty/Flipbook

Rotating an image

orta opened this issue · 2 comments

orta commented

I expect a lot of people will be interested in this, so I'm putting up my example code. This uses core image to rotate the image inside an imageview and records the rotation into a animation.

This is because I couldn't get a transform to work on my snapshots how I would normally do it:

        let number = CGFloat(-1.01 * M_PI)
        let rotationTransform = CATransform3DMakeRotation(number, 0, 0, 1)
        let rotationAnimation = CABasicAnimation(keyPath: "transform")

        rotationAnimation.toValue = NSValue(CATransform3D: rotationTransform);
        rotationAnimation.duration = 0.4
        rotationAnimation.cumulative = true
        rotationAnimation.repeatCount = 10000;

        let image = UIImage(named: "Spinner-0");
        let imageView = UIImageView(image: image);
        imageView.layer.addAnimation(rotationAnimation, forKey:"transform")

        let outer = UIView(frame: imageView.bounds)
        outer.addSubview(imageView)

        view.addSubview(outer)
        arcFlipbook = Flipbook()

        arcFlipbook.renderTargetView(outer, imagePrefix: "Progress-Spinner", frameCount: 20) { (view, frame) in
            return
        }

Zip of my working example using CIImage: http://cl.ly/3H20450t1T0F/Flipbook-orta.zip

I have a similar problem there I modify the view's transform inside the updateBlock, but because the UI loop is not running no "visible" changes are captured by Flipbook.

I tried using dispatch_async with no luck:

for frame in 0..<frameCount {
            dispatch_async(dispatch_get_main_queue(), { () -> Void in
                updateBlock(view: view, frame: frame)
                self.renderViewToImage(view)
            })
        }

I have made some changes in Flipbook class to make this, I'm sure there are better ways to do this but it works ^_^

I added 3 new private properties

private lazy var displayLinkByFrameCount: CADisplayLink = CADisplayLink(target: self, selector: "displayLinkTickByFrameCount:")
private var frameCount = 0
private var updateBlock: ((view: UIView, frame: Int) -> Void)?

I have modified the method func renderTargetView(view: UIView, imagePrefix: String, frameCount: Int, updateBlock: (view: UIView, frame: Int) -> Void)

func renderTargetView(view: UIView, imagePrefix: String, frameCount: Int, updateBlock: (view: UIView, frame: Int) -> Void) {
        self.targetView = view
        self.imagePrefix = imagePrefix
        self.frameCount = frameCount
        self.updateBlock = updateBlock
        self.imageCounter = 0
        displayLinkByFrameCount.frameInterval = 1
        displayLinkByFrameCount.addToRunLoop(NSRunLoop.mainRunLoop(), forMode: NSDefaultRunLoopMode)

        print("[Flipbook] Starting capture...")
    }

And I added this new method

    func displayLinkTickByFrameCount(sender: CADisplayLink) {

        renderViewToImage(self.targetView)

        if self.imageCounter > self.frameCount  {
            sender.invalidate()
            sender.removeFromRunLoop(NSRunLoop.mainRunLoop(), forMode: NSDefaultRunLoopMode)

            print("[Flipbook] Images exported to: \(documentsDirectory()!)")
            print("[Flipbook] Capture complete!")
        } else {
            self.updateBlock!(view: self.targetView!, frame: self.imageCounter)
        }
    }