diff options
author | Nico Weber <thakis@chromium.org> | 2023-03-15 11:08:43 +0100 |
---|---|---|
committer | Linus Groh <mail@linusgroh.de> | 2023-03-15 11:02:41 +0000 |
commit | 189ea375a5f018504f0553eca12f82133ee80189 (patch) | |
tree | 155023308af6cc1c3f8b5448cf27bd72d71703bf /Userland/Libraries | |
parent | 6e2d3fe0dfa56fece7c23043f17d8dc2d75ae91f (diff) | |
download | serenity-189ea375a5f018504f0553eca12f82133ee80189.zip |
LibGfx: Let PNGWriter optionally embed an ICC profile
Diffstat (limited to 'Userland/Libraries')
-rw-r--r-- | Userland/Libraries/LibGfx/PNGWriter.cpp | 19 | ||||
-rw-r--r-- | Userland/Libraries/LibGfx/PNGWriter.h | 13 |
2 files changed, 30 insertions, 2 deletions
diff --git a/Userland/Libraries/LibGfx/PNGWriter.cpp b/Userland/Libraries/LibGfx/PNGWriter.cpp index 985ff9f1cb..efd47d83f0 100644 --- a/Userland/Libraries/LibGfx/PNGWriter.cpp +++ b/Userland/Libraries/LibGfx/PNGWriter.cpp @@ -146,6 +146,21 @@ ErrorOr<void> PNGWriter::add_IHDR_chunk(u32 width, u32 height, u8 bit_depth, PNG return {}; } +ErrorOr<void> PNGWriter::add_iCCP_chunk(ReadonlyBytes icc_data) +{ + // https://www.w3.org/TR/png/#11iCCP + PNGChunk chunk { "iCCP" }; + + TRY(chunk.add("embedded profile"sv.bytes())); + TRY(chunk.add_u8(0)); // \0-terminate profile name + + TRY(chunk.add_u8(0)); // compression method deflate + TRY(chunk.compress_and_add(icc_data)); + + TRY(add_chunk(chunk)); + return {}; +} + ErrorOr<void> PNGWriter::add_IEND_chunk() { PNGChunk png_chunk { "IEND" }; @@ -273,11 +288,13 @@ ErrorOr<void> PNGWriter::add_IDAT_chunk(Gfx::Bitmap const& bitmap) return {}; } -ErrorOr<ByteBuffer> PNGWriter::encode(Gfx::Bitmap const& bitmap) +ErrorOr<ByteBuffer> PNGWriter::encode(Gfx::Bitmap const& bitmap, Options options) { PNGWriter writer; TRY(writer.add_png_header()); TRY(writer.add_IHDR_chunk(bitmap.width(), bitmap.height(), 8, PNG::ColorType::TruecolorWithAlpha, 0, 0, 0)); + if (options.icc_data.has_value()) + TRY(writer.add_iCCP_chunk(options.icc_data.value())); TRY(writer.add_IDAT_chunk(bitmap)); TRY(writer.add_IEND_chunk()); return ByteBuffer::copy(writer.m_data); diff --git a/Userland/Libraries/LibGfx/PNGWriter.h b/Userland/Libraries/LibGfx/PNGWriter.h index 2f53fe9907..9a19e3b91b 100644 --- a/Userland/Libraries/LibGfx/PNGWriter.h +++ b/Userland/Libraries/LibGfx/PNGWriter.h @@ -7,6 +7,7 @@ #pragma once +#include <AK/Optional.h> #include <AK/Vector.h> #include <LibGfx/Forward.h> #include <LibGfx/PNGShared.h> @@ -15,9 +16,18 @@ namespace Gfx { class PNGChunk; +// This is not a nested struct to work around https://llvm.org/PR36684 +struct PNGWriterOptions { + // Data for the iCCP chunk. + // FIXME: Allow writing cICP, sRGB, or gAMA instead too. + Optional<ReadonlyBytes> icc_data; +}; + class PNGWriter { public: - static ErrorOr<ByteBuffer> encode(Gfx::Bitmap const&); + using Options = PNGWriterOptions; + + static ErrorOr<ByteBuffer> encode(Gfx::Bitmap const&, Options options = Options {}); private: PNGWriter() = default; @@ -26,6 +36,7 @@ private: ErrorOr<void> add_chunk(PNGChunk&); ErrorOr<void> add_png_header(); ErrorOr<void> add_IHDR_chunk(u32 width, u32 height, u8 bit_depth, PNG::ColorType color_type, u8 compression_method, u8 filter_method, u8 interlace_method); + ErrorOr<void> add_iCCP_chunk(ReadonlyBytes icc_data); ErrorOr<void> add_IDAT_chunk(Gfx::Bitmap const&); ErrorOr<void> add_IEND_chunk(); }; |