From 5a47e71604f2e2f2f1f5f54c5d06db7c538ee490 Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Sat, 13 Jan 2024 21:36:30 -0500 Subject: [PATCH] Utilities: Add test-jpeg-roundtrip This creates a bitmap filled with a fixed color, then (in memory) saves it as jpeg and loads it again, and repeats that until the color of the bitmap no longer changes. It then reports how many iterations that took, and what the final color was. It does this for a couple of colors. This is for quality assessment of the jpeg codec. Ideally, it should converge quickly (in one iteration), and on a color not very far from the original input color. --- Meta/Lagom/CMakeLists.txt | 5 ++ Userland/Utilities/CMakeLists.txt | 1 + Userland/Utilities/test-jpeg-roundtrip.cpp | 66 ++++++++++++++++++++++ 3 files changed, 72 insertions(+) create mode 100644 Userland/Utilities/test-jpeg-roundtrip.cpp diff --git a/Meta/Lagom/CMakeLists.txt b/Meta/Lagom/CMakeLists.txt index e459853a65..417d7011bc 100644 --- a/Meta/Lagom/CMakeLists.txt +++ b/Meta/Lagom/CMakeLists.txt @@ -701,6 +701,11 @@ if (BUILD_LAGOM) # It is therefore not reasonable to run it on Lagom, and we only run the Regex test lagom_test(../../Tests/LibRegex/Regex.cpp LIBS LibRegex WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../../Tests/LibRegex) + # test-jpeg-roundtrip + add_executable(test-jpeg-roundtrip + ../../Userland/Utilities/test-jpeg-roundtrip.cpp) + target_link_libraries(test-jpeg-roundtrip LibGfx LibMain) + # JavaScriptTestRunner + LibTest tests # test-js add_executable(test-js diff --git a/Userland/Utilities/CMakeLists.txt b/Userland/Utilities/CMakeLists.txt index 947c8f8ca5..3a87027d80 100644 --- a/Userland/Utilities/CMakeLists.txt +++ b/Userland/Utilities/CMakeLists.txt @@ -146,6 +146,7 @@ target_link_libraries(ttfdisasm PRIVATE LibGfx) target_link_libraries(tar PRIVATE LibArchive LibCompress LibFileSystem) target_link_libraries(telws PRIVATE LibProtocol LibLine) target_link_libraries(test-imap PRIVATE LibIMAP) +target_link_libraries(test-jpeg-roundtrip PRIVATE LibGfx) target_link_libraries(test-pthread PRIVATE LibThreading) target_link_libraries(touch PRIVATE LibFileSystem) target_link_libraries(unzip PRIVATE LibArchive LibCompress LibCrypto LibFileSystem) diff --git a/Userland/Utilities/test-jpeg-roundtrip.cpp b/Userland/Utilities/test-jpeg-roundtrip.cpp new file mode 100644 index 0000000000..73b0df1e74 --- /dev/null +++ b/Userland/Utilities/test-jpeg-roundtrip.cpp @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2024, the SerenityOS developers. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include + +struct Fixpoint { + Gfx::Color fixpoint; + int number_of_iterations {}; +}; + +static ErrorOr compute_fixpoint(Gfx::Color start_color) +{ + auto bitmap = TRY(Gfx::Bitmap::create(Gfx::BitmapFormat::BGRx8888, { 8, 8 })); + bitmap->fill(start_color); + + int number_of_iterations = 1; + Color last_color = start_color; + while (true) { + AllocatingMemoryStream stream; + TRY(Gfx::JPEGWriter::encode(stream, *bitmap)); + auto data = TRY(stream.read_until_eof()); + auto plugin_decoder = TRY(Gfx::JPEGImageDecoderPlugin::create(data)); + auto frame = TRY(plugin_decoder->frame(0)); + + Color current_color = frame.image->get_pixel(4, 4); + if (current_color == last_color) + break; + + ++number_of_iterations; + last_color = current_color; + bitmap = *frame.image; + } + return Fixpoint { last_color, number_of_iterations }; +} + +static ErrorOr test(Gfx::Color color) +{ + auto fixpoint = TRY(compute_fixpoint(color)); + outln("color {} converges to {} after saving {} times", color, fixpoint.fixpoint, fixpoint.number_of_iterations); + return {}; +} + +ErrorOr serenity_main(Main::Arguments) +{ + TRY(test(Gfx::Color::Red)); + TRY(test(Gfx::Color::Green)); + TRY(test(Gfx::Color::Blue)); + + TRY(test(Gfx::Color::MidRed)); + TRY(test(Gfx::Color::MidGreen)); + TRY(test(Gfx::Color::MidBlue)); + + TRY(test(Gfx::Color::Cyan)); + TRY(test(Gfx::Color::Magenta)); + TRY(test(Gfx::Color::Yellow)); + + TRY(test(Gfx::Color::Black)); + TRY(test(Gfx::Color::White)); + + return 0; +}