【问题标题】:Creating Image from pixel data with CGBitmapContextCreate使用 CGBitmapContextCreate 从像素数据创建图像
【发布时间】:2014-04-23 14:50:31
【问题描述】:

我正在尝试编写可以将现有图像裁剪到某个指定大小/区域的代码。我正在处理 DICOM 图像,我使用的 API 允许我直接获取像素值。我已将图像中感兴趣区域的像素值放入浮点数组(dstImage,如下)。

我遇到的问题是使用此像素数据实际构建/创建新的裁剪图像文件。源图像是灰度的,但是我在网上找到的所有示例(如this one)都是针对 RGB 图像的。我尝试按照该链接中的示例进行调整,调整灰度并尝试许多不同的值,但我继续在 CGBitmapContextCreate 代码行上遇到错误,并且仍然不清楚这些值应该是什么。

我对源图像的强度值高于 255,所以我的印象是这不是 8 位灰度,而是 16 位灰度。

这是我的代码:

CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();

CGContextRef context;
context = CGBitmapContextCreate(dstImage, // pixel data from the region of interest
                                dstWidth, // width of the region of interest
                                dstHeight, // height of the region of interest
                                16, // bits per component
                                2 * dstWidth, // bytes per row
                                colorSpace,
                                kCGImageAlphaNoneSkipLast);

CFRelease(colorSpace);

CGImageRef cgImage = CGBitmapContextCreateImage(context);
CFURLRef url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault,
                                             CFSTR("test.png"),
                                             kCFURLPOSIXPathStyle,
                                             false);
CFStringRef type = kUTTypePNG;
CGImageDestinationRef dest = CGImageDestinationCreateWithURL(url,
                                                             type,
                                                             1,
                                                             0);
CGImageDestinationAddImage(dest,
                           cgImage,
                           0);
CFRelease(cgImage);
CFRelease(context);
CGImageDestinationFinalize(dest);
free(dstImage);

我一直收到的错误是:

CGBitmapContextCreate: unsupported parameter combination: 16 integer bits/component; 32 bits/pixel; 1-component color space; kCGImageAlphaNoneSkipLast; 42 bytes/row.

最终目标是从 dstImage 中的像素数据创建图像文件并将其保存到硬盘。非常感谢您对此提供帮助,以及深入了解如何确定我应该在 CGBitmapContextCreate 调用中使用哪些值。

谢谢

【问题讨论】:

    标签: objective-c macos image-processing


    【解决方案1】:

    首先,您应该熟悉 Quartz 2D 编程指南:图形上下文的 "Supported Pixel Formats" section

    如果您的图像数据位于 float 值的数组中,则它是每个组件 32 位,而不是 16。因此,您必须使用 kCGImageAlphaNone | kCGBitmapFloatComponents

    但是,我相信 Core Graphics 会将浮点组件解释为介于 0.0 和 1.0 之间。如果您的值不在此范围内,您可能需要使用(value - minimumValue) / (maximumValue - minimumValue) 之类的方式对其进行转换。另一种方法是使用CGColorSpaceCreateCalibratedGray() 或使用CGImageCreate() 创建CGImage 并指定适当的decode 参数,然后使用CGBitmapContextCreateImage() 创建位图上下文。

    事实上,如果您没有在位图上下文中绘图,那么无论如何您都应该创建一个CGImage

    【讨论】:

    • 谢谢,肯。这帮助我朝着正确的方向迈出了一步。虽然我现在得到了一个输出 png,但它看起来与我所期望的完全不同。似乎几乎所有像素都是黑色或白色。只有一对是中间灰色的。其次,png 看起来非常像素化(比我放大原始图像以将感兴趣区域设置为相似大小时发生的情况更多。
    • 我最终希望能够以编程方式在结果图像上绘制/写入文本,所以如果我理解你的最后一句话,听起来好像 'CGImage' 可能不允许这样做.
    • 正确,但您可以先创建CGImage,然后使用CGBitmapContextCreateImage() 创建位图上下文。抱歉,我错误地把那部分从我的答案中漏掉了。
    • 好的。我让它使用CGImage而不是CGBitmapContextCreateImage()输出PNG。但是,图像看起来完全一样(非常像素化,几乎所有像素都是黑色或白色,与我希望创建的没有太大相似之处)。我尝试打开和关闭插值,但这并没有什么不同。关于这个问题的任何想法?
    • 您是否将decode 数组传递给CGImageCreate() 以指示组件值的范围?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-14
    • 1970-01-01
    • 2011-09-27
    • 1970-01-01
    • 2016-09-02
    相关资源
    最近更新 更多