I'm trying to make an app with swift, and I want to use front-facing camera. I used AVFoundation and tried some codes. But I couldn't set front-facing zoom parameter. Is it possible? For back-camera, everything worked successfully.
I dont want to use Affine Transform. Because, it can be decrease image quality. So, how can I set this parameter programatically?
Thanks.
You'll need to add a zoomFactor variable to your camera.
var zoomFactor: CGFloat = 1.0
Next define a function zoom to be used in conjunction with a pinch recognizer. I assume you have created a front capture device and input. frontDevice is an optional capture device on my camera. Here's how I zoom that device.
public func zoom(pinch: UIPinchGestureRecognizer) {
guard let device = frontDevice else { return }
func minMaxZoom(_ factor: CGFloat) -> CGFloat { return min(max(factor, 1.0), device.activeFormat.videoMaxZoomFactor) }
func update(scale factor: CGFloat) {
do {
try device.lockForConfiguration()
defer { device.unlockForConfiguration() }
device.videoZoomFactor = factor
} catch {
debugPrint(error)
}
}
let newScaleFactor = minMaxZoom(pinch.scale * zoomFactor)
switch pinch.state {
case .began: fallthrough
case .changed: update(scale: newScaleFactor)
case .ended:
zoomFactor = minMaxZoom(newScaleFactor)
update(scale: zoomFactor)
default: break
}
}
Finally add a pinch recognizer to some view.
let pgr = UIPinchGestureRecognizer(target: self, action: #selector(zoom))
view.addGestureRecognizer(pgr)
The previous answer can be done without the internal methods, allowing it to be more straightforward and understandable.
To fully explain the code:
The zoom
variable keeps track of what zoom you were at after the last gesture. Before any gesture happens there is no zoom, so you're at 1.0.
During a gesture the scale
property of pinch
holds the ratio of the pinch during the active gesture. This is 1.0 when your fingers haven't moved from their initial position and grows and shrinks with pinching. By multiplying this with the previously held zoom
you get what scale to be at in the moment while the gesture is occurring. It's important to keep this scale in the range of [1, device.activeFormat.videoMaxZoomFactor]
or you'll get a SIGABRT
.
When the gesture finishes (pinch.state
) you need to update zoom
so that the next gesture starts at the current zoom level.
It's important to lock when modifying a camera property to avoid concurrent modification. defer
will release the lock after the block of code no matter what, similar to a finally
block.
var zoom: CGFloat = 1.0
@objc func pinch(_ pinch: UIPinchGestureRecognizer) {
guard let device = frontDevice
else { return }
let scaleFactor = min(max(pinch.scale * zoom, 1.0), device.activeFormat.videoMaxZoomFactor)
if pinch.state == .ended {
zoom = scaleFactor
}
do {
try device.lockForConfiguration()
defer { device.unlockForConfiguration() }
device.videoZoomFactor = scaleFactor
} catch {
print(error)
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With