diff --git a/Userland/Libraries/LibGfx/CMakeLists.txt b/Userland/Libraries/LibGfx/CMakeLists.txt index d0199b82c9..e1b90ad9e4 100644 --- a/Userland/Libraries/LibGfx/CMakeLists.txt +++ b/Userland/Libraries/LibGfx/CMakeLists.txt @@ -32,6 +32,7 @@ set(SOURCES ICC/Profile.cpp ICC/Tags.cpp ICC/TagTypes.cpp + ICC/WellKnownProfiles.cpp ICOLoader.cpp ImageDecoder.cpp JPEGLoader.cpp diff --git a/Userland/Libraries/LibGfx/ICC/WellKnownProfiles.cpp b/Userland/Libraries/LibGfx/ICC/WellKnownProfiles.cpp new file mode 100644 index 0000000000..389c40c7b7 --- /dev/null +++ b/Userland/Libraries/LibGfx/ICC/WellKnownProfiles.cpp @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2023, Nico Weber + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include + +namespace Gfx::ICC { + +static ProfileHeader rgb_header() +{ + ProfileHeader header; + header.version = Version(4, 0x40); + header.device_class = DeviceClass::DisplayDevice; + header.data_color_space = ColorSpace::RGB; + header.connection_space = ColorSpace::PCSXYZ; + header.creation_timestamp = time(NULL); + header.rendering_intent = RenderingIntent::Perceptual; + header.pcs_illuminant = XYZ { 0.9642, 1.0, 0.8249 }; + return header; +} + +static ErrorOr> en_US(StringView text) +{ + Vector records; + TRY(records.try_append({ ('e' << 8) | 'n', ('U' << 8) | 'S', TRY(String::from_utf8(text)) })); + return try_make_ref_counted(0, 0, records); +} + +static ErrorOr> XYZ_data(XYZ xyz) +{ + Vector xyzs; + TRY(xyzs.try_append(xyz)); + return try_make_ref_counted(0, 0, move(xyzs)); +} + +ErrorOr> sRGB() +{ + // Returns an sRGB profile. + // https://en.wikipedia.org/wiki/SRGB + + // FIXME: There's a surprising amount of variety in sRGB ICC profiles in the wild. + // Explain why, and why this picks the numbers it does. + + auto header = rgb_header(); + + OrderedHashMap> tag_table; + + TRY(tag_table.try_set(profileDescriptionTag, TRY(en_US("SerenityOS sRGB"sv)))); + TRY(tag_table.try_set(copyrightTag, TRY(en_US("Public Domain"sv)))); + + // Transfer function. + // Numbers from https://en.wikipedia.org/wiki/SRGB#From_sRGB_to_CIE_XYZ + Array curve_parameters = { 2.4, 1 / 1.055, 0.055 / 1.055, 1 / 12.92, 0.04045 }; + auto curve = TRY(try_make_ref_counted(0, 0, ParametricCurveTagData::FunctionType::sRGB, curve_parameters)); + TRY(tag_table.try_set(redTRCTag, curve)); + TRY(tag_table.try_set(greenTRCTag, curve)); + TRY(tag_table.try_set(blueTRCTag, curve)); + + // Chromatic adaptation matrix, chromacities and whitepoint. + // FIXME: Actual values for chromatic adaptation matrix and chromacities. + TRY(tag_table.try_set(mediaWhitePointTag, TRY(XYZ_data(XYZ { 0, 0, 0 })))); + TRY(tag_table.try_set(redMatrixColumnTag, TRY(XYZ_data(XYZ { 0, 0, 0 })))); + TRY(tag_table.try_set(greenMatrixColumnTag, TRY(XYZ_data(XYZ { 0, 0, 0 })))); + TRY(tag_table.try_set(blueMatrixColumnTag, TRY(XYZ_data(XYZ { 0, 0, 0 })))); + + Vector chromatic_adaptation_matrix = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + TRY(tag_table.try_set(chromaticAdaptationTag, TRY(try_make_ref_counted(0, 0, move(chromatic_adaptation_matrix))))); + + return Profile::create(header, move(tag_table)); +} + +} diff --git a/Userland/Libraries/LibGfx/ICC/WellKnownProfiles.h b/Userland/Libraries/LibGfx/ICC/WellKnownProfiles.h new file mode 100644 index 0000000000..aedbc14973 --- /dev/null +++ b/Userland/Libraries/LibGfx/ICC/WellKnownProfiles.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2023, Nico Weber + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include + +namespace Gfx::ICC { + +class Profile; + +ErrorOr> sRGB(); + +}