mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 12:47:35 +00:00
ICC: Implement TRC inversion in from_pcs for point curves
This allows converting to a color space that uses a non-parametric curve, for example: Build/lagom/image -o foo.png \ --convert-to-color-profile .../profiles/sRGB-v2-micro.icc \ input.jpg ...where profiles/sRGB-v2-micro.icc is from https://github.com/saucecontrol/Compact-ICC-Profiles/ (Parametric curves are new in ICC v4, which means all v2 profiles use point curves.)
This commit is contained in:
parent
926c0d8676
commit
9c3e36e72c
2 changed files with 37 additions and 4 deletions
|
@ -1570,10 +1570,8 @@ ErrorOr<void> Profile::from_pcs(FloatVector3 const& pcs, Bytes color) const
|
|||
auto evaluate_curve_inverse = [this](TagSignature curve_tag, float f) {
|
||||
auto const& trc = *m_tag_table.get(curve_tag).value();
|
||||
VERIFY(trc.type() == CurveTagData::Type || trc.type() == ParametricCurveTagData::Type);
|
||||
if (trc.type() == CurveTagData::Type) {
|
||||
TODO();
|
||||
return 0.f;
|
||||
}
|
||||
if (trc.type() == CurveTagData::Type)
|
||||
return static_cast<CurveTagData const&>(trc).evaluate_inverse(f);
|
||||
return static_cast<ParametricCurveTagData const&>(trc).evaluate_inverse(f);
|
||||
};
|
||||
|
||||
|
|
|
@ -179,6 +179,41 @@ public:
|
|||
return mix(values()[i] / 65535.f, values()[i + 1] / 65535.f, f);
|
||||
}
|
||||
|
||||
// y must be in [0..1].
|
||||
float evaluate_inverse(float y) const
|
||||
{
|
||||
VERIFY(0.f <= y && y <= 1.f);
|
||||
|
||||
if (values().is_empty())
|
||||
return y;
|
||||
|
||||
if (values().size() == 1)
|
||||
return powf(y, 1.f / (values()[0] / (float)0x100));
|
||||
|
||||
// FIXME: Verify somewhere that:
|
||||
// * values() is non-decreasing
|
||||
// * values()[0] is 0, values()[values().size() - 1] is 65535
|
||||
|
||||
// FIXME: Use binary search.
|
||||
size_t n = values().size() - 1;
|
||||
size_t i = 0;
|
||||
for (; i < n; ++i) {
|
||||
if (values()[i] / 65535.f <= y && y <= values()[i + 1] / 65535.f)
|
||||
break;
|
||||
}
|
||||
|
||||
float x1 = i / (float)n;
|
||||
float y1 = values()[i] / 65535.f;
|
||||
float x2 = (i + 1) / (float)n;
|
||||
float y2 = values()[i + 1] / 65535.f;
|
||||
|
||||
// Flat line segment?
|
||||
if (y1 == y2)
|
||||
return (x1 + x2) / 2;
|
||||
|
||||
return (y - y1) / (y2 - y1) * (x2 - x1) + x1; // Same as `((y - y1) / (y2 - y1) + i) / (float)n`
|
||||
}
|
||||
|
||||
private:
|
||||
Vector<u16> m_values;
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue