WICConvertBitmapSource BGR 到 Gray 意外像素格式转换

问题描述

我正在使用 WICConvertBitmapSource 函数将像素格式从 BGR 转换为灰色,但我得到了意外的像素值。

...

pIDecoder->GetFrame( 0,&pIDecoderFrame ); 

pIDecoderFrame->GetPixelFormat( &pixelFormat ); // GUID_WICPixelFormat24bppBGR

IWICBitmapSource * dst;
WICConvertBitmapSource( GUID_WICPixelFormat8bppGray,pIDecoderFrame,&dst );

4x3 图像示例,如下所示 BGR 像素值:

[  0,255,0;
   0,255;
   0,119,255;
 233,178,73,233,73]

我得到的灰色像素值:

[127,220,76;
 247,230,145;
   0,255;
 168,168,168]

我期望得到的灰度像素值 (ITU-R BT.601 conversion)

[ 76,149,29;
 225,105;
   0,255;
 152,152,152]

后台正在发生什么样的转换,有没有办法强制转换为我想要的行为?

另外值得一提的是,Gray -> BGR 和 BGRA -> BGR 的转换工作正常(如预期)

解决方法

至于“后台正在发生什么样的转换”这个问题:似乎使用了不同的转换算法。使用 WINE 项目来计算灰度值,似乎给出了相同的结果,因此它为我们提供了一个很好的近似值。使用的公式是func fetchimage(url: String) -> UIImage { return UIImage(systemName: "paperplane")! } func fetchRichLinkimage(url: String) -> UIImage { let metadataProvider = LPMetadataProvider() guard let urlURL = URL(string: url) else { return UIImage(systemName: "paperplane")! } metadataProvider.startFetchingMetadata(for: urlURL) { (metadata,error) in guard error == nil else { return } guard let imageProvider = metadata?.imageProvider else { return } imageProvider.loadObject(ofClass: UIImage.self) { (image,error) in guard error == nil else { return } if let image = image as? UIImage { DispatchQueue.main.async { return self.image } } else { print("no image available") } } } }

R * 0.2126 + G * 0.7152 + B * 0.0722 (source):

copypixels_to_8bppGray

除此之外,它还针对 sRGB 色彩空间进行了校正。

float gray = (bgr[2] * 0.2126f + bgr[1] * 0.7152f + bgr[0] * 0.0722f) / 255.0f; (source):

copypixels_to_8bppGray

gray = to_sRGB_component(gray) * 255.0f; (source):

to_sRGB_component

插入一些值:

static inline float to_sRGB_component(float f)
{
    if (f <= 0.0031308f) return 12.92f * f;
    return 1.055f * powf(f,1.0f/2.4f) - 0.055f;
}

至于另一个问题,我对框架太陌生,无法回答,所以我会留待其他人回答。