Bläddra i källkod

icc: Print if a curve looks like the sRGB curve

Nico Weber 2 år sedan
förälder
incheckning
6c7b3c56f2
1 ändrade filer med 67 tillägg och 0 borttagningar
  1. 67 0
      Userland/Utilities/icc.cpp

+ 67 - 0
Userland/Utilities/icc.cpp

@@ -74,6 +74,39 @@ static void out_parametric_curve(Gfx::ICC::ParametricCurveTagData const& paramet
     }
 }
 
+static float curve_distance_u8(Gfx::ICC::TagData const& tag1, Gfx::ICC::TagData const& tag2)
+{
+    VERIFY(tag1.type() == Gfx::ICC::CurveTagData::Type || tag1.type() == Gfx::ICC::ParametricCurveTagData::Type);
+    VERIFY(tag2.type() == Gfx::ICC::CurveTagData::Type || tag2.type() == Gfx::ICC::ParametricCurveTagData::Type);
+
+    float curve1_data[256];
+    if (tag1.type() == Gfx::ICC::CurveTagData::Type) {
+        auto& curve1 = static_cast<Gfx::ICC::CurveTagData const&>(tag1);
+        for (int i = 0; i < 256; ++i)
+            curve1_data[i] = curve1.evaluate(i / 255.f);
+    } else {
+        auto& parametric_curve1 = static_cast<Gfx::ICC::ParametricCurveTagData const&>(tag1);
+        for (int i = 0; i < 256; ++i)
+            curve1_data[i] = parametric_curve1.evaluate(i / 255.f);
+    }
+
+    float curve2_data[256];
+    if (tag2.type() == Gfx::ICC::CurveTagData::Type) {
+        auto& curve2 = static_cast<Gfx::ICC::CurveTagData const&>(tag2);
+        for (int i = 0; i < 256; ++i)
+            curve2_data[i] = curve2.evaluate(i / 255.f);
+    } else {
+        auto& parametric_curve2 = static_cast<Gfx::ICC::ParametricCurveTagData const&>(tag2);
+        for (int i = 0; i < 256; ++i)
+            curve2_data[i] = parametric_curve2.evaluate(i / 255.f);
+    }
+
+    float distance = 0;
+    for (int i = 0; i < 256; ++i)
+        distance += fabsf(curve1_data[i] - curve2_data[i]);
+    return distance;
+}
+
 static ErrorOr<void> out_curve_tag(Gfx::ICC::TagData const& tag, int indent_amount)
 {
     VERIFY(tag.type() == Gfx::ICC::CurveTagData::Type || tag.type() == Gfx::ICC::ParametricCurveTagData::Type);
@@ -81,6 +114,40 @@ static ErrorOr<void> out_curve_tag(Gfx::ICC::TagData const& tag, int indent_amou
         out_curve(static_cast<Gfx::ICC::CurveTagData const&>(tag), indent_amount);
     if (tag.type() == Gfx::ICC::ParametricCurveTagData::Type)
         out_parametric_curve(static_cast<Gfx::ICC::ParametricCurveTagData const&>(tag), indent_amount);
+
+    auto sRGB_curve = TRY(Gfx::ICC::sRGB_curve());
+
+    // Some example values (for abs distance summed over the 256 values of an u8):
+    // In Compact-ICC-Profiles/profiles:
+    //   AdobeCompat-v2.icc: 1.14 (this is a gamma 2.2 curve, so not really sRGB but close)
+    //   AdobeCompat-v4.icc: 1.13
+    //   AppleCompat-v2.icc: 11.94 (gamma 1.8 curve)
+    //   DCI-P3-v4.icc: 8.29 (gamma 2.6 curve)
+    //   DisplayP3-v2-magic.icc: 0.000912 (looks sRGB-ish)
+    //   DisplayP3-v2-micro.icc: 0.010819
+    //   DisplayP3-v4.icc: 0.001062 (yes, definitely sRGB)
+    //   Rec2020-g24-v4.icc: 4.119216 (gamma 2.4 curve)
+    //   Rec2020-v4.icc: 7.805417 (custom non-sRGB curve)
+    //   Rec709-v4.icc: 7.783267 (same custom non-sRGB curve as Rec2020)
+    //   sRGB-v2-magic.icc: 0.000912
+    //   sRGB-v2-micro.icc: 0.010819
+    //   sRGB-v2-nano.icc: 0.052516
+    //   sRGB-v4.icc: 0.001062
+    //   scRGB-v2.icc: 48.379859 (linear identity curve)
+    // Google sRGB IEC61966-2.1 (from a Pixel jpeg, parametric): 0
+    // Google sRGB IEC61966-2.1 (from a Pixel jpeg, LUT curve): 0.00096
+    // Apple 2015 Display P3 (from iPhone 7, parametric): 0.011427 (has the old, left intersection for switching from linear to exponent)
+    // HP sRGB: 0.00096
+    // color.org sRGB2014.icc: 0.00096
+    // color.org sRGB_ICC_v4_Appearance.icc, AToB1Tag, a curves: 0.441926 -- but this is not _really_ sRGB
+    // color.org sRGB_v4_ICC_preference.icc, AToB1Tag, a curves: 2.205453 -- not really sRGB either
+    // So `< 0.06` identifies sRGB in practice (for u8 values).
+    float u8_distance_to_sRGB = curve_distance_u8(*sRGB_curve, tag);
+    if (u8_distance_to_sRGB < 0.06f)
+        outln("{: >{}}Looks like sRGB's curve (distance {})", "", indent_amount, u8_distance_to_sRGB);
+    else
+        outln("{: >{}}Does not look like sRGB's curve (distance: {})", "", indent_amount, u8_distance_to_sRGB);
+
     return {};
 }