Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to take multiple photos in a sequence (1s delay each), using Swift on iOS8.1?

I am trying to take few photos after a single user click on a Camera preview so I can present them and user can pick one that was timed best or use all in a "film strip" mode. The expected user experience is: "I open a camera, take a picture and then I see 5 pictures taken second by second. I do not have to press the 'take picture' button 5 times, one is just enough to start the sequence".

I am new to iOS and Swift and I base my work on a 'Swift Recipes' book (https://www.safaribooksonline.com/library/view/ios-8-swift/9781491908969/).

The source code to take a single photo is:

controller = UIImagePickerController()
    if let theController = controller{
        theController.sourceType = .Camera
        theController.mediaTypes = [kUTTypeImage as NSString]
        theController.allowsEditing = true
        theController.delegate = self
        presentViewController(theController, animated: true, completion: nil)
    }

plus the relevant image handling (via func imagePickerController). I tried playing with the controller objecct above, but miserably failed :( I believe that this is not the right way to get what I look for, but I struggle to find the right one. Any help will be appreciated.

like image 364
Piotr Avatar asked Oct 29 '14 22:10

Piotr


People also ask

How do you take continuous pictures on iPhone?

On iPhone XS, iPhone XR, and later models: Swipe the Shutter button to the left. On iPhone X and earlier models: Touch and hold the Shutter button. The counter shows how many shots you've taken.

How do you select multiple pictures fast?

To grab several at once, you can enter selection mode by long-pressing on one photo, and then tapping on other pictures or on a date. Doing the latter will automatically select all the images taken on a specific day.

How do you take multiple pictures on iPhone without hands?

It's actually really simple! Open the built-in iPhone Camera app. If you have iPhone XS, iPhone XR, iPhone 11, or iPhone 12, slide the shutter button to the left. The camera will keep taking photos until you release the shutter button.


1 Answers

I don't know if there is a mode for this behavior in UIImagePickerController. If I were you I would use AVFoundation to implement this.

import UIKit
import AVFoundation

class ViewController: UIViewController {

    var connection: AVCaptureConnection!
    var output: AVCaptureStillImageOutput!
    var videoPreviewLayer: AVCaptureVideoPreviewLayer!
    @IBOutlet var videPreviewView: UIView!

    override func viewDidLoad() {
        super.viewDidLoad()

        self.createCamera()
    }

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()

        self.videoPreviewLayer.bounds = self.videPreviewView.bounds
        self.videoPreviewLayer.position = CGPoint(x: CGRectGetMidX(self.videPreviewView.bounds), y: CGRectGetMidY(self.videPreviewView.bounds))
    }

    func createCamera() {
        let captureSession = AVCaptureSession()

        if captureSession.canSetSessionPreset(AVCaptureSessionPresetHigh) {
            captureSession.sessionPreset = AVCaptureSessionPresetHigh
        } else {
            println("Error: Couldn't set preset = \(AVCaptureSessionPresetHigh)")
            return
        }

        let cameraDevice = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)

        var error: NSError?
        let inputDevice = AVCaptureDeviceInput.deviceInputWithDevice(cameraDevice, error: &error) as AVCaptureDeviceInput
        if let error = error {
            println("Error: \(error)")
            return
        }

        if captureSession.canAddInput(inputDevice) {
            captureSession.addInput(inputDevice)
        } else {
            println("Error: Couldn't add input device")
            return
        }

        let imageOutput = AVCaptureStillImageOutput()
        if captureSession.canAddOutput(imageOutput) {
            captureSession.addOutput(imageOutput)
        } else {
            println("Error: Couldn't add output")
            return
        }

        // Store imageOutput. We will need it to take photo
        self.output = imageOutput

        let connection = imageOutput.connections.first as AVCaptureConnection!
        // Store this connection in property. We will need it when we take image.
        self.connection = connection
        connection.videoOrientation = AVCaptureVideoOrientation.Portrait

        captureSession.startRunning()

        // This will preview the camera
        let videoLayer = AVCaptureVideoPreviewLayer(session: captureSession)
        videoLayer.videoGravity = AVLayerVideoGravityResizeAspectFill
        videoLayer.contentsScale = UIScreen.mainScreen().scale

        self.videPreviewView.layer.addSublayer(videoLayer)

        // Store this layer instance in property. We will place it into a view
        self.videoPreviewLayer = videoLayer
    }

    func takePhoto(completion: (UIImage?, NSError?) -> Void) {
        self.output.captureStillImageAsynchronouslyFromConnection(self.connection) { buffer, error in
            if let error = error {
                completion(nil, error)
            } else {
                let imageData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(buffer)
                let image = UIImage(data: imageData, scale: UIScreen.mainScreen().scale)
                completion(image, nil)
            }
        }
    }
}

Now all you have to do is create an action that calls takePhoto with 3 times. You can use NSTimer to do this.

like image 103
mustafa Avatar answered Sep 29 '22 05:09

mustafa