如何用AVFoundation获取1:1/16:9比例ProRAW图像及无损裁剪
获取1:1/16:9比例ProRAW图像及无损裁剪方案
一、通过AVFoundation直接获取对应比例的ProRAW
iPhone 11及以后机型的16:9/1:1 ProRAW确实是从传感器原生4:3画面裁剪而来,无需先获取4:3再手动裁剪,通过配置AVCapturePhotoOutput可直接得到对应比例输出:
配置ProRAW照片设置与目标比例
先获取设备支持的ProRAW格式,再为照片设置指定目标比例:// 获取支持ProRAW的像素格式 guard let rawFormat = capturePhotoOutput.availableRawPhotoPixelFormatTypes.first else { // 处理设备不支持ProRAW的情况 return } // 创建ProRAW拍摄设置 let photoSettings = AVCapturePhotoSettings(rawPixelFormatType: rawFormat) // 指定目标比例:1:1传CGSize(width:1, height:1),16:9传CGSize(width:16, height:9) let targetRatio = CGSize(width: 16, height: 9) if let matchedFormat = capturePhotoOutput.bestRawPhotoFormat(for: targetRatio, deliverablePreviewPixelFormatType: kCVPixelFormatType_32BGRA) { photoSettings.previewPhotoFormat = [kCVPixelBufferPixelFormatTypeKey as String: matchedFormat] photoSettings.maxPhotoDimensions = matchedFormat.dimensions } // 触发拍摄 capturePhotoOutput.capturePhoto(with: photoSettings, delegate: self)调整会话预设
确保AVCaptureSession使用.photo预设,避免固定为4:3的分辨率限制:captureSession.sessionPreset = .photo
二、ProRAW无损裁剪方案
如果必须先获取4:3 ProRAW再裁剪,需基于DNG原始数据操作,避免转码损失:
用ImageIO实现无损裁剪(保留DNG格式)
import ImageIO func cropProRAWToTargetRatio(rawURL: URL, targetRatio: CGSize) -> Data? { guard let imageSource = CGImageSourceCreateWithURL(rawURL as CFURL, nil) else { return nil } guard let rawProperties = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, nil) as? [CFString: Any] else { return nil } // 获取原始图像尺寸 let originalWidth = rawProperties[kCGImagePropertyPixelWidth] as! CGFloat let originalHeight = rawProperties[kCGImagePropertyPixelHeight] as! CGFloat let originalRatio = originalWidth / originalHeight // 计算居中裁剪区域 var cropRect: CGRect if (targetRatio.width / targetRatio.height) > originalRatio { // 16:9比例,裁剪上下部分 let targetHeight = originalWidth * targetRatio.height / targetRatio.width let yOffset = (originalHeight - targetHeight) / 2 cropRect = CGRect(x: 0, y: yOffset, width: originalWidth, height: targetHeight) } else { // 1:1比例,裁剪左右部分 let targetWidth = originalHeight * targetRatio.width / targetRatio.height let xOffset = (originalWidth - targetWidth) / 2 cropRect = CGRect(x: xOffset, y: 0, width: targetWidth, height: originalHeight) } // 配置裁剪选项,保留RAW元数据 let cropOptions: [CFString: Any] = [ kCGImageSourceCreateThumbnailFromImageAlways: true, kCGImageSourceCreateThumbnailWithTransform: true, kCGImageSourceThumbnailMaxPixelSize: max(cropRect.width, cropRect.height), kCGImageSourceCropRect: cropRect ] guard let croppedCGImage = CGImageSourceCreateThumbnailAtIndex(imageSource, 0, cropOptions as CFDictionary) else { return nil } // 将裁剪后的图像保存为DNG格式 let outputData = NSMutableData() guard let imageDestination = CGImageDestinationCreateWithData(outputData, kUTTypeDNG, 1, nil) else { return nil } CGImageDestinationAddImage(imageDestination, croppedCGImage, rawProperties as CFDictionary) guard CGImageDestinationFinalize(imageDestination) else { return nil } return outputData as Data }
三、现有代码调整建议
结合你提供的代码逻辑,需检查以下几点:
- 确认是否为
AVCapturePhotoSettings指定了匹配目标比例的maxPhotoDimensions或previewPhotoFormat; - 避免将
captureSession.sessionPreset设置为固定比例的预设(如.hd1920x1080),保持为.photo; - 创建
AVCapturePhotoSettings时,需明确关联ProRAW格式与目标比例的适配配置。
内容的提问来源于stack exchange,提问作者no13bus
相关产品推荐
相关产品推荐

