mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 05:17:35 +00:00
LibPDF: Implement LabColorSpace
This commit is contained in:
parent
cf3c8a216b
commit
1dfd49ef99
3 changed files with 76 additions and 5 deletions
|
@ -506,24 +506,90 @@ Vector<float> ICCBasedColorSpace::default_decode() const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PDFErrorOr<NonnullRefPtr<LabColorSpace>> LabColorSpace::create(Document*, Vector<Value>&& parameters)
|
PDFErrorOr<NonnullRefPtr<LabColorSpace>> LabColorSpace::create(Document* document, Vector<Value>&& parameters)
|
||||||
{
|
{
|
||||||
if (parameters.size() != 1)
|
if (parameters.size() != 1)
|
||||||
return Error { Error::Type::MalformedPDF, "Lab color space expects one parameter" };
|
return Error { Error::Type::MalformedPDF, "Lab color space expects one parameter" };
|
||||||
|
|
||||||
|
auto param = parameters[0];
|
||||||
|
if (!param.has<NonnullRefPtr<Object>>() || !param.get<NonnullRefPtr<Object>>()->is<DictObject>())
|
||||||
|
return Error { Error::Type::MalformedPDF, "Lab color space expects a dict parameter" };
|
||||||
|
|
||||||
|
auto dict = param.get<NonnullRefPtr<Object>>()->cast<DictObject>();
|
||||||
|
if (!dict->contains(CommonNames::WhitePoint))
|
||||||
|
return Error { Error::Type::MalformedPDF, "Lab color space expects a Whitepoint key" };
|
||||||
|
|
||||||
|
auto white_point_array = TRY(dict->get_array(document, CommonNames::WhitePoint));
|
||||||
|
if (white_point_array->size() != 3)
|
||||||
|
return Error { Error::Type::MalformedPDF, "Lab color space expects 3 Whitepoint parameters" };
|
||||||
|
|
||||||
auto color_space = adopt_ref(*new LabColorSpace());
|
auto color_space = adopt_ref(*new LabColorSpace());
|
||||||
// FIXME: Implement.
|
|
||||||
|
color_space->m_whitepoint[0] = white_point_array->at(0).to_float();
|
||||||
|
color_space->m_whitepoint[1] = white_point_array->at(1).to_float();
|
||||||
|
color_space->m_whitepoint[2] = white_point_array->at(2).to_float();
|
||||||
|
|
||||||
|
if (color_space->m_whitepoint[1] != 1.0f)
|
||||||
|
return Error { Error::Type::MalformedPDF, "Lab color space expects 2nd Whitepoint to be 1.0" };
|
||||||
|
|
||||||
|
if (dict->contains(CommonNames::BlackPoint)) {
|
||||||
|
auto black_point_array = TRY(dict->get_array(document, CommonNames::BlackPoint));
|
||||||
|
if (black_point_array->size() == 3) {
|
||||||
|
color_space->m_blackpoint[0] = black_point_array->at(0).to_float();
|
||||||
|
color_space->m_blackpoint[1] = black_point_array->at(1).to_float();
|
||||||
|
color_space->m_blackpoint[2] = black_point_array->at(2).to_float();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dict->contains(CommonNames::Range)) {
|
||||||
|
auto range_array = TRY(dict->get_array(document, CommonNames::Range));
|
||||||
|
if (range_array->size() == 4) {
|
||||||
|
color_space->m_range[0] = range_array->at(0).to_float();
|
||||||
|
color_space->m_range[1] = range_array->at(1).to_float();
|
||||||
|
color_space->m_range[2] = range_array->at(2).to_float();
|
||||||
|
color_space->m_range[3] = range_array->at(3).to_float();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return color_space;
|
return color_space;
|
||||||
}
|
}
|
||||||
|
|
||||||
PDFErrorOr<Color> LabColorSpace::color(ReadonlySpan<Value>) const
|
PDFErrorOr<Color> LabColorSpace::color(ReadonlySpan<Value> arguments) const
|
||||||
{
|
{
|
||||||
return Error::rendering_unsupported_error("Lab color spaces not yet implemented");
|
VERIFY(arguments.size() == 3);
|
||||||
|
auto L_star = clamp(arguments[0].to_float(), 0.0f, 100.0f);
|
||||||
|
auto a_star = clamp(arguments[1].to_float(), m_range[0], m_range[1]);
|
||||||
|
auto b_star = clamp(arguments[2].to_float(), m_range[2], m_range[3]);
|
||||||
|
|
||||||
|
auto L = (L_star + 16) / 116 + a_star / 500;
|
||||||
|
auto M = (L_star + 16) / 116;
|
||||||
|
auto N = (L_star + 16) / 116 - b_star / 200;
|
||||||
|
|
||||||
|
auto g = [](float x) {
|
||||||
|
if (x >= 6.0f / 29.0f)
|
||||||
|
return powf(x, 3);
|
||||||
|
return 108.0f / 841.0f * (x - 4.0f / 29.0f);
|
||||||
|
};
|
||||||
|
|
||||||
|
auto x = m_whitepoint[0] * g(L);
|
||||||
|
auto y = m_whitepoint[1] * g(M);
|
||||||
|
auto z = m_whitepoint[2] * g(N);
|
||||||
|
|
||||||
|
auto flattened_xyz = flatten_and_normalize_whitepoint(m_whitepoint, { x, y, z });
|
||||||
|
auto scaled_black_point_xyz = scale_black_point(m_blackpoint, flattened_xyz);
|
||||||
|
auto d65_normalized = convert_to_d65(scaled_black_point_xyz);
|
||||||
|
auto srgb = convert_to_srgb(d65_normalized);
|
||||||
|
|
||||||
|
auto red = static_cast<u8>(clamp(srgb[0], 0.0f, 1.0f) * 255.0f);
|
||||||
|
auto green = static_cast<u8>(clamp(srgb[1], 0.0f, 1.0f) * 255.0f);
|
||||||
|
auto blue = static_cast<u8>(clamp(srgb[2], 0.0f, 1.0f) * 255.0f);
|
||||||
|
|
||||||
|
return Color(red, green, blue);
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector<float> LabColorSpace::default_decode() const
|
Vector<float> LabColorSpace::default_decode() const
|
||||||
{
|
{
|
||||||
return { 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f };
|
return { 0.0f, 100.0f, m_range[0], m_range[1], m_range[2], m_range[3] };
|
||||||
}
|
}
|
||||||
|
|
||||||
PDFErrorOr<NonnullRefPtr<SeparationColorSpace>> SeparationColorSpace::create(Document*, Vector<Value>&&)
|
PDFErrorOr<NonnullRefPtr<SeparationColorSpace>> SeparationColorSpace::create(Document*, Vector<Value>&&)
|
||||||
|
|
|
@ -193,6 +193,10 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
LabColorSpace() = default;
|
LabColorSpace() = default;
|
||||||
|
|
||||||
|
Array<float, 3> m_whitepoint { 0, 0, 0 };
|
||||||
|
Array<float, 3> m_blackpoint { 0, 0, 0 };
|
||||||
|
Array<float, 4> m_range { -100, 100, -100, 100 };
|
||||||
};
|
};
|
||||||
|
|
||||||
class SeparationColorSpace final : public ColorSpace {
|
class SeparationColorSpace final : public ColorSpace {
|
||||||
|
|
|
@ -134,6 +134,7 @@
|
||||||
X(Producer) \
|
X(Producer) \
|
||||||
X(R) \
|
X(R) \
|
||||||
X(RI) \
|
X(RI) \
|
||||||
|
X(Range) \
|
||||||
X(Registry) \
|
X(Registry) \
|
||||||
X(Resources) \
|
X(Resources) \
|
||||||
X(Root) \
|
X(Root) \
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue