disable or enable capture button in UIImagePickerController - ios

I am using Gyroscope to determine my ipad is perpendicular (attitude of 88 to 92 degree) or not .
if it is then can take picture.
I have something like a traffic light red or green to show permission of take picture but I can not disable capture button when the light is red
any help would be appreciated
here is my code
#IBAction func camera1(_ sender: Any) {
var imageView : UIImageView
imageView = UIImageView(frame:CGRect(x:10, y:10, width:50, height:50));
let imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.allowsEditing = true
imagePicker.sourceType = .camera
imagePicker.cameraCaptureMode = .photo
imagePicker.cameraOverlayView = imageView
imagePicker.cameraViewTransform = imagePicker.cameraViewTransform.scaledBy(x: 3, y: 3);
//Gyroscop
func myGyroscope() {
motion.deviceMotionUpdateInterval = 0.2
motion.startDeviceMotionUpdates(to: OperationQueue()) { (motion, error) -> Void in
if let attitude = motion?.attitude {
// print(attitude.roll * 180 / Double.pi)
DispatchQueue.main.async{
if (((attitude.roll * 180 / Double.pi) * -1) > 88 && ((attitude.roll * 180 / Double.pi) * -1) < 92 ){
imageView.image = #imageLiteral(resourceName: "GREEN_Light")//Take picture is permitted
} else{
imageView.image = #imageLiteral(resourceName: "Red_Light")//Take picture is not permitted
}
}
}
}
}
myGyroscope()
present(imagePicker, animated: true, completion: nil)
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
if let pickedImage = info[UIImagePickerController.InfoKey.originalImage] as? UIImage {
frontpic.contentMode = .scaleAspectFit
if (picker.sourceType.rawValue == 1){//if camera
frontpic.image = pickedImage.cropedToRatio(ratio: 0.33)
} else{//if album
frontpic.image = pickedImage
}
}
dismiss(animated: true, completion: nil)
}

You cannot interfere with the built in camera controls. If you don't like way they behave, remove them and substitute your own interface as part of the cameraOverlayView.

Related

How to flip inverted selfie image in UIImagePickerController in preview view in swift 5

Initializing image picker
imagePicker.sourceType = UIImagePickerController.SourceType.camera
//If you dont want to edit the photo then you can set allowsEditing to false
imagePicker.allowsEditing = false
imagePicker.delegate = self
imagePicker.sourceType = .camera
imagePicker.cameraDevice = .front
imagePicker.cameraCaptureMode = .photo
// imagePicker.modalPresentationStyle = UIModalPresentationStyle.overCurrentContext
imagePicker.cameraOverlayView = nil
imagePicker.showsCameraControls = true
self.present(imagePicker, animated: true, completion: nil)
extension of ImagePickerController
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
guard var image = info [.originalImage] as? UIImage else {
return
}
if picker.cameraDevice == UIImagePickerController.CameraDevice.front {
image = UIImage(cgImage: image.cgImage!, scale: image.scale, orientation:.leftMirrored)
} else {
print("back")
}
picker.dismiss(animated: true)
}
The image taken from the selfie camera gets flipped. How can we fix this?
//MARK: - CGAffineTransform(scaleX: CGFloat, y: CGFloat) initializer helps flipping image according to x and y values
image.transform = CGAffineTransform(scaleX: -1, y: 1)
//image is imageView
Helpful references: You can find the all project codes in GitHub repo link and the other methods of flipping, and descriptions are exist in apple documentation link from below links.
https://github.com/ahmetbostanciklioglu/ImagePickerController.git
https://developer.apple.com/documentation/coregraphics/1455016-cgaffinetransformmakescale

Using Vision to scan images from photo library

