mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 13:57:35 +00:00
LibGfx/ICC: Implement LutBToATagData::evaluate() when there is no CLUT
This is enough to make these work: for f in VideoHD VideoNTSC VideoPAL; do Build/lagom/bin/icc --debug-roundtrip \ ~/Downloads/Adobe\ ICC\ Profiles\ \(end-user\)/RGB/$f.icc done It's also possible to convert images to those color spaces: Build/lagom/bin/image -o image-pal.png \ --convert-to-color-profile path/to/RGB/VideoPAL.icc \ image-srgb.png (If there's no png file with an embedded sRGB profile at hand, do first: Build/lagom/bin/icc --reencode-to serenity-sRGB.icc -n sRGB Build/lagom/bin/image -o image-srgb.png \ --assign-color-profile serenity-sRGB.icc image-no-color-space.png ) In color-managed viewers, images-srgb.png and image-pal.png should look identical. But if you either explicitly assign the sRGB profile to the pal image, or strip the embedded color space, they'll look different (since image viewers then assume the image in the VideoPAL space is in sRGB): Build/lagom/bin/image -o image-pal-strip.png --strip-color-profile \ image-pal.png Build/lagom/bin/image -o image-not-actually-srgb.png \ --assign-color-profile serenity-sRGB.icc image-pal.png
This commit is contained in:
parent
a75533b46b
commit
701d56f7ad
1 changed files with 63 additions and 2 deletions
|
@ -1303,13 +1303,74 @@ inline ErrorOr<FloatVector3> LutAToBTagData::evaluate(ColorSpace connection_spac
|
|||
return output_color;
|
||||
}
|
||||
|
||||
inline ErrorOr<void> LutBToATagData::evaluate(ColorSpace connection_space, FloatVector3 const&, Bytes out_bytes) const
|
||||
inline ErrorOr<void> LutBToATagData::evaluate(ColorSpace connection_space, FloatVector3 const& in_color, Bytes out_bytes) const
|
||||
{
|
||||
VERIFY(connection_space == ColorSpace::PCSXYZ || connection_space == ColorSpace::PCSLAB);
|
||||
VERIFY(number_of_input_channels() == 3);
|
||||
VERIFY(number_of_output_channels() == out_bytes.size());
|
||||
|
||||
return Error::from_string_literal("LutBToATagData::evaluate: Not yet implemented");
|
||||
// ICC v4, 10.13 lutBToAType
|
||||
// "Data are processed using these elements via the following sequence:
|
||||
// (“B” curves) ⇨ (matrix) ⇨ (“M” curves) ⇨ (multi-dimensional lookup table, CLUT) ⇨ (“A” curves)."
|
||||
|
||||
// See comment at start of LutAToBTagData::evaluate() for the clipping flow.
|
||||
// This function generally is the same as LutAToBTagData::evaluate() upside down.
|
||||
|
||||
auto evaluate_curve = [](LutCurveType const& curve, float f) {
|
||||
VERIFY(curve->type() == CurveTagData::Type || curve->type() == ParametricCurveTagData::Type);
|
||||
if (curve->type() == CurveTagData::Type)
|
||||
return static_cast<CurveTagData const&>(*curve).evaluate(f);
|
||||
return static_cast<ParametricCurveTagData const&>(*curve).evaluate(f);
|
||||
};
|
||||
|
||||
FloatVector3 color;
|
||||
if (connection_space == ColorSpace::PCSXYZ) {
|
||||
color = in_color * 32768 / 65535.0f;
|
||||
} else {
|
||||
VERIFY(connection_space == ColorSpace::PCSLAB);
|
||||
color[0] = in_color[0] / 100.0f;
|
||||
color[1] = (in_color[1] + 128.0f) / 255.0f;
|
||||
color[2] = (in_color[2] + 128.0f) / 255.0f;
|
||||
}
|
||||
|
||||
color = FloatVector3 {
|
||||
evaluate_curve(m_b_curves[0], color[0]),
|
||||
evaluate_curve(m_b_curves[1], color[1]),
|
||||
evaluate_curve(m_b_curves[2], color[2])
|
||||
};
|
||||
|
||||
VERIFY(m_e.has_value() == m_m_curves.has_value());
|
||||
if (m_e.has_value()) {
|
||||
// ICC v4, 10.13.3 Matrix
|
||||
// "The resultant values Y1, Y2 and Y3 shall be clipped to the range 0,0 to 1,0 and used as inputs to the “M” curves."
|
||||
EMatrix3x4 const& e = m_e.value();
|
||||
FloatVector3 new_color = {
|
||||
(float)e[0] * color[0] + (float)e[1] * color[1] + (float)e[2] * color[2] + (float)e[9],
|
||||
(float)e[3] * color[0] + (float)e[4] * color[1] + (float)e[5] * color[2] + (float)e[10],
|
||||
(float)e[6] * color[0] + (float)e[7] * color[1] + (float)e[8] * color[2] + (float)e[11],
|
||||
};
|
||||
color = new_color.clamped(0.f, 1.f);
|
||||
|
||||
auto const& m_curves = m_m_curves.value();
|
||||
color = FloatVector3 {
|
||||
evaluate_curve(m_curves[0], color[0]),
|
||||
evaluate_curve(m_curves[1], color[1]),
|
||||
evaluate_curve(m_curves[2], color[2])
|
||||
};
|
||||
}
|
||||
|
||||
VERIFY(m_clut.has_value() == m_a_curves.has_value());
|
||||
if (m_clut.has_value()) {
|
||||
// FIXME
|
||||
return Error::from_string_literal("LutBToATagData::evaluate: Not yet implemented when CLUT present");
|
||||
} else {
|
||||
VERIFY(number_of_output_channels() == 3);
|
||||
out_bytes[0] = round_to<u8>(color[0] * 255.0f);
|
||||
out_bytes[1] = round_to<u8>(color[1] * 255.0f);
|
||||
out_bytes[2] = round_to<u8>(color[2] * 255.0f);
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue