Swift - AVFoundation 捕获图像方向
Swift - AVFoundation capture image orientation
我有一个自定义相机,可以在人像模式下拍照。
我的问题是,如果我尝试拍摄横向照片并保存,那么照片仍然以纵向模式保存。
我有这个功能来设置 previewLayer:
static func setupPreviewLayer(view: UIView) {
cameraPreviewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
cameraPreviewLayer?.videoGravity = AVLayerVideoGravity.resizeAspectFill
switch UIDevice.current.orientation {
case .portrait:
cameraPreviewLayer?.connection?.videoOrientation =
AVCaptureVideoOrientation.portrait
case .portraitUpsideDown:
cameraPreviewLayer?.connection?.videoOrientation =
AVCaptureVideoOrientation.portraitUpsideDown
case .landscapeLeft:
cameraPreviewLayer?.connection?.videoOrientation =
AVCaptureVideoOrientation.landscapeLeft
case .landscapeRight:
cameraPreviewLayer?.connection?.videoOrientation =
AVCaptureVideoOrientation.landscapeRight
default:
cameraPreviewLayer?.connection?.videoOrientation =
AVCaptureVideoOrientation.portrait
}
cameraPreviewLayer?.frame = view.frame
view.layer.insertSublayer(cameraPreviewLayer!, at: 0)
}
我在 viewWillAppear 中调用它(我认为这不是正确的做法)。
我接着拍照:
@IBAction func takePhotoBtnPressed(_ sender: Any) {
let settings = AVCapturePhotoSettings()
useFlash(settings: settings)
settings.isAutoStillImageStabilizationEnabled = true
CustomCamera.photoOutput?.capturePhoto(with: settings, delegate: self)
}
并使用此扩展名:
extension FishCameraVC: AVCapturePhotoCaptureDelegate {
func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {
if let imageData = photo.fileDataRepresentation() {
image = UIImage(data: imageData)
performSegue(withIdentifier: "ShowTakenPhoto", sender: nil)
}
}
}
只要我拍摄肖像模式照片一切正常,但是当我旋转 phone 拍摄风景照片时,照片仍然是肖像拍摄。
这是我第一次使用自定义相机,我真的不知道从哪里开始解决这个问题...
如果有人能提供帮助,我将不胜感激。
谢谢!
----------------更新
我添加了这个功能:
func managePhotoOrientation() -> UIImageOrientation {
var currentDevice: UIDevice
currentDevice = .current
UIDevice.current.beginGeneratingDeviceOrientationNotifications()
var deviceOrientation: UIDeviceOrientation
deviceOrientation = currentDevice.orientation
var imageOrientation: UIImageOrientation!
if deviceOrientation == .portrait {
imageOrientation = .up
print("Device: Portrait")
}else if (deviceOrientation == .landscapeLeft){
imageOrientation = .left
print("Device: LandscapeLeft")
}else if (deviceOrientation == .landscapeRight){
imageOrientation = .right
CustomCamera.cameraPreviewLayer?.connection?.videoOrientation = .landscapeRight
print("Device LandscapeRight")
}else if (deviceOrientation == .portraitUpsideDown){
imageOrientation = .down
print("Device PortraitUpsideDown")
}else{
imageOrientation = .up
}
return imageOrientation
}
并将我的扩展名更改为:
extension FishCameraVC: AVCapturePhotoCaptureDelegate {
func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {
if let imageData = photo.fileDataRepresentation() {
image = UIImage(data: imageData)
let dataProvider = CGDataProvider(data: imageData as CFData)
let cgImageRef = CGImage(jpegDataProviderSource: dataProvider!, decode: nil, shouldInterpolate: true, intent: .defaultIntent)
self.image = UIImage(cgImage: cgImageRef!, scale: 1.0, orientation: imageOrientation!)
performSegue(withIdentifier: "ShowTakenPhoto", sender: nil)
}
}
}
图像在预览中以正确的方向显示,但当我保存它时它会变成纵向...
我遇到了类似的问题,并通过根据拍摄的照片生成新图像解决了这个问题:
UIGraphicsBeginImageContextWithOptions(image.size, false, image.scale)
image.draw(in: CGRect(origin: .zero, size: image.size))
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
显然 iOS 生成的图像元数据(包括方向)不完整,一些查看器(在我的情况下 Chrome 和 Safari 浏览器)无法正确呈现图像。通过重新呈现,元数据似乎已为所有查看器正确设置。
请注意,1) 在我的应用程序中,我还缩小了图像尺寸(不过我认为这不会改变效果)和 2) 我通过其他方式捕捉图像(即 UIImagePickerController
);尽管如此,你还是可以试试我的 hacky 修复程序。
调用 capturePhoto() 前需要运行以下代码
if let photoOutputConnection = CustomCamera.photoOutput.connection(with: AVMediaType.video) {
photoOutputConnection.videoOrientation = videoDeviceOrientation
}
您可以使用 managePhotoOrientation() 函数来获取 videoDeviceOrientation。
Swift AVFoundation 捕获图像方向的 4.2 最新语法(已测试代码)。
UIGraphicsBeginImageContextWithOptions((image?.size)!, false, (image?.scale)!)
image?.draw(in: CGRect(origin: .zero, size: (image?.size)!))
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
基于dr_barto源代码,我为UIImage写了一个扩展:
extension UIImage {
var orientationCorrectedImage: UIImage? {
UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale)
self.draw(in: CGRect(origin: .zero, size: self.size))
let result = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return result
}
}
我有一个自定义相机,可以在人像模式下拍照。
我的问题是,如果我尝试拍摄横向照片并保存,那么照片仍然以纵向模式保存。
我有这个功能来设置 previewLayer:
static func setupPreviewLayer(view: UIView) {
cameraPreviewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
cameraPreviewLayer?.videoGravity = AVLayerVideoGravity.resizeAspectFill
switch UIDevice.current.orientation {
case .portrait:
cameraPreviewLayer?.connection?.videoOrientation =
AVCaptureVideoOrientation.portrait
case .portraitUpsideDown:
cameraPreviewLayer?.connection?.videoOrientation =
AVCaptureVideoOrientation.portraitUpsideDown
case .landscapeLeft:
cameraPreviewLayer?.connection?.videoOrientation =
AVCaptureVideoOrientation.landscapeLeft
case .landscapeRight:
cameraPreviewLayer?.connection?.videoOrientation =
AVCaptureVideoOrientation.landscapeRight
default:
cameraPreviewLayer?.connection?.videoOrientation =
AVCaptureVideoOrientation.portrait
}
cameraPreviewLayer?.frame = view.frame
view.layer.insertSublayer(cameraPreviewLayer!, at: 0)
}
我在 viewWillAppear 中调用它(我认为这不是正确的做法)。
我接着拍照:
@IBAction func takePhotoBtnPressed(_ sender: Any) {
let settings = AVCapturePhotoSettings()
useFlash(settings: settings)
settings.isAutoStillImageStabilizationEnabled = true
CustomCamera.photoOutput?.capturePhoto(with: settings, delegate: self)
}
并使用此扩展名:
extension FishCameraVC: AVCapturePhotoCaptureDelegate {
func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {
if let imageData = photo.fileDataRepresentation() {
image = UIImage(data: imageData)
performSegue(withIdentifier: "ShowTakenPhoto", sender: nil)
}
}
}
只要我拍摄肖像模式照片一切正常,但是当我旋转 phone 拍摄风景照片时,照片仍然是肖像拍摄。
这是我第一次使用自定义相机,我真的不知道从哪里开始解决这个问题... 如果有人能提供帮助,我将不胜感激。
谢谢!
----------------更新 我添加了这个功能:
func managePhotoOrientation() -> UIImageOrientation {
var currentDevice: UIDevice
currentDevice = .current
UIDevice.current.beginGeneratingDeviceOrientationNotifications()
var deviceOrientation: UIDeviceOrientation
deviceOrientation = currentDevice.orientation
var imageOrientation: UIImageOrientation!
if deviceOrientation == .portrait {
imageOrientation = .up
print("Device: Portrait")
}else if (deviceOrientation == .landscapeLeft){
imageOrientation = .left
print("Device: LandscapeLeft")
}else if (deviceOrientation == .landscapeRight){
imageOrientation = .right
CustomCamera.cameraPreviewLayer?.connection?.videoOrientation = .landscapeRight
print("Device LandscapeRight")
}else if (deviceOrientation == .portraitUpsideDown){
imageOrientation = .down
print("Device PortraitUpsideDown")
}else{
imageOrientation = .up
}
return imageOrientation
}
并将我的扩展名更改为:
extension FishCameraVC: AVCapturePhotoCaptureDelegate {
func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {
if let imageData = photo.fileDataRepresentation() {
image = UIImage(data: imageData)
let dataProvider = CGDataProvider(data: imageData as CFData)
let cgImageRef = CGImage(jpegDataProviderSource: dataProvider!, decode: nil, shouldInterpolate: true, intent: .defaultIntent)
self.image = UIImage(cgImage: cgImageRef!, scale: 1.0, orientation: imageOrientation!)
performSegue(withIdentifier: "ShowTakenPhoto", sender: nil)
}
}
}
图像在预览中以正确的方向显示,但当我保存它时它会变成纵向...
我遇到了类似的问题,并通过根据拍摄的照片生成新图像解决了这个问题:
UIGraphicsBeginImageContextWithOptions(image.size, false, image.scale)
image.draw(in: CGRect(origin: .zero, size: image.size))
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
显然 iOS 生成的图像元数据(包括方向)不完整,一些查看器(在我的情况下 Chrome 和 Safari 浏览器)无法正确呈现图像。通过重新呈现,元数据似乎已为所有查看器正确设置。
请注意,1) 在我的应用程序中,我还缩小了图像尺寸(不过我认为这不会改变效果)和 2) 我通过其他方式捕捉图像(即 UIImagePickerController
);尽管如此,你还是可以试试我的 hacky 修复程序。
调用 capturePhoto() 前需要运行以下代码
if let photoOutputConnection = CustomCamera.photoOutput.connection(with: AVMediaType.video) {
photoOutputConnection.videoOrientation = videoDeviceOrientation
}
您可以使用 managePhotoOrientation() 函数来获取 videoDeviceOrientation。
Swift AVFoundation 捕获图像方向的 4.2 最新语法(已测试代码)。
UIGraphicsBeginImageContextWithOptions((image?.size)!, false, (image?.scale)!)
image?.draw(in: CGRect(origin: .zero, size: (image?.size)!))
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
基于dr_barto源代码,我为UIImage写了一个扩展:
extension UIImage {
var orientationCorrectedImage: UIImage? {
UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale)
self.draw(in: CGRect(origin: .zero, size: self.size))
let result = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return result
}
}