From 88b49a639e2204be7cfd0c4c9b13376b014de217 Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Wed, 24 Jan 2024 11:44:09 -0500 Subject: [PATCH] LibGfx/ICC: Add a convert_cmyk_image() method It converts from a CMYKBitmap to an (rgb) bitmap, using a real color profile. The API design here isn't super scalable (what if we want to also handle grayscale inputs? What if we also want to convert _to_ cmyk or grayscale?), but we have to start somewhere. Uses of this can inform future API improvements. --- Userland/Libraries/LibGfx/ICC/Profile.cpp | 26 +++++++++++++++++++++++ Userland/Libraries/LibGfx/ICC/Profile.h | 1 + 2 files changed, 27 insertions(+) diff --git a/Userland/Libraries/LibGfx/ICC/Profile.cpp b/Userland/Libraries/LibGfx/ICC/Profile.cpp index 0f5df41264..44503392ae 100644 --- a/Userland/Libraries/LibGfx/ICC/Profile.cpp +++ b/Userland/Libraries/LibGfx/ICC/Profile.cpp @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -1660,6 +1661,31 @@ ErrorOr Profile::convert_image(Gfx::Bitmap& bitmap, Profile const& source_ return {}; } +ErrorOr Profile::convert_cmyk_image(Bitmap& out, CMYKBitmap const& in, Profile const& source_profile) const +{ + if (out.size() != in.size()) + return Error::from_string_literal("ICC::Profile::convert_cmyk_image: out and in must have the same dimensions"); + + // Might fail if `out` has a scale_factor() != 1. + if (out.data_size() != in.data_size()) + return Error::from_string_literal("ICC::Profile::convert_cmyk_image: out and in must have the same buffer size"); + + static_assert(sizeof(ARGB32) == sizeof(CMYK)); + ARGB32* out_data = out.begin(); + CMYK const* in_data = const_cast(in).begin(); + + for (size_t i = 0; i < in.data_size() / sizeof(CMYK); ++i) { + u8 cmyk[] = { in_data[i].c, in_data[i].m, in_data[i].y, in_data[i].k }; + auto pcs = TRY(source_profile.to_pcs(cmyk)); + + u8 rgb[3]; + TRY(from_pcs(source_profile, pcs, rgb)); + out_data[i] = Color(rgb[0], rgb[1], rgb[2]).value(); + } + + return {}; +} + XYZ const& Profile::red_matrix_column() const { return xyz_data(redMatrixColumnTag); } XYZ const& Profile::green_matrix_column() const { return xyz_data(greenMatrixColumnTag); } XYZ const& Profile::blue_matrix_column() const { return xyz_data(blueMatrixColumnTag); } diff --git a/Userland/Libraries/LibGfx/ICC/Profile.h b/Userland/Libraries/LibGfx/ICC/Profile.h index 5826c5ec4e..91a6fc06dc 100644 --- a/Userland/Libraries/LibGfx/ICC/Profile.h +++ b/Userland/Libraries/LibGfx/ICC/Profile.h @@ -275,6 +275,7 @@ public: ErrorOr to_lab(ReadonlyBytes) const; ErrorOr convert_image(Bitmap&, Profile const& source_profile) const; + ErrorOr convert_cmyk_image(Bitmap&, CMYKBitmap const&, Profile const& source_profile) const; // Only call these if you know that this is an RGB matrix-based profile. XYZ const& red_matrix_column() const;