IOS Swift 3:拍摄相机图片后水平翻转前置摄像头图像

时间:2016-11-17 21:50:09

标签: ios iphone swift camera swift3

StackOverflow上有几个问题涉及图像翻转,例如here。默认情况下,iOS会在拍摄照片时反转前置摄像头水平图像。我试图防止前置摄像头图像被翻转或将其翻转回正确的方向。我正在与WKWebview进行互动。

问题在于我不知道在我的ViewController中调用或放入什么方法来获取相机,然后将其设置为正确的方向或正确的设置以防止此行为。我也不知道如何获取拍摄图像的相机信息。

这是我尝试的一种解决方案,它基于翻译一些Objective-C代码,在相机完成照片后更改图像。但是图片变量是常量,无法更改:

func didTakePicture(_ picture: UIImage) {
    var flippedImage = UIImage(cgImage: picture.cgImage!, scale: picture.scale, orientation: .leftMirrored)
    picture = flippedImage
}

非常感谢任何帮助。谢谢!

5 个答案:

答案 0 :(得分:12)

您正在正确翻转图像,但为什么要将翻转的图像分配回picture变量,您可以使用flippedImage变量并将其传递到需要的位置。

func didTakePicture(_ picture: UIImage) {
    var flippedImage = UIImage(CGImage: picture.CGImage!, scale: picture.scale, orientation: .leftMirrored)
    // Here you have got flipped image you can pass it wherever you are using image
}
  

我要做的是仅防止前置摄像头图像   被翻转

如果使用默认相机,则无法防止相机阻止翻转图像。要做到这一点,您需要使用AVFoundation创建自己的相机,并需要在那里应用您的逻辑。

如果您准备使用任何三方图书馆,则可以查看LEMirroredImagePicker

答案 1 :(得分:3)

之前我遇到过这个问题。老实说,我不完全理解它,但这就是我的问题,它可能与你的问题有关:

正在发生的事情是iPhone相机(可能由于某些硬件原因)并不总是以正确的方向保存图像数据。根据iPhone型号和相机的不同,它们可以上下颠倒,侧面保存,和/或甚至可以在一个或两个轴上翻转。每当你在iPhone上拍照时,它有时会通过应用EXIF转换元数据来反转它来“纠正”这一点。

在转换的情况下,EXIF元数据告诉如何在打开数据后旋转和翻转数据。我猜这个存在的原因是因为将EXIF转换元数据应用于图像而不是将实际图像数据转换为内存会更便宜。

这有时会出现问题,因为在iOS中显示图像的所有内容都不会影响转换元数据。这可能发生在WKWebview上。它可能是在不检查EXIF数据进行转换的情况下显示图像。

我在过去构建一些图像处理应用时遇到了这个问题。虽然我没有为您提供任何简单的修复,但我的解决方法如下:1)首先从UIImage中删除所有EXIF转换数据。这在计算上更加昂贵,但IMO值得,因为它使图像更容易处理,您不必担心不处理EXIF数据的事情。 2)如果iPhone相机以不合适的方向保存图像,则以正确的方式正确转换图像。

这些可能是一个开始的好地方

剥离EXIF:

https://stackoverflow.com/a/34161629/4102858

https://stackoverflow.com/a/25595495/4102858

UIImage转换:

https://stackoverflow.com/a/29753437/4102858

这些可能不适合您,但希望它们可以帮助您更好地理解您的问题。

答案 2 :(得分:2)

试试这个:

if captureDevice.position == AVCaptureDevicePosition.back {
  if let image = context.createCGImage(ciImage, from: imageRect) {
    return UIImage(cgImage: image, scale: UIScreen.main.scale, orientation: .right)
  }
}

if captureDevice.position == AVCaptureDevicePosition.front {
  if let image = context.createCGImage(ciImage, from: imageRect) {
    return UIImage(cgImage: image, scale: UIScreen.main.scale, orientation: .leftMirrored)
  }
}

答案 3 :(得分:1)

首先获取设备型号 扩展以检查UIDevice的设备模型 link

import UIKit

public extension UIDevice {

