I have a custom camera which takes photo in portrait mode.
My issue is that if i try to take a photo in landscape and save it then the picture is still saved in portrait mode.
I have this function to setup the 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)
}
And I Call this in viewWillAppear (Which I believe is not the right way to do).
I then take the photo:
@IBAction func takePhotoBtnPressed(_ sender: Any) {
let settings = AVCapturePhotoSettings()
useFlash(settings: settings)
settings.isAutoStillImageStabilizationEnabled = true
CustomCamera.photoOutput?.capturePhoto(with: settings, delegate: self)
}
and use this extension:
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)
}
}
}
Everything works fine as long as i shot a portrait mode photo but when i rotate the phone to shot a landscape photo then the the photo is still shot in portrait.
It is the first time i work with a custom camera and I really don't know where to start to fix this... If anybody could help i would really appreciate it.
Thank you!
---------------UPDATE I have added this function:
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
}
And changed my extension to this:
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)
}
}
}
The image is shown in the preview in the right orientation but then when i save it it goes to portrait...
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.
I had a similar issue and fixed it by generating a new image based on the taken photo:
UIGraphicsBeginImageContextWithOptions(image.size, false, image.scale)
image.draw(in: CGRect(origin: .zero, size: image.size))
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
Apparently the image metadata (which includes the orientation) produced by iOS is incomplete and some viewers (in my case Chrome and Safari browsers) fail to render the image correctly. By re-rendering, the metadata seems to be set correctly for all viewers.
Note that 1) in my app I also downscale the image (I don't think this changes the effect though) and 2) I capture the image by other means (i.e. UIImagePickerController
); still, you might give my hacky fix a try.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With