2016-04-27 20 views
3

Apple hat kürzlich die 30-Bit-Farbunterstützung unter OS X aktiviert. Sie haben einige sample code veröffentlicht, die zeigen, wie dies aktiviert wird. Sie bieten jedoch kein Beispiel dafür, wie Sie feststellen können, wenn Ihre App auf einem Bildschirm mit 30-Bit-Farben ausgeführt wird.Erkennen, ob ein Display 30-Bit-Farbe unterstützt

Wir möchten erkennen, wenn die Anzeige (n) eine 30-Bit-Farbe unterstützen und nur 30-Bit-Farbe für Displays, die dies unterstützen, aktivieren und andernfalls auf 24-Bit-Farbe zurücksetzen.

Weiß jemand, wie man das macht?

Bisher habe ich versucht, mit den CGDisplay APIs (CGDisplayCopyDisplayMode und CGDisplayModeCopyPixelEncoding) die Pixelcodierung des Displays abzufragen. Diese scheinen jedoch immer 24-Bit-Codierungen zurückzuliefern, und CGDisplayModeCopyPixelEncoding war in Mac OS X 10.11 veraltet. Ich habe auch versucht, NSScreen’s "Tiefe" -Eigenschaft zu verwenden, aber das gibt auch 24 Bits pro Pixel zurück.

Die integrierte System Information App ist offensichtlich in der Lage, diese Informationen zu bekommen, ich kann einfach nicht herausfinden, wie sie es tun. Irgendwelche Hinweise?

Antwort

1

Ab macOS 10.12 Apple verfügt über einige neue APIs, mit denen Sie erkennen können, ob eine Anzeige eine breite Farbskala (d. H. Eine tiefe Farbe) aufweist. Es gibt ein paar Möglichkeiten, dies zu tun:

  1. Verwenden NSScreen des - (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. Verwendung CGColorSpaceIsWideGamutRGB(...):

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

Ich weiß nicht, dass Sie auf einer 30-Bit-fähig Anzeige sein sind garantiert, wenn die Anzeige „Wide Gamut RGB“ oder in der Lage NSDisplayGamutP3 betrachtet wird, aber dies scheint von Apples offizieller Weg zu sein, Bestimmen, ob eine Anzeige eine breite Gamut-Farbe haben kann.

0

Es gibt verschiedene schlechte Optionen.

Erstens, wenn Sie einen Anzeigemodus protokollieren (also an id übertragen und an NSLog(@"%@", ...) übergeben), werden Sie feststellen, dass die echte Pixelcodierung dort ist. Das ist interessant, aber Sie wirklich wollen diese Beschreibung nicht analysieren. Wenn Sie (__bridge CFDictionaryRef)@{ (__bridge NSString*)kCGDisplayShowDuplicateLowResolutionModes: @YES } als Optionsparameter an CGDisplayCopyAllDisplayModes() übergeben, werden Sie feststellen, dass Sie eine Reihe zusätzlicher Anzeigemodi erhalten. Dieser Schlüssel ist in den Kopfzeilen, aber nicht in der Referenzdokumentation dokumentiert. Für einen Retina-Bildschirm sind einige der zusätzlichen Modi die 2-skaligen Gegenstücke der unskalierten Anzeigemodi. Andere sind die 24-Bit-Gegenstücke der 30-Bit-Masquerading-as-24-Bit-Modi. Diese sind in jeder Hinsicht identisch, die Sie über die API abfragen können, aber die Protokollierung zeigt den Unterschied. (Übrigens wird der Versuch, zu einem dieser Modi zu wechseln, fehlschlagen.)

Ich denke, aber Sie müssten überprüfen, dass Sie diese Paare von scheinbar identischen Modi nicht erhalten, außer für eine 30- Bit-Farb-fähiges Display.

Sie können möglicherweise die Informationen von IOKit erhalten. Sie müssten die veraltete Funktion CGDisplayIOServicePort() verwenden, um den Service-Port des Objekts IOFramebuffer zu erhalten, das das GPU-Display-Paar darstellt. Sie könnten dann IORegistryEntrySearchCFProperty() verwenden, um die Containment-Hierarchie in der Service-Ebene nach einem Objekt mit einer Eigenschaft wie "display-bpc" oder "display-pixel-component-bits" zu durchsuchen und dessen Wert zu ermitteln. Zumindest gibt es ein solches Objekt und Eigenschaften auf ein paar Systemen, die ich testen kann, obwohl beide AMD GPUs verwenden und die Eigenschaft auf einem AMD-spezifischen Objekt liegt, daher ist es möglicherweise nicht zuverlässig.

Schließlich können Sie einen Subprozess starten, um system_profiler -xml SPDisplaysDataType auszuführen und die Property-List-Serialisierungs-API verwenden, um ein Eigenschaftslistenobjekt aus dem resultierenden XML zu erstellen. Dann können Sie die Informationen dort finden. Sie finden die entsprechende Anzeige, indem Sie _spdisplays_display-vendor-id mit , _spdisplays_display-product-id mit CGDisplayModelNumber() und _spdisplays_display-serial-number mit CGDisplaySerialNumber() übereinstimmen. Dann ist die Tiefe unter dem Schlüssel spdisplays_depth, wo ein Wert von CGSThirtyBitColor bedeutet 30-Bit-Farbe.

Sie sollten auch einen Fehlerbericht bei Apple einreichen, in dem Sie nach einem vernünftigen Verfahren gefragt werden.

+1

Wow, diese ** sind ** ziemlich schlechte Optionen. Nach dem 'NSLog'-Hinweis habe ich festgestellt, dass die 'CGDisplayModeRef'-Struktur einen Zeiger auf ein Wörterbuch (' CFDictionary') hat, das 16 Bytes von der Basis der Struktur im Speicher entfernt ist. Sie können dann dieses Wörterbuch für die Schlüssel "PixelEncoding" oder "BitsPerSample" abfragen. Dies ist jedoch eine ziemlich schreckliche Lösung, da ich mich nicht auf die private Implementierung der 'CGDisplayModeRef'-Struktur verlassen möchte, da sie sich bei zukünftigen OS-Aktualisierungen ändern kann. Ich möchte 'CGDisplayIOServicePort()' nicht wirklich verwenden, da es veraltet ist. Wirklich schlechte Möglichkeiten ... – Cutterpillow

0

Was für mich gearbeitet wird das Bestehen der depthLimit Eigentum meines NSWindow zu und prüfen, ob der Rückgabewert von mehr als 24 Caveat ist: Ich habe nur zwei iMacs auf prüfen, eine von 2012 und eine weitere von 2017 und sie laufen beide High Sierra.