icc: Print if a curve looks like the sRGB curve

This commit is contained in:
Nico Weber 2023-04-11 09:41:46 -04:00 committed by Linus Groh
parent fe8c0292ad
commit 6c7b3c56f2
Notes: sideshowbarker 2024-07-16 22:34:39 +09:00

View file

@ -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 {};
}