AVCaptureStillImageOutput& UIImagePNGRepresentation [英] AVCaptureStillImageOutput & UIImagePNGRepresentation

查看:113
本文介绍了AVCaptureStillImageOutput& UIImagePNGRepresentation的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于某些我认为不应该那么困难的事情,我一直很苦,所以我想我必须从错误的角度看问题. 为了了解AVCaptureStillImageOutput和相机的工作原理,我制作了一个小应用程序.

I am having a hard time for something I think shouldn’t be so difficult, so I presume I must be looking at the problem from the wrong angle. In order to understand how AVCaptureStillImageOutput and the camera work I made a tiny app.

此应用程序可以拍照并将其另存为PNG文件(我不需要JPEG).下次启动该应用程序时,它将检查是否存在文件,如果存在,则将文件中存储的图像用作该应用程序的背景视图.这个想法很简单.

This app is able to take a picture and save it as a PNG file (I do not want JPEG). The next time the app is launched, it checks if a file is present and if it is, the image stored inside the file is used as the background view of the app. The idea is rather simple.

问题是它不起作用.如果有人可以告诉我我在做什么错,那将非常有帮助.

The problem is that it does not work. If someone can tell me what I am doing wrong that will be very helpful.

我希望图片以与拍摄时一样的背景显示为背景,但是它被旋转或缩放比例错误..等.

I would like the picture to appear as a background the same way it was on the display when it was taken, but it is rotated or has the wrong scale ..etc..

这是相关的代码(如有需要,我可以提供更多信息).

Here is the relevant code (I can provide more information if ever needed).

viewDidLoad方法:

override func viewDidLoad() {
    super.viewDidLoad()

    // For the photo capture:
    captureSession.sessionPreset = AVCaptureSessionPresetHigh

    // Select the appropriate capture devices:
    for device in AVCaptureDevice.devices() {
        // Make sure this particular device supports video.
        if (device.hasMediaType(AVMediaTypeVideo)) {
            // Finally check the position and confirm we've got the back camera.
            if(device.position == AVCaptureDevicePosition.Back) {
                captureDevice = device as? AVCaptureDevice
            }
        }
    }

    tapGesture = UITapGestureRecognizer(target: self, action: Selector("takePhoto"))
    self.view.addGestureRecognizer(tapGesture)

    let filePath = self.toolBox.getDocumentsDirectory().stringByAppendingPathComponent("BackGroundImage@2x.png")

    if !NSFileManager.defaultManager().fileExistsAtPath(filePath) {return}

    let bgImage = UIImage(contentsOfFile: filePath),
    bgView = UIImageView(image: bgImage)
    self.view.addSubview(bgView)
}

处理照片的方法:

func takePhoto() {
    if !captureSession.running {
        beginPhotoCaptureSession()
        return
    }

    if let videoConnection = stillImageOutput.connectionWithMediaType(AVMediaTypeVideo) {
        stillImageOutput.captureStillImageAsynchronouslyFromConnection(videoConnection) {
            (imageDataSampleBuffer, error) -> Void in
            if error == nil {
                var localImage = UIImage(fromSampleBuffer: imageDataSampleBuffer)
                UIGraphicsBeginImageContext(localImage!.size)
                CGContextRotateCTM (UIGraphicsGetCurrentContext(), CGFloat(M_PI_2))
                //localImage!.drawAtPoint(CGPointZero)
                localImage!.drawAtPoint(CGPoint(x: -localImage!.size.height, y: -localImage!.size.width))
                //localImage!.drawAtPoint(CGPoint(x: -localImage!.size.width, y: -localImage!.size.height))
                localImage = UIGraphicsGetImageFromCurrentImageContext()
                UIGraphicsEndImageContext()
                localImage = resizeImage(localImage!, toSize: self.view.frame.size)

                if let data = UIImagePNGRepresentation(localImage!) {
                    let bitMapName = "BackGroundImage@2x"
                    let filename = self.toolBox.getDocumentsDirectory().stringByAppendingPathComponent("\(bitMapName).png")
                    data.writeToFile(filename, atomically: true)
                    print("Picture saved: \(bitMapName)\n\(filename)")
                }
            } else {print("Error on taking a picture:\n\(error)")}
        }
    }

    captureSession.stopRunning()
    previewLayer!.removeFromSuperlayer()
}

启动AVCaptureSession的方法:

The method to start the AVCaptureSession:

func beginPhotoCaptureSession() {
    do {let input = try AVCaptureDeviceInput(device: captureDevice)
        captureSession.addInput(input)
    } catch let error as NSError {
        // Handle any errors:
        print(error)
    }

    previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
    previewLayer?.frame = self.view.layer.frame
    self.view.layer.addSublayer(previewLayer!)
    captureSession.startRunning()

    stillImageOutput.outputSettings = [kCVPixelBufferPixelFormatTypeKey:Int(kCVPixelFormatType_32BGRA)]
    if captureSession.canAddOutput(stillImageOutput) {
        captureSession.addOutput(stillImageOutput)
    }
}

作为示例,以下是使用该应用程序拍摄的照片的图像:

As an example here is an image of a picture taken with the app:

现在,这是我重新启动时作为应用程序背景的内容:

Now here is what I get as the background of the app when it is relaunched:

如果工作正常,则两张图片会相似.

If it was working correctly the 2 pictures would be similar.

推荐答案

对于那些可能一时遇到相同问题的人,我在下面固定的代码中发布以使其正常工作.为了支持所有可能的定位,可能仍需要进行一些改进,但是可以从头开始.

For those who might be hitting the same issue at one point, I post below what I fixed in the code to make it work. There may still be some improvement needed to support all possible orientation, but it's OK for a start.

    if let videoConnection = stillImageOutput.connectionWithMediaType(AVMediaTypeVideo) {
        stillImageOutput.captureStillImageAsynchronouslyFromConnection(videoConnection) {
            (imageDataSampleBuffer, error) -> Void in
            if error == nil {
                var localImage = UIImage(fromSampleBuffer: imageDataSampleBuffer)
                var imageSize = CGSize(width: UIScreen.mainScreen().bounds.height * UIScreen.mainScreen().scale,
                    height: UIScreen.mainScreen().bounds.width * UIScreen.mainScreen().scale)
                localImage = resizeImage(localImage!, toSize: imageSize)

                imageSize = CGSize(width: imageSize.height, height: imageSize.width)
                UIGraphicsBeginImageContext(imageSize)
                CGContextRotateCTM (UIGraphicsGetCurrentContext(), CGFloat(M_PI_2))
                localImage!.drawAtPoint(CGPoint(x: 0.0, y: -imageSize.width))
                localImage = UIGraphicsGetImageFromCurrentImageContext()
                UIGraphicsEndImageContext()

                if let data = UIImagePNGRepresentation(localImage!) {
                    data.writeToFile(self.bmpFilePath, atomically: true)
                }
            } else {print("Error on taking a picture:\n\(error)")}
        }
    }

这篇关于AVCaptureStillImageOutput& UIImagePNGRepresentation的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