Search code examples
iosiphoneswiftcamerauiimagepickercontroller

Camera view rotate 90 degree in Swift


When I'm making a customized camera app in Swift. But when I try to access the camera, the view in camera rotated 90 degrees. I try to find the solution. One solution I find is adding a fixOrientation function to fix the view. But not working... Here is my full code:

let CIHueAdjust = "CIHueAdjust"
let CIHueAdjustFilter = CIFilter(name: "CIHueAdjust", withInputParameters: ["inputAngle" : 1.24])

let Filters = [CIHueAdjust: CIHueAdjustFilter]

let FilterNames = [String](Filters.keys).sort()

class LiveCamViewController : UIViewController,AVCaptureVideoDataOutputSampleBufferDelegate{
let mainGroup = UIStackView()
let imageView = UIImageView(frame: CGRectZero)
let filtersControl = UISegmentedControl(items: FilterNames)

override func viewDidLoad()
{
    super.viewDidLoad()

    view.addSubview(mainGroup)
    mainGroup.axis = UILayoutConstraintAxis.Vertical
    mainGroup.distribution = UIStackViewDistribution.Fill

    mainGroup.addArrangedSubview(imageView)
    mainGroup.addArrangedSubview(filtersControl)

    imageView.contentMode = UIViewContentMode.ScaleAspectFit

    filtersControl.selectedSegmentIndex = 0

    let captureSession = AVCaptureSession()
    captureSession.sessionPreset = AVCaptureSessionPresetPhoto

    let backCamera = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)

    do
    {
        let input = try AVCaptureDeviceInput(device: backCamera)

        captureSession.addInput(input)
    }
    catch
    {
        print("can't access camera")
        return
    }

    //get captureOutput invoked
    let previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
    view.layer.addSublayer(previewLayer)

    let videoOutput = AVCaptureVideoDataOutput()

    videoOutput.setSampleBufferDelegate(self, queue: dispatch_queue_create("sample buffer delegate", DISPATCH_QUEUE_SERIAL))
    if captureSession.canAddOutput(videoOutput)
    {
        captureSession.addOutput(videoOutput)
    }

    captureSession.startRunning()
}

func captureOutput(captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, fromConnection connection: AVCaptureConnection!)
{
    guard let filter = Filters[FilterNames[filtersControl.selectedSegmentIndex]] else
    {
        return
    }

    let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)
    let cameraImage = CIImage(CVPixelBuffer: pixelBuffer!)

    filter!.setValue(cameraImage, forKey: kCIInputImageKey)

    let filteredImage = UIImage(CIImage: filter!.valueForKey(kCIOutputImageKey) as! CIImage!)
    let fixedImage = fixOrientation(filteredImage)

    dispatch_async(dispatch_get_main_queue())
    {
        self.imageView.image = fixedImage
    }
}

func fixOrientation(image: UIImage) -> UIImage {
    if (image.imageOrientation == UIImageOrientation.Up) {
        return image;
    }

    print(image.imageOrientation)

    var transform = CGAffineTransformIdentity

    switch (image.imageOrientation) {
    case .Down, .DownMirrored:
        transform = CGAffineTransformTranslate(transform, image.size.width, image.size.height)
        transform = CGAffineTransformRotate(transform, CGFloat(M_PI))
        break
    case .Left, .LeftMirrored:
        transform = CGAffineTransformTranslate(transform, image.size.width, 0)
        transform = CGAffineTransformRotate(transform, CGFloat(M_PI_2))
        break
    case .Right, .RightMirrored:
        transform = CGAffineTransformTranslate(transform, 0, image.size.height)
        transform = CGAffineTransformRotate(transform, CGFloat(-M_PI_2))
        break
    case .Up, .UpMirrored:
        break
    }

    switch (image.imageOrientation) {
    case .UpMirrored, .DownMirrored:
        transform = CGAffineTransformTranslate(transform, image.size.width, 0)
        transform = CGAffineTransformScale(transform, -1, 1)
        break
    case .LeftMirrored, .RightMirrored:
        transform = CGAffineTransformTranslate(transform, image.size.height, 0)
        transform = CGAffineTransformScale(transform, -1, 1)
        break
    case .Up, .Down, .Left, .Right:
        break
    }

    //Draw the underlying CGImage into a new context, applying the transform
    let ctx = CGBitmapContextCreate(nil, Int(image.size.width), Int(image.size.height), CGImageGetBitsPerComponent(image.CGImage), 0, CGImageGetColorSpace(image.CGImage), UInt32(CGImageGetBitmapInfo(image.CGImage).rawValue))

    CGContextConcatCTM(ctx, transform);

    switch (image.imageOrientation) {
    case .Left, .LeftMirrored, .Right, .RightMirrored:
        CGContextDrawImage(ctx, CGRectMake(0, 0, image.size.height, image.size.width), image.CGImage)
        break
    default:
        CGContextDrawImage(ctx, CGRectMake(0, 0, image.size.width, image.size.height), image.CGImage)
        break
    }

    let cgimg = CGBitmapContextCreateImage(ctx)
    let img = UIImage(CGImage:cgimg!)

    return img
}

override func viewDidLayoutSubviews()
{
    mainGroup.frame = CGRect(x: 37, y: 115, width: 301, height: 481)
}

}

I set a breakpoint to test, the code seems only run until

if (image.imageOrientation == UIImageOrientation.Up) {
        return image;
    }

then it returns the same view...

Can anyone help me? Thanks!!!


Solution

  • In capture() where you get your CIImage from CMSampleBuffer do this after:

       yourCIImage = yourCIImage.applyingOrientation(6)
    

    Change the number from 1-8 depending on how you want to rotate and mirror. https://developer.apple.com/documentation/imageio/kcgimagepropertyorientation