0

I'm building a live filter camera app in swift.

I'm changing from AVCaptureVideoDataOutput() to AVCaptureStillImageOutput() to perform the capturing photo function. After I changed, there is no preview view when I open the app.

The capture photo function is working, I can hear the capture sound "Ka" when I click the main group area. There is just no view here.

Here is my full code

import Foundation
import UIKit
import AVFoundation
import CoreMedia

let CIHueAdjust = "CIHueAdjust"
let CIHueAdjustFilter = CIFilter(name: "CIHueAdjust", withInputParameters: ["inputAngle" : 1.24])

let Filters = [CIHueAdjust: CIHueAdjustFilter]

let FilterNames = [String](Filters.keys).sort()

class LiveCamViewController :       UIViewController,AVCaptureVideoDataOutputSampleBufferDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate{
let mainGroup = UIStackView()
let imageView = UIImageView(frame: CGRectZero)
let filtersControl = UISegmentedControl(items: FilterNames)
var videoOutput = AVCaptureStillImageOutput()

override func viewDidLoad()
{
    super.viewDidLoad()

    view.addSubview(mainGroup)
    mainGroup.axis = UILayoutConstraintAxis.Vertical
    mainGroup.distribution = UIStackViewDistribution.Fill

    mainGroup.addArrangedSubview(imageView)
    mainGroup.addArrangedSubview(filtersControl)
    mainGroup.addGestureRecognizer(UITapGestureRecognizer(target: self, action:#selector(LiveCamViewController.saveToCamera(_:))))

    imageView.contentMode = UIViewContentMode.ScaleAspectFit

    filtersControl.selectedSegmentIndex = 0

    let captureSession = AVCaptureSession()
    captureSession.sessionPreset = AVCaptureSessionPresetPhoto

    let backCamera = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)

    do
    {
        let input = try AVCaptureDeviceInput(device: backCamera)

        captureSession.addInput(input)
    }
    catch
    {
        print("can't access camera")
        return
    }

    //get captureOutput invoked
    let previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
    view.layer.addSublayer(previewLayer)

    videoOutput.outputSettings = [AVVideoCodecKey:AVVideoCodecJPEG]

    if captureSession.canAddOutput(videoOutput)
    {
        captureSession.addOutput(videoOutput)
    }

    captureSession.startRunning()
}

func captureOutput(captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, fromConnection connection: AVCaptureConnection!)
{
    guard let filter = Filters[FilterNames[filtersControl.selectedSegmentIndex]] else
    {
        return
    }

    let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)
    let cameraImage = CIImage(CVPixelBuffer: pixelBuffer!)

    filter!.setValue(cameraImage, forKey: kCIInputImageKey)

    let filteredImage = UIImage(CIImage: filter!.valueForKey(kCIOutputImageKey) as! CIImage!)
    let fixedImage = correctlyOrientedImage(filteredImage)

    dispatch_async(dispatch_get_main_queue())
    {
        self.imageView.image = fixedImage
    }

}

func correctlyOrientedImage(image: UIImage) -> UIImage {

    UIGraphicsBeginImageContextWithOptions(image.size, false, image.scale)
    image.drawInRect(CGRectMake(0, 0, image.size.width, image.size.height))
    let normalizedImage:UIImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    let imageRef: CGImageRef = normalizedImage.CGImage!
    let rotatedImage: UIImage = UIImage(CGImage: imageRef, scale: 1.0, orientation: .Right)

    return rotatedImage
}

override func viewDidLayoutSubviews()
{
    mainGroup.frame = CGRect(x: 37, y: 115, width: 301, height: 481)
}

func saveToCamera(sender: UITapGestureRecognizer) {

    videoOutput.outputSettings = [AVVideoCodecKey:AVVideoCodecJPEG]

    if let videoConnection = videoOutput.connectionWithMediaType(AVMediaTypeVideo) {
        videoOutput.captureStillImageAsynchronouslyFromConnection(videoConnection) {
            (imageDataSampleBuffer, error) -> Void in
            let imageData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(imageDataSampleBuffer)
            UIImageWriteToSavedPhotosAlbum(UIImage(data: imageData)!, nil, nil, nil)
        }
    }
}

}

Thanks.

rmaddy
  • 314,917
  • 42
  • 532
  • 579
dididaisy
  • 141
  • 3
  • 10
  • Possible duplicate of [How to capture picture with AVCaptureSession in Swift?](http://stackoverflow.com/questions/28756363/how-to-capture-picture-with-avcapturesession-in-swift) – iYoung May 01 '16 at 06:13
  • You can refer this http://stackoverflow.com/questions/25871513/swift-take-photo-from-avfoundation?rq=1 – iYoung May 01 '16 at 06:15
  • if you can hear the sound. probably your code is working for Avfoundation. your view layout (autolayout) or outlets might be messed up, – Shubhank May 01 '16 at 06:27
  • you can't beat this sample code .. http://drivecurrent.com/devops/using-swift-and-avfoundation-to-create-a-custom-camera-view-for-an-ios-app/#comment-4686 – Fattie May 17 '16 at 21:52

2 Answers2

0

If you want to capture photo or video from camera, then you should use UIImagePickerController instead AVFoundation. Check Applce documentation for more information about it.

Update :

Refer this link. It have too many examples of customize imagePickercontroller. and you can refer this and this answer of stackobverflow.

Hope this will help :)

Community
  • 1
  • 1
Ketan Parmar
  • 27,092
  • 9
  • 50
  • 75
0

The problem might be because you don't have a frame for the previewLayer.

Type this:

previewLayer.frame = self.view.bounds

And also explicitly set the video gravity: (I think this is optional)

previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill // Or choose some other option if you prefer
Lawrence413
  • 1,976
  • 1
  • 14
  • 28
  • Hi, thx for your answer. It works. But the filter is gone.. No live filter cover on the screen.. Should I ask u here, or should I open a new question? Thank u! – dididaisy May 02 '16 at 03:38
  • Adding the filters AFTER you set up & present the preview layer should work. They are probably gone since they are added to the view before you show the preview layer and they are below it. So add the `view.addSubview(mainGroup)` below `view.addSubview(previewLayer)` and it should work. If my answer was the right one for you, then please accept it and upvote it. (press the greyed out tick button and the up arrow above the number left to the answer) – Lawrence413 May 02 '16 at 07:59