2017-10-24 5 views
3

enter image description here 나는 사용자가 사진을 찍을 수있는보기 컨트롤러가 있습니다. avcapture 경계를 화면의 경계로 설정합니다.AVCAPTURE 이미지 방향

위의보기에는 컬렉션보기가 있습니다. 따라서 사용자는 여러 그림을 캡처 할 수 있으며 위의 컬렉션보기에 추가됩니다.

위의 미리보기에 올바른 방향이 나타나는 데 문제가 있습니다. 다음과 같이

코드는 다음과 같습니다

@IBOutlet weak var imagePreviews: UICollectionView! 
@IBOutlet weak var imgPreview: UIView! 

var session: AVCaptureSession? 
var stillImageOutput: AVCaptureStillImageOutput? 
var videoPreviewLayer: AVCaptureVideoPreviewLayer? 
var images: [UIImage] = [UIImage]() 

var isLandscapeLeft  : Bool = false 
var isLandscapeRight : Bool = false 
var isPortrait   : Bool = false 
var isPortraitUpsideDown: Bool = false 

@IBAction func capture(_ sender: UIButton) 
    { 
    if let videoConnection = stillImageOutput?.connection(withMediaType: AVMediaTypeVideo) 
      { 
       stillImageOutput?.captureStillImageAsynchronously(from: videoConnection, completionHandler: { (sampleBuffer, error) in 
        if sampleBuffer != nil { 
         if let imageData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(sampleBuffer), let dataProvider = CGDataProvider(data: imageData as CFData), let cgImageRef = CGImage(jpegDataProviderSource: dataProvider, decode: nil, shouldInterpolate: true, intent: CGColorRenderingIntent.defaultIntent) 
         { 
          var image: UIImage 

          if (self.isLandscapeLeft || self.isLandscapeRight) 
          { 
           image = UIImage(cgImage: cgImageRef, scale: 1.0, orientation: self.isLandscapeLeft ? UIImageOrientation.left : UIImageOrientation.right) 
          } else { 
           image = UIImage(cgImage: cgImageRef, scale: 1.0, orientation: self.isPortrait ? UIImageOrientation.up : UIImageOrientation.down) 
          } 

          image = self.fixOrientation(img: image) 
          self.images.append(image) 


          DispatchQueue.main.async { 
           self.imagePreviews.reloadData() 
          } 
         } 
        } 
       }) 
      } 
     } 
    } 

override func viewDidLayoutSubviews() { 

    super.viewDidLayoutSubviews() 

    if let connection = self.videoPreviewLayer?.connection { 

     let currentDevice: UIDevice = UIDevice.current 

     let orientation: UIDeviceOrientation = currentDevice.orientation 

     let previewLayerConnection : AVCaptureConnection = connection 

     if (previewLayerConnection.isVideoOrientationSupported) { 

      switch (orientation) { 
      case .portrait: 

       isLandscapeLeft  = false 
       isLandscapeRight  = false 
       isPortrait   = true 
       isPortraitUpsideDown = false 
       updatePreviewLayer(layer: previewLayerConnection, orientation: .portrait) 
       break 

      case .landscapeRight: 

       isLandscapeLeft  = false 
       isLandscapeRight  = true 
       isPortrait   = false 
       isPortraitUpsideDown = false 
       updatePreviewLayer(layer: previewLayerConnection, orientation: .landscapeRight) 
       break 

      case .landscapeLeft: 

       isLandscapeLeft  = true 
       isLandscapeRight  = false 
       isPortrait   = false 
       isPortraitUpsideDown = false 
       updatePreviewLayer(layer: previewLayerConnection, orientation: .landscapeLeft) 
       break 
      case .portraitUpsideDown: 

       isLandscapeLeft  = false 
       isLandscapeRight  = false 
       isPortrait   = false 
       isPortraitUpsideDown = true 
       updatePreviewLayer(layer: previewLayerConnection, orientation: .portraitUpsideDown) 
       break 
      default: 

       updatePreviewLayer(layer: previewLayerConnection, orientation: .portrait) 

       break 
      } 
     } 
    } 
} 

func fixOrientation(img: UIImage) -> UIImage { 
     if (img.imageOrientation == .up) { 
      return img 
     } 

     UIGraphicsBeginImageContextWithOptions(img.size, false, img.scale) 
     let rect = CGRect(x: 0, y: 0, width: img.size.width, height: img.size.height) 
     img.draw(in: rect) 

     let normalizedImage = UIGraphicsGetImageFromCurrentImageContext()! 
     UIGraphicsEndImageContext() 

     return normalizedImage 
    } 
+0

"방향에 문제가 있습니다"를 정의하십시오. 이미지 미리보기에서 방향 변경을 처리해야합니까? – PoolHallJunkie

+0

@PoolHallJunkie 컬렉션의 이미지 미리보기에서 이미지 방향이 잘못되었습니다 – user2363025

+1

@dasblinkenlight가 예제를 추가했습니다. 바라기를 이것은 내 문제 – user2363025

답변

1

