• Stars
    star
    2,000
  • Rank 23,169 (Top 0.5 %)
  • Language
    OCaml
  • License
    MIT License
  • Created about 4 years ago
  • Updated 3 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

The fastest pixel-by-pixel image visual difference tool in the world.

ODIFF

The fastest* (one-thread) pixel-by-pixel image difference tool in the world.

made with reason npm

Why Odiff?

ODiff is a blazing fast native image comparison tool. Check benchmarks for the results, but it compares the visual difference between 2 images in milliseconds. It was originally designed to handle the "big" images. Thanks to OCaml and its speedy and predictable compiler we can significantly speed up your CI pipeline.

Stand With Ukraine

Demo

base comparison diff
1diff
1diff
1diff

Features

  • βœ… Cross-format comparison - Yes .jpg vs .png comparison without any problems.
  • βœ… Support for .png, .jpeg, .jpg, and .tiff
  • βœ… Supports comparison of images with different layouts.
  • βœ… Anti-aliasing detection
  • βœ… Ignoring regions
  • βœ… Using YIQ NTSC transmission algorithm to determine visual difference.

Coming in the nearest future:

  • ⏹ Reading image from memory buffer
  • ⏹ Reading images from url

Usage

Basic comparison

Run the simple comparison. Image paths can be one of supported formats, diff output can only be .png.

odiff <IMG1 path> <IMG2 path> <DIFF output path>

Node.js

We also provides direct node.js binding for the odiff. Run the odiff from nodejs:

const { compare } = require("odiff-bin");

const { match, reason } = await compare(
  "path/to/first/image.png",
  "path/to/second/image.png",
  "path/to/diff.png"
);

Cypress

Checkout cypress-odiff, a cypress plugin to add visual regression tests using odiff-bin.

Visual regression services

LostPixel – Holistic visual testing for your Frontend allows very easy integration with storybook and uses odiff for comparison

Argos CI – Visual regression service powering projects like material-ui. (It became 8x faster with odiff)

Visual Regression Tracker – Self hosted visual regression service that allows to use odiff as screenshot comparison engine

OSnap – Snapshot testing tool written in OCaml that uses config based declaration to define test and was built by odiff collaborator.

Api

Here is an api reference:

CLI

The best way to get up-to-date cli interface is just to type the

odiff --help

Node.js

NodeJS Api is pretty tiny as well. Here is a typescript interface we have:

export type ODiffOptions = Partial<{
  /** Color used to highlight different pixels in the output (in hex format e.g. #cd2cc9). */
  diffColor: string;
  /** Output full diff image. */
  outputDiffMask: boolean;
  /** Do not compare images and produce output if images layout is different. */
  failOnLayoutDiff: boolean;
  /** Return { match: false, reason: '...' } instead of throwing error if file is missing. */
  noFailOnFsErrors: boolean;
  /** Color difference threshold (from 0 to 1). Less more precise. */
  threshold: number;
  /** If this is true, antialiased pixels are not counted to the diff of an image */
  antialiasing: boolean;
  /** If `true` reason: "pixel-diff" output will contain the set of line indexes containing different pixels */
  captureDiffLines: boolean;
  /** An array of regions to ignore in the diff. */
  ignoreRegions: Array<{
    x1: number;
    y1: number;
    x2: number;
    y2: number;
  }>;
}>;

declare function compare(
  basePath: string,
  comparePath: string,
  diffPath: string,
  options?: ODiffOptions
): Promise<
  | { match: true }
  | { match: false; reason: "layout-diff" }
  | {
      match: false;
      reason: "pixel-diff";
      /** Amount of different pixels */
      diffCount: number;
      /** Percentage of different pixels in the whole image */
      diffPercentage: number;
      /** Individual line indexes containing different pixels. Guaranteed to be ordered and distinct.  */
      diffLines?: number[];
    }
  | {
      match: false;
      reason: "file-not-exists";
      /** Errored file path */
      file: string;
    }
>;

export { compare };
"

Compare option will return { match: true } if images are identical. Otherwise return { match: false, reason: "*" } with a reason why images were different.

Make sure that diff output file will be created only if images have pixel difference we can see πŸ‘€

Installation

We provide prebuilt binaries for most of the used platforms, there are a few ways to install them:

Cross-platform

The recommended and cross-platform way to install this lib is npm and node.js. Make sure that this package is compiled directly to the platform binary executable, so the npm package contains all binaries and post-install script will automatically link the right one for the current platform.

Important: package name is odiff-bin. But the binary itself is odiff

npm install odiff-bin

Then give it a try πŸ‘€

odiff --help

From binaries

