mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-08-07 00:29:15 +00:00
LibGfx: Replace Bitmap::visually_equals() with ::diff()
This produces more granural information on the actual pixel errors present between two bitmaps. It now also asserts that both bitmaps are the same size, since we should never compare two differently sized bitmaps anyway.
This commit is contained in:
parent
b7b504cf2d
commit
0f642ecb5c
Notes:
github-actions[bot]
2025-07-17 12:00:38 +00:00
Author: https://github.com/gmta
Commit: 0f642ecb5c
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/5470
Reviewed-by: https://github.com/tcl3 ✅
3 changed files with 55 additions and 8 deletions
|
@ -228,21 +228,47 @@ ErrorOr<BackingStore> Bitmap::allocate_backing_store(BitmapFormat format, IntSiz
|
||||||
return BackingStore { data, pitch, data_size_in_bytes };
|
return BackingStore { data, pitch, data_size_in_bytes };
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Bitmap::visually_equals(Bitmap const& other) const
|
Bitmap::DiffResult Bitmap::diff(Bitmap const& other) const
|
||||||
{
|
{
|
||||||
auto own_width = width();
|
auto own_width = width();
|
||||||
auto own_height = height();
|
auto own_height = height();
|
||||||
if (other.width() != own_width || other.height() != own_height)
|
VERIFY(own_width == other.width() && own_height == other.height());
|
||||||
return false;
|
|
||||||
|
|
||||||
|
DiffResult result;
|
||||||
for (auto y = 0; y < own_height; ++y) {
|
for (auto y = 0; y < own_height; ++y) {
|
||||||
for (auto x = 0; x < own_width; ++x) {
|
for (auto x = 0; x < own_width; ++x) {
|
||||||
if (get_pixel(x, y) != other.get_pixel(x, y))
|
auto own_pixel = get_pixel(x, y);
|
||||||
return false;
|
auto other_pixel = other.get_pixel(x, y);
|
||||||
|
if (own_pixel == other_pixel)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
++result.pixel_error_count;
|
||||||
|
|
||||||
|
u8 red_error = abs(static_cast<int>(own_pixel.red()) - other_pixel.red());
|
||||||
|
u8 green_error = abs(static_cast<int>(own_pixel.green()) - other_pixel.green());
|
||||||
|
u8 blue_error = abs(static_cast<int>(own_pixel.blue()) - other_pixel.blue());
|
||||||
|
u8 alpha_error = abs(static_cast<int>(own_pixel.alpha()) - other_pixel.alpha());
|
||||||
|
|
||||||
|
result.total_red_error += red_error;
|
||||||
|
result.total_green_error += green_error;
|
||||||
|
result.total_blue_error += blue_error;
|
||||||
|
result.total_alpha_error += alpha_error;
|
||||||
|
|
||||||
|
result.maximum_red_error = max(result.maximum_red_error, red_error);
|
||||||
|
result.maximum_green_error = max(result.maximum_green_error, green_error);
|
||||||
|
result.maximum_blue_error = max(result.maximum_blue_error, blue_error);
|
||||||
|
result.maximum_alpha_error = max(result.maximum_alpha_error, alpha_error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
result.identical = result.pixel_error_count == 0;
|
||||||
|
result.total_error = result.total_red_error + result.total_green_error + result.total_blue_error + result.total_alpha_error;
|
||||||
|
|
||||||
|
u8 maximum_red_green_error = max(result.maximum_red_error, result.maximum_green_error);
|
||||||
|
u8 maximum_blue_alpha_error = max(result.maximum_blue_error, result.maximum_alpha_error);
|
||||||
|
result.maximum_error = max(maximum_red_green_error, maximum_blue_alpha_error);
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Bitmap::set_alpha_type_destructive(AlphaType alpha_type)
|
void Bitmap::set_alpha_type_destructive(AlphaType alpha_type)
|
||||||
|
|
|
@ -137,7 +137,28 @@ public:
|
||||||
[[nodiscard]] Core::AnonymousBuffer& anonymous_buffer() { return m_buffer; }
|
[[nodiscard]] Core::AnonymousBuffer& anonymous_buffer() { return m_buffer; }
|
||||||
[[nodiscard]] Core::AnonymousBuffer const& anonymous_buffer() const { return m_buffer; }
|
[[nodiscard]] Core::AnonymousBuffer const& anonymous_buffer() const { return m_buffer; }
|
||||||
|
|
||||||
[[nodiscard]] bool visually_equals(Bitmap const&) const;
|
struct DiffResult {
|
||||||
|
bool identical { false };
|
||||||
|
|
||||||
|
// Cumulative channel differences.
|
||||||
|
u64 total_red_error { 0 };
|
||||||
|
u64 total_green_error { 0 };
|
||||||
|
u64 total_blue_error { 0 };
|
||||||
|
u64 total_alpha_error { 0 };
|
||||||
|
u64 total_error { 0 };
|
||||||
|
|
||||||
|
// Maximum channel differences.
|
||||||
|
u8 maximum_red_error { 0 };
|
||||||
|
u8 maximum_green_error { 0 };
|
||||||
|
u8 maximum_blue_error { 0 };
|
||||||
|
u8 maximum_alpha_error { 0 };
|
||||||
|
u8 maximum_error { 0 };
|
||||||
|
|
||||||
|
// Number of pixels with errors.
|
||||||
|
u64 pixel_error_count { 0 };
|
||||||
|
};
|
||||||
|
|
||||||
|
[[nodiscard]] DiffResult diff(Bitmap const&) const;
|
||||||
|
|
||||||
[[nodiscard]] AlphaType alpha_type() const { return m_alpha_type; }
|
[[nodiscard]] AlphaType alpha_type() const { return m_alpha_type; }
|
||||||
void set_alpha_type_destructive(AlphaType);
|
void set_alpha_type_destructive(AlphaType);
|
||||||
|
|
|
@ -376,7 +376,7 @@ static void run_ref_test(TestWebView& view, Test& test, URL::URL const& url, int
|
||||||
auto handle_completed_test = [&test, url]() -> ErrorOr<TestResult> {
|
auto handle_completed_test = [&test, url]() -> ErrorOr<TestResult> {
|
||||||
VERIFY(test.ref_test_expectation_type.has_value());
|
VERIFY(test.ref_test_expectation_type.has_value());
|
||||||
auto should_match = test.ref_test_expectation_type == RefTestExpectationType::Match;
|
auto should_match = test.ref_test_expectation_type == RefTestExpectationType::Match;
|
||||||
auto screenshot_matches = test.actual_screenshot->visually_equals(*test.expectation_screenshot);
|
auto screenshot_matches = test.actual_screenshot->diff(*test.expectation_screenshot).identical;
|
||||||
if (should_match == screenshot_matches)
|
if (should_match == screenshot_matches)
|
||||||
return TestResult::Pass;
|
return TestResult::Pass;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue