summaryrefslogtreecommitdiff
path: root/Userland/Libraries
diff options
context:
space:
mode:
authorNico Weber <thakis@chromium.org>2023-03-15 11:08:43 +0100
committerLinus Groh <mail@linusgroh.de>2023-03-15 11:02:41 +0000
commit189ea375a5f018504f0553eca12f82133ee80189 (patch)
tree155023308af6cc1c3f8b5448cf27bd72d71703bf /Userland/Libraries
parent6e2d3fe0dfa56fece7c23043f17d8dc2d75ae91f (diff)
downloadserenity-189ea375a5f018504f0553eca12f82133ee80189.zip
LibGfx: Let PNGWriter optionally embed an ICC profile
Diffstat (limited to 'Userland/Libraries')
-rw-r--r--Userland/Libraries/LibGfx/PNGWriter.cpp19
-rw-r--r--Userland/Libraries/LibGfx/PNGWriter.h13
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();
};