Download the binaries for your platform from release page.

Benchmarks

Run the benchmarks by yourself. Instructions of how to run the benchmark is here

benchmark

Performance matters. At least for sort of tasks like visual regression. For example, if you are running 25000 image snapshots per month you can save 20 hours of CI time per month by speeding up comparison time in just 3 seconds per snapshot.

3s * 25000 / 3600 = 20,83333 hours

Here is odiff performance comparison with other popular visual difference solutions. We are going to compare some real-world use cases.

Lets compare 2 screenshots of full-size https::/cypress.io page:

Command Mean [s] Min [s] Max [s] Relative
pixelmatch www.cypress.io-1.png www.cypress.io.png www.cypress-diff.png 7.712 Β± 0.069 7.664 7.896 6.67 Β± 0.03
ImageMagick compare www.cypress.io-1.png www.cypress.io.png -compose src diff-magick.png 8.881 Β± 0.121 8.692 9.066 7.65 Β± 0.04
odiff www.cypress.io-1.png www.cypress.io.png www.cypress-diff.png 1.168 Β± 0.008 1.157 1.185 1.00

Wow. Odiff is mostly 6 times faster than imagemagick and pixelmatch. And this will be even clearer if image will become larger. Lets compare an 8k image to find a difference with another 8k image:

Command Mean [s] Min [s] Max [s] Relative
pixelmatch water-4k.png water-4k-2.png water-diff.png 10.614 Β± 0.162 10.398 10.910 5.50 Β± 0.05
Imagemagick compare water-4k.png water-4k-2.png -compose src water-diff.png 9.326 Β± 0.436 8.819 10.394 5.24 Β± 0.10
odiff water-4k.png water-4k-2.png water-diff.png 1.951 Β± 0.014 1.936 1.981 1.00

Yes it is significant improvement. And the produced difference will be the same for all 3 commands.

Changelog

If you have recently updated, please read the changelog for details of what has changed.

License

The project is licensed under the terms of MIT license

Thanks

This project was highly inspired by pixelmatch and imagemagick.

Support the project

...one day a donation button will appear here. But for now you can follow author's twitter :)

More Repositories

1

cypress-real-events

Fire native system events from Cypress.
HTML
754
star
2

date-io

Abstraction over common javascript date management libraries
TypeScript
718
star
3

blendr

The hacker's BLE (bluetooth low energy) browser terminal app
Rust
292
star
4

eslint-plugin-pretty-imports

Do you hate chaos in javascript imports?
TypeScript
204
star
5

subtitler

Free on-device web app for audio transcribing and rendering subtitles
ReScript
129
star
6

reason-date-fns

Reason binding for date-fns/fp. Curried by default :3
Reason
45
star
7

workspace-climate-control

Your own open-source CO2 sensor with ready to use TUI
C
37
star
8

material-ui-datetimepicker

[UNMAINTAINED] Wrapper for Material UI Date and Time picker components
JavaScript
31
star
9

hook2hoc

Typesafe converter of React hooks to React hocs πŸ€“
TypeScript
25
star
10

trololors

Not the fastest terminal colors library. Don't even ask about size.
Rust
16
star
11

caps-word.nvim

Much better way to type SCREAMING_SNAKE_CASE words aka constants
Lua
14
star
12

my-nvim-config

My neovim configs (terminal profile neovim 😱)
Lua
12
star
13

CV

The personal CV
TypeScript
8
star
14

ns-react-18next

[Unmaintained] Namespaced i18next localization in react with no tears
TypeScript
8
star
15

bots

TypeScript
2
star
16

date-fns-comparison

JavaScript
2
star
17

reasonml-for-geese-intro

Introduction in ReasonML
JavaScript
2
star
18

bff-workshop

JavaScript
2
star
19

testcon-cypress-demo

Demo project for testcon 2019
JavaScript
2
star
20

Kova-player

The most beautifull music player for Windows
C#
2
star
21

MeetingLiveStream

JavaScript
1
star
22

holyjs-component-testing-workshop

TypeScript
1
star
23

cypress-qa-fwdays-webinar

JavaScript
1
star
24

cypress-4-2020

Repository for the members of https://fwdays.com/en/event/cypress-workshop workshop
TypeScript
1
star
25

test_opam_windows

C
1
star
26

test-date-io-type

Test repo shows how to use @date-io/type
JavaScript
1
star
27

ina3222-pico

Python
1
star
28

odiff-debug

JavaScript
1
star
29

minecraft2024

1
star
30

fframes_ios_demo_project

Rust
1
star
31

chernihiv-it-cypress-demo

TypeScript
1
star
32

meeting-sticker

C
1
star