diff --git a/Userland/Libraries/LibGfx/ImageFormats/PortableFormatWriter.cpp b/Userland/Libraries/LibGfx/ImageFormats/PortableFormatWriter.cpp index 56bf8b0bd6..80b6218bed 100644 --- a/Userland/Libraries/LibGfx/ImageFormats/PortableFormatWriter.cpp +++ b/Userland/Libraries/LibGfx/ImageFormats/PortableFormatWriter.cpp @@ -5,47 +5,45 @@ */ #include "PortableFormatWriter.h" -#include +#include namespace Gfx { -ErrorOr PortableFormatWriter::encode(Bitmap const& bitmap, Options options) +ErrorOr PortableFormatWriter::encode(Stream& output, 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 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())); + TRY(add_header(output, options, bitmap.width(), bitmap.height(), 255)); + TRY(add_pixels(output, options, bitmap)); return {}; } -ErrorOr PortableFormatWriter::add_pixels(ByteBuffer& buffer, Options const& options, Bitmap const& bitmap) +ErrorOr PortableFormatWriter::add_header(Stream& output, Options const& options, u32 width, u32 height, u32 maximal_value) +{ + TRY(output.write_formatted("P{}\n", options.format == Options::Format::ASCII ? "3"sv : "6"sv)); + TRY(output.write_formatted("# {}\n", options.comment)); + TRY(output.write_formatted("{} {}\n", width, height)); + TRY(output.write_formatted("{}\n", maximal_value)); + + return {}; +} + +ErrorOr PortableFormatWriter::add_pixels(Stream& output, 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())); + TRY(output.write_formatted("{} {} {}\t", color.red(), color.green(), color.blue())); } else { - TRY(buffer.try_append(color.red())); - TRY(buffer.try_append(color.green())); - TRY(buffer.try_append(color.blue())); + TRY(output.write_value(color.red())); + TRY(output.write_value(color.green())); + TRY(output.write_value(color.blue())); } } if (options.format == Options::Format::ASCII) - TRY(buffer.try_append('\n')); + TRY(output.write_value('\n')); } return {}; diff --git a/Userland/Libraries/LibGfx/ImageFormats/PortableFormatWriter.h b/Userland/Libraries/LibGfx/ImageFormats/PortableFormatWriter.h index 30da31a703..f7ba20d7c2 100644 --- a/Userland/Libraries/LibGfx/ImageFormats/PortableFormatWriter.h +++ b/Userland/Libraries/LibGfx/ImageFormats/PortableFormatWriter.h @@ -26,13 +26,13 @@ class PortableFormatWriter { public: using Options = PortableFormatWriterOptions; - static ErrorOr encode(Bitmap const&, Options options = Options {}); + static ErrorOr encode(Stream&, Bitmap const&, Options options = Options {}); private: PortableFormatWriter() = delete; - static ErrorOr add_header(ByteBuffer&, Options const& options, u32 width, u32 height, u32 max_value); - static ErrorOr add_pixels(ByteBuffer&, Options const& options, Bitmap const&); + static ErrorOr add_header(Stream&, Options const& options, u32 width, u32 height, u32 max_value); + static ErrorOr add_pixels(Stream&, Options const& options, Bitmap const&); }; } diff --git a/Userland/Utilities/image.cpp b/Userland/Utilities/image.cpp index 1353bdc0f2..4de6a49da9 100644 --- a/Userland/Utilities/image.cpp +++ b/Userland/Utilities/image.cpp @@ -83,6 +83,9 @@ ErrorOr serenity_main(Main::Arguments arguments) if (strip_color_profile) icc_data.clear(); + auto output_stream = TRY(Core::File::open(out_path, Core::File::OpenMode::Write)); + auto buffered_stream = TRY(Core::OutputBufferedFile::create(move(output_stream))); + ByteBuffer bytes; if (out_path.ends_with(".bmp"sv, CaseSensitivity::CaseInsensitive)) { bytes = TRY(Gfx::BMPWriter::encode(*frame, { .icc_data = icc_data })); @@ -90,7 +93,8 @@ ErrorOr serenity_main(Main::Arguments arguments) bytes = TRY(Gfx::PNGWriter::encode(*frame, { .icc_data = icc_data })); } else if (out_path.ends_with(".ppm"sv, CaseSensitivity::CaseInsensitive)) { auto const format = ppm_ascii ? Gfx::PortableFormatWriter::Options::Format::ASCII : Gfx::PortableFormatWriter::Options::Format::Raw; - bytes = TRY(Gfx::PortableFormatWriter::encode(*frame, { .format = format })); + TRY(Gfx::PortableFormatWriter::encode(*buffered_stream, *frame, { .format = format })); + return 0; } else if (out_path.ends_with(".qoi"sv, CaseSensitivity::CaseInsensitive)) { bytes = TRY(Gfx::QOIWriter::encode(*frame)); } else { @@ -98,8 +102,7 @@ ErrorOr serenity_main(Main::Arguments arguments) return 1; } - auto output_stream = TRY(Core::File::open(out_path, Core::File::OpenMode::Write)); - TRY(output_stream->write_until_depleted(bytes)); + TRY(buffered_stream->write_until_depleted(bytes)); return 0; }