Share via


Verwenden der Gammakorrektur

Gammakorrektur, kurz Gammakorrektur, ist der Name eines nichtlinearen Vorgangs, den Systeme zum Codieren und Decodieren von Pixelwerten in Bildern verwenden.

Was ist Gamma und wofür ist es?

Am Ende der Grafikpipeline, genau dort, wo das Bild den Computer verlässt, um seine Reise entlang des Monitorkabels zu machen, gibt es ein kleines Stück Hardware, das Pixelwerte im Flug transformieren kann. Diese Hardware verwendet in der Regel eine Nachschlagetabelle, um die Pixel zu transformieren. Diese Hardware verwendet die roten, grünen und blauen Werte, die von der anzuzeigenden Oberfläche stammen, um gammakorrierte Werte in der Tabelle nachzuschlagen, und sendet dann die korrigierten Werte an den Monitor anstelle der tatsächlichen Oberflächenwerte. Diese Nachschlagetabelle bietet also die Möglichkeit, jede Farbe durch eine andere Farbe zu ersetzen. Während die Tabelle über diese Leistungsstufe verfügt, besteht die typische Verwendung darin, Bilder subtil zu optimieren, um Unterschiede in der Reaktion des Monitors auszugleichen. Die Antwort des Monitors ist die Funktion, die den numerischen Wert der roten, grünen und blauen Komponenten eines Pixels mit der angezeigten Helligkeit dieses Pixels in Beziehung setzt.

Dafür war diese Tabelle gedacht, aber Spieleentwickler fanden kreative Verwendungen dafür, z. B. das Blinken des gesamten Bildschirms rot für psychologische Effekte. In modernen Spiele-Apps bieten wir im Rahmen der Nachbearbeitung der einzelnen Frames in der Regel andere Möglichkeiten, solche Dinge zu tun. In der Tat empfehlen wir, die Gammatabelle in Ruhe zu lassen, da sie möglicherweise verwendet wird, um die Reaktion des Monitors zu kalibrieren, und umfassende Änderungen an der Gammarampe werden diese sorgfältige Kalibrierung zerstören.

Die Wissenschaft der Bestimmung der Gammakorrektur ist komplex und wird hier nicht vorgestellt, außer zu beleuchten, wo der Name "Gamma" herkam. Die Reaktion eines CRT-Monitors (d. a. ein altmodisches Glas) ist eine komplexe Funktion, aber die Physik dieser Monitore bedeutet, dass sie eine Antwort aufweisen, die durch diese Leistungsfunktion grob dargestellt werden kann:

Helligkeit( Eingabe ) = Eingabegamma

Der Gammawert liegt in der Regel nahe dem Wert 2,0. LCD-Monitore und alle anderen neueren Technologien sind speziell dafür entwickelt, eine ähnliche Reaktion zu zeigen, sodass alle unsere Software und Bilder nicht für diese neuen Technologien neu kalibriert werden müssen. Der sRGB-Standard deklariert, dass dieser Gammawert genau 2,2 ist, und dieser Wert hat sich zu einem weit verbreiteten Standard entwickelt.

Das menschliche Auge verfügt auch über eine Reaktionsfunktion, die die CRT-Leistungsfunktion ungefähr invertiert. Dies bedeutet, dass die wahrgenommene Helligkeit eines Pixels mit den RGB-Werten in diesem Pixel sehr linear steigt.

Da ein Gammawert von 2,2 zu einem de-facto-Standard geworden ist, müssen wir uns in der Regel nicht allzu viel um die gammakurve kümmern, die in dieser Tabelle codiert ist, und können sie als lineare 1:1-Zuordnung belassen. Der richtige Farbabgleich erfordert natürlich exquisite Sorgfalt bei dieser Funktion, aber diese Diskussion sprengt den Rahmen dieses Themas. Windows enthält ein Tool, mit dem Benutzer ihre Displays auf Gamma 2.2 kalibrieren können, und dieses Tool verwendet die Hardware der Nachschlagetabelle, um eine sorgfältig ausgewählte subtile Optimierung für ihre Computer abzuleiten. Benutzer können dieses Tool ausführen, indem Sie nach "Farbe kalibrieren" suchen. Es gibt auch klar definierte Farbprofile für bestimmte Monitore, die diesen Prozess automatisieren. Das Tool "Farbe kalibrieren" kann diese neueren Monitore erkennen und Benutzer darüber informieren, dass die Kalibrierung bereits vorhanden ist.

Diese Vorstellung, ein Energiegesetz in Farbwerte zu codieren, ist auch an anderer Stelle in der Grafikpipeline nützlich, insbesondere in Texturen. Bei Texturen möchten Sie aufgrund der logarithmischen Reaktion des menschlichen Auges, über die wir gerade gesprochen haben, mehr Genauigkeit bei dunkleren Farben. Ein sorgfältiger Umgang mit Gamma in diesem Teil der Pipeline ist wichtig. Weitere Informationen finden Sie unter Konvertieren von Daten für den Farbraum.

Der Rest dieses Themas konzentriert sich nur auf die Gammakorrektur in diesem letzten Teil der Pipeline zwischen den Framepufferdaten und dem Monitor. Wenn Sie einen Kalibrierungs-Assistenten schreiben oder Spezialeffekte in einer Vollbild-App erstellen möchten, bei der ein Nachbearbeitungsschritt nicht praktikabel ist, finden Sie hier die erforderlichen Informationen.

Hintergrund von Gamma unter Windows

Windows-Computer verfügen in der Regel über eine Gammatabelle, bei der es sich um eine Nachschlagetabelle handelt, die ein Triplet von Bytes akzeptiert und ein Triplet von Bytes ausgibt. Diese Triplets sind 768 (256 x 3) Bytes RAM. Dies ist in Ordnung, wenn Ihr Anzeigeformat ein Triplet von RGB-BYTE-Werten enthält, aber nicht ausdrucksstark genug ist, um die Transformationen zu beschreiben, die Sie möglicherweise benötigen, wenn das Anzeigeformat einen größeren Bereich als [0,1] aufweist, z. B. Gleitkommawerte. Die APIs in Windows, die gamma steuern, sind einer Entwicklung gefolgt, da die Anzeigeformate komplexer geworden sind.

Die ersten Windows-APIs, die Gammasteuerung bieten, sind SetDeviceGammaRamp (Windows Graphics Device Interface, GDI) und GetDeviceGammaRamp. Diese APIs arbeiten mit drei 256-Eingangsarrays von WORDs, wobei jede WORD-Codierung null bis eins ist, dargestellt durch DIE WORD-Werte 0 und 65535. Die zusätzliche Genauigkeit eines WORD ist in der Regel nicht in tatsächlichen Hardware-Nachschlagetabellen verfügbar, aber diese APIs sollten flexibel sein. Diese APIs lassen im Gegensatz zu den anderen APIs, die weiter unten in diesem Abschnitt beschrieben werden, nur eine kleine Abweichung von einer Identitätsfunktion zu. Tatsächlich muss jeder Eintrag in der Rampe innerhalb von 32768 des Identitätswerts sein. Diese Einschränkung bedeutet, dass keine App das Display vollständig schwarz oder in eine andere nicht lesbare Farbe schalten kann.

Die nächste API ist SetGammaRamp von Microsoft Direct3D 9, die demselben Muster und Datenformat wie SetDeviceGammaRamp folgt. Der Standardwert der Direct3D 9-Gammarampe ist nicht besonders nützlich. Es handelt sich um eine Rampe von WORDs, die auf 0-255 und nicht auf 0-65535 initialisiert werden, obwohl die API in Bezug auf 0-65535 definiert ist.

Die neueste API ist IDXGIOutput::SetGammaControl. Diese API verfügt über ein flexibleres Schema zum Ausdrücken der Gammasteuerung, wie es sich für den erweiterten Satz von DXGI-Anzeigeformaten gehört, einschließlich zehn ganzzahliger Bits pro Kanal, 16-Bit-Float-Formaten und dem XR_BIAS erweiterten Bereichsformats.

Alle diese APIs arbeiten auf derselben Hardware und ändern dieselben Werte. Die Direct3D 9- und DXGI-APIs sind schreibgeschützter Typ. Sie können den Wert der Hardware nicht lesen, ändern und dann festlegen. Sie können nur die Rampe festlegen. Darüber hinaus können Sie Gamma nur festlegen, wenn die App vollbildlich ist. Diese Einschränkung ist eine weitere Möglichkeit, um sicherzustellen, dass der Desktop immer lesbar ist. Das heißt, die App kann ihre eigene Anzeige stören, aber Windows stellt die vorherige Gamma-Rampe wieder her, wenn die App den Vollbildmodus verliert (z. B. über alt-Tab oder STRG-ALT-ENTF).

Entwicklung der Anzeigehardware

Einige neuere Monitore können eine breite Palette von Intensitäten anzeigen. Wenn das Anzeigeformat jedoch nur Werte zwischen 0 und 1 darstellen kann, muss die Anzeige null dem dunkelsten Wert und eins dem hellsten Wert zuordnen. Dieser hellste Wert ist möglicherweise viel zu hell, um Webseiten mit schwarzem Text auf weißem Hintergrund bequem zu sehen, ist aber wunderbar für überhelle Spezialeffekte, wie z. B. das Betrachten von Sonnenlicht, das von einem See glitzert oder blitzt der Himmel. Wir brauchen also eine Möglichkeit, diese größeren Bereiche auszudrücken. DXGI 1.1 und höher enthält Anzeigeformatwerte, mit denen 1.0 einen komfortablen Weißwert darstellen lässt und breitere Anzeigeformatwerte für überhelle Spezialeffekte reserviert. DXGI 1.1 unterstützt zwei Anzeigeformate, die diese größeren Werte ausdrücken können: DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM und 16-Bit-Gleitkomma. Eine vollständige Erläuterung dieser Formate finden Sie unter Details zum erweiterten Format. Als Nächstes untersuchen wir, warum die GAMMA-API IDXGIOutput::SetGammaControl Pixelwerte über 1,0 benötigt.

Gammasteuerungsfunktionen in DXGI

DXGI ermöglicht es dem Anzeigetreiber, seine Gammasteuerungen als schrittweise lineare Funktion auszudrücken. Diese schrittweise lineare Funktion wird durch die Kontrollpunkte dieser Funktion, den Wertebereich, in den die Funktion konvertiert werden kann, und durch einen zusätzlichen optionalen Skalierungs- und Offsetvorgang definiert, der nach der Konvertierung angewendet werden kann. Eine App kann die IDXGIOutput::GetGammaControlCapabilities-Methode aufrufen, um alle diese Steuerelementfunktionen in der DXGI_GAMMA_CONTROL_CAPABILITIES-Struktur abzurufen.

Dieses Diagramm zeigt eine lineare Funktion mit nur vier Kontrollpunkten.

Gammakorrektur lineare Funktion

DXGI definiert Steuerungspunkte anhand ihrer Position entlang der Farbachse der Oberfläche. Im vorherigen Diagramm sind die Positionen der Kontrollpunkte 0, 0,5, 0,75 und 1,0. Diese Kontrollpunkte geben an, dass die Hardware Werte im Bereich 0 bis 1.0 konvertieren kann. DXGI listet diese Kontrollpunkte im ControlPointPositions-Arraymitglied von DXGI_GAMMA_CONTROL_CAPABILITIES auf und deklariert sie immer in zunehmender Reihenfolge. DXGI füllt nur die ersten Elemente des ControlPointPositions-Arrays aus und gibt die Anzahl der Elemente mit dem NumGammaControlPoints-Elementvon DXGI_GAMMA_CONTROL_CAPABILITIES an. Wenn NumGammaControlPoints kleiner als 1025 ist, lässt DXGI den Rest der ControlPointPositions-Elemente nicht definiert.

Die in diesem Diagramm dargestellte Hardware kann Werte in einen Bereich von 0 bis 1,25 konvertieren. Daher legt DXGI die Member MinConvertedValue und MaxConvertedValue auf 0.0f bzw. 1.25f fest.

DXGI legt das ScaleAndOffsetSupported-Element von DXGI_GAMMA_CONTROL_CAPABILITIES fest, um anzugeben, ob die Hardware die Skalierungs- und Offsetfunktion unterstützt. Wenn die Hardware Skalierung und Offset unterstützt, behält sie eine einfache 1:1-Nachschlagetabelle bei, passt dann aber die Ausgabe der Tabelle an, um die Ausgabe auf einen Bereich zu strecken, der größer als [0,1] ist. Die Hardware skaliert zuerst die Werte, die aus der Nachschlagetabelle stammen, und versetzt sie dann.

