A C++17 port of the JavaScript pixelmatch library, providing a small pixel-level image comparison library.
Features accurate anti-aliased pixels detection and perceptual color difference metrics.
Based on mapbox/pixelmatch. pixelmatch-cpp17 is around 300 lines of code, and has no dependencies, operating on RGBA-encoded buffers.
#include <pixelmatch/pixelmatch.h>
pixelmatch::Options options;
options.threshold = 0.1f;
const std::vector<uint8_t> img1 = ...;
const std::vector<uint8_t> img2 = ...;
std::vector<uint8_t> diffImage(img1.size());
const int numDiffPixels = pixelmatch::pixelmatch(img1, img2, diffImage, width, height, stride, options);
Compared to mapbox/pixelmatch-cpp, pixelmatch-cpp17 ports the latest features from the JavaScript library, and is built with production-grade practices, including thorough test coverage and fuzz-testing. Build files are included for Bazel, but contributions for other build systems are welcome.
Implements ideas from the following papers:
- Measuring perceived color difference using YIQ NTSC transmission color space in mobile applications (2010, Yuriy Kotsarenko, Fernando Ramos)
- Anti-aliased pixel and intensity slope detector (2009, Vytautas Vyšniauskas)
expected | actual | diff |
---|---|---|
img1
,img2
— Image data of the images to compare, as a RGBA-encoded byte array. Note: image dimensions must be equal.output
— Image data to write the diff to, orstd::nullopt
if you don't need a diff image.width
,height
— Width and height of the images. Note that all three images need to have the same dimensions.strideInPixels
— Stride of the images. Note that all three images need to have the same stride.options
is a struct with the following fields:threshold
— Matching threshold, ranges from0.0f
to1.0f
. Smaller values make the comparison more sensitive.0.1
by default.includeAA
— Iftrue
, disables detecting and ignoring anti-aliased pixels.false
by default.alpha
— Blending factor of unchanged pixels in the diff output. Ranges from0
for pure white to1
for original brightness.0.1
by default.aaColor
— The color of anti-aliased pixels in the diff output as an RGBA color.(255, 255, 0, 255)
by default.diffColor
— The color of differing pixels in the diff output as an RGBA color(255, 0, 0, 255)
by default.diffColorAlt
— An alternative color to use for dark on light differences to differentiate between "added" and "removed" parts. If not provided, all differing pixels use the color specified bydiffColor
.std::nullopt
by default.diffMask
— Draw the diff over a transparent background (a mask), rather than over the original image. Will not draw anti-aliased pixels (if detected).
Compares two images, writes the output diff and returns the number of mismatched pixels.
Add the following to your MODULE.bazel
file:
bazel_dep(name = "pixelmatch-cpp17", version = "0.0.0")
git_override(
module_name = "pixelmatch-cpp17",
remote = "https://github.com/jwmcglynn/pixelmatch-cpp17",
commit = "<latest commit hash>", # Ex: 2ab1b929916b97668698523a91e752413d01939c
)
Add the following to your WORKSPACE
file:
git_repository(
name = "pixelmatch-cpp17",
branch = "main",
remote = "https://github.com/jwmcglynn/pixelmatch-cpp17",
)
Then add a dependency on @pixelmatch-cpp17
:
cc_test(
name = "my_test",
# ...
data = glob([
"testdata/*.png",
]),
deps = [
"@pixelmatch-cpp17",
# ...
],
)
In your test file, include pixelmatch with:
#include <pixelmatch/pixelmatch.h>
- Python bindings: https://github.com/cubao/pybind11_pixelmatch