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

iOS中如何将CVPixelBuffer格式的灰度深度图转换为JPEG/PNG并保存?

解决iOS中CVPixelBuffer格式的深度图保存为JPEG/PNG的问题

我之前也碰到过一模一样的问题!能把深度图渲染到屏幕却存不了本地文件,核心原因是得把CVPixelBuffer里的灰度深度数据转换成可编码的图像格式,下面给你两种亲测有效的解决方法:

方法一:转成UIImage再保存(简单易上手)

先把CVPixelBuffer转换成UIImage,再利用UIImage自带的方法保存成JPEG/PNG,代码逻辑很直观:

import UIKit
import CoreImage

// 将CVPixelBuffer转为UIImage
func pixelBufferToUIImage(_ pixelBuffer: CVPixelBuffer) -> UIImage? {
    let ciImage = CIImage(cvPixelBuffer: pixelBuffer)
    // 用硬件加速的CIContext提升转换效率
    let context = CIContext(options: [.useSoftwareRenderer: false])
    guard let cgImage = context.createCGImage(ciImage, from: ciImage.extent) else {
        return nil
    }
    return UIImage(cgImage: cgImage)
}

// 保存UIImage到本地
if let depthImage = pixelBufferToUIImage(yourDepthPixelBuffer) {
    // 保存为JPEG(压缩质量0.8,可调整)
    if let jpegData = depthImage.jpegData(compressionQuality: 0.8) {
        let saveURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
            .appendingPathComponent("depth_map.jpg")
        try? jpegData.write(to: saveURL)
    }
    
    // 保存为PNG(无损,适合保留精确深度值)
    if let pngData = depthImage.pngData() {
        let saveURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
            .appendingPathComponent("depth_map.png")
        try? pngData.write(to: saveURL)
    }
}

如果你的CVPixelBuffer是16位灰度格式(比如kCVPixelFormatType_OneComponent16),记得在转换时指定对应的颜色空间和位图信息,避免出现颜色失真。

方法二:用ImageIO直接编码(高效适合大尺寸)

如果深度图尺寸较大,直接用ImageIO编码CVPixelBuffer会更高效,跳过UIImage的中间转换步骤:

import UIKit
import ImageIO
import MobileCoreServices

// 直接将CVPixelBuffer保存为图像文件
func saveDepthPixelBuffer(_ pixelBuffer: CVPixelBuffer, to url: URL, isPNG: Bool) throws {
    // 锁定像素缓冲区的内存地址
    CVPixelBufferLockBaseAddress(pixelBuffer, .readOnly)
    defer { CVPixelBufferUnlockBaseAddress(pixelBuffer, .readOnly) }
    
    let width = CVPixelBufferGetWidth(pixelBuffer)
    let height = CVPixelBufferGetHeight(pixelBuffer)
    let bytesPerRow = CVPixelBufferGetBytesPerRow(pixelBuffer)
    let baseAddress = CVPixelBufferGetBaseAddress(pixelBuffer)
    
    // 创建灰度颜色空间
    let colorSpace = CGColorSpaceCreateDeviceGray()
    // 根据像素格式设置位图信息(这里以8位灰度为例)
    let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.none.rawValue)
    
    // 创建CGContext
    guard let context = CGContext(data: baseAddress,
                                  width: width,
                                  height: height,
                                  bitsPerComponent: 8,
                                  bytesPerRow: bytesPerRow,
                                  space: colorSpace,
                                  bitmapInfo: bitmapInfo.rawValue) else {
        throw NSError(domain: "DepthSaveError", code: 0, userInfo: [NSLocalizedDescriptionKey: "无法创建CGContext"])
    }
    
    // 生成CGImage
    guard let cgImage = context.makeImage() else {
        throw NSError(domain: "DepthSaveError", code: 1, userInfo: [NSLocalizedDescriptionKey: "无法生成CGImage"])
    }
    
    // 创建图像编码目标
    let imageType = isPNG ? kUTTypePNG : kUTTypeJPEG
    guard let destination = CGImageDestinationCreateWithURL(url as CFURL, imageType, 1, nil) else {
        throw NSError(domain: "DepthSaveError", code: 2, userInfo: [NSLocalizedDescriptionKey: "无法创建编码目标"])
    }
    
    // 如果是JPEG,可以添加压缩质量参数
    let properties = isPNG ? nil : [kCGImageDestinationLossyCompressionQuality as String: 0.8] as CFDictionary
    CGImageDestinationAddImage(destination, cgImage, properties)
    
    // 完成编码
    guard CGImageDestinationFinalize(destination) else {
        throw NSError(domain: "DepthSaveError", code: 3, userInfo: [NSLocalizedDescriptionKey: "编码图像失败"])
    }
}

// 调用示例
let saveURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
    .appendingPathComponent("depth_map.png")
try? saveDepthPixelBuffer(yourDepthPixelBuffer, to: saveURL, isPNG: true)

额外注意事项

  • 确保你的CVPixelBuffer格式是标准灰度格式(比如kCVPixelFormatType_OneComponent8或kCVPixelFormatType_OneComponent16),否则需要先做格式转换。
  • 若要保留精确的深度数据,优先选择PNG格式保存;如果追求文件体积小,再选JPEG。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 09:03:00