Как установить уровень масштабирования задней камеры на 0,5x с помощью Swift?
У меня работает функция масштабирования (1x и далее) для пользовательской камеры, реализованной с использованием AVFoundation. Это нормально до моделей iPhone X. Но я хотел иметь 0,5-кратный зум на устройствах iPhone 11 и iPhone 11 Pro.
Код, который я написал, не работает для увеличения 0,5x. Я перепробовал все возможные комбинации
[.builtInTripleCamera, .builtInDualWideCamera, .builtInUltraWideCamera]
. Устройство захвата с типом устройства
.builtinUltraWideCamera
не дает 0,5 для
minAvailableVideoZoomFactor
.
Во время тестирования на iPhone 11 я также удалил
[.builtInDualCamera, .builtInTelephotoCamera, .builtInWideAngleCamera, .builtInTrueDepthCamera]
из
deviceTypes
.
Благодарим за любую помощь в решении этой проблемы. Ниже приведен код, который работает для увеличения на 1х.
/// Called from -handlePinchGesture
private func zoom(_ scale: CGFloat) {
let captureDevice = cameraDevice(.back)
do {
try captureDevice?.lockForConfiguration()
var minZoomFactor: CGFloat = captureDevice?.minAvailableVideoZoomFactor ?? 1.0
let maxZoomFactor: CGFloat = captureDevice?.maxAvailableVideoZoomFactor ?? 1.0
if #available(iOS 13.0, *) {
if captureDevice?.deviceType == .builtInDualWideCamera || captureDevice?.deviceType == .builtInTripleCamera || captureDevice?.deviceType == .builtInUltraWideCamera {
minZoomFactor = 0.5
}
}
zoomScale = max(minZoomFactor, min(beginZoomScale * scale, maxZoomFactor))
captureDevice?.videoZoomFactor = zoomScale
captureDevice?.unlockForConfiguration()
} catch {
print("ERROR: locking configuration")
}
}
@objc private func handlePinchGesture(_ recognizer: UIPinchGestureRecognizer) {
var allTouchesOnPreviewLayer = true
let numTouch = recognizer.numberOfTouches
for i in 0 ..< numTouch {
let location = recognizer.location(ofTouch: i, in: view)
let convertedTouch = previewLayer.convert(location, from: previewLayer.superlayer)
if !previewLayer.contains(convertedTouch) {
allTouchesOnPreviewLayer = false
break
}
}
if allTouchesOnPreviewLayer {
zoom(recognizer.scale)
}
}
func cameraDevice(_ position: AVCaptureDevice.Position) -> AVCaptureDevice? {
var deviceTypes = [AVCaptureDevice.DeviceType]()
deviceTypes.append(contentsOf: [.builtInDualCamera, .builtInTelephotoCamera, .builtInWideAngleCamera, .builtInTrueDepthCamera])
if #available(iOS 13.0, *) {
deviceTypes.append(contentsOf: [.builtInTripleCamera, .builtInDualWideCamera, .builtInUltraWideCamera])
}
let availableCameraDevices = AVCaptureDevice.DiscoverySession(deviceTypes: deviceTypes, mediaType: .video, position: position).devices
guard availableCameraDevices.isEmpty == false else {
debugPrint("ERROR: No camera devices found!!!")
return nil
}
for device in availableCameraDevices {
if device.position == position {
return device
}
}
guard let defaultDevice = AVCaptureDevice.default(for: AVMediaType.video) else {
debugPrint("ERROR: Can't initialize default back camera!!!")
return nil
}
return defaultDevice
}
4 ответа
Минимальное свойство zoomFactor для AVCaptureDevice не может быть меньше 1.0 согласно Apple Docs. Это немного сбивает с толку, потому что в зависимости от того, какую камеру вы выбрали, коэффициент масштабирования 1 будет другим полем зрения или оптическим углом обзора. В приложении камеры iPhone по умолчанию отображается метка «0,5», но это просто метка для сверхширокоугольного объектива по отношению к коэффициенту масштабирования стандартной камеры.
Вы уже получаете minZoomFactor от устройства (который, вероятно, будет равен 1), поэтому вам следует использовать считываемые вами минимальные и максимальные значения устройства, чтобы установить границы фактора, вводимого вами в "captureDevice.videoZoomFactor". Затем, когда вы выбрали сверхширокоугольный объектив, установка коэффициента масштабирования на 1 будет настолько широкой, насколько это возможно! (коэффициент 0,5 по отношению к полю зрения стандартного объектива).
Обновление для людей, которые хотят установить уровень оптического увеличения 0,5x
любезно предоставлено: https://github.com/NextLevel/NextLevel/issues/187
public class func primaryVideoDevice(forPosition position: AVCaptureDevice.Position) -> AVCaptureDevice? {
// -- Changes begun
if #available(iOS 13.0, *) {
let hasUltraWideCamera: Bool = true // Set this variable to true if your device is one of the following - iPhone 11, iPhone 11 Pro, & iPhone 11 Pro Max
if hasUltraWideCamera {
// Your iPhone has UltraWideCamera.
let deviceTypes: [AVCaptureDevice.DeviceType] = [AVCaptureDevice.DeviceType.builtInUltraWideCamera]
let discoverySession = AVCaptureDevice.DiscoverySession(deviceTypes: deviceTypes, mediaType: AVMediaType.video, position: position)
return discoverySession.devices.first
}
}
// -- Changes end
var deviceTypes: [AVCaptureDevice.DeviceType] = [AVCaptureDevice.DeviceType.builtInWideAngleCamera] // builtInWideAngleCamera // builtInUltraWideCamera
if #available(iOS 11.0, *) {
deviceTypes.append(.builtInDualCamera)
} else {
deviceTypes.append(.builtInDuoCamera)
}
// prioritize duo camera systems before wide angle
let discoverySession = AVCaptureDevice.DiscoverySession(deviceTypes: deviceTypes, mediaType: AVMediaType.video, position: position)
for device in discoverySession.devices {
if #available(iOS 11.0, *) {
if (device.deviceType == AVCaptureDevice.DeviceType.builtInDualCamera) {
return device
}
} else {
if (device.deviceType == AVCaptureDevice.DeviceType.builtInDuoCamera) {
return device
}
}
}
return discoverySession.devices.first
}
Мы не можем установить коэффициент масштабирования меньше 1.
Я решаю эту проблему, используя ".builtInDualWideCamera".
В этом случае мы используем «сверхширокоугольную камеру» с коэффициентом масштабирования 2,0 (будет значением по умолчанию), равным нормальному коэффициенту масштабирования «широкоугольной камеры». (минимальное значение будет 1.0)
Если ваш iPhone не поддерживает «.builtInDualWideCamera», мы будем использовать «.builtInWideAngleCamera» как обычно, а коэффициент масштабирования равен 1.0 (минимальное значение).
func getCameraDevices() -> [AVCaptureDevice] {
var deviceTypes = [AVCaptureDevice.DeviceType]()
if #available(iOS 13.0, *) {
deviceTypes.append(contentsOf: [.builtInDualWideCamera])
self.isUltraWideCamera = true
self.defaultZoomFactor = 2.0
}
if(deviceTypes.isEmpty){
deviceTypes.append(contentsOf: [.builtInWideAngleCamera])
self.isUltraWideCamera = false
self.defaultZoomFactor = 1.0
}
return AVCaptureDevice.DiscoverySession(deviceTypes: deviceTypes, mediaType: .video, position: .unspecified).devices
}
Проблема в том, что вы пытаетесь достать какой-нибудь девайс из
Так было для меня с iPhone 12Pro Max, возвращая только одно устройство для позиции «Назад», тип отчета.
Решение не было очевидным: используйте