    var modelName: String {
        var systemInfo = utsname()
        uname(&systemInfo)
        let machineMirror = Mirror(reflecting: systemInfo.machine)
        let identifier = machineMirror.children.reduce("") { identifier, element in
            guard let value = element.value as? Int8 where value != 0 else { return identifier }
            return identifier + String(UnicodeScalar(UInt8(value)))
        }

        switch identifier {
        case "iPod5,1":                                 return "iPod Touch 5"
        case "iPod7,1":                                 return "iPod Touch 6"
        case "iPhone3,1", "iPhone3,2", "iPhone3,3":     return "iPhone 4"
        case "iPhone4,1":                               return "iPhone 4s"
        case "iPhone5,1", "iPhone5,2":                  return "iPhone 5"
        case "iPhone5,3", "iPhone5,4":                  return "iPhone 5c"
        case "iPhone6,1", "iPhone6,2":                  return "iPhone 5s"
        case "iPhone7,2":                               return "iPhone 6"
        case "iPhone7,1":                               return "iPhone 6 Plus"
        case "iPhone8,1":                               return "iPhone 6s"
        case "iPhone8,2":                               return "iPhone 6s Plus"
        case "iPhone9,1", "iPhone9,3":                  return "iPhone 7"
        case "iPhone9,2", "iPhone9,4":                  return "iPhone 7 Plus"
        case "iPhone8,4":                               return "iPhone SE"
        case "iPad2,1", "iPad2,2", "iPad2,3", "iPad2,4":return "iPad 2"
        case "iPad3,1", "iPad3,2", "iPad3,3":           return "iPad 3"
        case "iPad3,4", "iPad3,5", "iPad3,6":           return "iPad 4"
        case "iPad4,1", "iPad4,2", "iPad4,3":           return "iPad Air"
        case "iPad5,3", "iPad5,4":                      return "iPad Air 2"
        case "iPad2,5", "iPad2,6", "iPad2,7":           return "iPad Mini"
        case "iPad4,4", "iPad4,5", "iPad4,6":           return "iPad Mini 2"
        case "iPad4,7", "iPad4,8", "iPad4,9":           return "iPad Mini 3"
        case "iPad5,1", "iPad5,2":                      return "iPad Mini 4"
        case "iPad6,3", "iPad6,4", "iPad6,7", "iPad6,8":return "iPad Pro"
        case "AppleTV5,3":                              return "Apple TV"
        case "i386", "x86_64":                          return "Simulator"
        default:                                        return identifier
        }
    }

}

您可以这样称呼:

let modelName = UIDevice.currentDevice().modelName

逻辑是检查图像分辨率。我们可以通过以下代码获取图像的heightwidth,并检查FaceTime(前置)相机的分辨率:

主要代码块

//Getting model Name
let modelName = UIDevice.currentDevice().modelName
//Getting the height and the width of the image captured. The apple devices either have a 7 MP,5 MP front camera or a 1.2 MP front camera. 
let heightInPoints = image.size.height
let heightInPixels = heightInPoint * image.scale

let widthInPoints = image.size.width
let widthInPixels = widthInPoints * image.scale

//Checking for 7 megapixel
//3,072 x 2304 or 3180x2375 (Sorry I am not sure about the exact resolution)
if (heightInPixels == 2304 && widthInPixels== 3,072)
{
 var flippedImage = UIImage(cgImage: picture.cgImage!, scale: picture.scale, orientation: .leftMirrored)
}
//Checking for 5 megapixel 
//2592 x 1936 resolution 
if (heightInPixels == 1944 && widthInPixels== 2592)
{
 if (modelName == "iPad Mini 2" || modelName == "iPad Mini 3" || modelName == "iPad Air" || modelName == "iPad 4")
{
print ("iPad models with 5mp back camera")
}
else
{
 var flippedImage = UIImage(cgImage: picture.cgImage!, scale: picture.scale, orientation: .leftMirrored)
}
     }
//Checking for 1.2 MP camera
//1200 x 780 pixels 2MP resolution for iPhone 6/6+/someipad Models they have a 1.2MP camera 

//No apple iDevice has a main camera below this resolution
else if (heightInPixels == 780 && widthInPixel == 1200)
{
 var flippedImage = UIImage(cgImage: picture.cgImage!, scale: picture.scale, orientation: .leftMirrored)
}

希望这有帮助。

答案 4 :(得分:0)

我知道这个问题已经回答了,但是我认为人们可能会发现下面的链接有用。

摄像机图像始终是横向的,但包含指示捕获时设备方向的元数据方向字段。

不幸的是,有些观众没有阅读此字段并旋转图像。

一种不错的方法是读取此变量并相应地旋转图像。

代码是从这里获取的-https://github.com/nativ18/Swift-Extensions/blob/master/UIImage%2BExtensions

extension UIImage {

func alignOrientationMetadataAndSize() -> UIImage? {
    let landscapeMetadata = imageOrientation == .left || imageOrientation == .leftMirrored || imageOrientation == .right || imageOrientation == .rightMirrored
    let landscapeSize = size.width > size.height
    switch (landscapeSize, landscapeMetadata) {
    case (false, true), (true, false):
        var newSize = CGSize(width: size.height, height: size.width)
        // Trim off the extremely small float value to prevent core graphics from rounding it up
        newSize.width = floor(newSize.width)
        newSize.height = floor(newSize.height)
        UIGraphicsBeginImageContextWithOptions(newSize, false, self.scale)
        let context = UIGraphicsGetCurrentContext()!
        context.translateBy(x: newSize.width/2, y: newSize.height/2)
        self.draw(in: CGRect(x: -self.size.width/2, y: -self.size.height/2, width: self.size.width, height: self.size.height))
        let newImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return newImage
    default:
        return self
    }
}
}