세로 방향 장치에서 이미지를 만들 때 고려해야 할 90 개도, 예를 들어 회전 된 UIImage하십시오 들어

switch UIApplication.shared.statusBarOrientation { 
case .portrait: 
    image = UIImage(cgImage: cgImageRef, scale: 1.0, orientation: .right) 
case .landscapeRight: 
    image = UIImage(cgImage: cgImageRef, scale: 1.0, orientation: .up) 
case .landscapeLeft: 
    image = UIImage(cgImage: cgImageRef, scale: 1.0, orientation: .down) 
case .portraitUpsideDown: 
    image = UIImage(cgImage: cgImageRef, scale: 1.0, orientation: .left) 
default: 
    fatalError("Unexpected orientation") 
} 

을 완전한 예 : 참조 :

import UIKit 
import AVFoundation 

class ViewController: UIViewController { 

    @IBOutlet weak var imageView: UIImageView! 
    @IBOutlet weak var videoPreviewView: UIView! 
    var videoPreviewLayer: AVCaptureVideoPreviewLayer! 

    var session: AVCaptureSession = AVCaptureSession() 
    var stillImageOutput: AVCaptureStillImageOutput = { 
     let output = AVCaptureStillImageOutput() 
     output.outputSettings = [AVVideoCodecKey: AVVideoCodecJPEG] 
     return output 
    }() 

    var images: [UIImage] = [UIImage]() 

    var orientation = UIApplication.shared.statusBarOrientation 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     guard let device = AVCaptureDevice.default(for: .video) else { 
      print("Unable to create capture device") 
      return 
     } 

     let input: AVCaptureDeviceInput 
     do { 
      input = try AVCaptureDeviceInput(device: device) 
     } catch { 
      print("Unable to create input", error) 
      return 
     } 

     guard session.canAddInput(input) else { 
      print("Cannot add input") 
      return 
     } 
     session.addInput(input) 

     guard session.canAddOutput(stillImageOutput) else { 
      print("Cannot add output") 
      return 
     } 
     session.addOutput(stillImageOutput) 

     session.startRunning() 
     videoPreviewLayer = AVCaptureVideoPreviewLayer(session: session) 
     videoPreviewView.layer.addSublayer(videoPreviewLayer) 
    } 

    @IBAction func didTapCaptureButton(_ sender: Any) { 
     if let connection = stillImageOutput.connection(with: .video) { 
      stillImageOutput.captureStillImageAsynchronously(from: connection) { sampleBuffer, error in 
       guard let sampleBuffer = sampleBuffer, error == nil else { 
        print(error ?? "Unknown error") 
        return 
       } 

       guard 
        let imageData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(sampleBuffer), 
        let dataProvider = CGDataProvider(data: imageData as CFData), 
        let cgImageRef = CGImage(jpegDataProviderSource: dataProvider, decode: nil, shouldInterpolate: true, intent: .defaultIntent) else { 
         print("unable to capture image") 
         return 
       } 

       var image: UIImage? 

       switch self.orientation { 
       case .portrait: 
        image = UIImage(cgImage: cgImageRef, scale: 1.0, orientation: .right) 
       case .landscapeRight: 
        image = UIImage(cgImage: cgImageRef, scale: 1.0, orientation: .up) 
       case .landscapeLeft: 
        image = UIImage(cgImage: cgImageRef, scale: 1.0, orientation: .down) 
       case .portraitUpsideDown: 
        image = UIImage(cgImage: cgImageRef, scale: 1.0, orientation: .left) 
       default: 
        fatalError("Unexpected orientation") 
       } 

       guard image != nil else { 
        print("unable to create UIImage") 
        return 
       } 

       DispatchQueue.main.async { 
        self.images.append(image!) 
        self.imageView.image = image 
       } 
      } 

     } 
    } 

    override func viewDidLayoutSubviews() { 
     super.viewDidLayoutSubviews() 

     if let connection = self.videoPreviewLayer?.connection { 
      orientation = UIApplication.shared.statusBarOrientation 

      switch orientation { 
      case .portrait:   updatePreviewOrientation(for: connection, to: .portrait) 
      case .landscapeRight:  updatePreviewOrientation(for: connection, to: .landscapeRight) 
      case .landscapeLeft:  updatePreviewOrientation(for: connection, to: .landscapeLeft) 
      case .portraitUpsideDown: updatePreviewOrientation(for: connection, to: .portraitUpsideDown) 
      default:     updatePreviewOrientation(for: connection, to: .portrait) 
      } 
     } 
    } 

    private func updatePreviewOrientation(for connection: AVCaptureConnection, to orientation: AVCaptureVideoOrientation) { 
     if connection.isVideoOrientationSupported { 
      connection.videoOrientation = orientation 
     } 
     videoPreviewLayer.frame = videoPreviewView.bounds 
    } 
} 

이미지 방향은 fixOrientation입니다. orientation을 사용하여 에서 UIImage을 만든 후에는 원하지 않는 경우 이미지를 다시 만들지 않아도됩니다.

+0

완벽하게 작동 감사합니다 보여줍니다. – user2363025