Is there a way that I can use the Vision framework to scan an existing image from the user's photo library? As in, not taking a new picture using the camera, but just choosing an image that the user already has?
Yes, you can. Adding on to #Zulqarnayn's answer, here's a working example to detect and draw a bounding box on rectangles.
1. Set up the image view where the image will be displayed
#IBOutlet weak var imageView: UIImageView!
#IBAction func pickImage(_ sender: Any) {
let picker = UIImagePickerController()
picker.delegate = self
self.present(picker, animated: true)
}
override func viewDidLoad() {
super.viewDidLoad()
imageView.layer.borderWidth = 4
imageView.layer.borderColor = UIColor.blue.cgColor
imageView.contentMode = .scaleAspectFill
imageView.backgroundColor = UIColor.green.withAlphaComponent(0.3)
imageView.layer.masksToBounds = false /// allow image to overflow, for testing purposes
}
2. Get the image from the image picker
extension ViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
guard let image = info[.originalImage] as? UIImage else { return }
/// set the imageView's image
imageView.image = image
/// start the request & request handler
detectCard()
/// dismiss the picker
dismiss(animated: true)
}
}
3. Start the vision request
func detectCard() {
guard let cgImage = imageView.image?.cgImage else { return }
/// perform on background thread, so the main screen is not frozen
DispatchQueue.global(qos: .userInitiated).async {
let request = VNDetectRectanglesRequest { request, error in
/// this function will be called when the Vision request finishes
self.handleDetectedRectangle(request: request, error: error)
}
request.minimumAspectRatio = 0.0
request.maximumAspectRatio = 1.0
request.maximumObservations = 1 /// only look for 1 rectangle
let imageRequestHandler = VNImageRequestHandler(cgImage: cgImage, orientation: .up)
do {
try imageRequestHandler.perform([request])
} catch let error {
print("Error: \(error)")
}
}
}
4. Get the result from the Vision request
func handleDetectedRectangle(request: VNRequest?, error: Error?) {
if let results = request?.results {
if let observation = results.first as? VNRectangleObservation {
/// get back to the main thread
DispatchQueue.main.async {
guard let image = self.imageView.image else { return }
let convertedRect = self.getConvertedRect(
boundingBox: observation.boundingBox,
inImage: image.size,
containedIn: self.imageView.bounds.size
)
self.drawBoundingBox(rect: convertedRect)
}
}
}
}
5. Convert observation.boundingBox to the UIKit coordinates of the image view, then draw a border around the detected rectangle
I explain this more in detail in this answer.
func getConvertedRect(boundingBox: CGRect, inImage imageSize: CGSize, containedIn containerSize: CGSize) -> CGRect {
let rectOfImage: CGRect
let imageAspect = imageSize.width / imageSize.height
let containerAspect = containerSize.width / containerSize.height
if imageAspect > containerAspect { /// image extends left and right
let newImageWidth = containerSize.height * imageAspect /// the width of the overflowing image
let newX = -(newImageWidth - containerSize.width) / 2
rectOfImage = CGRect(x: newX, y: 0, width: newImageWidth, height: containerSize.height)
} else { /// image extends top and bottom
let newImageHeight = containerSize.width * (1 / imageAspect) /// the width of the overflowing image
let newY = -(newImageHeight - containerSize.height) / 2
rectOfImage = CGRect(x: 0, y: newY, width: containerSize.width, height: newImageHeight)
}
let newOriginBoundingBox = CGRect(
x: boundingBox.origin.x,
y: 1 - boundingBox.origin.y - boundingBox.height,
width: boundingBox.width,
height: boundingBox.height
)
var convertedRect = VNImageRectForNormalizedRect(newOriginBoundingBox, Int(rectOfImage.width), Int(rectOfImage.height))
/// add the margins
convertedRect.origin.x += rectOfImage.origin.x
convertedRect.origin.y += rectOfImage.origin.y
return convertedRect
}
/// draw an orange frame around the detected rectangle, on top of the image view
func drawBoundingBox(rect: CGRect) {
let uiView = UIView(frame: rect)
imageView.addSubview(uiView)
uiView.backgroundColor = UIColor.clear
uiView.layer.borderColor = UIColor.orange.cgColor
uiView.layer.borderWidth = 3
}
Result | Demo repo
Input image
Result
Yes, you can. First, take an instance of UIImagePickerController & present it.
let picker = UIImagePickerController()
picker.delegate = self
picker.sourceType = .photoLibrary
present(picker, animated: true, completion: nil)
Then implement the delegate method take the desired image
extension YourViewController: UIImagePickerControllerDelegate {
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
if let pickedImage = info[.originalImage] as? UIImage {
## here start your request & request handler
}
picker.dismiss(animated: true, completion: nil)
}
}

