Ios 从摄像头拍摄的iphone图像会自动快速旋转
通过编程,我已经在我的应用程序中从相机中捕获了图像。它已经被很好地抓取了,但是当我切换到另一个视图时,查看并关闭该视图,此时我想将图像旋转到风景中。我用照相机拍下了照片。当我从照片库中获取图像时,没有发现任何问题 以下图像是我的原始图像。 我想旋转图像。 下面的代码:Ios 从摄像头拍摄的iphone图像会自动快速旋转,ios,swift,xcode,camera,Ios,Swift,Xcode,Camera,通过编程,我已经在我的应用程序中从相机中捕获了图像。它已经被很好地抓取了,但是当我切换到另一个视图时,查看并关闭该视图,此时我想将图像旋转到风景中。我用照相机拍下了照片。当我从照片库中获取图像时,没有发现任何问题 以下图像是我的原始图像。 我想旋转图像。 下面的代码: var captureSesssion : AVCaptureSession! var cameraOutput : AVCapturePhotoOutput! var previewLayer : AVCaptureVide
var captureSesssion : AVCaptureSession!
var cameraOutput : AVCapturePhotoOutput!
var previewLayer : AVCaptureVideoPreviewLayer!
var device:AVCaptureDevice!
var currentViewControl = UIViewController()
var tempImageHolder = UIImage()
func beginCamera(_ targetView: UIView, _ currentVC: UIViewController)
{
currentViewControl = currentVC
// Do any additional setup after loading the view, typically from a nib.
captureSesssion = AVCaptureSession()
captureSesssion.sessionPreset = AVCaptureSession.Preset.photo
cameraOutput = AVCapturePhotoOutput()
if #available(iOS 11.1, *) {
let availableDevices = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInWideAngleCamera, .builtInTelephotoCamera, .builtInTrueDepthCamera], mediaType: AVMediaType.video, position: .back).devices
device = availableDevices.first
} else {
// Fallback on earlier versions
device = AVCaptureDevice.default(for: .video)!
}
if let input = try? AVCaptureDeviceInput(device: device!) {
if (captureSesssion.canAddInput(input)) {
captureSesssion.addInput(input)
if (captureSesssion.canAddOutput(cameraOutput)) {
captureSesssion.addOutput(cameraOutput)
let connection = cameraOutput.connection(with: AVFoundation.AVMediaType.video)
connection?.videoOrientation = .portrait
previewLayer = AVCaptureVideoPreviewLayer(session: captureSesssion)
self.previewLayer.frame = targetView.frame
self.previewLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill
//setOutputOrientation()
targetView.layer.addSublayer(previewLayer)
captureSesssion.startRunning()
}
} else {
print("issue here : captureSesssion.canAddInput")
}
} else {
print("some problem here")
}
previewLayer?.frame.size = targetView.frame.size
}
func image(_ image: UIImage, didFinishSavingWithError error: Error?, contextInfo: UnsafeRawPointer) {
if let error = error {
// we got back an error!
let alert = UIAlertController(title: "Error", message: error.localizedDescription, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default))
currentViewControl.present(alert, animated: true)
} else {
}}
func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {
let imageData = photo.fileDataRepresentation()
let imageSize: Int = imageData!.count
print(imageSize)
tempImageHolder = UIImage(data: (imageData! as NSData) as Data)!
//When use this below line works fine when take images from left landscape, but when take images from right landscape image not show properly screen shot below:
tempImageHolder = UIImage(cgImage: tempImageHolder.cgImage!, scale: tempImageHolder.scale, orientation: .up)
}
}
从左侧风景拍摄图像时:
var captureSesssion : AVCaptureSession!
var cameraOutput : AVCapturePhotoOutput!
var previewLayer : AVCaptureVideoPreviewLayer!
var device:AVCaptureDevice!
var currentViewControl = UIViewController()
var tempImageHolder = UIImage()
func beginCamera(_ targetView: UIView, _ currentVC: UIViewController)
{
currentViewControl = currentVC
// Do any additional setup after loading the view, typically from a nib.
captureSesssion = AVCaptureSession()
captureSesssion.sessionPreset = AVCaptureSession.Preset.photo
cameraOutput = AVCapturePhotoOutput()
if #available(iOS 11.1, *) {
let availableDevices = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInWideAngleCamera, .builtInTelephotoCamera, .builtInTrueDepthCamera], mediaType: AVMediaType.video, position: .back).devices
device = availableDevices.first
} else {
// Fallback on earlier versions
device = AVCaptureDevice.default(for: .video)!
}
if let input = try? AVCaptureDeviceInput(device: device!) {
if (captureSesssion.canAddInput(input)) {
captureSesssion.addInput(input)
if (captureSesssion.canAddOutput(cameraOutput)) {
captureSesssion.addOutput(cameraOutput)
let connection = cameraOutput.connection(with: AVFoundation.AVMediaType.video)
connection?.videoOrientation = .portrait
previewLayer = AVCaptureVideoPreviewLayer(session: captureSesssion)
self.previewLayer.frame = targetView.frame
self.previewLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill
//setOutputOrientation()
targetView.layer.addSublayer(previewLayer)
captureSesssion.startRunning()
}
} else {
print("issue here : captureSesssion.canAddInput")
}
} else {
print("some problem here")
}
previewLayer?.frame.size = targetView.frame.size
}
func image(_ image: UIImage, didFinishSavingWithError error: Error?, contextInfo: UnsafeRawPointer) {
if let error = error {
// we got back an error!
let alert = UIAlertController(title: "Error", message: error.localizedDescription, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default))
currentViewControl.present(alert, animated: true)
} else {
}}
func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {
let imageData = photo.fileDataRepresentation()
let imageSize: Int = imageData!.count
print(imageSize)
tempImageHolder = UIImage(data: (imageData! as NSData) as Data)!
//When use this below line works fine when take images from left landscape, but when take images from right landscape image not show properly screen shot below:
tempImageHolder = UIImage(cgImage: tempImageHolder.cgImage!, scale: tempImageHolder.scale, orientation: .up)
}
}
输入:
输出:
从右侧风景拍摄图像时
输入:
输出:
当使用此选项时,从左侧横向拍摄图像时,上面的线条效果良好,但从右侧横向拍摄图像时,屏幕截图无法正确显示
有人能给我解释一下如何旋转图像吗。任何帮助都将不胜感激
提前谢谢
enum CGImageOrientation {
case up
case down
case left
case right
case upMirrored
case downMirrored
case leftMirrored
case rightMirrored
}
extension CGImage {
func orientImage(_ imageOrientation: CGImageOrientation) ->
CGImage? {
return orientImageWithTransform(imageOrientation).0
}
func orientImageWithTransform(_ imageOrientation: CGImageOrientation) -> (CGImage?, CGAffineTransform) {
var transform = CGAffineTransform.identity
if imageOrientation == .up { return (self.copy(), transform)}
let size = CGSize(width: width, height: height)
let newSize = [.left,.leftMirrored, .right, .rightMirrored].contains(imageOrientation)
? CGSize(width: size.height, height: size.width) : size
// Guard that we have color space and core graphics context.
guard let colorSpace = self.colorSpace,
// New graphic context uses transformed width and height.
let ctx = CGContext(data: nil, width: Int(newSize.width), height: Int(newSize.height),
bitsPerComponent: self.bitsPerComponent, bytesPerRow: 0,
space: colorSpace, bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue)
else { return (nil, transform)}
// OK, now the actual work of constructing transform and creating new image.
switch imageOrientation {
case .down, .downMirrored:
transform = transform.translatedBy(x: size.width, y: size.height)
transform = transform.rotated(by: CGFloat.pi)
break
case .left,.leftMirrored:
transform = transform.translatedBy(x: size.height, y: 0)
transform = transform.rotated(by: CGFloat.pi/2)
break
case .right, .rightMirrored:
transform = transform.translatedBy(x: 0, y: size.width)
transform = transform.rotated(by: -CGFloat.pi/2)
break
case .up, .upMirrored:
break
}
if [.upMirrored, .downMirrored,.leftMirrored, .rightMirrored].contains(imageOrientation) {
transform = transform.translatedBy(x: size.width, y: 0)
transform = transform.scaledBy(x: -1, y: 1)
}
ctx.concatenate(transform)
// Interestingly, drawing with the original width and height?!
// So width and height here are pre-transform.
ctx.draw(self, in: CGRect(x: 0, y: 0, width: size.width, height: size.height))
return (ctx.makeImage(), transform)
}
}
使用:-
var tempImage = imgae
guard let cgImage = imgae?.cgImage else {return}
if let orientedImage = cgImage.orientImage(.upMirrored) {
tempImage = UIImage(cgImage: orientedImage)
}
let image = UIImageView(image: tempImage)
}
使用:-
var tempImage = imgae
guard let cgImage = imgae?.cgImage else {return}
if let orientedImage = cgImage.orientImage(.upMirrored) {
tempImage = UIImage(cgImage: orientedImage)
}
let image = UIImageView(image: tempImage)
问题在于,在将
UIImage
转换为CGImage
时,您正在丢弃图像元数据(包括方向)。在访问其cgImage
属性之前,需要呈现一个新的UIImage
,如本文所示
问题在于,在将
UIImage
转换为CGImage
时,您正在丢弃图像元数据(包括方向)。在访问其cgImage
属性之前,需要呈现一个新的UIImage
,如本文所示
尝试以下功能以固定方向:
extension UIImage {
func makeFixOrientation() -> UIImage {
if self.imageOrientation == UIImage.Orientation.up {
return self
}
UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale)
self.draw(in: CGRect(x: 0, y: 0, width: self.size.width, height: self.size.height))
let normalizedImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
return normalizedImage;
}
}
尝试以下功能以固定方向:
extension UIImage {
func makeFixOrientation() -> UIImage {
if self.imageOrientation == UIImage.Orientation.up {
return self
}
UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale)
self.draw(in: CGRect(x: 0, y: 0, width: self.size.width, height: self.size.height))
let normalizedImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
return normalizedImage;
}
}
这是一个非常恼人的问题,我真的不敢相信AVFoundation没有更容易的解决方案。但在我的应用程序中,我通过保持当前的设备方向来实现这一点。当照片输出返回图像时,使用方向旋转图像,以确保所有内容都向上拍摄
class MyViewController: UIViewController {
var currentOrientation: UIDeviceOrientation = .portrait
override func viewDidLoad() {
NotificationCenter.default.addObserver(self, selector: #selector(orientationChanged), name: UIDevice.orientationDidChangeNotification, object: nil)
}
@objc func orientationChanged() {
currentOrientation = UIDevice.current.orientation
}
func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {
guard let img = photo.cgImageRepresentation()?.takeUnretainedValue() else { return }
let temp = CIImage(cgImage: img)
var ciImage = temp;
switch currentOrientation {
case .portrait:
ciImage = temp.oriented(forExifOrientation: 6)
case .landscapeRight:
ciImage = temp.oriented(forExifOrientation: 3)
case .landscapeLeft:
ciImage = temp.oriented(forExifOrientation: 1)
default:
break
}
guard let cgImage = CIContext(options: nil).createCGImage(ciImage, from: ciImage.extent) else { return }
let fixedImage = UIImage(cgImage: cgImage)
}
}
最后,根据您的需要使用fixedImage。请注意,我订阅了通知中心以更改方向。这是一个非常烦人的问题,我真的无法相信AVFoundation没有任何更方便我们的方法。但在我的应用程序中,我通过保持当前的设备方向来实现这一点。当照片输出返回图像时,使用方向旋转图像,以确保所有内容都向上拍摄
class MyViewController: UIViewController {
var currentOrientation: UIDeviceOrientation = .portrait
override func viewDidLoad() {
NotificationCenter.default.addObserver(self, selector: #selector(orientationChanged), name: UIDevice.orientationDidChangeNotification, object: nil)
}
@objc func orientationChanged() {
currentOrientation = UIDevice.current.orientation
}
func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {
guard let img = photo.cgImageRepresentation()?.takeUnretainedValue() else { return }
let temp = CIImage(cgImage: img)
var ciImage = temp;
switch currentOrientation {
case .portrait:
ciImage = temp.oriented(forExifOrientation: 6)
case .landscapeRight:
ciImage = temp.oriented(forExifOrientation: 3)
case .landscapeLeft:
ciImage = temp.oriented(forExifOrientation: 1)
default:
break
}
guard let cgImage = CIContext(options: nil).createCGImage(ciImage, from: ciImage.extent) else { return }
let fixedImage = UIImage(cgImage: cgImage)
}
}
最后,根据您的需要使用fixedImage。请注意,我订阅了通知中心,以更改方向
从iOS 4.0开始,相机拍照时不会旋转
在保存之前先保存,然后再保存
- 只需在JPEG的EXIF数据中设置旋转标志。如果将UIImage保存为JPEG
- 它将设置旋转标志。PNG不支持旋转标志
- 因此,如果将UIImage保存为PNG,它将被错误地旋转,并且没有设置用于修复它的标志。所以如果你想要PNG图像,你必须 自己旋转它们
- 只需在JPEG的EXIF数据中设置旋转标志。如果将UIImage保存为JPEG
- 它将设置旋转标志。PNG不支持旋转标志
- 因此,如果将UIImage保存为PNG,它将被错误地旋转,并且没有设置用于修复它的标志。所以如果你想要PNG图像,你必须 自己旋转它们
你能发布你用来显示图像的代码吗?最好知道您在这里使用的是哪种视图层次结构。好的,我会…@ev350请检查您能发布用于显示图像的代码吗?最好知道您在这里使用的是哪种视图层次结构。好的,我会…@ev350请检查谢谢您的答复,但使用您的解决方案时也会出现同样的问题,请检查我更新的问题以了解更多信息您在将图像设置到Imageview时是否尝试过上述方法?这应该是imageView.image=capturedImage.fixOrientation(),谢谢您的回复,但使用您的解决方案时也会出现同样的问题,请查看我更新的问题以了解更多信息在将图像设置到imageView中时,您是否尝试过上述方法?这应该是imageView.image=capturedImage.fixOrientation()什么是
ImageRenderFormat
?什么是ImageRenderFormat
?