mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-09-11 13:36:13 +03:00
LibGfx: Add a function to create an in-memory sRGB profile
This might be useful for converting data from arbitrary profiles to sRGB. For now, this only encodes the transfer function and puts in zero values for chromaticities, whitepoint, and chromatic adaptation matrix. This makes the profile unusable for now. But I've spent a very long time reading things and need to check in some code, and it's some progress. The encoded transfer function exactly matches the one in GIMP's built-in sRGB ICC profile (but not the Compact-ICC-Profiles v4 one or the RawTherapee v4 one -- I'll add a comment about why later.)
This commit is contained in:
parent
8f415e7b21
commit
0ba532e14e
Notes:
sideshowbarker
2024-07-17 06:35:23 +09:00
Author: https://github.com/nico Commit: https://github.com/SerenityOS/serenity/commit/0ba532e14e Pull-request: https://github.com/SerenityOS/serenity/pull/17714 Reviewed-by: https://github.com/linusg
@ -32,6 +32,7 @@ set(SOURCES
|
||||
ICC/Profile.cpp
|
||||
ICC/Tags.cpp
|
||||
ICC/TagTypes.cpp
|
||||
ICC/WellKnownProfiles.cpp
|
||||
ICOLoader.cpp
|
||||
ImageDecoder.cpp
|
||||
JPEGLoader.cpp
|
||||
|
77
Userland/Libraries/LibGfx/ICC/WellKnownProfiles.cpp
Normal file
77
Userland/Libraries/LibGfx/ICC/WellKnownProfiles.cpp
Normal file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (c) 2023, Nico Weber <thakis@chromium.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibGfx/ICC/Profile.h>
|
||||
#include <LibGfx/ICC/Tags.h>
|
||||
#include <LibGfx/ICC/WellKnownProfiles.h>
|
||||
#include <time.h>
|
||||
|
||||
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<NonnullRefPtr<MultiLocalizedUnicodeTagData>> en_US(StringView text)
|
||||
{
|
||||
Vector<MultiLocalizedUnicodeTagData::Record> records;
|
||||
TRY(records.try_append({ ('e' << 8) | 'n', ('U' << 8) | 'S', TRY(String::from_utf8(text)) }));
|
||||
return try_make_ref_counted<MultiLocalizedUnicodeTagData>(0, 0, records);
|
||||
}
|
||||
|
||||
static ErrorOr<NonnullRefPtr<XYZTagData>> XYZ_data(XYZ xyz)
|
||||
{
|
||||
Vector<XYZ> xyzs;
|
||||
TRY(xyzs.try_append(xyz));
|
||||
return try_make_ref_counted<XYZTagData>(0, 0, move(xyzs));
|
||||
}
|
||||
|
||||
ErrorOr<NonnullRefPtr<Profile>> 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<TagSignature, NonnullRefPtr<TagData>> 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<S15Fixed16, 7> curve_parameters = { 2.4, 1 / 1.055, 0.055 / 1.055, 1 / 12.92, 0.04045 };
|
||||
auto curve = TRY(try_make_ref_counted<ParametricCurveTagData>(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<S15Fixed16, 9> chromatic_adaptation_matrix = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
TRY(tag_table.try_set(chromaticAdaptationTag, TRY(try_make_ref_counted<S15Fixed16ArrayTagData>(0, 0, move(chromatic_adaptation_matrix)))));
|
||||
|
||||
return Profile::create(header, move(tag_table));
|
||||
}
|
||||
|
||||
}
|
18
Userland/Libraries/LibGfx/ICC/WellKnownProfiles.h
Normal file
18
Userland/Libraries/LibGfx/ICC/WellKnownProfiles.h
Normal file
@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2023, Nico Weber <thakis@chromium.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/Error.h>
|
||||
#include <AK/NonnullRefPtr.h>
|
||||
|
||||
namespace Gfx::ICC {
|
||||
|
||||
class Profile;
|
||||
|
||||
ErrorOr<NonnullRefPtr<Profile>> sRGB();
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user