Wie in diesem Thread angekündigt, habe ich ein Avisynth-Script geschrieben, mit dem man bestimmte Bildparameter simulieren und per Splitscreen gegenüberstellen kann.
Das Script kann folgende Bildparameter sowohl links als auch rechts unabhängig voneinander verändern:
- Statischen Kontrast um definierten Faktor erhöhen. Das erhöht den Schwarzwert fix.
- Dynamischen Kontrast simulieren (folgt einer hinterlegten Kurve, die ADL einbezieht). Der Schwarzwert ändert sich je nach Bildinhalt.
- Statische Helligkeit (statische Lichtquelle): der native Kontrast wird in Bereiche aufgeteilt und es wird einer ausgewählt (ähnlich der statischen Stufen im Projektor).
- Dynamische Helligkeit (dynamische Lichtquelle): der Weißwert folgt analog dem Schwarzwert der hinterlegten Kurve. Der Kontrast bleibt konstant, die Helligkeit ändert sich je nach Bildinhalt.
Wichtig ist dabei, dass der native Kontrast des Anzeigegerätes korrekt angegeben wird (gemessener Wert). Das ist deshalb wichtig, weil ich auf der Basis den Zielschwarzwert ausrechne. Bei eine, Anzeigegerät mit einem Kontrast von 1000 : 1 führt ja eine Verdopplung des Schwarzwertes zu einem deutlich größeren Wert als bei einem mit 1.000.000 : 1. Wichtig ist weiterhin, dass das Anzeigegerät möglichst sauber der Gammafunktion folgt. Ansonsten steigt der Fehler beim Zielschwarzwert.
Per Untertitel sieht man, welche Werte auf das Bild angewendet werden. Hier ein Beispiel:
Hier ist das Script:
Avisynth+:
nativeContrast = 3700.0 # enter the native contrast ratio of your display here
# defines behaviour of left picture
factorToLowerContrastStatic1 = 4.0 # enter the factor by which to lower the on/off contrast statically
factorToLowerContrastDynamic1 = 1.0 # enter the factor by which to lower the on/off contrast depending on ADL of each frame
lightSourceLevel1 = 1.0 # enter value for light source here. 1 = means that light source is on full power. Setting to static contrast factor means least power. Works only when dynamic contrast factor is 1!
lightSourceMode1 = false # if enabled white levels will be adjusted, too. Contrast stays constant in this case. When dynamic contrast is used it works like a auto light source. Otherwise like a static light source.
# defines behaviour of right picture
factorToLowerContrastStatic2 = 1.0 # enter the factor by which to lower the on/off contrast statically
factorToLowerContrastDynamic2 = 4.0 # enter the factor by which to lower the on/off contrast depending on ADL of each frame
lightSourceLevel2 = 1.0 # enter value for light source here. 1 = means that light source is on full power. Setting to static contrast factor means least power. Works only when dynamic contrast factor is 1!
lightSourceMode2 = true # if enabled white levels will be adjusted, too. Contrast stays constant in this case. When dynamic contrast is used it works like a auto light source. Otherwise like a static light source.
cinemascope = true # if enabled the picture will be cropped for cinemscope to save CPU usage (works only on 1080p source)
debugSubtitle = true # enable debug subtitle
import("SourceDefinition.avs")
# crop for cinemscope (reduces CPU usage)
if(cinemascope) {
Crop(0, 140, -0, -140)
}
# evaluate new values
adlPercent = 0.0
contrastFactor1 = 1.0
contrastFactor2 = 1.0
newBlackLevel1 = 0.0
newBlackLevel2 = 0.0
newWhiteLevel1 = 255.0
newWhiteLevel2 = 255.0
FrameEvaluate("
Levels(16, 1/2.2, 235, 0, 255, coring=false, dither=false)
\adlPercent = AverageLuma(1) / 255.0 * 100.0
\contrastFactorFunction = -0.0000056 * pow(adlPercent, 4) + 0.0018 * pow(adlPercent, 3) - 0.2096 * pow(adlPercent, 2) + 10.812 * adlPercent
\contrastFactor1 = factorToLowerContrastStatic1 + (factorToLowerContrastDynamic1 - 1) * contrastFactorFunction / 226.2
\contrastFactor2 = factorToLowerContrastStatic2 + (factorToLowerContrastDynamic2 - 1) * contrastFactorFunction / 226.2
\newBlackLevel1 = 255.0 * pow((contrastFactor1 - lightSourceLevel1) / nativeContrast, 1.0 / 2.2)
\newBlackLevel2 = 255.0 * pow((contrastFactor2 - lightSourceLevel2) / nativeContrast, 1.0 / 2.2)
\if(lightSourceMode1) {newWhiteLevel1 = 255.0 * pow((contrastFactor1 - lightSourceLevel1 + 1.0) / (factorToLowerContrastStatic1 + factorToLowerContrastDynamic1 - 1), 1.0 / 2.2)}
\if(lightSourceMode2) {newWhiteLevel2 = 255.0 * pow((contrastFactor2 - lightSourceLevel2 + 1.0) / (factorToLowerContrastStatic2 + factorToLowerContrastDynamic2 - 1), 1.0 / 2.2)}
")
# crop for split screen
clip2 = last
clip1 = last.crop(0,0,-960,0)
clip2 = clip2.crop(960,0,0,0)
function AddInfo(clip c, float adlPercent, float nativeContrast, float contrastFactor, float newBlackLevel, float newWhiteLevel, bool lightSourceMode)
{
c.Subtitle("ADL=" + String(adlPercent, "%02.1f") + " %, Contrast=" + String(nativeContrast / contrastFactor, "%03.0f:1") + ", Black level=" + String(newBlackLevel, "%02.1f") + ", White level=" + String(newWhiteLevel, "%02.1f") + ", Light source mode=" + String(lightSourceMode, "%d"), align=2)
}
# apply levels
clip1 = clip1.ScriptClip("""
Levels(0, 1, 255, newBlackLevel1, newWhiteLevel1, coring=true, dither=true)
if(lightSourceMode1 && factorToLowerContrastDynamic1 > 1) {
contrastFactor1 = factorToLowerContrastStatic1 + factorToLowerContrastDynamic1 - 1
}
\if(debugSubtitle) {AddInfo(last, adlPercent, nativeContrast, contrastFactor1, newBlackLevel1, newWhiteLevel1, lightSourceMode1)}
""")
clip2 = clip2.ScriptClip("""
Levels(0, 1, 255, newBlackLevel2, newWhiteLevel2, coring=true, dither=true)
if(lightSourceMode2 && factorToLowerContrastDynamic2 > 1) {
contrastFactor2 = factorToLowerContrastStatic2 + factorToLowerContrastDynamic2 - 1
}
\if(debugSubtitle) {AddInfo(last, adlPercent, nativeContrast, contrastFactor2, newBlackLevel2, newWhiteLevel2, lightSourceMode2)}
""")
StackHorizontal(clip1, clip2)
Alles anzeigen
Avisynth:
LoadPlugin("C:\Program Files (x86)\AviSynth\plugins\GScript_26_32.dll")
nativeContrast = 30000.0 # enter the native contrast ratio of your display here
# defines behaviour of left picture
factorToLowerContrastStatic1 = 1.0 # enter the factor by which to lower the on/off contrast statically
factorToLowerContrastDynamic1 = 50.0 # enter the factor by which to lower the on/off contrast depending on ADL of each frame
lightSourceLevel1 = 1.0 # enter value for light source here. 1 = means that light source is on full power. Setting to static contrast factor means least power. Works only when dynamic contrast factor is 1!
lightSourceMode1 = false # if enabled white levels will be adjusted, too. Contrast stays constant in this case. When dynamic contrast is used it works like a auto light source. Otherwise like a static light source.
# defines behaviour of right picture
factorToLowerContrastStatic2 = 2.0 # enter the factor by which to lower the on/off contrast statically
factorToLowerContrastDynamic2 = 1.0 # enter the factor by which to lower the on/off contrast depending on ADL of each frame
lightSourceLevel2 = 1.0 # enter value for light source here. 1 = means that light source is on full power. Setting to static contrast factor means least power. Works only when dynamic contrast factor is 1!
lightSourceMode2 = true # if enabled white levels will be adjusted, too. Contrast stays constant in this case. When dynamic contrast is used it works like a auto light source. Otherwise like a static light source.
cinemascope = true # if enabled the picture will be cropped for cinemscope to save CPU usage (works only on 1080p source)
debugSubtitle = true # enable debug subtitle
# crop for cinemscope (reduces CPU usage)
GScript("
if (cinemascope) {
Crop(0, 140, -0, -140)
}
")
# evaluate new values
adlPercent = 0.0
contrastFactor1 = 1.0
contrastFactor2 = 1.0
newBlackLevel1 = 0.0
newBlackLevel2 = 0.0
newWhiteLevel1 = 255.0
newWhiteLevel2 = 255.0
FrameEvaluate("""Levels(16, 1/2.2, 235, 0, 255, coring=false, dither=false)
\adlPercent = AverageLuma() / 255.0 * 100.0
\contrastFactorFunction = -0.0000056 * pow(adlPercent, 4) + 0.0018 * pow(adlPercent, 3) - 0.2096 * pow(adlPercent, 2) + 10.812 * adlPercent
\contrastFactor1 = factorToLowerContrastStatic1 + (factorToLowerContrastDynamic1 - 1) * contrastFactorFunction / 226.2
\contrastFactor2 = factorToLowerContrastStatic2 + (factorToLowerContrastDynamic2 - 1) * contrastFactorFunction / 226.2
\newBlackLevel1 = 255.0 * pow((contrastFactor1 - lightSourceLevel1) / nativeContrast, 1.0 / 2.2)
\newBlackLevel2 = 255.0 * pow((contrastFactor2 - lightSourceLevel2) / nativeContrast, 1.0 / 2.2)
\GScript("if(lightSourceMode1) {newWhiteLevel1 = 255.0 * pow((contrastFactor1 - lightSourceLevel1 + 1.0) / (factorToLowerContrastStatic1 + factorToLowerContrastDynamic1 - 1), 1.0 / 2.2)}")
\GScript("if(lightSourceMode2) {newWhiteLevel2 = 255.0 * pow((contrastFactor2 - lightSourceLevel2 + 1.0) / (factorToLowerContrastStatic2 + factorToLowerContrastDynamic2 - 1), 1.0 / 2.2)}")
""")
# crop for split screen
clip2 = last
clip1 = last.crop(0,0,-960,0)
clip2 = clip2.crop(960,0,0,0)
function AddInfo(clip c, float adlPercent, float nativeContrast, float contrastFactor, float newBlackLevel, float newWhiteLevel, bool lightSourceMode)
{
c.Subtitle("ADL=" + String(adlPercent, "%02.1f") + " %, Contrast=" + String(nativeContrast / contrastFactor, "%03.0f:1") + ", Black level=" + String(newBlackLevel, "%02.1f") + ", White level=" + String(newWhiteLevel, "%02.1f") + ", Light source mode=" + String(lightSourceMode, "%d"), align=2)
}
# apply levels
clip1 = clip1.ScriptClip("""
Levels(0, 1, 255, Round(newBlackLevel1), Round(newWhiteLevel1), coring=true, dither=true)
\GScript("
if(lightSourceMode1 && factorToLowerContrastDynamic1 > 1) {
contrastFactor1 = factorToLowerContrastStatic1 + factorToLowerContrastDynamic1 - 1
}
\if(debugSubtitle) {AddInfo(last, adlPercent, nativeContrast, contrastFactor1, newBlackLevel1, newWhiteLevel1, lightSourceMode1)}
return last
")
""")
clip2 = clip2.ScriptClip("""
Levels(0, 1, 255, Round(newBlackLevel2), Round(newWhiteLevel2), coring=true, dither=true)
\GScript("
if(lightSourceMode2 && factorToLowerContrastDynamic2 > 1) {
contrastFactor2 = factorToLowerContrastStatic2 + factorToLowerContrastDynamic2 - 1
}
\if(debugSubtitle) {AddInfo(last, adlPercent, nativeContrast, contrastFactor2, newBlackLevel2, newWhiteLevel2, lightSourceMode2)}
return last
")
""")
StackHorizontal(clip1, clip2)
Alles anzeigen
Notwendige Software:
Oder Alternativ zu Avisynth+:
ffdshow müsst ihr in eurem Player einbinden und das Script in ffdshow in den Avisynth-Reiter reinkopieren. Dann sollte es laufen.
Am besten ihr testet das auf einem TV mit hohem Inbildkontrast. Meiner z.B. hat einen An-/Aus-Kontrast von 3700 : 1 und der ANSI-Kontrast ist nahezu identisch. Grundsätzlich überlagert sich der Inbildkontrast des Anzeigegerätes mit dem simulierten, so dass man nicht unbedingt das sieht, was man sehen möchte.
Ansonsten gibt es noch ein paar Einschränkungen:
- Dynamischer Kontrast und statische Helligkeit funktionieren nicht zusammen
- Der Schwarzwert wird immer für das gesamte Bild gleichmäßig angehoben. Effekte wie Halos, Blooming usw. werden nicht simuliert.
Viel Spaß damit!