iOS使用AVCapturePhotoOutput拍照相比预览向下偏移如何解决?
问题原因
这个偏移本质是预览画面的显示比例、朝向和最终输出照片的比例、朝向不匹配导致的:
你当前用的AVCaptureSession.Preset.photo输出的照片是4:3比例,而预览层默认用的是和屏幕匹配的16:9比例,你设置了.resizeAspectFill作为预览的填充模式,相当于把4:3的原始画面上下裁掉一部分之后显示为16:9的预览;但最终输出的照片是完整的4:3比例,你直接放到ImageView里显示的时候如果填充模式和裁剪规则和预览层不一致,就会出现上下偏移的视觉效果。
另外你没有显式设置捕获连接的朝向,也会导致输出照片的方向和预览方向不匹配,放大偏移问题。
解决步骤
- 首先保证显示拍照结果的
outputImageView的填充规则和预览层完全一致,同时开启边界裁剪:
// 放在viewDidLoad里配置outputImageView outputImageView.contentMode = .scaleAspectFill outputImageView.clipsToBounds = true outputImageView.frame = previewView.frame // 保证和预览层大小位置完全一致
- 显式设置捕获输出的朝向和预览朝向保持同步:
在调用capturePhoto之前,先同步photoOutput的连接朝向:
let photoSettings = AVCapturePhotoSettings() // 先同步朝向 if let photoConnection = photoOutput.connection(with: .video) { // 从预览层获取当前朝向,保持一致 photoConnection.videoOrientation = previewView.videoPreviewLayer.connection!.videoOrientation } if let photoPreviewType = photoSettings.availablePreviewPhotoPixelFormatTypes.first { photoSettings.previewPhotoFormat = [kCVPixelBufferPixelFormatTypeKey as String: photoPreviewType] photoOutput.capturePhoto(with: photoSettings, delegate: self) }
- 可选:如果不需要完整的4:3高分辨率照片,也可以直接修改会话预设为和预览比例匹配的16:9规格,从根源避免比例差导致的裁剪偏移:
// 把原来的avSession.sessionPreset = .photo替换为 avSession.sessionPreset = .hd1920x1080 // 16:9比例,和绝大多数iPhone的全屏预览比例一致
- 如果以上操作还有概率出现偏移,可以在拍照前锁定对焦和曝光,避免拍照瞬间的自动调整导致画面偏移:
// 拍照前执行这段代码锁定设备配置 do { try cameraDevice.lockForConfiguration() if cameraDevice.isExposureModeSupported(.locked) { cameraDevice.exposureMode = .locked } if cameraDevice.isFocusModeSupported(.locked) { cameraDevice.focusMode = .locked } cameraDevice.unlockForConfiguration() } catch { print("锁定配置失败: \(error)") } // 拍照完成之后再改回自动模式即可
注:使用该方案需要把你之前在viewDidLoad中定义的
cameraDevice改为ViewController的全局属性,方便访问调用。
内容的提问来源于stack exchange,提问作者aheze
相关产品推荐
相关产品推荐

