[英]iphone image captured from camera rotate automatically Swift
Programmatically, I have captured image from my camera in my app.以编程方式,我在我的应用程序中从我的相机捕获了图像。 It has been fetched nicely, but when I shift to another, view and dismiss that view at that time my image I want to rotate into landscape.
它已被很好地获取,但是当我转移到另一个视图时,查看并关闭该视图,当时我的图像我想旋转为横向。 I captured images from camera.
我从相机捕捉图像。 When I fetch image from photo library no issue has been found.
当我从照片库中获取图像时,没有发现任何问题。
Following image is my original image.下图是我的原图。 Screen Shot
截屏
And I want to rotate image.我想旋转图像。 Screen Shot
截屏
Code Below:代码如下:
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)
}
}
When take images from left landscape:从左侧风景拍摄图像时:
Input: Screen Shot输入:屏幕截图
Output: Screen Shot输出:屏幕截图
When take images from right landscape当从正确的风景拍摄图像时
Input: Screen Shot输入:屏幕截图
Output: Screen Shot输出:屏幕截图
UIImage(cgImage: tempImageHolder.cgImage!, scale: tempImageHolder.scale, orientation: .up)
When use this above line works fine when take images from left landscape, but when take images from right landscape image not show properly screen shot当从左侧风景拍摄图像时使用上面这条线工作正常,但是当从右侧风景图像拍摄图像时无法正确显示屏幕截图
Can someone please explain to me how to rotate image.有人可以向我解释如何旋转图像。 Any help would be greatly appreciated.
任何帮助将不胜感激。
Thanks in advance.提前致谢。
This is a really annoying problem, and I really cannot believe AVFoundation does not have anything easier for us.这是一个非常烦人的问题,我真的不敢相信 AVFoundation 对我们来说没有什么更容易的。 But in my apps I do this by holding around the current device orientation.
但是在我的应用程序中,我通过保持当前设备方向来做到这一点。 When photo output comes back with an image, rotate the image using orientation to make sure everything is pictured upward.
当照片输出带有图像时,使用方向旋转图像以确保所有图像都向上。
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)
}
}
In the end, use fixedImage for your needs.最后,根据您的需要使用fixedImage 。 Please note that I subscribe to notification center for changes in orientation.
请注意,我订阅了通知中心以了解方向的变化。
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)
}
} }
To use:-使用:-
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)
The problem there is that you are discarding your image metadata (including the orientation) when converting your UIImage
to CGImage
.问题在于您在将
UIImage
转换为CGImage
时丢弃了图像元数据(包括方向)。 You need to render a new UIImage
before accessing its cgImage
property as I showed in this post你需要在访问它的
cgImage
属性之前呈现一个新的UIImage
,正如我在这篇文章中展示的
if let data = photo.fileDataRepresentation(), let image = UIImage(data: data) {
let renderedImage = UIGraphicsImageRenderer(size: size, format: imageRendererFormat).image { _ in image.draw(at: .zero) }
// use renderedImage image
}
Try following function to fix the orientation:尝试以下功能来修复方向:
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;
}
}
Starting with iOS 4.0 when the camera takes a photo it does not rotate it before saving, it
从 iOS 4.0 开始,当相机拍照时,在保存之前不会旋转它,它
- simply sets a rotation flag in the EXIF data of the JPEG.If you save a UIImage as a JPEG
只需在 JPEG 的 EXIF 数据中设置一个旋转标志。如果将 UIImage 保存为 JPEG
- it will set the rotation flag.PNGs do not support a rotation flag.
它将设置旋转标志。PNG 不支持旋转标志。
- so if you save a UIImage as a PNG, it will be rotated incorrectly and not have a flag set to fix it.
因此,如果您将 UIImage 保存为 PNG,它将被错误地旋转并且没有设置标志来修复它。 So if you want PNG images you must rotate them yourself.
因此,如果您想要 PNG 图像,则必须自己旋转它们。
func rotateImage(image: UIImage) -> UIImage? {
if (image.imageOrientation == UIImage.Orientation.up ) {
return image
}
UIGraphicsBeginImageContext(image.size)
image.draw(in: CGRect(origin: CGPoint.zero, size: image.size))
let copy = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return copy
}
You should set the orientation in output before capture the photo.您应该在拍摄照片之前在输出中设置方向。
// set the image orientation in output
if let photoOutputConnection = self.photoOutput.connection(with: .video) {
photoOutputConnection.videoOrientation = videoPreviewLayerOrientation!
}
self.photoOutput.capturePhoto(with: photoSettings, delegate: photoCaptureProcessor) // capture image
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.