Камера быстро снимает только в портретном режиме

Как перевести камеру в ландшафтный режим? Каждый раз, когда я делаю снимок, изображение сохраняется как портретное изображение. Когда устройство находится в ландшафтном режиме, фотография выглядит нормально, но если я вижу ее в фотопленке, это все еще портретный режим. Это моя функция фотосъемки:

// take a photo
@IBAction func takePhoto(sender: AnyObject) {
self.fullScreenView.hidden = false
self.recordButton.enabled = false
self.takephoto.enabled = false
self.recordButton.hidden = true
self.takephoto.hidden = true

session.startRunning()

// customize the quality level or bitrate of the output photo
session.sessionPreset = AVCaptureSessionPresetPhoto

// add the AVCaptureVideoPreviewLayer to the view and set the view in fullscreen
fullScreenView.frame = view.bounds
videoPreviewLayer.frame = fullScreenView.bounds
fullScreenView.layer.addSublayer(videoPreviewLayer)

// add action to fullScreenView
gestureFullScreenView = UITapGestureRecognizer(target: self, action: #selector(ViewController.takePhoto(_:)))
self.fullScreenView.addGestureRecognizer(gestureFullScreenView)

// add action to myView
gestureView = UITapGestureRecognizer(target: self, action: #selector(ViewController.setFrontpage(_:)))
self.view.addGestureRecognizer(gestureView)

if (preview == true) {
    if let videoConnection = stillImageOutput!.connectionWithMediaType(AVMediaTypeVideo) {
        // code for photo capture goes here...

        stillImageOutput?.captureStillImageAsynchronouslyFromConnection(videoConnection, completionHandler: { (sampleBuffer, error) -> Void in
            // process the image data (sampleBuffer) here to get an image file we can put in our view

            if (sampleBuffer != nil) {
                let imageData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(sampleBuffer)
                let image = UIImage(data: imageData, scale: 1.0)

                self.fullScreenView.hidden = true
                self.fullScreenView.gestureRecognizers?.forEach(self.fullScreenView.removeGestureRecognizer)
                self.session.stopRunning()

                // save image to the library
                UIImageWriteToSavedPhotosAlbum(image!, nil, nil, nil)

                self.imageViewBackground = UIImageView(frame: self.view.bounds)
                self.imageViewBackground.image = image
                self.imageViewBackground.tag = self.key

                self.view.addSubview(self.imageViewBackground)
            }
        })
    }
}
else {
    preview = true
}
}

Мой предварительный просмотр выглядит так, и это нормально:

http://img5.fotos-hochladen.net/uploads/bildschirmfotom4s7diaehy.png

но в итоге это выглядит так:

http://img5.fotos-hochladen.net/uploads/bildschirmfoto3c2rlwtevf.png

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


person mafioso    schedule 02.08.2016    source источник


Ответы (2)


Поскольку ориентация videoConnection всегда в портретной ориентации, независимо от того, находится ли ваше устройство в книжной или альбомной ориентации. Таким образом, вы должны настроить ориентацию videoConnection на правильную, прежде чем делать фото.

Добавьте следующий метод, чтобы получить videoOrientation для текущего устройстваOrientation.

func videoOrientation(for deviceOrientation: UIDeviceOrientation) -> AVCaptureVideoOrientation {
    switch deviceOrientation {
    case UIDeviceOrientation.portrait:
        return AVCaptureVideoOrientation.portrait
    case UIDeviceOrientation.landscapeLeft:
        return AVCaptureVideoOrientation.landscapeRight
    case UIDeviceOrientation.landscapeRight:
        return AVCaptureVideoOrientation.landscapeLeft
    case UIDeviceOrientation.portraitUpsideDown:
        return AVCaptureVideoOrientation.portraitUpsideDown
    default:
        return AVCaptureVideoOrientation.portrait
    }
}

Сразу после следующей строки

if let videoConnection = stillImageOutput.connectionWithMediaType(AVMediaTypeVideo) {

Добавьте следующую строку

videoConnection.videoOrientation = videoOrientation(for: UIDevice.current.orientation)

Примечание. Если ваше приложение поддерживает только портретный или ландшафтный режим, эта проблема все равно возникает, поскольку UIDevice.current.orientation всегда возвращает поддерживаемую ориентацию. Чтобы преодолеть это, вы можете использовать CoreMotion для определения ориентации устройства, а затем передать его методу videoOrientation(for:).

Надеюсь это поможет :)

person Binh Le    schedule 12.02.2020
comment
Для текущей быстрой версии я внес небольшие изменения, но она работает нормально, я поместил ее в свою функцию фотосъемки. - person zampnrs; 02.06.2020

Возможное решение: сохранение изображения в формате JPEG вместо PNG

Это происходит потому, что PNG не хранят информацию об ориентации. Вместо этого сохраните фотографию в формате JPG, и она будет правильно ориентирована.

Используйте этот код, чтобы преобразовать ваше изображение в JPG сразу после получения изображения (здесь вторая строка является рабочей):

let image = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(sampleBuffer)
let imageData:NSData = UIImageJPEGRepresentation(image, 0.9)! // 0.9 is compression value: 0.0 is most compressed/lowest quality and 1.0 is least compressed/highest quality

Источник + дополнительная информация: https://stackoverflow.com/a/34796890/5700898


Если это не сработает

Я отредактировал ваш код в нескольких местах, посмотрите, работает ли приведенный ниже код так, как вы надеетесь:

// initialize saving photo capabilities
func image(image: UIImage, didFinishSavingWithError error: NSError?, contextInfo:UnsafePointer<Void>) {
        if error == nil {
            print("image saved")
        } else {
            print("save error: \(error?.localizedDescription)")
        }
}

// take a photo
@IBAction func takePhoto(sender: AnyObject) {
self.fullScreenView.hidden = false
self.recordButton.enabled = false
self.takephoto.enabled = false
self.recordButton.hidden = true
self.takephoto.hidden = true

session.startRunning()

// customize the quality level or bitrate of the output photo
session.sessionPreset = AVCaptureSessionPresetPhoto

// add the AVCaptureVideoPreviewLayer to the view and set the view in fullscreen
fullScreenView.frame = view.bounds
videoPreviewLayer.frame = fullScreenView.bounds
fullScreenView.layer.addSublayer(videoPreviewLayer)

// add action to fullScreenView
gestureFullScreenView = UITapGestureRecognizer(target: self, action: #selector(ViewController.takePhoto(_:)))
self.fullScreenView.addGestureRecognizer(gestureFullScreenView)

// add action to myView
gestureView = UITapGestureRecognizer(target: self, action: #selector(ViewController.setFrontpage(_:)))
self.view.addGestureRecognizer(gestureView)

if (preview == true) {
    if let videoConnection = stillImageOutput!.connectionWithMediaType(AVMediaTypeVideo) {
        // code for photo capture goes here...

        stillImageOutput?.captureStillImageAsynchronouslyFromConnection(videoConnection, completionHandler: { (sampleBuffer, error) -> Void in
            // process the image data (sampleBuffer) here to get an image file we can put in our view

            if (sampleBuffer != nil) {
                self.stillImageOutput!.outputSettings = [AVVideoCodecKey: AVVideoCodecJPEG]
        if let videoConnection = self.stillImageOutput!.connectionWithMediaType(AVMediaTypeVideo){
            videoConnection.videoOrientation = self.interfaceToVideoOrientation()
            self.stillImageOutput!.captureStillImageAsynchronouslyFromConnection(videoConnection, completionHandler: {
                (sampleBuffer, error) in
                let imageData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(sampleBuffer)
                let image = UIImage(data: imageData)

                self.fullScreenView.hidden = true
                self.fullScreenView.gestureRecognizers?.forEach(self.fullScreenView.removeGestureRecognizer)
                self.session.stopRunning()

                // save image to the library
                UIImageWriteToSavedPhotosAlbum(image, self, #selector(ViewController.image(_:didFinishSavingWithError:contextInfo:)), nil)

                self.imageViewBackground = UIImageView(frame: self.view.bounds)
                self.imageViewBackground.image = image
                self.imageViewBackground.tag = self.key

                self.view.addSubview(self.imageViewBackground)
            }
        })
    }
}
else {
    preview = true
}
}
person owlswipe    schedule 02.08.2016
comment
Я думаю, что сохранить его как JPEG или я ошибаюсь? let imageData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(sampleBuffer) - person mafioso; 02.08.2016
comment
@mafioso Попробуйте изменить объявление imageData на то, что я сделал выше, я не уверен, что ваше работает. Если это не решит вашу проблему, я буду копать глубже;). Просто дай мне знать. - person owlswipe; 02.08.2016
comment
хорошо, я попробую ;) но я до сих пор не знаю, почему он отлично работает в портретном режиме, а не в ландшафтном - person mafioso; 02.08.2016
comment
что мне делать с imageData? - person mafioso; 02.08.2016
comment
Замените эту строку кода в своем проекте (let imageData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(sampleBuffer)) строкой, которую я указал в своем ответе выше, @mafioso. - person owlswipe; 02.08.2016
comment
Но это строка кода, где я получаю фотографию, поэтому, если я ее заменю, мне нужен параметр изображения. - person mafioso; 02.08.2016
comment
@mafioso Я представил вам ваш код, но отредактировал его так, чтобы, я думаю, он работал. Попробуйте весь этот код в своем проекте и расскажите, как это все работает (могут быть ошибки, просто дайте мне знать). - person owlswipe; 02.08.2016