Skip to content

refactor: skip ignored regions with pixelmatch's ignoreMask - #1301

Merged
plum117 merged 2 commits into
webdriverio:mainfrom
plum117:refactor/pixelmatch-ignore-mask
Oct 9, 2026
Merged

plum117 merged 2 commits into
webdriverio:mainfrom
plum117:refactor/pixelmatch-ignore-mask

Conversation

@plum117

@plum117 plum117 commented Oct 9, 2026

Copy link
Copy Markdown
Contributor

Summary

Uses pixelmatch 8's new ignoreMask option for the ignored regions (ignored elements and block-outs), instead of painting those regions black in both images before the comparison.

What changes for users

  • Nothing in the files: the baseline, actual and diff files are the same. The ignore regions were only painted in memory before; now pixelmatch skips them. The diff image still shows the ignored regions in green (that is our own drawing in processDiffPixels).
  • Edge pixels are judged more correctly: before, the pixels next to an ignored region had black neighbours (the painted box) in both images, which pixelmatch's anti-aliasing detection used. Now they keep their real neighbours.

Measured with pixelmatch 8 on real image pairs, with ignored boxes over changed areas:

Pair Default (0.063, AA counted): black / mask ignoreAntialiasing (0.13, AA forgiven): black / mask
iPhone full page, 1-px shift 0 / 0 0 / 0
Linux vs Docker fonts 71 265 / 71 265 61 208 / 61 223 (+15)
Android 2 display states 7 028 / 7 028 4 365 / 4 365

So the counts change only a little, and only with anti-aliasing forgiven, at the edges of ignored regions. Patch changeset with that note.

Changes

  • compareImages.ts: createIgnoreMask() builds one byte per pixel (1 inside a box, clamped to the image size) and passes it as ignoreMask; zeroIgnoredBoxes() is removed.
  • compareImages.test.ts: the mocked test checks the mask and that the images are not changed; a test checks that no mask is passed without ignored boxes.
  • New compareImages.ignoredBoxes.test.ts with the real pixelmatch: a difference inside a box does not count, a difference outside it counts (exactly the 4 pixels of a 2×2 square), and a box larger than the image is clamped.

Test

  • pnpm test (lint, types, 1083 unit tests): pass.
  • Local e2e: test.local.chrome.v10, .jasmine, test.local.desktop.multi, test.local.desktop (setup run, then the real run; includes the ignore-region checks): pass.
  • Before the merge, a cloud run is recommended: the committed cloud baselines include ignore-region checks (desktop, Android, iOS). This branch is on a fork, so a maintainer can run scheduled-tests with refs/pull/<number>/head after reviewing the commit.

Not in this PR: windowSize

pixelmatch 8 also has windowSize (the largest number of different pixels in any N×N square instead of the total). That would be a new user-facing compare mode and needs a design first (option name, how the result and the threshold are reported, docs).

🤖 Generated with Claude Code

pixelmatch 8 can skip pixels with an ignoreMask (one byte per pixel).
compareImages now builds that mask from the ignored boxes (clamped to
the image) instead of painting the boxes black in both images. The
files on disk and the green regions of the diff image do not change.

The pixels next to an ignored box keep their real neighbours for the
anti-aliasing detection. With AA forgiven this can change the count a
little at the box edges (+15 of 61 208 pixels on a real pair); with the
default settings the counts on the real pairs did not change.

Tests: the mocked test checks the mask and that the images are not
changed; new tests run the real pixelmatch with ignored boxes (a
difference inside a box does not count, outside it does, a box larger
than the image is clamped).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@changeset-bot

changeset-bot Bot commented Oct 9, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 76a2cf2

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 2 packages
Name Type
@wdio/image-comparison-core Patch
@wdio/visual-service Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@plum117
plum117 marked this pull request as ready for review October 9, 2026 10:22
@greptile-apps

greptile-apps Bot commented Oct 9, 2026 •

Copy link
Copy Markdown

RetriggerConfidence Score: 5/5

[Medium impact] The PR appears safe to merge, with the previous finding fixed and no new actionable issues.

Summary

This PR replaces blacked-out ignored regions with pixelmatch's ignoreMask.

  • Pixelmatch skips ignored regions without changing the comparison images.

Reviews (2) · Last reviewed commit: "test: check both images and the full mas..." · Reviewed by Greptile

Comment thread packages/image-comparison-core/src/pixelmatch/compareImages.test.ts Outdated
The test passed when an ignored pixel of an image was set to 0, and it did
not check the second image. Use 2 small images with a different value in
each channel and compare both images and the mask with the expected values.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@plum117
plum117 merged commit c1db350 into webdriverio:main Oct 9, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants