【问题标题】:CGImageCreate with CGColorSpaceCreateDeviceGray on iOS12iOS12 上的 CGImageCreate 和 CGColorSpaceCreateDeviceGray
【发布时间】:2019-03-27 03:12:12
【问题描述】:

我使用 CGImageCreate 和 CGColorSpaceCreateDeviceGray 将缓冲区 (CVPixelBufferRef) 转换为灰度图像。它非常快并且在 iOS 12 之前运行良好......现在返回的图像是空的。

代码如下:

bitmapInfo = kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst;

CGDataProviderRef provider = CGDataProviderCreateWithData((void *)i_PixelBuffer,
                                                              sourceBaseAddr,
                                                              sourceRowBytes * height,
                                                              ReleaseCVPixelBuffer);
    retImage = CGImageCreate(width,
                             height,
                             8,
                             32,
                             sourceRowBytes,
                             CGColorSpaceCreateDeviceGray(),
                             bitmapInfo,
                             provider,
                             NULL,
                             true,
                             kCGRenderingIntentDefault);
    CGDataProviderRelease(provider);

这是 iOS 12 中的一个已知错误?如果此功能不再支持设备灰色,您能建议我另一种方法吗?

请注意,4K 图像的转换时间应少于 0.1 秒。

提前致谢!

【问题讨论】:

  • 我想您可以将缓冲区视为 CIImage 并去饱和或类似。
  • 顺便说一句,我想知道这是否与 iOS 12 的新功能有关,其中图形上下文根据您在其中绘制的内容自行配置其深度。这个新功能也给我带来了不小的麻烦。

标签: objective-c core-image ios12


【解决方案1】:

根据Supported Pixel Formats in the Quartz 2D Programming Guide 的列表,iOS 不支持具有灰色空间的每像素 32 位。即使在 macOS 上,32 bpp gray 也需要使用 kCGBitmapFloatComponents(和浮点数据)。

您的数据真的是 32 bpp 吗?如果是这样,它是浮动的吗? bitmapInfo你用什么?

我不希望CGImageCreate() 将缓冲区“转换”为灰度。您提供的参数告诉它如何解释数据。如果您不使用浮点组件,我怀疑它只是采用其中一个颜色通道并将其解释为灰度级并忽略其他组件。所以,这不是正确的灰度转换。

Apple 的建议是创建一个能够正确表示图像的图像;使用所需的色彩空间、像素布局和位图信息创建位图上下文;将前者拉入后者;并根据上下文创建最终图像。

【讨论】:

  • 您对此的了解比我多,但我不禁觉得我们不明白为什么这应该在 iOS 11 中有效。
  • @matt 我的猜测在我的第三段中,但如果没有 a) 更多信息和 b) 对源和结果图像的一些测试等,我们无法确定。这是一个有趣的谜,但是…… *耸耸肩*
  • 感谢您回答我的问题!我的数据大概没问题,因为它已经工作了很长时间,目前数据是kCVPixelFormatType_32BGRA。是的,有可能其中一个颜色通道用于黑白转换。
【解决方案2】:

我终于找到了我的目的的解决方法。请注意,CVPixelBuffer 来自摄像机。

  • 将相机输出像素格式更改为
    kCVPixelFormatType_420YpCbCr8BiPlanarFullRange (AVCaptureVideoDataOutput)
  • 从 YpCbCr 中提取 Y 平面
  • 使用 Y 平面构建 CGImage

代码:

// some code

colorSpace = CGColorSpaceCreateDeviceGray();
sourceRowBytes = CVPixelBufferGetBytesPerRowOfPlane(i_PixelBuffer, 0);
sourceBaseAddr = (unsigned char*)CVPixelBufferGetBaseAddressOfPlane(i_PixelBuffer,0);
bitmapInfo = kCGImageByteOrderDefault;

// some code

CGContextRef context = CGBitmapContextCreate(sourceBaseAddr,
                                             width,
                                             height,
                                             8,
                                             sourceRowBytes,
                                             colorSpace,
                                             bitmapInfo);
retImage = CGBitmapContextCreateImage(context);

// some code

你也可以看看这个相关的帖子: 420YpCbCr8BiPlanarVideoRange To YUV420 ?/How to copy Y and Cbcr plane to Single plane?

【讨论】:

    猜你喜欢
    • 2021-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-01
    • 2019-03-28
    • 2017-08-19
    • 2019-04-01
    • 1970-01-01
    相关资源
    最近更新 更多