Hinweis

Verschiedene Monitore, die mit demselben Computer verbunden sind, verfügen möglicherweise über unterschiedliche Gammasteuerungsfunktionen. Darüber hinaus können sich die Gammasteuerungsfunktionen je nach Anzeigemodus der Ausgabe ändern. Daher wird empfohlen, immer IDXGIOutput::GetGammaControlCapabilities aufzurufen, um Gammasteuerungsfunktionen abzufragen, nachdem Ihre App in den Vollbildmodus wechselt.

 

Sie können diese Werte der Gammasteuerungsfunktion verwenden, um Steuerelementwerte abzuleiten, die Sie dann mit der IDXGIOutput::SetGammaControl-API festlegen können.

Festlegen der Gammasteuerung mit DXGI

Zum Festlegen von Gammasteuerelementen übergeben Sie einen Zeiger auf eine DXGI_GAMMA_CONTROL-Struktur , wenn Sie die IDXGIOutput::SetGammaControl-API aufrufen.

Sie legen die Skalierungs- und Offsetmembervon DXGI_GAMMA_CONTROL fest, um die Skalierungs- und Offsetwerte anzugeben, die die Hardware auf die Werte anwenden soll, die Sie aus der Nachschlagetabelle erhalten. Sie können Skalierung auf 1 und Offset auf 0 (d. h. eine Skalierung nach 1 hat keine Auswirkung, und ein Offset von Null hat keine Auswirkung), wenn Sie die Skalierungs- und Offsetfunktion nicht verwenden möchten oder wenn die Hardware nicht über diese Funktion verfügt.

Sie legen das GammaCurve-Arrayelement von DXGI_GAMMA_CONTROL auf eine Liste von DXGI_RGB Strukturen für die Punkte auf der Gammakurve fest. Jedes DXGI_RGB-Element gibt die Floatwerte an, die die roten, grünen und blauen Komponenten für diesen Punkt darstellen. Die Gammakurve verwendet keine Alphawerte. Sie verwenden die Zahl, die Sie von NumGammaControlPoints von DXGI_GAMMA_CONTROL_CAPABILITIES erhalten haben, um diese Anzahl von Elementen im GammaCurve-Array zu füllen. Jedes Element, das Sie im GammaCurve-Array platzieren, ist die Höhe für jeden Steuerungspunkt.

Beachten Sie im vorherigen Diagramm, dass Sie jetzt die Kontrolle über die vertikale Platzierung der einzelnen Kontrollpunkte haben und dass Sie über eine separate Steuerung für Rot, Grün und Blau verfügen. Beispielsweise können Sie alle grünen und blauen Werte auf Null festlegen und die roten Werte auf eine aufsteigende Treppe von 0 auf 1 festlegen. In diesem Szenario zeigt das angezeigte Bild nur seine roten Teile, wobei blau und grün als schwarz angezeigt werden. Sie können auch eine absteigende Treppe für alle Farben festlegen, was zu einer invertierten Anzeige führt. Alle Werte, die Sie im GammaCurve-Array platzieren, müssen sich inklusive innerhalb der Werte befinden, die Sie aus den Membern MinConvertedValue und MaxConvertedValuevon DXGI_GAMMA_CONTROL_CAPABILITIES erhalten haben.

Gamma-Kontrollpraktitäten

Die Gamma-Steuerelemente von DXGI gelten nur so lange, wie die App vollbildlich ist. Windows stellt den vorherigen Zustand der Anzeige wieder her, wenn die App beendet wird oder in den Fenstermodus zurückkehrt. Windows stellt jedoch den Gammazustand Ihrer App nicht wieder her, wenn die App wieder in den Vollbildmodus wechselt. Ihre App muss den Gammazustand explizit wiederherstellen, wenn sie wieder in den Vollbildmodus wechselt.

Nicht alle Adapter unterstützen die Gammasteuerung. Wenn ein Adapter die Gammasteuerung nicht unterstützt, werden Aufrufe zum Festlegen einer Gammarampe ignoriert.

Apps, die unter Remotedesktop ausgeführt werden, können Gamma überhaupt nicht steuern.

Der Mauscursor reagiert normalerweise nicht auf die Gammaeinstellung, wenn er in der Hardware implementiert ist (wie die meisten).

Programmierhandbuch für DXGI