问题描述
我正在使用 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;
}
至于另一个问题,我对框架太陌生,无法回答,所以我会留待其他人回答。