上下文
我在OSX应用程序中显示一个充满红色(255,0,0)颜色的窗口。当显示此窗口时,我也在进行屏幕抓取。现在,当我读取绘制窗口的像素的值时,我看到像素的值实际上是251,0,7。
我怀疑在进行屏幕抓取时有些东西搞砸了,所以我使用mac中的数字颜色实用程序来检查颜色,我得到了相同的值 - 251,0,7。
当我渲染图像时,有哪些事情发生了。所以,我尝试了另外一个实验如下:在所有像素上创建一个充满红色(255,0,0)的图像,将其导出为png并在mac的图像查看器中打开它。在这个由操作系统本身渲染的图像上,我运行了数字色度计,我仍然得到251,0,7作为像素值。
此时,我想,也许这只是Mac所做的事情 - 但作为最后一次实验,我将图像邮寄给自己并使用gmail中的图像查看器打开它,我看到现在是数字颜色米显示图像中像素的值为255,0,0 - 这意味着谷歌的图像查看器可以呈现精确的颜色 - 因此可以显示确切的颜色。虽然红色显示正确(255,0,0),绿色和蓝色不正确。
问题:
有人能指向我演示如何在Mac中显示真实颜色的资源/代码吗?换句话说,是否有办法在窗口中显示颜色,这样,当我对显示的窗口进行屏幕抓取时,我得到与我绘制的完全相同的颜色?
更新
添加我正在使用的图像。
我现在正在使用的代码:
NSRect windowRect = {200,200,200,200};//{m_windowOriginX, m_windowOriginY, m_windowSizeX, m_windowSizeY};
m_NSWindow = [[NSWindow alloc] initWithContentRect:windowRect styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO];
[m_NSWindow setTitle:@"overlayWindow"];
[m_NSWindow makeKeyAndOrderFront:nil];
g_imageView = [[NSImageView alloc] initWithFrame:NSMakeRect(0,0,200,200)];
[m_NSWindow.contentView addSubview:g_imageView];
NSColor *backgroundColor = [m_NSWindow backgroundColor];
backgroundColor = [NSColor clearColor];
[m_NSWindow setBackgroundColor:backgroundColor];
[m_NSWindow setOpaque:YES];
//[m_NSWindow setAlphaValue:1.0];
naivePremultiplyRGBAMat(m_paintBuffer);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef bitmapContext = CGBitmapContextCreate(m_paintBuffer.data, 200, 200, 8, 800, colorSpace, kCGImageAlphaPremultipliedLast);
CFRelease(colorSpace);
CGImageRef cgImage = CGBitmapContextCreateImage(bitmapContext);
CGContextRelease(bitmapContext);
这里naivePreMultiplyRGBAMat
是我编写的自定义函数,用于预先乘以alpha分量。
NSSize imageSize = NSMakeSize(200,200);
NSImage* myImage = [[NSImage alloc] initWithCGImage: cgImage size: NSMakeSize(
CGBitmapContextGetWidth(bitmapContext),
CGBitmapContextGetHeight(bitmapContext))];
[g_imageView setImage:myImage];
答案 0 :(得分:1)
通过颜色配置文件解释了在我的图像的原始数据中没有获得截图/数字色度计中相同颜色的问题。基本上,如果我说,我有RGB值255,0,0它没有任何意义,除非我将它与颜色配置文件相关联。当我要在mac上显示图像时,有三个不同的缓冲区,这个图像将通过这些缓冲区,每个缓冲区都有一个相关的颜色配置文件。
第一个缓冲区是图像缓冲区本身,它由我在上面发布的代码中的以下代码行创建:
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef bitmapContext = CGBitmapContextCreate(m_paintBuffer.data, 200, 200, 8, 800, colorSpace, kCGImageAlphaPremultipliedLast);
此处colorSpace
变量正在设置此颜色空间的颜色配置文件。
第二个缓冲区是窗口缓冲区,我可以使用以下代码指定颜色空间:
[m_NSWindow setColorSpace: [NSColorSpace genericRGBColorSpace]]
并且第三个缓冲区是监视器本身,它可能有一些与之关联的颜色空间 - 您可以通过进入系统首选项然后选择显示来更改它。
所以,现在,当我通过此管道发送图像(图像缓冲区到窗口缓冲区以监视缓冲区)时,如果每个缓冲区都有不同的颜色配置文件,则会进行适当的颜色转换。因此,图像缓冲区中r,g,b
的颜色值可能会在到达监视缓冲区时转换为r',g',b'
。
此外,当您将监视缓冲区中的任何内容复制到与屏幕抓取相对应的缓冲区时,将发生另一次转换,您最终读取的值是这些值。
现在,确保在图像缓冲区中使用带有screengrab的源图像和图像缓冲区具有相同值的简单方法是确保它们具有相同的颜色配置文件。但是,我建议您在管道(窗口/监视器等)的所有缓冲区中保持相同的颜色配置文件,因为当您从颜色配置文件A转换为颜色配置文件B并返回到颜色配置文件A时,会丢失信息。