检测显示器是否支持 30 位颜色



Apple 最近在 OS X 上启用了 30 位颜色支持。他们发布了一些示例代码来演示如何启用此功能。但是,它们似乎没有提供有关如何检测应用何时在支持 30 位颜色的显示器上运行的示例。

我们希望能够检测显示器何时支持 30 位颜色,并且仅为支持 30 位颜色的显示器启用 30 位颜色,否则将恢复为 24 位颜色。

有谁知道该怎么做?

到目前为止,我已经尝试使用CGDisplay API(CGDisplayCopyDisplayModeCGDisplayModeCopyPixelEncoding)来查询显示器的像素编码。但这些似乎总是返回 24 位编码,并且CGDisplayModeCopyPixelEncoding在 Mac OS X 10.11 中已弃用。我也尝试使用NSScreen’s"深度"属性,但这也返回每像素 24 位。

内置的系统信息应用程序显然能够获取这些信息,我只是无法弄清楚他们是怎么做到的。有什么提示吗?

从macOS 10.12开始,Apple有一些新的API,允许您检测显示器是否能够使用宽色域颜色(即深色)。有几种方法可以做到这一点:

  1. 使用 NSScreen 的- (BOOL)canRepresentDisplayGamut:(NSDisplayGamut)displayGamut

    NSArray<NSScreen *> * screens = [NSScreen screens];
    BOOL hasWideGamutScreen = NO;
    for ( NSScreen * screen in screens )
    {
        if ( [screen canRepresentDisplayGamut:NSDisplayGamutP3] )
        {
            hasWideGamutScreen = YES;
            break;
        }
    }
    
  2. 使用CGColorSpaceIsWideGamutRGB(...)

    hasWideGamutScreen = CGColorSpaceIsWideGamutRGB( screen.colorSpace.CGColorSpace );
    
  3. NSWindow也有- (BOOL)canRepresentDisplayGamut:(NSDisplayGamut)displayGamut.

我不知道当显示器被认为是"广色域RGB"或能够NSDisplayGamutP3时,您是否可以保证在30位支持显示器的显示器上,但这似乎是Apple确定显示器是否能够进行宽色域颜色的官方方法。

有各种糟糕的选择。

首先,如果您记录显示模式(即投射到id并传递给NSLog(@"%@", ...)),您会发现真实的像素编码在那里。这很有趣,但你真的不想解析该描述。

如果将(__bridge CFDictionaryRef)@{ (__bridge NSString*)kCGDisplayShowDuplicateLowResolutionModes: @YES }作为选项参数传递给CGDisplayCopyAllDisplayModes(),您会发现您将获得一堆额外的显示模式。此键记录在标头中,但不记录在参考文档中。对于 Retina 显示器,一些额外模式是未缩放显示模式的 2 倍缩放对应项。其他是伪装成 24 位模式的 30 位对应项。它们在您可以通过 API 查询的所有方式上都是相同的,但日志记录显示了差异。(顺便说一下,尝试切换到其中一种模式将失败。

我认为,但你必须验证,除了30位彩色显示器之外,你没有得到这些看似相同的模式。

您可以从IOKit获取信息。您必须使用已弃用的函数CGDisplayIOServicePort()来获取表示 GPU 显示对的 IOFramebuffer 对象的服务端口。然后,您可以使用IORegistryEntrySearchCFProperty()在服务平面中搜索包含层次结构,以查找具有"display-bpc"或"display-pixel-component-bits"等属性的对象并获取其值。至少,在我能够测试的几个系统上有这样的对象和属性,尽管它们都使用 AMD GPU,并且该属性位于 AMD 特定的对象上,因此它可能不可靠。

最后,可以启动子进程以运行system_profiler -xml SPDisplaysDataType并使用属性列表序列化 API 从生成的 XML 生成属性列表对象。然后,您可以在那里找到信息。您可以通过将_spdisplays_display-vendor-idCGDisplayVendorNumber()_spdisplays_display-product-idCGDisplayModelNumber()以及_spdisplays_display-serial-numberCGDisplaySerialNumber()匹配来找到相关的显示。然后,深度在键spdisplays_depth下,其中值 CGSThirtyBitColor 表示 30 位颜色。

您还应该向Apple提交错误报告,要求采取合理的方法来执行此操作。

对我有用的是将NSWindowdepthLimit 属性传递给 NSBitsPerPixelFromDepth 并检查返回值是否大于 24。警告:我只有两台iMac要测试,一台是2012年的,另一台是2017年的,它们都运行High Sierra。

相关内容

  • 没有找到相关文章

最新更新