【问题标题】:Help please with CGBitmapContext and 16 bit images请帮助 CGBitmapContext 和 16 位图像
【发布时间】:2010-10-20 03:15:03
【问题描述】:

我很想知道我在这里做错了什么。我是 CGImageRefs 的新手,所以任何建议都会有所帮助。

我正在尝试创建一个位图图像,其像素值是来自另一个位图的像素的加权和,并且两个位图都是每个通道 16 位。出于某种原因,我可以毫不费力地让它与 8 位图像一起使用,但它在 16 位时却惨遭失败。我的猜测是我只是没有正确设置。我尝试使用 CGFloats、floats 和 UInt16s 作为数据类型,但没有任何效果。输入图像没有 Alpha 通道。我得到的输出图像看起来像彩色雪。

标题中的相关内容:

UInt16 *inBaseAddress;
UInt16 *outBaseAddress;
CGFloat inAlpha[5];
CGFloat inRed[5];
CGFloat inGreen[5];
CGFloat inBlue[5];
CGFloat alphaSum, redSum, greenSum, blueSum;
int shifts[5];
CGFloat weight[5];
CGFloat weightSum;

我使用以下方法为输入位图(使用 CGImageSourceCreateImageAtIndex(source, 0, NULL) 创建的 CGImageRef)创建上下文:

size_t width = CGImageGetWidth(inBitmap);
size_t height = CGImageGetHeight(inBitmap);
size_t bitmapBitsPerComponent = CGImageGetBitsPerComponent(inBitmap);
size_t bitmapBytesPerRow = (pixelsWide * 4 * bitmapBitsPerComponent / 8);
CGColorSpaceRef colorSpace = CGImageGetColorSpace(inImage);

CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault | kCGImageAlphaNoneSkipLast;


CGContextRef inContext = CGBitmapContextCreate (NULL,width,height,bitmapBitsPerComponent,bitmapBytesPerRow,colorSpace,bitmapInfo);

输出位图的上下文以相同的方式创建。我使用以下方法将 inBitmap 绘制到 inContext 中:

CGRect rect = {{0,0},{width,height}}; 
CGContextDrawImage(inContext, rect, inBitmap);

然后我像这样初始化 inBaseAddress 和 outBaseAddress:

inBaseAddress = CGBitmapContextGetData(inContext);
outBaseAddress = CGBitmapContextGetData(outContext);

然后我用 inBaseAddress 中的值填充 outBaseAddress:

for (n = 0; n < 5; n++)
{
    inRed[n] = inBaseAddress[inSpot + 0 + shifts[n]];
    inGreen[n] = inBaseAddress[inSpot + 1 + shifts[n]];
    inBlue[n] = inBaseAddress[inSpot + 2 + shifts[n]];
    inAlpha[n] = inBaseAddress[inSpot + 3 + shifts[n]];

}

alphaSum = 0.0;
redSum = 0.0;
greenSum = 0.0;
blueSum = 0.0;

for (n = 0; n < 5; n++)
{
    redSum  += inRed[n] * weight[n];
    greenSum += inGreen[n] * weight[n];
    blueSum += inBlue[n] * weight[n];
    alphaSum += inAlpha[n] * weight[n];

}

outBaseAddress[outSpot + 0] = (UInt16)roundf(redSum);
outBaseAddress[outSpot + 1] = (UInt16)roundf(greenSum);
outBaseAddress[outSpot + 2] = (UInt16)roundf(blueSum);
outBaseAddress[outSpot + 3] = (UInt16)roundf(alphaSum);

作为我尝试过的简单检查:

outBaseAddress[outSpot + 0] = inBaseAddress[inSpot + 0];
outBaseAddress[outSpot + 1] = inBaseAddress[inSpot + 1];
outBaseAddress[outSpot + 2] = inBaseAddress[inSpot + 2];
outBaseAddress[outSpot + 3] = inBaseAddress[inSpot + 3];

这有效,至少意味着位图数据的上下文和指针有效。

感谢您的任何意见。这非常令人沮丧,因为它适用于 8 位图像。

【问题讨论】:

    标签: cocoa cgimage 16-bit cgbitmapcontextcreate


    【解决方案1】:

    好的,我知道了。对于 16bit 图像,我需要将 bitmapInfo 设置为 kCGBitmapByteOrder16Little,对于 8bit 图像,我需要将其设置为 kCGBitmapByteOrder32Little。实际上,我对此感到有些惊讶,正如预期的相反(16 位为 32Little,8 位为 16Little)。

    我还需要将指向位图的指针定义为UInt8*UInt16*。看来我必须在bitmapContext 中包含一个 alpha 通道。我不知道为什么,但是没有它返回的上下文总是 nil。

    【讨论】:

      【解决方案2】:

      这听起来像是一个字节排序问题

      【讨论】:

      • 喜欢大端还是小端?我对这些 CGBitmapContexts 的字节排序选项不太熟悉,这就是我使用“kCGBitmapByteOrderDefault”作为位图信息的原因。
      【解决方案3】:

      您是否检查过 CGImageGetBitsPerComponent 是否返回 16?作为风格问题,如果您假设您正在创建一个每像素 16 位的位图上下文(因为您将数据视为UInt16*),您应该显式设置size_t bitmapBitsPerComponent = 16

      你的shifts 数组是干什么用的?这似乎是最有可能出错的地方,因为它会影响您正在读取的地址,但您根本没有解释它。 shifts 中的值是 16 的倍数吗?

      【讨论】:

      • CGImageGetBitsPerComponent 返回 16。 shifts 数组用于选择最近邻像素(该程序是一种抗锯齿类型的过滤器)。班次[0] = 0;班次[1] = -宽度* 4;班次[2] = 宽度 * 4;班次[3] = -4;班次[4] = 4;
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-07-02
      • 2018-04-01
      • 2012-11-18
      • 2021-10-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多