How to crop area from camera

I have draw a rectangle with in the native camera view, I'm trying to use it as a guide or crop area to capture only the business card image, I'm unable to crop image from camera native view within drawn rectangle
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/3*2)
}
func isLandscape() -> Bool {
return UIScreen.main.bounds.size.width > UIScreen.main.bounds.size.height
}
}
func guideForCameraOverlay() -> UIView {
let guide = UIView(frame: UIScreen.main.fullScreenSquare())
guide.backgroundColor = UIColor.clear
guide.layer.borderWidth = 4
guide.layer.borderColor = UIColor.orange.cgColor
guide.isUserInteractionEnabled = false
return guide
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
if setPhoto == 1 {
if let image = info[UIImagePickerController.InfoKey.editedImage] as? UIImage{
let size = CGSize(width: 600, height: 400)
//let imageCroped = image.cgImage?.cropping(to: size)
let imageCroped = image.crop(to: size)
frontPhotoImageView.image = UIImage(cgImage: imageCroped as! CGImage)
setPhoto = 0
frontPhotoImage.setTitle("", for: UIControl.State.normal)
}
else {
// Error message
}
self.dismiss(animated: true, completion: nil)
}
if setPhoto == 2 {
if let image = info[UIImagePickerController.InfoKey.editedImage] as? UIImage{
backPhotoImageView.image = image
setPhoto = 0
backPhotoImage.setTitle("", for: UIControl.State.normal)
}
else {
// Error message
}
self.dismiss(animated: true, completion: nil)
}
}
I expect to have the image from with in the drawn rectangle, but it does not happen.
I expect to crop the image to the size inside the orange rectangle on this image

Image Selected From Image Picker Not Displaying

I'm kind of lost. My Image Picker is working but the image is not displaying in my Image View. I have looked over my code and various solutions and it still is not working. I have set the delegate to self and double checked my methods and it is still not showing the image where it is supposed to.
import UIKit
class AlterProfileViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
view?.backgroundColor = UIColor.white
navigationItem.title = "Profile Settings"
view.addSubview(selectProfileImage)
///Constraints for all views will go here
_ = selectProfileImage.anchor(view.centerYAnchor, left: view.leftAnchor, bottom: nil, right: nil, topConstant: -275, leftConstant: 135, bottomConstant: 0, rightConstant: 0, widthConstant: 100, heightConstant: 100)
// selectProfileImage.layer.cornerRadius = selectProfileImage.frame.size.width/2
///////////////////////////////////////////////
// Do any additional setup after loading the view.
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
selectProfileImage.layer.cornerRadius = selectProfileImage.frame.size.width / 2;
selectProfileImage.layer.masksToBounds = true
}
//Where all buttons and labels will be added
//will just be a nice looking image view to be next to the profile settings button
lazy var selectProfileImage: UIImageView = {
let selectPicture = UIImageView()
// self.selectProfileImage.layer.cornerRadius = self.selectProfileImage.frame.size.width / 2;
selectPicture.image = UIImage(named: "Paris")
// selectPicture.layer.cornerRadius = selectPicture.frame.size.width / 2;
selectPicture.clipsToBounds = true
selectPicture.translatesAutoresizingMaskIntoConstraints = false
selectPicture.layer.cornerRadius = selectPicture.frame.size.width/2
selectPicture.contentMode = .scaleAspectFill
selectPicture.isUserInteractionEnabled = true
selectPicture.layer.shouldRasterize = true
// will allow you to add a target to an image click
selectPicture.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(handleSelectProfileImageView)))
selectPicture.layer.masksToBounds = true
return selectPicture
}()
func handleSelectProfileImageView() {
print("123")
let picker = UIImagePickerController()
picker.delegate = self
picker.allowsEditing = true
present(picker, animated: true, completion: nil)
}
// will dispaly info of image selected
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
print("info")
var selectedImageFromPicker: UIImage?
if let editedImage = info["UIImagePickerControllerEditedImage"] as? UIImage{
print((editedImage as AnyObject).size)
selectedImageFromPicker = editedImage
}else if let originalImage = info["UIImagePickerControllerOriginalImage"] as? UIImage{
print((originalImage as AnyObject).size)
selectedImageFromPicker = originalImage
}
if let selectedImage = selectedImageFromPicker {
selectProfileImage.image = selectedImage
}
dismiss(animated: true, completion: nil)
}
// will handle the picker being closed/canceled
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
print("picker canceled")
dismiss(animated: true, completion: nil)
}
///////////////////////////////////////////////////////////////////////////////////
}

imagepicker doesnt show the image when using cameraoverlay

I wanted to customize the camera scene so i used custom overlay. It is hiding the default camera buttons and showing other buttons. When i take the picture, I want to see the static image but I see only the camera again.I tried putting a image view in the customView but the camera still runs in the background.
func cameraProperty()
{
DispatchQueue.main.async(execute: {
//let imagePicker = UIImagePickerController()
self.picker.navigationBar.isTranslucent = false
self.picker.navigationBar.barTintColor = .blue // Background color
self.picker.navigationBar.tintColor = .white // Cancel button ~ any UITabBarButton items
self.picker.navigationBar.titleTextAttributes = [
NSForegroundColorAttributeName : UIColor.white
] //
self.picker.sourceType = UIImagePickerControllerSourceType.camera
self.picker.cameraDevice = .front
self.picker.delegate = self
self.picker.showsCameraControls = false
self.picker.modalPresentationStyle = .fullScreen
//customView stuff
let customViewController = CustomOverlayViewController(
nibName:"CustomOverlayViewController",
bundle: nil
)
let customView:CustomOverlayView = customViewController.view as! CustomOverlayView
customView.frame = self.picker.view.frame
customView.delegate = self
customView.skipBtn.setTitle("SKIP", for: .normal)
customView.createSongBtn.isHidden = true
customView.takePhotoBtn.isHidden = false
customView.curImg.isHidden = true
//CGSize screenSize = [[UIScreen mainScreen] bounds].size;
let screenSize:CGSize = UIScreen.main.bounds.size
let ratio:CGFloat = 4.0 / 3.0
let cameraHeight:CGFloat = screenSize.width * ratio
let scale:CGFloat = screenSize.height / cameraHeight
//need to test it for different phone sizes
self.picker.cameraViewTransform = CGAffineTransform(translationX: 0, y: (screenSize.height - cameraHeight) / 2.0)
self.picker.cameraViewTransform = self.picker.cameraViewTransform.scaledBy(x: scale, y: scale)
self.picker.cameraOverlayView = customView
self.picker.allowsEditing = false
})
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController){
picker.dismiss(animated: true, completion: nil)
}
//MARK: Custom View Delegates
func didCancel(overlayView:CustomOverlayView) {
DispatchQueue.main.async(execute: {
if overlayView.skipBtn.titleLabel?.text == "SKIP"
{
self.picker.dismiss(animated: true,completion: nil)
print("dismissed!!")
}
else
{
overlayView.skipBtn.setTitle("SKIP", for: .normal)
overlayView.createSongBtn.isHidden = true
// overlayView.curImg.isHidden = true
overlayView.takePhotoBtn.isHidden = false
print("Reset camera")
}
})
}
func didShoot(overlayView:CustomOverlayView) {
DispatchQueue.main.async(execute: {
self.picker.takePicture()
overlayView.skipBtn.setTitle("Try Again", for: .normal)
// overlayView.sendSubview(toBack: overlayView.curImg)
overlayView.createSongBtn.isHidden = false
overlayView.takePhotoBtn.isHidden = true
})
print("Shot Photo")
}
How can I show the view with image(that is also custom view) and something like "Use photo" option.

Resources