Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pinch to zoom camera

I'm trying to make a pinch to zoom camera but I'm encountering two problems. First is that it allows the user to zoom way too much in and way to much out, secondly when I take a picture it doesn't take it of the zoomed in view. Here is my code for the pinch function...

func pinch(pinch: UIPinchGestureRecognizer) {
    if let view = cameraView {
        view.transform = CGAffineTransformScale(view.transform,
            pinch.scale, pinch.scale)
            pinch.scale = 1
    }

}

Tell me if you need to see any more code. Thanks!

like image 441
John Doe Avatar asked Oct 16 '15 22:10

John Doe


People also ask

What is a pinch zoom?

What is pinch-to-zoom? Pinch-to-zoom is when a user uses two fingers and pinches to zoom in or out on their mobile device. While it wasn't present on the original touchscreen phones, pinch-to-zoom is now a nearly universal motion for adjusting size on touchscreen devices.

How do I pinch my screen to zoom?

Pinch 2 or more fingers together or apart to adjust zoom. To zoom temporarily, quickly tap the screen 3 times and hold down your finger on the third tap. Drag your finger to move around the screen. Lift your finger to zoom out.

Is the finger zoom real?

Pinch to zoom is a mechanical gesture you make with your fingers on a touchscreen that enacts a bit of digital manipulation. It's not actually a pinch, though, more of a reverse pinch. However, calling it "pinch out to zoom in and pinch in to zoom out" would make things even more confusing.

What is pinch screen?

1. Pinch describes a finger gesture used with a touch screen interface that supports multi-touch. The user touches the screen with two or more fingers, and moves them together or apart to zoom in or out. This function is also referred to as a semantic zoom or pinch-to-zoom. 2.


2 Answers

I have experienced the same issues with the camera implementation. To solve this you need to know about two things.

  • The max and min zoom has to be within a value or else it results in the camera zooming in way too much.
  • As with the actual image not saving the zoomed in image, it is a common bug a lot of solutions online do not cover. This is actually because you are only changing the view's zoom and not the actual AVCaptureDevice's zoom.

To change the two things you need something like this:

func pinch(pinch: UIPinchGestureRecognizer) {
   var device: AVCaptureDevice = self.videoDevice
   var vZoomFactor = ((gestureRecognizer as! UIPinchGestureRecognizer).scale)
   var error:NSError!
        do{
            try device.lockForConfiguration()
            defer {device.unlockForConfiguration()}
            if (vZoomFactor <= device.activeFormat.videoMaxZoomFactor){
                device.videoZoomFactor = vZoomFactor
            }else{
            NSLog("Unable to set videoZoom: (max %f, asked %f)", device.activeFormat.videoMaxZoomFactor, vZoomFactor);
            }
        }catch error as NSError{
             NSLog("Unable to set videoZoom: %@", error.localizedDescription);
        }catch _{

        }
}

As you can see I use a class variable for the video device (videoDevice) to keep track of the capture device I am using for visual component. I restrict the zoom to a particular range and change the zoom property on the device and not the view itself!

like image 33
Ritvik Upadhyaya Avatar answered Oct 18 '22 22:10

Ritvik Upadhyaya


Swift 3.0 || 4.0


1. Define zoom levels.

let minimumZoom: CGFloat = 1.0
let maximumZoom: CGFloat = 3.0
var lastZoomFactor: CGFloat = 1.0


2. Add Pinch Gesture on CameraView.

let pinchRecognizer = UIPinchGestureRecognizer(target: self, action:#selector(pinch(_:)))        
            self.viewCamera.addGestureRecognizer(pinchRecognizer)


3. Pinch-action method with the logic of zoomin and zoom out

func pinch(_ pinch: UIPinchGestureRecognizer) {
        guard let device = videoDeviceInput.device else { return }

        // Return zoom value between the minimum and maximum zoom values
        func minMaxZoom(_ factor: CGFloat) -> CGFloat {
            return min(min(max(factor, minimumZoom), maximumZoom), device.activeFormat.videoMaxZoomFactor)
        }

        func update(scale factor: CGFloat) {
            do {
                try device.lockForConfiguration()
                defer { device.unlockForConfiguration() }
                device.videoZoomFactor = factor
            } catch {
                print("\(error.localizedDescription)")
            }
        }

        let newScaleFactor = minMaxZoom(pinch.scale * lastZoomFactor)

        switch pinch.state {
        case .began: fallthrough
        case .changed: update(scale: newScaleFactor)
        case .ended:
            lastZoomFactor = minMaxZoom(newScaleFactor)
            update(scale: lastZoomFactor)
        default: break
        }
    }


Thanks. Happy coding 👍🏼

like image 191
Hanny Avatar answered Oct 18 '22 22:10

Hanny