iphone изображение, снятое с камеры, поворачивается автоматически Swift - PullRequest
0 голосов
/ 14 января 2020

Программно, я захватил изображение с моей камеры в моем приложении. Это было красиво получено, но когда я переключаюсь на другое, просматриваю и отклоняю это представление в то время, как мое изображение, я хочу повернуть в пейзаж. Я захватил изображения с камеры. Когда я получаю изображение из библиотеки фотографий, проблема не обнаружена.

Следующее изображение является моим исходным изображением. Снимок экрана

И Я хочу повернуть изображение. Снимок экрана

Код ниже:

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

При съемке с левого пейзажа :

Ввод: Снимок экрана

Выход: Снимок экрана

При съемке изображений с правого пейзажа

Ввод: Снимок экрана

Вывод: Снимок экрана

UIImage(cgImage: tempImageHolder.cgImage!, scale: tempImageHolder.scale, orientation: .up)

При использовании этой строки выше работает хорошо, когда снимок с левого пейзажа, но когда снимок с правого пейзажа изображение не показывает правильно снимок экрана

Может кто-нибудь объяснить мне, как повернуть изображение. Любая помощь будет принята с благодарностью.

Заранее спасибо.

Ответы [ 5 ]

0 голосов
/ 23 января 2020

Начиная с iOS 4.0, когда камера делает фотографию, она не поворачивает ее перед сохранением, она

  • просто устанавливает флаг поворота в данных EXIF ​​файла JPEG. Если вы сохраняете UIImage как JPEG
  • , он устанавливает флаг поворота. PNG не поддерживают флаг поворота.
  • , поэтому, если вы сохраняете UIImage как PNG, он будет вращаться неправильно и не установлен флаг, чтобы исправить это. Поэтому, если вы хотите 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
        }
0 голосов
/ 22 января 2020

Это действительно раздражающая проблема, и я действительно не могу поверить, что 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 для своих нужд. Обратите внимание, что я подписываюсь на центр уведомлений об изменении ориентации.

0 голосов
/ 17 января 2020

Проблема в том, что вы отбрасываете метаданные изображения (включая ориентацию) при конвертации UIImage в CGImage. Вам нужно визуализировать новый UIImage перед доступом к его свойству cgImage, как я показал в этом сообщении


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
}
0 голосов
/ 20 января 2020

Попробуйте следующую функцию, чтобы исправить ориентацию:

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;
    }
}
0 голосов
/ 14 января 2020
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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...