LibGfx/ICC: Extract matrix computation functions

No behavior (or perf) change.
This commit is contained in:
Nico Weber 2024-01-08 18:26:13 -05:00 committed by Sam Atkins
parent 5c5a24c6b7
commit 19d434b229
Notes: sideshowbarker 2024-07-17 11:29:41 +09:00
2 changed files with 33 additions and 25 deletions
Userland/Libraries/LibGfx/ICC

View file

@ -1304,19 +1304,13 @@ ErrorOr<FloatVector3> Profile::to_pcs(ReadonlyBytes color) const
// [connection_X] = [redMatrixColumn_X greenMatrixColumn_X blueMatrixColumn_X] [ linear_r ]
// [connection_Y] = [redMatrixColumn_Y greenMatrixColumn_Y blueMatrixColumn_Y] * [ linear_g ]
// [connection_Z] = [redMatrixColumn_Z greenMatrixColumn_Z blueMatrixColumn_Z] [ linear_b ]"
float linear_r = evaluate_curve(redTRCTag, color[0] / 255.f);
float linear_g = evaluate_curve(greenTRCTag, color[1] / 255.f);
float linear_b = evaluate_curve(blueTRCTag, color[2] / 255.f);
FloatVector3 linear_rgb {
evaluate_curve(redTRCTag, color[0] / 255.f),
evaluate_curve(greenTRCTag, color[1] / 255.f),
evaluate_curve(blueTRCTag, color[2] / 255.f),
};
auto const& red_matrix_column = this->red_matrix_column();
auto const& green_matrix_column = this->green_matrix_column();
auto const& blue_matrix_column = this->blue_matrix_column();
float X = red_matrix_column.X * linear_r + green_matrix_column.X * linear_g + blue_matrix_column.X * linear_b;
float Y = red_matrix_column.Y * linear_r + green_matrix_column.Y * linear_g + blue_matrix_column.Y * linear_b;
float Z = red_matrix_column.Z * linear_r + green_matrix_column.Z * linear_g + blue_matrix_column.Z * linear_b;
return FloatVector3 { X, Y, Z };
return rgb_to_xyz_matrix() * linear_rgb;
}
return Error::from_string_literal("ICC::Profile::to_pcs: What happened?!");
@ -1512,19 +1506,7 @@ ErrorOr<void> Profile::from_pcs(Profile const& source_profile, FloatVector3 pcs,
// Convert from XYZ to linear rgb.
// FIXME: Inverting matrix and curve on every call to this function is very inefficient.
auto const& red_matrix_column = this->red_matrix_column();
auto const& green_matrix_column = this->green_matrix_column();
auto const& blue_matrix_column = this->blue_matrix_column();
FloatMatrix3x3 forward_matrix {
red_matrix_column.X, green_matrix_column.X, blue_matrix_column.X,
red_matrix_column.Y, green_matrix_column.Y, blue_matrix_column.Y,
red_matrix_column.Z, green_matrix_column.Z, blue_matrix_column.Z
};
if (!forward_matrix.is_invertible())
return Error::from_string_literal("ICC::Profile::from_pcs: matrix not invertible");
auto matrix = forward_matrix.inverse();
FloatVector3 linear_rgb = matrix * pcs;
FloatVector3 linear_rgb = TRY(xyz_to_rgb_matrix()) * pcs;
auto evaluate_curve_inverse = [this](TagSignature curve_tag, float f) {
auto const& trc = *m_tag_table.get(curve_tag).value();
@ -1635,4 +1617,25 @@ Optional<String> Profile::tag_string_data(TagSignature signature) const
return {};
}
ErrorOr<FloatMatrix3x3> Profile::xyz_to_rgb_matrix() const
{
FloatMatrix3x3 forward_matrix = rgb_to_xyz_matrix();
if (!forward_matrix.is_invertible())
return Error::from_string_literal("ICC::Profile::from_pcs: matrix not invertible");
return forward_matrix.inverse();
}
FloatMatrix3x3 Profile::rgb_to_xyz_matrix() const
{
auto const& red_matrix_column = this->red_matrix_column();
auto const& green_matrix_column = this->green_matrix_column();
auto const& blue_matrix_column = this->blue_matrix_column();
return FloatMatrix3x3 {
red_matrix_column.X, green_matrix_column.X, blue_matrix_column.X,
red_matrix_column.Y, green_matrix_column.Y, blue_matrix_column.Y,
red_matrix_column.Z, green_matrix_column.Z, blue_matrix_column.Z
};
}
}

View file

@ -18,6 +18,7 @@
#include <LibGfx/CIELAB.h>
#include <LibGfx/ICC/DistinctFourCC.h>
#include <LibGfx/ICC/TagTypes.h>
#include <LibGfx/Matrix3x3.h>
#include <LibGfx/Vector3.h>
namespace Gfx::ICC {
@ -247,6 +248,10 @@ private:
// FIXME: The color conversion stuff should be in some other class.
ErrorOr<FloatVector3> to_pcs_a_to_b(TagData const& tag_data, ReadonlyBytes) const;
ErrorOr<void> from_pcs_b_to_a(TagData const& tag_data, FloatVector3 const&, Bytes) const;
// Only valid for RGB matrix-based profiles.
ErrorOr<FloatMatrix3x3> xyz_to_rgb_matrix() const;
FloatMatrix3x3 rgb_to_xyz_matrix() const;
};
}