From 7880e11690a520db1011510dfe6c5350b2d8f22c Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Fri, 17 Feb 2023 13:24:08 -0500 Subject: [PATCH] icc: Add flags for writing and dumping profiles This adds three flags to icc: * --reencode-to= re-serializes a profile to a given file, using Gfx::ICC::encode(). This is mainly useful for testing that code. * --dump-to= dumps the raw ICC profile bytes read from the input to disk. This is useful for extracting ICC profiles from images, and for comparing the raw profile bytes to the profile bytes written by --reencode-to=. If either of these flags is passed, icc by default no longer dumps the icc data to stdout. To force priting of the data even if either of these flags is present, this also adds: * --print, which forces printing ICC contents, even if either or both of the icc-data writing flags are present. --- Userland/Utilities/icc.cpp | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/Userland/Utilities/icc.cpp b/Userland/Utilities/icc.cpp index 99cc71fee10..131bbe09ddf 100644 --- a/Userland/Utilities/icc.cpp +++ b/Userland/Utilities/icc.cpp @@ -8,7 +8,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -89,8 +91,18 @@ ErrorOr serenity_main(Main::Arguments arguments) { Core::ArgsParser args_parser; - static StringView path; + StringView path; args_parser.add_positional_argument(path, "Path to ICC profile or to image containing ICC profile", "FILE"); + + StringView dump_out_path; + args_parser.add_option(dump_out_path, "Dump unmodified ICC profile bytes to this path", "dump-to", 0, "FILE"); + + StringView reencode_out_path; + args_parser.add_option(reencode_out_path, "Reencode ICC profile to this path", "reencode-to", 0, "FILE"); + + bool force_print = false; + args_parser.add_option(force_print, "Print profile even when writing ICC files", "print", 0); + args_parser.parse(arguments); auto file = TRY(Core::MappedFile::map(path)); @@ -108,8 +120,23 @@ ErrorOr serenity_main(Main::Arguments arguments) icc_bytes = file->bytes(); } + if (!dump_out_path.is_empty()) { + auto output_stream = TRY(Core::File::open(dump_out_path, Core::File::OpenMode::Write)); + TRY(output_stream->write_entire_buffer(icc_bytes)); + } + auto profile = TRY(Gfx::ICC::Profile::try_load_from_externally_owned_memory(icc_bytes)); + if (!reencode_out_path.is_empty()) { + auto reencoded_bytes = TRY(Gfx::ICC::encode(profile)); + auto output_stream = TRY(Core::File::open(reencode_out_path, Core::File::OpenMode::Write)); + TRY(output_stream->write_entire_buffer(reencoded_bytes)); + } + + bool do_print = (dump_out_path.is_empty() && reencode_out_path.is_empty()) || force_print; + if (!do_print) + return 0; + outln(" size: {} bytes", profile->on_disk_size()); out_optional(" preferred CMM type", profile->preferred_cmm_type()); outln(" version: {}", profile->version());