mirror of
https://github.com/SerenityOS/serenity.git
synced 2025-01-22 09:21:57 -05:00
imgcmp: Add a --write-diff-image option
This writes a bitmap that has pixels that are identical between the two input images blended with 0.5 alpha against white, and differing pixels are highlighted in red. Use like so: imgcmp --write-diff-image diff.webp image1.png image2.webp
This commit is contained in:
parent
bd5e5c1a0c
commit
b50f3132ef
1 changed files with 46 additions and 0 deletions
|
@ -9,6 +9,8 @@
|
|||
#include <LibCore/MappedFile.h>
|
||||
#include <LibCore/MimeData.h>
|
||||
#include <LibGfx/ImageFormats/ImageDecoder.h>
|
||||
#include <LibGfx/ImageFormats/PNGWriter.h>
|
||||
#include <LibGfx/ImageFormats/WebPWriter.h>
|
||||
|
||||
static ErrorOr<RefPtr<Gfx::Bitmap>> load_image(StringView path)
|
||||
{
|
||||
|
@ -20,10 +22,49 @@ static ErrorOr<RefPtr<Gfx::Bitmap>> load_image(StringView path)
|
|||
return TRY(decoder->frame(0)).image;
|
||||
}
|
||||
|
||||
static ErrorOr<void> save_image(NonnullRefPtr<Gfx::Bitmap> bitmap, StringView out_path)
|
||||
{
|
||||
if (!out_path.ends_with(".png"sv, CaseSensitivity::CaseInsensitive) && !out_path.ends_with(".webp"sv, CaseSensitivity::CaseInsensitive))
|
||||
return Error::from_string_view("can only save to .png and .webp files"sv);
|
||||
|
||||
auto output_stream = TRY(Core::File::open(out_path, Core::File::OpenMode::Write));
|
||||
auto buffered_stream = TRY(Core::OutputBufferedFile::create(move(output_stream)));
|
||||
|
||||
if (out_path.ends_with(".png"sv, CaseSensitivity::CaseInsensitive))
|
||||
return Gfx::PNGWriter::encode(*buffered_stream, *bitmap);
|
||||
|
||||
VERIFY(out_path.ends_with(".webp"sv, CaseSensitivity::CaseInsensitive));
|
||||
return Gfx::WebPWriter::encode(*buffered_stream, *bitmap);
|
||||
}
|
||||
|
||||
static ErrorOr<NonnullRefPtr<Gfx::Bitmap>> make_diff_image(NonnullRefPtr<Gfx::Bitmap> first_image, NonnullRefPtr<Gfx::Bitmap> second_image)
|
||||
{
|
||||
VERIFY(first_image->size() == second_image->size());
|
||||
|
||||
auto diff_image = TRY(Gfx::Bitmap::create(Gfx::BitmapFormat::BGRA8888, first_image->size()));
|
||||
|
||||
for (int y = 0; y < first_image->height(); ++y) {
|
||||
for (int x = 0; x < first_image->width(); ++x) {
|
||||
auto first_pixel = first_image->get_pixel<Gfx::StorageFormat::BGRA8888>(x, y);
|
||||
auto second_pixel = second_image->get_pixel<Gfx::StorageFormat::BGRA8888>(x, y);
|
||||
if (first_pixel == second_pixel) {
|
||||
diff_image->set_pixel(x, y, first_pixel.interpolate(Gfx::Color::White, 0.5f));
|
||||
} else {
|
||||
diff_image->set_pixel(x, y, Gfx::Color::Red);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return diff_image;
|
||||
}
|
||||
|
||||
ErrorOr<int> serenity_main(Main::Arguments arguments)
|
||||
{
|
||||
Core::ArgsParser args_parser;
|
||||
|
||||
StringView write_diff_image_path;
|
||||
args_parser.add_option(write_diff_image_path, "Write image that highlights differing pixels", "write-diff-image", {}, "FILE");
|
||||
|
||||
StringView first_image_path;
|
||||
args_parser.add_positional_argument(first_image_path, "Path to first input image", "FILE1");
|
||||
|
||||
|
@ -40,6 +81,11 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
|||
return 1;
|
||||
}
|
||||
|
||||
if (!write_diff_image_path.is_empty()) {
|
||||
auto diff_image = TRY(make_diff_image(*first_image, *second_image));
|
||||
TRY(save_image(diff_image, write_diff_image_path));
|
||||
}
|
||||
|
||||
for (int y = 0; y < first_image->physical_height(); ++y) {
|
||||
for (int x = 0; x < first_image->physical_width(); ++x) {
|
||||
auto first_pixel = first_image->get_pixel(x, y);
|
||||
|
|
Loading…
Reference in a new issue