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


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

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

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

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

任何帮助将不胜感激。谢谢!


12128
2017-11-17 21:50


起源



答案:


您正在正确翻转图像,但为什么要将翻转图像分配给 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


7
2017-11-20 08:23



那就是问题所在。我正在使用html文件输入标签通过相机拍摄照片。在拍摄相机照片后,我不知道如何将翻转后的图像发送回文件上传。 - applecrusher
@applecrusher你完成了将图像设置为输入标签吗?我认为不一定要将图像设置为输入标签。只是提示将图像上传到WKWebView中的服务器就足够了。比如缩略图。 - 季亨达
我想我明白。所以告诉wkwebview前置摄像头拍摄的照片,甚至可能通过元数据这样做。这可能会有效,但我不知道如何通过该方法拍摄照片。 - applecrusher
@applecrusher你可以通过检查照片的分辨率知道哪个相机拍了照片点击所有前置摄像头拍摄的照片分别为1.2,5或7 mp。 iPad mini 2,3,iPad第4代和iPad air都有5 mpx后置摄像头,在我的解决方案中处理。看看它我认为它应该工作。 - Md. Ibrahim Hassan


答案:


您正在正确翻转图像,但为什么要将翻转图像分配给 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


7
2017-11-20 08:23



那就是问题所在。我正在使用html文件输入标签通过相机拍摄照片。在拍摄相机照片后,我不知道如何将翻转后的图像发送回文件上传。 - applecrusher
@applecrusher你完成了将图像设置为输入标签吗?我认为不一定要将图像设置为输入标签。只是提示将图像上传到WKWebView中的服务器就足够了。比如缩略图。 - 季亨达
我想我明白。所以告诉wkwebview前置摄像头拍摄的照片,甚至可能通过元数据这样做。这可能会有效,但我不知道如何通过该方法拍摄照片。 - applecrusher
@applecrusher你可以通过检查照片的分辨率知道哪个相机拍了照片点击所有前置摄像头拍摄的照片分别为1.2,5或7 mp。 iPad mini 2,3,iPad第4代和iPad air都有5 mpx后置摄像头,在我的解决方案中处理。看看它我认为它应该工作。 - Md. Ibrahim Hassan


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

发生的事情是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
2017-11-23 14:56





首先获取设备模型 扩展检查UIDevice的设备模型  链接

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

逻辑是检查 图像分辨率。我们可以得到 height 和 width 通过以下代码以像素为单位的图像,并检查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)
}

希望这可以帮助。


1
2017-11-23 13:10



我将不得不更仔细地查看您的代码,但是您是说只有一些模型可以翻转图像吗?我在使用前置摄像头时注意到iPhone 7+上的y轴反射。 - Moondra


尝试这个:

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)
  }
}

1
2017-07-30 14:43