我有变焦功能(1x以上(,用于使用AVFoundation实现的自定义相机。在iPhone X型号之前,这是可以的。但我想在iPhone 11和iPhone 11 Pro设备上放大0.5倍。
我写的代码无法将其放大0.5倍。我已经尝试了[.builtInTripleCamera, .builtInDualWideCamera, .builtInUltraWideCamera]
的所有可能组合。具有设备类型.builtinUltraWideCamera
的捕获设备对于minAvailableVideoZoomFactor
没有给出0.5。
在iPhone 11上测试时,我还从deviceTypes
中删除了[.builtInDualCamera, .builtInTelephotoCamera, .builtInWideAngleCamera, .builtInTrueDepthCamera]
。
感谢为解决此问题提供的任何帮助。以下是适用于1x放大的代码。
/// 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
}
最小"zoomFactor";根据Apple Docs的规定,AVCaptureDevice的属性不能小于1.0。这有点令人困惑,因为根据您选择的相机,缩放因子1将是不同的视场或光学视角。默认的iPhone相机应用程序显示标签;0.5〃;但这只是超宽镜头相对于标准相机变焦系数的一个标签。
你已经从设备中获得了minZoomFactor(可能是1(,所以你应该使用你正在读取的设备的最小值和最大值来设置你输入到";captureDevice.videoZoomFactor";。然后当你;我选择了超宽镜头,将缩放因子设置为1将尽可能宽!(相对于标准透镜的视场,系数为0.5(。
为希望设置光学变焦级别0.5倍的用户更新
礼貌: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
}
问题是,当您尝试从discoverySession.devices
获取某种类型的设备时,它会返回默认设备,该设备可能不支持您需要的超宽。
对我来说,iPhone 12Pro Max就是这样,只返回了一台设备作为后退位置,报告类型为BuiltInWideAngleCamera
,但那只是碱液,是中间的摄像头,不是广角的,不是长焦的。不知道为什么苹果开发人员会这样做,看起来像是一个过时的遗留架构。
解决方案并不明显:使用AVCaptureDevice.default(.builtInTripleCamera, for: .video, position: .back)
获得能够从1(逻辑0.5(缩放的真实设备
我们不能将缩放因子设置为小于1。
我通过使用";。内置双广角相机";。
在这种情况下,我们使用";超宽照相机";其中缩放因子2.0(将是默认值(等于"0"上的正常缩放因子;广角相机";。(最小值为1.0(
如果您的iPhone不支持";。builtInDualWideCamer";,我们将使用";。内置广角相机";正常情况下,缩放因子为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
}