You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS中基于Swift 4实现自定义画中画(PIP)相机的技术问询

针对你用Swift 4实现iOS画中画(PIP)相机的需求,结合你提到的几个控件,我整理了一套实时效果处理的可行方案,帮你落地实现:

核心控件职责梳理

先明确你用到的几个视图的分工,确保流程清晰:

  • FrontCameraView: 作为背景层,显示模糊化的前置摄像头画面
  • BackCameraView: 作为前景画中画窗口,显示后置摄像头的清晰画面
  • MaskedCameraView: 叠加在最上层,显示自定义遮罩图像,配合Frame Image实现画中画边框效果
  • Frame Image: 承载画中画的边框UI,和MaskedCameraView配合强化视觉层级
实时效果核心实现(captureOutput代理方法)

相机捕获帧的实时处理逻辑都在captureOutput(_:didOutput:from:)方法里,这里要完成帧转图像、效果处理、UI更新三个核心步骤,代码示例如下:

func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
    // 1. 将CMSampleBuffer转换为可处理的UIImage
    guard let imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else {
        print("无法获取图像缓冲区")
        return
    }
    
    let ciImage = CIImage(cvImageBuffer: imageBuffer)
    let context = CIContext(options: [.useSoftwareRenderer: false]) // 用GPU加速渲染
    guard let cgImage = context.createCGImage(ciImage, from: ciImage.extent) else {
        print("无法转换为CGImage")
        return
    }
    let capturedImage = UIImage(cgImage: cgImage)
    
    // 2. 判断当前捕获的是前置/后置摄像头画面,分别处理
    if connection.inputDevice.position == .front {
        // 给前置画面添加模糊效果
        let blurredFrontImage = applyGaussianBlur(to: capturedImage, radius: 8)
        // 必须回到主线程更新UI
        DispatchQueue.main.async {
            self.FrontCameraView.image = blurredFrontImage
        }
    } else if connection.inputDevice.position == .back {
        // 后置画面作为画中画内容,直接赋值并调整位置
        DispatchQueue.main.async {
            self.BackCameraView.image = capturedImage
            // 设置画中画的位置(示例:右下角),也可以用AutoLayout适配不同屏幕
            self.BackCameraView.frame = CGRect(
                x: self.view.bounds.width - 140,
                y: self.view.bounds.height - 190,
                width: 120,
                height: 160
            )
        }
    }
    
    // 3. 更新遮罩层图像,实现自定义视觉效果
    DispatchQueue.main.async {
        self.MaskedCameraView.image = self.customMaskImage // 替换为你的遮罩图
        // 设置混合模式让遮罩和底层画面融合,可根据需求调整
        self.MaskedCameraView.blendMode = .overlay
    }
}

// 自定义高斯模糊工具方法
private func applyGaussianBlur(to image: UIImage, radius: CGFloat) -> UIImage? {
    guard let ciImage = CIImage(image: image) else { return nil }
    
    let blurFilter = CIFilter(name: "CIGaussianBlur")!
    blurFilter.setValue(ciImage, forKey: kCIInputImageKey)
    blurFilter.setValue(radius, forKey: kCIInputRadiusKey)
    
    guard let outputImage = blurFilter.outputImage,
          let cgImage = CIContext().createCGImage(outputImage, from: outputImage.extent) else {
        return nil
    }
    
    return UIImage(cgImage: cgImage)
}
关键注意事项
  • 所有UI更新操作必须放在DispatchQueue.main.async中,因为captureOutput方法在后台线程执行,直接操作UI会导致崩溃
  • 画中画的位置和尺寸建议用AutoLayout约束代替硬编码frame,适配不同屏幕尺寸
  • 遮罩图像的混合模式可以尝试不同选项(比如.normal、.multiply、.screen),得到不同的视觉效果
  • 别忘了在Info.plist中添加NSCameraUsageDescription字段,申请相机权限,否则App会直接崩溃

内容的提问来源于stack exchange,提问作者Pratz_iOS

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:47:44