Avcapture Image Orientation

AVCAPTURE image orientation

When creating the image from a portrait orientation device, you should consider that a UIImage that has been rotated 90 degrees, e.g.:

switch UIApplication.shared.statusBarOrientation {
case .portrait:
image = UIImage(cgImage: cgImageRef, scale: 1.0, orientation: .right)
case .landscapeRight:
image = UIImage(cgImage: cgImageRef, scale: 1.0, orientation: .up)
case .landscapeLeft:
image = UIImage(cgImage: cgImageRef, scale: 1.0, orientation: .down)
case .portraitUpsideDown:
image = UIImage(cgImage: cgImageRef, scale: 1.0, orientation: .left)
default:
fatalError("Unexpected orientation")
}

For a complete example, see:

import UIKit
import AVFoundation

class ViewController: UIViewController {

@IBOutlet weak var imageView: UIImageView!
@IBOutlet weak var videoPreviewView: UIView!
var videoPreviewLayer: AVCaptureVideoPreviewLayer!

var session: AVCaptureSession = AVCaptureSession()
var stillImageOutput: AVCaptureStillImageOutput = {
let output = AVCaptureStillImageOutput()
output.outputSettings = [AVVideoCodecKey: AVVideoCodecJPEG]
return output
}()

var images: [UIImage] = [UIImage]()

var orientation = UIApplication.shared.statusBarOrientation

override func viewDidLoad() {
super.viewDidLoad()

guard let device = AVCaptureDevice.default(for: .video) else {
print("Unable to create capture device")
return
}

let input: AVCaptureDeviceInput
do {
input = try AVCaptureDeviceInput(device: device)
} catch {
print("Unable to create input", error)
return
}

guard session.canAddInput(input) else {
print("Cannot add input")
return
}
session.addInput(input)

guard session.canAddOutput(stillImageOutput) else {
print("Cannot add output")
return
}
session.addOutput(stillImageOutput)

session.startRunning()
videoPreviewLayer = AVCaptureVideoPreviewLayer(session: session)
videoPreviewView.layer.addSublayer(videoPreviewLayer)
}

@IBAction func didTapCaptureButton(_ sender: Any) {
if let connection = stillImageOutput.connection(with: .video) {
stillImageOutput.captureStillImageAsynchronously(from: connection) { sampleBuffer, error in
guard let sampleBuffer = sampleBuffer, error == nil else {
print(error ?? "Unknown error")
return
}

guard
let imageData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(sampleBuffer),
let dataProvider = CGDataProvider(data: imageData as CFData),
let cgImageRef = CGImage(jpegDataProviderSource: dataProvider, decode: nil, shouldInterpolate: true, intent: .defaultIntent) else {
print("unable to capture image")
return
}

var image: UIImage?

switch self.orientation {
case .portrait:
image = UIImage(cgImage: cgImageRef, scale: 1.0, orientation: .right)
case .landscapeRight:
image = UIImage(cgImage: cgImageRef, scale: 1.0, orientation: .up)
case .landscapeLeft:
image = UIImage(cgImage: cgImageRef, scale: 1.0, orientation: .down)
case .portraitUpsideDown:
image = UIImage(cgImage: cgImageRef, scale: 1.0, orientation: .left)
default:
fatalError("Unexpected orientation")
}

guard image != nil else {
print("unable to create UIImage")
return
}

DispatchQueue.main.async {
self.images.append(image!)
self.imageView.image = image
}
}

}
}

override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()

if let connection = self.videoPreviewLayer?.connection {
orientation = UIApplication.shared.statusBarOrientation

switch orientation {
case .portrait: updatePreviewOrientation(for: connection, to: .portrait)
case .landscapeRight: updatePreviewOrientation(for: connection, to: .landscapeRight)
case .landscapeLeft: updatePreviewOrientation(for: connection, to: .landscapeLeft)
case .portraitUpsideDown: updatePreviewOrientation(for: connection, to: .portraitUpsideDown)
default: updatePreviewOrientation(for: connection, to: .portrait)
}
}
}

private func updatePreviewOrientation(for connection: AVCaptureConnection, to orientation: AVCaptureVideoOrientation) {
if connection.isVideoOrientationSupported {
connection.videoOrientation = orientation
}
videoPreviewLayer.frame = videoPreviewView.bounds
}
}

You are manually converting the image orientation in fixOrientation. Once you create UIImage from CGImage using the appropriate orientation, you don't have to mess around with recreating the image if you don't want.

Swift - AVFoundation capture image orientation

You need to run the following code before calling capturePhoto()

if let photoOutputConnection = CustomCamera.photoOutput.connection(with: AVMediaType.video) {
photoOutputConnection.videoOrientation = videoDeviceOrientation
}

You could use your managePhotoOrientation() function to get videoDeviceOrientation.

AVCaptureSession rotate | orientation while video transmitting

Thanks for looking into it, basically the solution is, orientation of connection should be set, and i was playing with the preview layer, so its affecting the preview layer but not the orientation.

here goes the code snippet

-(void) orientationChanged
{
// get the new orientation from device
AVCaptureVideoOrientation newOrientation = [self videoOrientationFromDeviceOrientation];

// set the orientation of preview layer :( which will be displayed in the device )
[previewLayer.connection setVideoOrientation:newOrientation];

// set the orientation of the connection: which will take care of capture
[pCaptureConnection setVideoOrientation:newOrientation];

}

iOS get Camera orientation

AVCaptureConnection has the videoOrientation property.

You can also try using device orientation, if you need to transform photo output somehow. Here you can find some instruction, how to work with device orientation if you need.



Related Topics



Leave a reply



Submit