结果图像方向的 AVFoundation CaptureStillImage 问题
AVFoundation CaptureStillImage issue with orientation of result image
我有一个自定义相机视图控制器,它使用 AVFoundation 来捕捉静止图像,您可以在此处看到:
我的问题是,一旦拍摄图像,方向总是横向的,您可以在此处看到
我的代码如下:
var captureInput: AVCaptureInput?
var stillImageOutput: AVCaptureStillImageOutput?
var previewLayer: AVCaptureVideoPreviewLayer?
var currentDevice: AVCaptureDevice?
var currentLayer: AVCaptureVideoPreviewLayer?
@IBAction func captureButtonTap(sender: UIButton) {
if(!capturingPhoto){
capturingPhoto = true
if let videoConnection = stillImageOutput!.connectionWithMediaType(AVMediaTypeVideo) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
videoConnection.videoOrientation = AVCaptureVideoOrientation.Portrait
self.stillImageOutput?.captureStillImageAsynchronouslyFromConnection(videoConnection, completionHandler: {(sampleBuffer, error) in
if (sampleBuffer != nil) {
var imageData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(sampleBuffer)
var image = UIImage(data: imageData)
var imageWidth = image?.size.width
var cropRect = CGRect(x: 0, y: 0, width: imageWidth!, height: imageWidth!)
var imageRef: CGImageRef = CGImageCreateWithImageInRect(image!.CGImage, cropRect)
var croppedImage: UIImage = UIImage(CGImage: imageRef)!
self.imagePreview.image = croppedImage
self.image = croppedImage
self.switchModeToPreview()
}
})
}
}
}
}
func initCameraSession(){
configureDevice()
NSLog(String(selectedCamera))
captureSession = AVCaptureSession()
captureSession!.sessionPreset = AVCaptureSessionPresetPhoto
if(selectedCamera == 0){
var backCamera = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
currentDevice = backCamera
}else if(selectedCamera == 1){
var frontCamera = frontCameraIfAvalible()
currentDevice = frontCamera
}
if(currentDevice == nil){
NSException(name: "Error", reason: "Device Has No Camera.", userInfo: nil)
}
updateButtons()
var error: NSError?
var input = AVCaptureDeviceInput(device: currentDevice, error: &error)
if error == nil && captureSession!.canAddInput(input) {
captureSession!.addInput(input)
captureInput = input
stillImageOutput = AVCaptureStillImageOutput()
stillImageOutput!.outputSettings = [AVVideoCodecKey: AVVideoCodecJPEG]
if captureSession!.canAddOutput(stillImageOutput) {
captureSession!.addOutput(stillImageOutput)
previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
previewLayer!.videoGravity = AVLayerVideoGravityResizeAspectFill
previewLayer!.connection?.videoOrientation = AVCaptureVideoOrientation.Portrait
cameraPreview.layer.addSublayer(previewLayer)
previewLayer?.frame = CGRect(x: 0.0, y: 0.0, width: self.view.bounds.width, height: self.view.bounds.width + 139)
if(currentLayer != nil){
currentLayer!.removeFromSuperlayer()
}
currentLayer = previewLayer!
captureSession!.startRunning()
}
}
}
请注意,我故意遗漏了一些代码,如果您需要更多信息,请提出要求。感谢您的帮助。
尝试使用类似这样的东西,当我旋转设备时,我用它来变换我视图中的按钮。这可以与拍摄的图像一起使用。回忆一下线性代数中的标准变换旋转矩阵,如果你曾经学过 class。基本上,只需更改此代码以旋转您捕获的图像的框架,然后确保将其框架边界设置回视图的框架,以便使其正确适合视图。这可能比需要的更复杂,但我以前从未遇到过图像问题。请记住,这是由于已注册的旋转更改观察器而被调用的,您可能不需要使用它。但是这个基本概念被使用了很多
每当我遇到旋转问题时,我都会使用它。
/**************************************************************************
DEVICE ORIENTATION DID CHANGE
**************************************************************************/
func deviceOrientationDidChange() {
println("DEVICE ORIENTATION DID CHANGE CALLED")
let orientation: UIDeviceOrientation = UIDevice.currentDevice().orientation
//------ IGNORE THESE ORIENTATIONS ------
if orientation == UIDeviceOrientation.FaceUp || orientation == UIDeviceOrientation.FaceDown || orientation == UIDeviceOrientation.Unknown || orientation == UIDeviceOrientation.PortraitUpsideDown || self.currentOrientation == orientation {
println("device orientation does not need to change --- returning...")
return
}
self.currentOrientation = orientation
//------ APPLY A ROTATION USING THE STANDARD ROTATION TRANSFORMATION MATRIX in R3 ------
/*
x y z
--- ---
x | cosø sinø 0 |
y | -sinø consø 0 |
z | 0 0 1 |
--- ---
*/
//----- PERFORM BUTTON AND VIDEO DATA BUFFER ROTATIONS ------
switch orientation {
case UIDeviceOrientation.Portrait:
println("Device Orientation Portrait")
if self.usingFrontCamera == true {
}
else {
self.playBackTransformation = CGAffineTransformMakeRotation(self.degrees0)
self.switchCaptureSession.transform = self.playBackTransformation!
self.switchCaptureSession.frame = self.view.bounds
self.flipCamera.transform = self.playBackTransformation!
self.flipCamera.frame = self.view.bounds
self.captureButton.transform = self.playBackTransformation!
self.captureButton.frame = self.view.bounds
}
break
case UIDeviceOrientation.LandscapeLeft:
println("Device Orientation LandScapeLeft")
if self.usingFrontCamera == true {
}
else {
self.playBackTransformation = CGAffineTransformMakeRotation(CGFloat(self.degrees90))
self.switchCaptureSession.transform = self.playBackTransformation!
self.switchCaptureSession.frame = self.view.bounds
self.flipCamera.transform = self.playBackTransformation!
self.flipCamera.frame = self.view.bounds
self.captureButton.transform = self.playBackTransformation!
self.captureButton.frame = self.view.bounds
}
break
case UIDeviceOrientation.LandscapeRight:
println("Device Orientation LandscapeRight")
if self.usingFrontCamera == true {
}
else {
self.playBackTransformation = CGAffineTransformMakeRotation(-self.degrees90)
self.switchCaptureSession.transform = self.playBackTransformation!
self.switchCaptureSession.frame = self.view.bounds
self.flipCamera.transform = self.playBackTransformation!
self.flipCamera.frame = self.view.bounds
self.captureButton.transform = self.playBackTransformation!
self.captureButton.frame = self.view.bounds
}
break
default:
break
}
仿射变换非常适合旋转。可能有一个功能可以在捕获时设置默认图像方向。查看 Apple 的参考资料。
我有一个自定义相机视图控制器,它使用 AVFoundation 来捕捉静止图像,您可以在此处看到:
我的问题是,一旦拍摄图像,方向总是横向的,您可以在此处看到
我的代码如下:
var captureInput: AVCaptureInput?
var stillImageOutput: AVCaptureStillImageOutput?
var previewLayer: AVCaptureVideoPreviewLayer?
var currentDevice: AVCaptureDevice?
var currentLayer: AVCaptureVideoPreviewLayer?
@IBAction func captureButtonTap(sender: UIButton) {
if(!capturingPhoto){
capturingPhoto = true
if let videoConnection = stillImageOutput!.connectionWithMediaType(AVMediaTypeVideo) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
videoConnection.videoOrientation = AVCaptureVideoOrientation.Portrait
self.stillImageOutput?.captureStillImageAsynchronouslyFromConnection(videoConnection, completionHandler: {(sampleBuffer, error) in
if (sampleBuffer != nil) {
var imageData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(sampleBuffer)
var image = UIImage(data: imageData)
var imageWidth = image?.size.width
var cropRect = CGRect(x: 0, y: 0, width: imageWidth!, height: imageWidth!)
var imageRef: CGImageRef = CGImageCreateWithImageInRect(image!.CGImage, cropRect)
var croppedImage: UIImage = UIImage(CGImage: imageRef)!
self.imagePreview.image = croppedImage
self.image = croppedImage
self.switchModeToPreview()
}
})
}
}
}
}
func initCameraSession(){
configureDevice()
NSLog(String(selectedCamera))
captureSession = AVCaptureSession()
captureSession!.sessionPreset = AVCaptureSessionPresetPhoto
if(selectedCamera == 0){
var backCamera = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
currentDevice = backCamera
}else if(selectedCamera == 1){
var frontCamera = frontCameraIfAvalible()
currentDevice = frontCamera
}
if(currentDevice == nil){
NSException(name: "Error", reason: "Device Has No Camera.", userInfo: nil)
}
updateButtons()
var error: NSError?
var input = AVCaptureDeviceInput(device: currentDevice, error: &error)
if error == nil && captureSession!.canAddInput(input) {
captureSession!.addInput(input)
captureInput = input
stillImageOutput = AVCaptureStillImageOutput()
stillImageOutput!.outputSettings = [AVVideoCodecKey: AVVideoCodecJPEG]
if captureSession!.canAddOutput(stillImageOutput) {
captureSession!.addOutput(stillImageOutput)
previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
previewLayer!.videoGravity = AVLayerVideoGravityResizeAspectFill
previewLayer!.connection?.videoOrientation = AVCaptureVideoOrientation.Portrait
cameraPreview.layer.addSublayer(previewLayer)
previewLayer?.frame = CGRect(x: 0.0, y: 0.0, width: self.view.bounds.width, height: self.view.bounds.width + 139)
if(currentLayer != nil){
currentLayer!.removeFromSuperlayer()
}
currentLayer = previewLayer!
captureSession!.startRunning()
}
}
}
请注意,我故意遗漏了一些代码,如果您需要更多信息,请提出要求。感谢您的帮助。
尝试使用类似这样的东西,当我旋转设备时,我用它来变换我视图中的按钮。这可以与拍摄的图像一起使用。回忆一下线性代数中的标准变换旋转矩阵,如果你曾经学过 class。基本上,只需更改此代码以旋转您捕获的图像的框架,然后确保将其框架边界设置回视图的框架,以便使其正确适合视图。这可能比需要的更复杂,但我以前从未遇到过图像问题。请记住,这是由于已注册的旋转更改观察器而被调用的,您可能不需要使用它。但是这个基本概念被使用了很多
每当我遇到旋转问题时,我都会使用它。
/**************************************************************************
DEVICE ORIENTATION DID CHANGE
**************************************************************************/
func deviceOrientationDidChange() {
println("DEVICE ORIENTATION DID CHANGE CALLED")
let orientation: UIDeviceOrientation = UIDevice.currentDevice().orientation
//------ IGNORE THESE ORIENTATIONS ------
if orientation == UIDeviceOrientation.FaceUp || orientation == UIDeviceOrientation.FaceDown || orientation == UIDeviceOrientation.Unknown || orientation == UIDeviceOrientation.PortraitUpsideDown || self.currentOrientation == orientation {
println("device orientation does not need to change --- returning...")
return
}
self.currentOrientation = orientation
//------ APPLY A ROTATION USING THE STANDARD ROTATION TRANSFORMATION MATRIX in R3 ------
/*
x y z
--- ---
x | cosø sinø 0 |
y | -sinø consø 0 |
z | 0 0 1 |
--- ---
*/
//----- PERFORM BUTTON AND VIDEO DATA BUFFER ROTATIONS ------
switch orientation {
case UIDeviceOrientation.Portrait:
println("Device Orientation Portrait")
if self.usingFrontCamera == true {
}
else {
self.playBackTransformation = CGAffineTransformMakeRotation(self.degrees0)
self.switchCaptureSession.transform = self.playBackTransformation!
self.switchCaptureSession.frame = self.view.bounds
self.flipCamera.transform = self.playBackTransformation!
self.flipCamera.frame = self.view.bounds
self.captureButton.transform = self.playBackTransformation!
self.captureButton.frame = self.view.bounds
}
break
case UIDeviceOrientation.LandscapeLeft:
println("Device Orientation LandScapeLeft")
if self.usingFrontCamera == true {
}
else {
self.playBackTransformation = CGAffineTransformMakeRotation(CGFloat(self.degrees90))
self.switchCaptureSession.transform = self.playBackTransformation!
self.switchCaptureSession.frame = self.view.bounds
self.flipCamera.transform = self.playBackTransformation!
self.flipCamera.frame = self.view.bounds
self.captureButton.transform = self.playBackTransformation!
self.captureButton.frame = self.view.bounds
}
break
case UIDeviceOrientation.LandscapeRight:
println("Device Orientation LandscapeRight")
if self.usingFrontCamera == true {
}
else {
self.playBackTransformation = CGAffineTransformMakeRotation(-self.degrees90)
self.switchCaptureSession.transform = self.playBackTransformation!
self.switchCaptureSession.frame = self.view.bounds
self.flipCamera.transform = self.playBackTransformation!
self.flipCamera.frame = self.view.bounds
self.captureButton.transform = self.playBackTransformation!
self.captureButton.frame = self.view.bounds
}
break
default:
break
}
仿射变换非常适合旋转。可能有一个功能可以在捕获时设置默认图像方向。查看 Apple 的参考资料。