相机仅在人像模式下快速拍照
Posted
技术标签:
【中文标题】相机仅在人像模式下快速拍照【英文标题】:Camera only takes pictures in portrait mode swift 【发布时间】:2016-08-02 12:33:37 【问题描述】:如何将相机设置为横向模式?每次我拍照时,图像都会保存为肖像图像。当设备处于横向模式时,照片看起来不错,但如果我在相机胶卷中看到它,它仍然是纵向模式。 这是我的拍照功能:
// take a photo
@IBAction func takePhoto(sender: AnyObject)
self.fullScreenView.hidden = false
self.recordButton.enabled = false
self.takephoto.enabled = false
self.recordButton.hidden = true
self.takephoto.hidden = true
session.startRunning()
// customize the quality level or bitrate of the output photo
session.sessionPreset = AVCaptureSessionPresetPhoto
// add the AVCaptureVideoPreviewLayer to the view and set the view in fullscreen
fullScreenView.frame = view.bounds
videoPreviewLayer.frame = fullScreenView.bounds
fullScreenView.layer.addSublayer(videoPreviewLayer)
// add action to fullScreenView
gestureFullScreenView = UITapGestureRecognizer(target: self, action: #selector(ViewController.takePhoto(_:)))
self.fullScreenView.addGestureRecognizer(gestureFullScreenView)
// add action to myView
gestureView = UITapGestureRecognizer(target: self, action: #selector(ViewController.setFrontpage(_:)))
self.view.addGestureRecognizer(gestureView)
if (preview == true)
if let videoConnection = stillImageOutput!.connectionWithMediaType(AVMediaTypeVideo)
// code for photo capture goes here...
stillImageOutput?.captureStillImageAsynchronouslyFromConnection(videoConnection, completionHandler: (sampleBuffer, error) -> Void in
// process the image data (sampleBuffer) here to get an image file we can put in our view
if (sampleBuffer != nil)
let imageData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(sampleBuffer)
let image = UIImage(data: imageData, scale: 1.0)
self.fullScreenView.hidden = true
self.fullScreenView.gestureRecognizers?.forEach(self.fullScreenView.removeGestureRecognizer)
self.session.stopRunning()
// save image to the library
UIImageWriteToSavedPhotosAlbum(image!, nil, nil, nil)
self.imageViewBackground = UIImageView(frame: self.view.bounds)
self.imageViewBackground.image = image
self.imageViewBackground.tag = self.key
self.view.addSubview(self.imageViewBackground)
)
else
preview = true
我的预览看起来像这样,没关系:
http://img5.fotos-hochladen.net/uploads/bildschirmfotom4s7diaehy.png
但最终看起来是这样的:
http://img5.fotos-hochladen.net/uploads/bildschirmfoto3c2rlwtevf.png
提前致谢!
【问题讨论】:
【参考方案1】:因为无论您的设备是纵向还是横向,您的 videoConnection 的方向 始终是纵向的。所以你应该在拍摄静态照片之前将 videoConnection 的方向调整到正确的方向
添加如下方法获取当前deviceOrientation的videoOrientation
func videoOrientation(for deviceOrientation: UIDeviceOrientation) -> AVCaptureVideoOrientation
switch deviceOrientation
case UIDeviceOrientation.portrait:
return AVCaptureVideoOrientation.portrait
case UIDeviceOrientation.landscapeLeft:
return AVCaptureVideoOrientation.landscapeRight
case UIDeviceOrientation.landscapeRight:
return AVCaptureVideoOrientation.landscapeLeft
case UIDeviceOrientation.portraitUpsideDown:
return AVCaptureVideoOrientation.portraitUpsideDown
default:
return AVCaptureVideoOrientation.portrait
就在下面一行
if let videoConnection = stillImageOutput.connectionWithMediaType(AVMediaTypeVideo)
添加以下行
videoConnection.videoOrientation = videoOrientation(for: UIDevice.current.orientation)
注意:如果您的应用仅支持纵向或横向模式,此问题仍然会发生,因为UIDevice.current.orientation
将始终返回支持的方向。为了克服这个问题,您可以使用CoreMotion
来检测设备方向,然后将其传递给videoOrientation(for:)
方法。
希望这会有所帮助:)
【讨论】:
对于当前的 swift 版本,我做了一些小改动,但效果很好,我把它放在我的拍照功能中【参考方案2】:我从@Yodagama 得到了答案,但他没有添加如何检测方向
if let photoOutputConnection = self.photoOutput.connection(with: .video)
// USE the below function HERE
photoOutputConnection.videoOrientation = videoOrientation()
photoOutput.capturePhoto(with: settings, delegate: self)
检测设备方向的功能:
func videoOrientation() -> AVCaptureVideoOrientation
var videoOrientation: AVCaptureVideoOrientation!
let orientation: UIDeviceOrientation = UIDevice.current.orientation
switch orientation
case .faceUp, .faceDown, .unknown:
// let interfaceOrientation = UIApplication.shared.statusBarOrientation
if let interfaceOrientation = UIApplication.shared.windows.first(where: $0.isKeyWindow )?.windowScene?.interfaceOrientation
switch interfaceOrientation
case .portrait, .portraitUpsideDown, .unknown:
videoOrientation = .portrait
case .landscapeLeft:
videoOrientation = .landscapeRight
case .landscapeRight:
videoOrientation = .landscapeLeft
@unknown default:
videoOrientation = .portrait
case .portrait, .portraitUpsideDown:
videoOrientation = .portrait
case .landscapeLeft:
videoOrientation = .landscapeRight
case .landscapeRight:
videoOrientation = .landscapeLeft
@unknown default:
videoOrientation = .portrait
return videoOrientation
【讨论】:
【参考方案3】:可能的解决方案:将图像保存为 JPEG 而不是 PNG
这是因为 PNG 不存储方向信息。将照片另存为 JPG,它的方向会正确。
使用此代码在拍摄图像后立即将图像转换为 JPG(第二行是此处的操作):
let image = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(sampleBuffer)
let imageData:NSData = UIImageJPEGRepresentation(image, 0.9)! // 0.9 is compression value: 0.0 is most compressed/lowest quality and 1.0 is least compressed/highest quality
来源+更多信息:https://***.com/a/34796890/5700898
如果这不起作用
我已经在几个地方编辑了你的代码,看看下面的代码现在是否能如你所愿:
// initialize saving photo capabilities
func image(image: UIImage, didFinishSavingWithError error: NSError?, contextInfo:UnsafePointer<Void>)
if error == nil
print("image saved")
else
print("save error: \(error?.localizedDescription)")
// take a photo
@IBAction func takePhoto(sender: AnyObject)
self.fullScreenView.hidden = false
self.recordButton.enabled = false
self.takephoto.enabled = false
self.recordButton.hidden = true
self.takephoto.hidden = true
session.startRunning()
// customize the quality level or bitrate of the output photo
session.sessionPreset = AVCaptureSessionPresetPhoto
// add the AVCaptureVideoPreviewLayer to the view and set the view in fullscreen
fullScreenView.frame = view.bounds
videoPreviewLayer.frame = fullScreenView.bounds
fullScreenView.layer.addSublayer(videoPreviewLayer)
// add action to fullScreenView
gestureFullScreenView = UITapGestureRecognizer(target: self, action: #selector(ViewController.takePhoto(_:)))
self.fullScreenView.addGestureRecognizer(gestureFullScreenView)
// add action to myView
gestureView = UITapGestureRecognizer(target: self, action: #selector(ViewController.setFrontpage(_:)))
self.view.addGestureRecognizer(gestureView)
if (preview == true)
if let videoConnection = stillImageOutput!.connectionWithMediaType(AVMediaTypeVideo)
// code for photo capture goes here...
stillImageOutput?.captureStillImageAsynchronouslyFromConnection(videoConnection, completionHandler: (sampleBuffer, error) -> Void in
// process the image data (sampleBuffer) here to get an image file we can put in our view
if (sampleBuffer != nil)
self.stillImageOutput!.outputSettings = [AVVideoCodecKey: AVVideoCodecJPEG]
if let videoConnection = self.stillImageOutput!.connectionWithMediaType(AVMediaTypeVideo)
videoConnection.videoOrientation = self.interfaceToVideoOrientation()
self.stillImageOutput!.captureStillImageAsynchronouslyFromConnection(videoConnection, completionHandler:
(sampleBuffer, error) in
let imageData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(sampleBuffer)
let image = UIImage(data: imageData)
self.fullScreenView.hidden = true
self.fullScreenView.gestureRecognizers?.forEach(self.fullScreenView.removeGestureRecognizer)
self.session.stopRunning()
// save image to the library
UIImageWriteToSavedPhotosAlbum(image, self, #selector(ViewController.image(_:didFinishSavingWithError:contextInfo:)), nil)
self.imageViewBackground = UIImageView(frame: self.view.bounds)
self.imageViewBackground.image = image
self.imageViewBackground.tag = self.key
self.view.addSubview(self.imageViewBackground)
)
else
preview = true
【讨论】:
我想我把它保存为 JPEG 还是我错了?let imageData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(sampleBuffer)
@mafioso 尝试将您的 imageData 声明更改为我在上面所做的声明,我不确定您的是否有效。如果那不能解决您的问题,我会更深入地研究;)。请告诉我。
好的,我会试试的 ;) 但我仍然不知道为什么它在纵向模式下完美地工作,而不是在横向模式下
我应该如何处理 imageData ?
将项目中的这行代码 (let imageData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(sampleBuffer)
) 替换为我在上面的答案中输入的行,@mafioso。以上是关于相机仅在人像模式下快速拍照的主要内容,如果未能解决你的问题,请参考以下文章