mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 02:37:35 +00:00
LibGfx/ICC: Extract a lab_from_xyz() function
Pure code move, no behavior change.
This commit is contained in:
parent
fda9840f48
commit
9f7b33c31f
1 changed files with 47 additions and 40 deletions
|
@ -1331,6 +1331,51 @@ ErrorOr<FloatVector3> Profile::to_pcs(ReadonlyBytes color) const
|
||||||
VERIFY_NOT_REACHED();
|
VERIFY_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static FloatVector3 lab_from_xyz(FloatVector3 xyz, XYZ white_point)
|
||||||
|
{
|
||||||
|
// 6.3.2.2 Translation between media-relative colorimetric data and ICC-absolute colorimetric data
|
||||||
|
// 6.3.2.3 Computation of PCSLAB
|
||||||
|
// 6.3.4 Colour space encodings for the PCS
|
||||||
|
// A.3 PCS encodings
|
||||||
|
|
||||||
|
auto f = [](float x) {
|
||||||
|
if (x > powf(6.f / 29.f, 3))
|
||||||
|
return cbrtf(x);
|
||||||
|
return x / (3 * powf(6.f / 29.f, 2)) + 4.f / 29.f;
|
||||||
|
};
|
||||||
|
|
||||||
|
// "X/Xn is replaced by Xr/Xi (or Xa/Xmw)"
|
||||||
|
|
||||||
|
// 6.3.2.2 Translation between media-relative colorimetric data and ICC-absolute colorimetric data
|
||||||
|
// "The translation from ICC-absolute colorimetric data to media-relative colorimetry data is given by Equations
|
||||||
|
// Xr = (Xi/Xmw) * Xa
|
||||||
|
// where
|
||||||
|
// Xr media-relative colorimetric data (i.e. PCSXYZ);
|
||||||
|
// Xa ICC-absolute colorimetric data (i.e. nCIEXYZ);
|
||||||
|
// Xmw nCIEXYZ values of the media white point as specified in the mediaWhitePointTag;
|
||||||
|
// Xi PCSXYZ values of the PCS white point defined in 6.3.4.3."
|
||||||
|
// 6.3.4.3 PCS encodings for white and black
|
||||||
|
// "Table 14 — Encodings of PCS white point: X 0,9642 Y 1,0000 Z 0,8249"
|
||||||
|
// That's identical to the values in 7.2.16 PCS illuminant field (Bytes 68 to 79).
|
||||||
|
// 9.2.36 mediaWhitePointTag
|
||||||
|
// "For displays, the values specified shall be those of the PCS illuminant as defined in 7.2.16."
|
||||||
|
// ...so for displays, this is all equivalent I think? It's maybe different for OutputDevice profiles?
|
||||||
|
|
||||||
|
float Xn = white_point.X;
|
||||||
|
float Yn = white_point.Y;
|
||||||
|
float Zn = white_point.Z;
|
||||||
|
|
||||||
|
float x = xyz[0] / Xn;
|
||||||
|
float y = xyz[1] / Yn;
|
||||||
|
float z = xyz[2] / Zn;
|
||||||
|
|
||||||
|
float L = 116 * f(y) - 16;
|
||||||
|
float a = 500 * (f(x) - f(y));
|
||||||
|
float b = 200 * (f(y) - f(z));
|
||||||
|
|
||||||
|
return { L, a, b };
|
||||||
|
}
|
||||||
|
|
||||||
static TagSignature backward_transform_tag_for_rendering_intent(RenderingIntent rendering_intent)
|
static TagSignature backward_transform_tag_for_rendering_intent(RenderingIntent rendering_intent)
|
||||||
{
|
{
|
||||||
// ICCv4, Table 25 — Profile type/profile tag and defined rendering intents
|
// ICCv4, Table 25 — Profile type/profile tag and defined rendering intents
|
||||||
|
@ -1492,46 +1537,8 @@ ErrorOr<CIELAB> Profile::to_lab(ReadonlyBytes color) const
|
||||||
return Error::from_string_literal("ICC::Profile::to_lab: conversion for DeviceLink not implemented");
|
return Error::from_string_literal("ICC::Profile::to_lab: conversion for DeviceLink not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 6.3.2.2 Translation between media-relative colorimetric data and ICC-absolute colorimetric data
|
FloatVector3 lab = lab_from_xyz(pcs, pcs_illuminant());
|
||||||
// 6.3.2.3 Computation of PCSLAB
|
return CIELAB { lab[0], lab[1], lab[2] };
|
||||||
// 6.3.4 Colour space encodings for the PCS
|
|
||||||
// A.3 PCS encodings
|
|
||||||
|
|
||||||
auto f = [](float x) {
|
|
||||||
if (x > powf(6.f / 29.f, 3))
|
|
||||||
return cbrtf(x);
|
|
||||||
return x / (3 * powf(6.f / 29.f, 2)) + 4.f / 29.f;
|
|
||||||
};
|
|
||||||
|
|
||||||
// "X/Xn is replaced by Xr/Xi (or Xa/Xmw)"
|
|
||||||
|
|
||||||
// 6.3.2.2 Translation between media-relative colorimetric data and ICC-absolute colorimetric data
|
|
||||||
// "The translation from ICC-absolute colorimetric data to media-relative colorimetry data is given by Equations
|
|
||||||
// Xr = (Xi/Xmw) * Xa
|
|
||||||
// where
|
|
||||||
// Xr media-relative colorimetric data (i.e. PCSXYZ);
|
|
||||||
// Xa ICC-absolute colorimetric data (i.e. nCIEXYZ);
|
|
||||||
// Xmw nCIEXYZ values of the media white point as specified in the mediaWhitePointTag;
|
|
||||||
// Xi PCSXYZ values of the PCS white point defined in 6.3.4.3."
|
|
||||||
// 6.3.4.3 PCS encodings for white and black
|
|
||||||
// "Table 14 — Encodings of PCS white point: X 0,9642 Y 1,0000 Z 0,8249"
|
|
||||||
// That's identical to the values in 7.2.16 PCS illuminant field (Bytes 68 to 79).
|
|
||||||
// 9.2.36 mediaWhitePointTag
|
|
||||||
// "For displays, the values specified shall be those of the PCS illuminant as defined in 7.2.16."
|
|
||||||
// ...so for displays, this is all equivalent I think? It's maybe different for OutputDevice profiles?
|
|
||||||
|
|
||||||
float Xn = pcs_illuminant().X;
|
|
||||||
float Yn = pcs_illuminant().Y;
|
|
||||||
float Zn = pcs_illuminant().Z;
|
|
||||||
|
|
||||||
float x = pcs[0] / Xn;
|
|
||||||
float y = pcs[1] / Yn;
|
|
||||||
float z = pcs[2] / Zn;
|
|
||||||
|
|
||||||
float L = 116 * f(y) - 16;
|
|
||||||
float a = 500 * (f(x) - f(y));
|
|
||||||
float b = 200 * (f(y) - f(z));
|
|
||||||
return CIELAB { L, a, b };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorOr<void> Profile::convert_image(Gfx::Bitmap& bitmap, Profile const& source_profile) const
|
ErrorOr<void> Profile::convert_image(Gfx::Bitmap& bitmap, Profile const& source_profile) const
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue