Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UIImagePickerController Camera Overlay that matches the default cropping

Here's my problem. I'm using UIImagePickerController to take a picture from the camera. After it's been taken (and because I set allowsEditing to TRUE), the preview image shows a white rectangle delimiting the default cropping area (which doesn't appear to be in the center of the picture).

What I want is to set a custom Camera Overlay that matches exactly that cropping area so that the user knows exactly that the picture he took will be the resulting image after cropping.

See picture below, basically I want the Camera Overlay to only display the red rectangle that represents the cropping rectangle in the preview. enter image description here

Any idea on how to implement this so it will work on all type of Iphone device (iphone 4, 5, 6, 6 plus) and Portrait/Landscape mode ?

Thanks for your help.

like image 264
fabdarice Avatar asked Feb 09 '15 21:02

fabdarice


1 Answers

To place a square in the center of your screen to give the user a 'guide' as to where they should be focusing the camera, do the following:


1) Add an extension to UIScreen and get an exact square based on either the height or width of screen (depending on if in landscape or not):

extension UIScreen {
    func fullScreenSquare() -> CGRect {
        var hw:CGFloat = 0
        var isLandscape = false
        if UIScreen.main.bounds.size.width < UIScreen.main.bounds.size.height {
        hw = UIScreen.main.bounds.size.width
    }
    else {
        isLandscape = true
        hw = UIScreen.main.bounds.size.height
    }

    var x:CGFloat = 0
    var y:CGFloat = 0
    if isLandscape {
        x = (UIScreen.main.bounds.size.width / 2) - (hw / 2)
    }
    else {
        y = (UIScreen.main.bounds.size.height / 2) - (hw / 2)
    }
        return CGRect(x: x, y: y, width: hw, height: hw)
    }
    func isLandscape() -> Bool {
        return UIScreen.main.bounds.size.width > UISc    reen.main.bounds.size.height
    }
}

2) Then write a method that you will utilize this to create a guide for the camera overlay:

func guideForCameraOverlay() -> UIView {
    let guide = UIView(frame: UIScreen.main.fullScreenSquare())
    guide.backgroundColor = UIColor.clear           
    guide.layer.borderWidth = 4
    guide.layer.borderColor = UIColor.red.cgColor
    guide.isUserInteractionEnabled = false
    return guide
}

3) Add the guide to your overlay:

picker.cameraOverlayView = guideForCameraOverlay()


BONUS Handle Orientation Change

In the class that you create your UIImagePickerController:

// Add this line where you instantiate your image picker
self.imagePicker.view.layer.addObserver(self, forKeyPath: "bounds", options: .new, context: nil)

And listen to the bounds change on the camera to reset the guide in the center of the screen:

override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
    if keyPath == "bounds" {
        if let picker = mediaPicker, picker.cameraCaptureMode == .photo {
            picker.cameraOverlayView = nil
            picker.cameraOverlayView = guideForCameraOverlay()
        }
    }
}

And don't forget to remove the observer when you are finished:

self.imagePicker.view.layer.removeObserver(self, forKeyPath: "bounds")

like image 166
Brandon A Avatar answered Sep 28 '22 18:09

Brandon A