summaryrefslogtreecommitdiff
path: root/Userland/Libraries
diff options
context:
space:
mode:
authorLucas CHOLLET <lucas.chollet@free.fr>2023-03-12 22:18:16 -0400
committerLinus Groh <mail@linusgroh.de>2023-03-13 15:15:41 +0000
commit9c9bd271c8ffe7cfcd8f50389121a1c4ba5a34be (patch)
tree0e507c7157a78c2882019555fe65e65709ef50b2 /Userland/Libraries
parente32267c902c779678466294b5d00a87e67c94a05 (diff)
downloadserenity-9c9bd271c8ffe7cfcd8f50389121a1c4ba5a34be.zip
LibGfx/PortableFormat: Add `PortableFormatWriter`
Currently, the encoder only output ppm files, but it can easily be extended to support both PBM and PGM.
Diffstat (limited to 'Userland/Libraries')
-rw-r--r--Userland/Libraries/LibGfx/CMakeLists.txt1
-rw-r--r--Userland/Libraries/LibGfx/PortableFormatWriter.cpp54
-rw-r--r--Userland/Libraries/LibGfx/PortableFormatWriter.h38
3 files changed, 93 insertions, 0 deletions
diff --git a/Userland/Libraries/LibGfx/CMakeLists.txt b/Userland/Libraries/LibGfx/CMakeLists.txt
index 5ffa912f9f..259dd78fc9 100644
--- a/Userland/Libraries/LibGfx/CMakeLists.txt
+++ b/Userland/Libraries/LibGfx/CMakeLists.txt
@@ -41,6 +41,7 @@ set(SOURCES
PGMLoader.cpp
PNGLoader.cpp
PNGWriter.cpp
+ PortableFormatWriter.cpp
PPMLoader.cpp
Painter.cpp
Palette.cpp
diff --git a/Userland/Libraries/LibGfx/PortableFormatWriter.cpp b/Userland/Libraries/LibGfx/PortableFormatWriter.cpp
new file mode 100644
index 0000000000..56bf8b0bd6
--- /dev/null
+++ b/Userland/Libraries/LibGfx/PortableFormatWriter.cpp
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2023, Lucas Chollet <lucas.chollet@serenityos.org >
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include "PortableFormatWriter.h"
+#include <AK/String.h>
+
+namespace Gfx {
+
+ErrorOr<ByteBuffer> PortableFormatWriter::encode(Bitmap const& bitmap, Options options)
+{
+ ByteBuffer buffer;
+
+ // FIXME: Add support for PBM and PGM
+
+ TRY(add_header(buffer, options, bitmap.width(), bitmap.height(), 255));
+ TRY(add_pixels(buffer, options, bitmap));
+
+ return buffer;
+}
+
+ErrorOr<void> PortableFormatWriter::add_header(ByteBuffer& buffer, Options const& options, u32 width, u32 height, u32 maximal_value)
+{
+ TRY(buffer.try_append(TRY(String::formatted("P{}\n", options.format == Options::Format::ASCII ? "3"sv : "6"sv)).bytes()));
+ TRY(buffer.try_append(TRY(String::formatted("# {}\n", options.comment)).bytes()));
+ TRY(buffer.try_append(TRY(String::formatted("{} {}\n", width, height)).bytes()));
+ TRY(buffer.try_append(TRY(String::formatted("{}\n", maximal_value)).bytes()));
+
+ return {};
+}
+
+ErrorOr<void> PortableFormatWriter::add_pixels(ByteBuffer& buffer, Options const& options, Bitmap const& bitmap)
+{
+ for (int i = 0; i < bitmap.height(); ++i) {
+ for (int j = 0; j < bitmap.width(); ++j) {
+ auto color = bitmap.get_pixel(j, i);
+ if (options.format == Options::Format::ASCII) {
+ TRY(buffer.try_append(TRY(String::formatted("{} {} {}\t", color.red(), color.green(), color.blue())).bytes()));
+ } else {
+ TRY(buffer.try_append(color.red()));
+ TRY(buffer.try_append(color.green()));
+ TRY(buffer.try_append(color.blue()));
+ }
+ }
+ if (options.format == Options::Format::ASCII)
+ TRY(buffer.try_append('\n'));
+ }
+
+ return {};
+}
+
+}
diff --git a/Userland/Libraries/LibGfx/PortableFormatWriter.h b/Userland/Libraries/LibGfx/PortableFormatWriter.h
new file mode 100644
index 0000000000..30da31a703
--- /dev/null
+++ b/Userland/Libraries/LibGfx/PortableFormatWriter.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2023, Lucas Chollet <lucas.chollet@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <AK/ByteBuffer.h>
+#include <LibGfx/Bitmap.h>
+
+namespace Gfx {
+
+// This is not a nested struct to work around https://llvm.org/PR36684
+struct PortableFormatWriterOptions {
+ enum class Format {
+ ASCII,
+ Raw,
+ };
+
+ Format format = Format::Raw;
+ StringView comment = "Generated with SerenityOS - LibGfx."sv;
+};
+
+class PortableFormatWriter {
+public:
+ using Options = PortableFormatWriterOptions;
+
+ static ErrorOr<ByteBuffer> encode(Bitmap const&, Options options = Options {});
+
+private:
+ PortableFormatWriter() = delete;
+
+ static ErrorOr<void> add_header(ByteBuffer&, Options const& options, u32 width, u32 height, u32 max_value);
+ static ErrorOr<void> add_pixels(ByteBuffer&, Options const& options, Bitmap const&);
+};
+
+}