mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 06:57:45 +00:00
LibGfx+icc: Read viewingConditionsType
Not terribly useful in practice either and also mostly for completionism. But with this, we can dump all types present in Lightroom Classic-exported jpegs :^)
This commit is contained in:
parent
664946c543
commit
c61cfdd5ed
4 changed files with 60 additions and 1 deletions
|
@ -600,6 +600,8 @@ ErrorOr<NonnullRefPtr<TagData>> Profile::read_tag(ReadonlyBytes bytes, u32 offse
|
||||||
return TextDescriptionTagData::from_bytes(tag_bytes, offset_to_beginning_of_tag_data_element, size_of_tag_data_element);
|
return TextDescriptionTagData::from_bytes(tag_bytes, offset_to_beginning_of_tag_data_element, size_of_tag_data_element);
|
||||||
case TextTagData::Type:
|
case TextTagData::Type:
|
||||||
return TextTagData::from_bytes(tag_bytes, offset_to_beginning_of_tag_data_element, size_of_tag_data_element);
|
return TextTagData::from_bytes(tag_bytes, offset_to_beginning_of_tag_data_element, size_of_tag_data_element);
|
||||||
|
case ViewingConditionsTagData::Type:
|
||||||
|
return ViewingConditionsTagData::from_bytes(tag_bytes, offset_to_beginning_of_tag_data_element, size_of_tag_data_element);
|
||||||
case XYZTagData::Type:
|
case XYZTagData::Type:
|
||||||
return XYZTagData::from_bytes(tag_bytes, offset_to_beginning_of_tag_data_element, size_of_tag_data_element);
|
return XYZTagData::from_bytes(tag_bytes, offset_to_beginning_of_tag_data_element, size_of_tag_data_element);
|
||||||
default:
|
default:
|
||||||
|
@ -1259,7 +1261,8 @@ ErrorOr<void> Profile::check_tag_types()
|
||||||
|
|
||||||
// ICC v4, 9.2.51 viewingConditionsTag
|
// ICC v4, 9.2.51 viewingConditionsTag
|
||||||
// "Permitted tag types: viewingConditionsType"
|
// "Permitted tag types: viewingConditionsType"
|
||||||
// FIXME
|
if (!has_type(viewingConditionsTag, { ViewingConditionsTagData::Type }, {}))
|
||||||
|
return Error::from_string_literal("ICC::Profile: viewingConditionsTag has unexpected type");
|
||||||
|
|
||||||
// FIXME: Add validation for v2-only tags:
|
// FIXME: Add validation for v2-only tags:
|
||||||
// - ICC v2, 6.4.14 crdInfoTag
|
// - ICC v2, 6.4.14 crdInfoTag
|
||||||
|
|
|
@ -934,6 +934,31 @@ ErrorOr<NonnullRefPtr<TextTagData>> TextTagData::from_bytes(ReadonlyBytes bytes,
|
||||||
return adopt_ref(*new TextTagData(offset, size, TRY(String::from_utf8(StringView(text_data, length - 1)))));
|
return adopt_ref(*new TextTagData(offset, size, TRY(String::from_utf8(StringView(text_data, length - 1)))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ErrorOr<NonnullRefPtr<ViewingConditionsTagData>> ViewingConditionsTagData::from_bytes(ReadonlyBytes bytes, u32 offset, u32 size)
|
||||||
|
{
|
||||||
|
// ICC v4, 10.30 viewingConditionsType
|
||||||
|
VERIFY(tag_type(bytes) == Type);
|
||||||
|
TRY(check_reserved(bytes));
|
||||||
|
|
||||||
|
// Table 84 — viewingConditionsType encoding
|
||||||
|
struct ViewingConditionsHeader {
|
||||||
|
XYZNumber unnormalized_ciexyz_values_for_illuminant; // "(in which Y is in cd/m2)"
|
||||||
|
XYZNumber unnormalized_ciexyz_values_for_surround; // "(in which Y is in cd/m2)"
|
||||||
|
BigEndian<MeasurementTagData::StandardIlluminant> illuminant_type;
|
||||||
|
};
|
||||||
|
static_assert(AssertSize<ViewingConditionsHeader, 28>());
|
||||||
|
|
||||||
|
if (bytes.size() < 2 * sizeof(u32) + sizeof(ViewingConditionsHeader))
|
||||||
|
return Error::from_string_literal("ICC::Profile: viewingConditionsType has not enough data");
|
||||||
|
|
||||||
|
auto& header = *bit_cast<ViewingConditionsHeader const*>(bytes.data() + 8);
|
||||||
|
|
||||||
|
TRY(MeasurementTagData::validate_standard_illuminant(header.illuminant_type));
|
||||||
|
|
||||||
|
return adopt_ref(*new ViewingConditionsTagData(offset, size, header.unnormalized_ciexyz_values_for_illuminant,
|
||||||
|
header.unnormalized_ciexyz_values_for_surround, header.illuminant_type));
|
||||||
|
}
|
||||||
|
|
||||||
ErrorOr<NonnullRefPtr<XYZTagData>> XYZTagData::from_bytes(ReadonlyBytes bytes, u32 offset, u32 size)
|
ErrorOr<NonnullRefPtr<XYZTagData>> XYZTagData::from_bytes(ReadonlyBytes bytes, u32 offset, u32 size)
|
||||||
{
|
{
|
||||||
// ICC v4, 10.31 XYZType
|
// ICC v4, 10.31 XYZType
|
||||||
|
|
|
@ -679,6 +679,32 @@ private:
|
||||||
String m_text;
|
String m_text;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ICC v4, 10.30 viewingConditionsType
|
||||||
|
class ViewingConditionsTagData : public TagData {
|
||||||
|
public:
|
||||||
|
static constexpr TagTypeSignature Type { 0x76696577 }; // 'view'
|
||||||
|
|
||||||
|
static ErrorOr<NonnullRefPtr<ViewingConditionsTagData>> from_bytes(ReadonlyBytes, u32 offset, u32 size);
|
||||||
|
|
||||||
|
ViewingConditionsTagData(u32 offset, u32 size, XYZ const& unnormalized_ciexyz_values_for_illuminant,
|
||||||
|
XYZ const& unnormalized_ciexyz_values_for_surround, MeasurementTagData::StandardIlluminant illuminant_type)
|
||||||
|
: TagData(offset, size, Type)
|
||||||
|
, m_unnormalized_ciexyz_values_for_illuminant(unnormalized_ciexyz_values_for_illuminant)
|
||||||
|
, m_unnormalized_ciexyz_values_for_surround(unnormalized_ciexyz_values_for_surround)
|
||||||
|
, m_illuminant_type(illuminant_type)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
XYZ const& unnormalized_ciexyz_values_for_illuminant() const { return m_unnormalized_ciexyz_values_for_illuminant; }
|
||||||
|
XYZ const& unnormalized_ciexyz_values_for_surround() const { return m_unnormalized_ciexyz_values_for_surround; }
|
||||||
|
MeasurementTagData::StandardIlluminant illuminant_type() const { return m_illuminant_type; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
XYZ m_unnormalized_ciexyz_values_for_illuminant; // "(in which Y is in cd/m2)"
|
||||||
|
XYZ m_unnormalized_ciexyz_values_for_surround; // "(in which Y is in cd/m2)"
|
||||||
|
MeasurementTagData::StandardIlluminant m_illuminant_type;
|
||||||
|
};
|
||||||
|
|
||||||
// ICC v4, 10.31 XYZType
|
// ICC v4, 10.31 XYZType
|
||||||
class XYZTagData : public TagData {
|
class XYZTagData : public TagData {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -311,6 +311,11 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
||||||
out_optional(" macintosh", MUST(text_description.macintosh_description().map([](auto description) { return String::formatted("\"{}\"", description); })));
|
out_optional(" macintosh", MUST(text_description.macintosh_description().map([](auto description) { return String::formatted("\"{}\"", description); })));
|
||||||
} else if (tag_data->type() == Gfx::ICC::TextTagData::Type) {
|
} else if (tag_data->type() == Gfx::ICC::TextTagData::Type) {
|
||||||
outln(" text: \"{}\"", static_cast<Gfx::ICC::TextTagData&>(*tag_data).text());
|
outln(" text: \"{}\"", static_cast<Gfx::ICC::TextTagData&>(*tag_data).text());
|
||||||
|
} else if (tag_data->type() == Gfx::ICC::ViewingConditionsTagData::Type) {
|
||||||
|
auto& viewing_conditions = static_cast<Gfx::ICC::ViewingConditionsTagData&>(*tag_data);
|
||||||
|
outln(" unnormalized CIEXYZ values for illuminant (in which Y is in cd/m²): {}", viewing_conditions.unnormalized_ciexyz_values_for_illuminant());
|
||||||
|
outln(" unnormalized CIEXYZ values for surround (in which Y is in cd/m²): {}", viewing_conditions.unnormalized_ciexyz_values_for_surround());
|
||||||
|
outln(" illuminant type: {}", Gfx::ICC::MeasurementTagData::standard_illuminant_name(viewing_conditions.illuminant_type()));
|
||||||
} else if (tag_data->type() == Gfx::ICC::XYZTagData::Type) {
|
} else if (tag_data->type() == Gfx::ICC::XYZTagData::Type) {
|
||||||
for (auto& xyz : static_cast<Gfx::ICC::XYZTagData&>(*tag_data).xyzs())
|
for (auto& xyz : static_cast<Gfx::ICC::XYZTagData&>(*tag_data).xyzs())
|
||||||
outln(" {}", xyz);
|
outln(" {}", xyz);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue