Giter Site home page Giter Site logo

dmtrkovalenko / odiff Goto Github PK

View Code? Open in Web Editor NEW
1.9K 17.0 70.0 41.58 MB

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

License: MIT License

JavaScript 15.78% C 13.19% TypeScript 0.70% OCaml 70.33%
visual diff snapshot image-comparison testing-tool pixel-perfect odiff

odiff's Issues

accept buffers as input

I'm trying to integrate odiff into a third-party lib. It would be great if the compare function would also accept buffers instead of paths. This would save the round trip to write a buffer to disk in some use cases.

odiff-bin. TypeError: odiff: option `--antialiasing' is a flag, it cannot take the argument `true'

(async () => {
  const result = await odiff.compare(
    getImagePath("1.png"),
    getImagePath("diffLayout2.png"),
    getImagePath("diff.png"),
    {
      antialiasing: true
    }
  );

  console.log(result);
})();
(node:74741) UnhandledPromiseRejectionWarning: TypeError: odiff: option `--antialiasing' is a flag, it cannot take the argument `true'

    at ChildProcess.<anonymous> (.../node_modules/odiff-bin/odiff.js:123:13)
    at ChildProcess.emit (events.js:327:22)
    at maybeClose (internal/child_process.js:1021:16)
    at Socket.<anonymous> (internal/child_process.js:443:11)
    at Socket.emit (events.js:315:20)
    at Pipe.<anonymous> (net.js:674:12)

The benchmark should say "Pixelmatch + pngjs" to better reflect the code compared.

The benchmark in the README.MD mentions "Pixelmatch", and shows a graph comparing Odiff, ImageMagick and Pixelmatch.

However the benchmark includes the PNG decoding, image diffing, and finally PNG encoding of the diff image. Given the resolution of the images, the PNG codec will take a significant share of the time.

It would be more fair to say "Pixelmatch + pngjs" together.

hang on when run macbook mini

(base) wenke@wenkedeMac-mini odiff-e7f41c97 % odiff 20201123/N_0_2006255981_B.bmp 20201123/N_0_2006255981_T.bmp 1.png

hang on there with no result at all , two image are all 300kb
download source code and run npm install ,rename bin/ODiffBin to odiff ,add this bin path to zsh

Make diff code available as a separate package

Would you be open to the idea of publishing the diff code (everything located under src) to opam?
Or at least separate it into its own opam library, so you can install it using esy without installing all requirements needed for the io part.

Some background:
I am currently working on a snapshot testing library, using odiff.
Right now, installing odiff with esy also installs everything needed for the io package, which I don't use.

So it would be great to be able to just install the diff part.

Feature request: Add option to specify acceptable percentage of different pixels

I am trying to use odiff in the CI pipeline of a plotting tool I maintain called NicePlots to test that the images output by our examples remain consistent. We are running into the issue that, even using the --antialiasing command line option, we still have images differing on very small numbers of pixels due to what I assume are slight differences in anti-aliasing on different systems.

Here's an example from one of our recent CI runs:

Reference image

doumont-light_style_demo_reference

Test image

doumont-light_style_demo

Difference

odiff --aa --threshold=0.1 --dm doumont-light_style_demo_reference.png doumont-light_style_demo.png doumont-light_style_demo-diff.png
Failure! Images are different.
Different pixels: 386 (0.003490%)

doumont-light_style_demo-diff

In our case, these minor differences are not the kind of thing we're looking to catch with our tests. We tried playing around with the --threshold option but found we had to make it impractically high to get past these issues.

It would be extremely useful to be able to specify that a certain percentage of differing pixels (e.g <= 0.01%) is acceptable, by adding a command line option like --tolerance=0.01.

Cannot compare images - Library not loaded, image not found

not sure why it's not working

here is the repo to reproduce
https://github.com/pashidlos/image-compare-tryouts/blob/main/src/odiff.js

node src/odiff.js

(node:24395) UnhandledPromiseRejectionWarning: Error: dyld: Library not loaded: _____________________________________________________________________________________/i/esy_libpng-635d6ecc/lib/libpng16.16.dylib
  Referenced from: /Users/pashidlos/work/image-compare-try/node_modules/odiff-bin/3/i/odiff-4d94fb12/bin/ODiffBin
  Reason: image not found

Difference in Procentage

Hi,

nice project, but I did not find information if it can show the difference in percentage how two images differ?

Why I ask that?

For example I have more then 2000 wallpapers and some of them are places there twice, with different resolutions and file names but they are generally the same image. It would be nice if odiff would show that image X is 97% the same as image Y.

Just an idea.

Regards.

odiff: internal error, uncaught exception

Hello, I'm using odiff with cypress. Everything is working fine, but only in Jenkins, I'm getting the following error in some scenarios (not in all scenarios):

CypressError: cy.task('compare') failed with the following error:

odiff: internal error, uncaught exception:
Failure("Can not save the output :(")

Do you have any idea why is this happened?

The whole error:
image

*When the scenarios run locally with docker, this error never appeared. I face this error only in Jenkins

Add ignore regions

In order to ignore some parts of an image it would be useful pass them as array of objects

{
 x: number;
 y: number;
 width: number;
 height: number;
}

Using odiff as a node dependency on mac

First off, I gotta say, I love this thing. Thank you so much for your work!

I'm currently using it as a dependency for my own open source Node project and it works perfectly on Windows but on a Mac I actually have to go into the node_modules/odiff-bin dependency folder and explicitly do an "npm install" or it won't work (I think it doesn't automatically copy the binary into the bin folder).

Install fails on Windows CI

While it works locally, it fails to install on our CI Jenkins (Windows):

package.json:
"dependencies": { "odiff-bin": "^2.1.1" }

log:

[email protected] postinstall C:\Jenkins\workspace\Web\CubeMobileApps@3\Webpages\CubeMobileApps\node_modules\odiff-bin
node ./postinstall.js
Couldn't find C:\Jenkins\workspace\Web\CubeMobileApps@3\Webpages\CubeMobileApps\node_modules\odiff-bin\platform-windows-x64\bin\odiff trying with .exe
error: Esy prefix path is too deep in the filesystem, Esy won't be able to relocate artefacts
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] postinstall: node ./postinstall.js
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] postinstall script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

As this is a shared CI setup with other projects, we can't change the directory containing the pipeline workspaces.

No output option

Would be nice to be able to not save the diffOutput. I just need the diff info :)

Screenshot's resolution varies on different screen resolution.

By default the screenshot which are taken are having the resolution of 1503x791 px ( When my PC resolution is 1920x1080)
And if we reduce display resolution in PC and the resolution of screenshots taken is varying.
Is there any way to fix this and make this independent of screen resolution.
Thanks!

[Feature] Combine reference and diff images and add custom color parameter

Hi,
Problem: sometimes diff image is really small and it's hard to understand the difference between current and reference images.
Proposal: allow to generate diff2 image that add diff-mask above the reference image;
Proposal 2: mark such differences somehow if there are small (circle around them or so);

Of course, if the reference image has a lot of red it could be a problem (because diff-image is always red), so we need also a parameter for diff-image color.

Thanks in advance :)

Antialiasing is failing on tiny font differences

Hi,

We're currently experiencing some issues with small differences in our images. These are always related to fonts that have a few pixels different. Although the config is passing antialiasing: true, it still fails the comparison.

To give some background, the base images are created on a Windows OS. The actual comparison is run through Cypress on a Linux VM.

I have taken the liberty to include the images that are causing these issues (base, screenshot & failure output).
Zooming in on the base and the screenshot image shows how little difference there is on the fonts, but enough for the test to fail.
image
image_comparison.zip

As for the config that we use, it is simply the following snippet:
compare(base, comp, diff, { threshold: 0.3, antialiasing: true })

A Cypress plugin

What about creating a Cypress plugin to facilitate the use of odiff within Cypress?

Undocumented fourth arg to compare()

For the npm package, the fourth options arg is required for compare() but isn't documented. When calling compare with this code:

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

I get this error:

(node:87053) UnhandledPromiseRejectionWarning: TypeError: Cannot read property '__binaryPath' of undefined
    at /home/raven/Documents/jobs/deviate-labs/repos/Deviate-Site-Tester/node_modules/odiff-bin/odiff.js:86:32
    at new Promise (<anonymous>)
    at compare (/home/raven/Documents/jobs/deviate-labs/repos/Deviate-Site-Tester/node_modules/odiff-bin/odiff.js:83:10)
    at tmp (file:///home/raven/Documents/jobs/deviate-labs/repos/Deviate-Site-Tester/test.js:3:35)
    at file:///home/raven/Documents/jobs/deviate-labs/repos/Deviate-Site-Tester/test.js:7:1
    at ModuleJob.run (internal/modules/esm/module_job.js:152:23)
    at async Loader.import (internal/modules/esm/loader.js:166:24)
    at async Object.loadESM (internal/process/esm_loader.js:68:5)
(Use `node --trace-warnings ...` to show where the warning was created)
(node:87053) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 2)
(node:87053) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

The fourth argument should be documented or made optional. Note that the fourth arg can be "" and it works fine. This code doesn't error out:

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

rm bug report

const a = [
  {},
  {},
  {
    "b": null,
    "i": 2587.884,
    "j": 89.2944,
    "k": 1254.2556,
    "l": 1880.97
  },
  {
    "b": null,
    "i": 386.11559999999986,
    "j": 1102.9512,
    "k": 1252.6019999999999,
    "l": 814.398
  },
  {
    "b": null,
    "i": 386.11559999999986,
    "j": 150.4776,
    "k": 1252.6019999999999,
    "l": 814.398
  },
  {}
]
const b = [
  {},
  {},
  {
    "b": "603c8f2d-db93-45ec-bea3-f6cd2f6be5b7",
    "i": 2587.825865625,
    "j": 89.2944,
    "k": 1254.37186875,
    "l": 1880.97
  },
  {
    "b": "3c1a45a6-b776-4a54-852a-6a4103105ddc",
    "i": 386.11559999999986,
    "j": 570.9921868791004,
    "k": 1252.6019999999999,
    "l": 1878.3160262417994
  },
  {
    "b": "5f3f02f7-e0e4-4a01-8126-73e33845f6cd",
    "i": 386.11559999999986,
    "j": -381.4814131208996,
    "k": 1252.6019999999999,
    "l": 1878.3160262417994
  },
  {}
]
console.log(odiff(a, b))

The result is

[{
  "type": "rm",
  "path": [],
  "index": 0,
  "num": 3,
  "vals": [{}, {}, {
    "b": null,
    "i": 2587.884,
    "j": 89.2944,
    "k": 1254.2556,
    "l": 1880.97
  }]
}, {
  "type": "add",
  "path": [],
  "index": 2,
  "vals": [{
    "b": "603c8f2d-db93-45ec-bea3-f6cd2f6be5b7",
    "i": 2587.825865625,
    "j": 89.2944,
    "k": 1254.37186875,
    "l": 1880.97
  }, {
    "b": "3c1a45a6-b776-4a54-852a-6a4103105ddc",
    "i": 386.11559999999986,
    "j": 570.9921868791004,
    "k": 1252.6019999999999,
    "l": 1878.3160262417994
  }, {
    "b": "5f3f02f7-e0e4-4a01-8126-73e33845f6cd",
    "i": 386.11559999999986,
    "j": -381.4814131208996,
    "k": 1252.6019999999999,
    "l": 1878.3160262417994
  }]
}]

Reduce size of npm package

I recently investigated why the size of the package is that big and found out, that we include a lot of unnecessary stuff.
It also seems like esy includes the RunTests.exe in the release build.

Things that can be removed from the package:

  • odiff-Linux-xxx.tar.gz
  • odiff-MacOS-xxx.tar.gz
  • odiff-Windows_x64-xxx.tar.gz
  • RunTests.exe

NodeJS demo code?

I can't find any demonstration code how to use this lib anywhere. Doesn't help that both NPM & Oracle have packages of the same name....

TIA :)

bug: can't install using pnpm

Description

Can't install odiff-bin using pnpm: Esy prefix path is too deep in the filesystem, Esy won't be able to relocate artefacts

Installing using npm works fine though.

Stderr:

$ pnpm i odiff-bin

Packages: +1
+
Downloading registry.npmjs.org/odiff-bin/2.2.0: 12.3 MB/12.3 MB, done
Packages are hard linked from the content-addressable store to the virtual store.
  Content-addressable store is at: /Users/privatenumber/.pnpm-store/v3
  Virtual store is at:             node_modules/.pnpm
Progress: resolved 1, reused 0, downloaded 1, added 1, done
node_modules/.pnpm/[email protected]/node_modules/odiff-bin: Running postinstall script, failed in 166ms
.../node_modules/odiff-bin postinstall$ node ./postinstall.js
│ error: Esy prefix path is too deep in the filesystem, Esy won't be able to relocate artefacts
└─ Failed in 166ms
 ERROR  Command failed with exit code 1.

Reproduction steps

  1. Make a new directory and cd into it
  2. npm init
  3. pnpm i odiff-bin (If you don't have pnpm installed, you can use npx: npx pnpm i odiff-bin)

Environment info

macOS Big Sur v11.3.1

$ node -v
v14.16.1
$ pnpm -v
6.2.1

Windows build

Can you please make a Windows build? I'm having problems using the latest available which is 2.4.2 because I get

odiff: internal error, uncaught exception:
       Failure("This format is not supported: .jpg")

And installing through npm doesn't work either, it outputs a weird unix error by just using --help.

Linux alpine. Can't compare images - empty error

docker image node:12.18.4-alpine
odiff-bin 2.4.1

api_1        | [Nest] 25   - 07/15/2021, 3:59:59 PM   Object:
api_1        | {}
api_1        |  +31481ms
api_1        | Error
api_1        |     at ChildProcess.<anonymous> (/node_modules/odiff-bin/odiff.js:134:13)
api_1        |     at ChildProcess.emit (events.js:327:22)
api_1        |     at maybeClose (internal/child_process.js:1021:16)
api_1        |     at Socket.<anonymous> (internal/child_process.js:443:11)
api_1        |     at Socket.emit (events.js:315:20)
api_1        |     at Pipe.<anonymous> (net.js:674:12)

npm has Version 2.6.1 but there is no 2.6.1 in this repo

Hello, we are looking to sanity check the post-install scripts and binaries — we are wanting to try out Lost Pixel which uses odiff-bin.

They specify version 2.6.1 which exists on npm, but not here in this project apparently.

I've diffed the release tars via npm pack [email protected] / npm pack [email protected] and the only changes are the version numbers in the package.json and the platform binary files (darwin, linux, windows-x64)

@dmtrKovalenko any chance you have information on the 2.6.1 release please?

Thanks

Could not create _export folder: EEXIST: file already exists

I've been using this with lost-pixel, and it gives me this error sometimes when I deploy to vercel and it uses the existing node_modules folder when reinstalling dependencies:

[14:52:43.956] [4/4] Building fresh packages...
[14:52:44.436] error /vercel/path0/node_modules/odiff-bin: Command failed.
[14:52:44.436] Exit code: 1
[14:52:44.437] Command: node ./postinstall.js
[14:52:44.437] Arguments: 
[14:52:44.437] Directory: /vercel/path0/node_modules/odiff-bin
[14:52:44.437] Output:
[14:52:44.437] Could not create _export folder
[14:52:44.438] error: Error: EEXIST: file already exists, mkdir '/vercel/path0/node_modules/odiff-bin/3'
[14:52:44.439] info Visit https://yarnpkg.com/en/docs/cli/install for documentation about this command.
[14:52:52.090] Error: Command "yarn install" exited with 1

Installation problem on Ubuntu 20.04

After performing npm install odiff-bin without errors, the library cannot be imported:

Error: Cannot find module 'odiff-bin'
Require stack:
- ~/dev/project-dir/src/project.js
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:831:15)
    at Function.Module._load (internal/modules/cjs/loader.js:687:27)
    at Module.require (internal/modules/cjs/loader.js:903:19)
    at require (internal/modules/cjs/helpers.js:74:18)
    at Object.<anonymous> (~/dev/project-dir/src/project.js:1:21)
    at Module._compile (internal/modules/cjs/loader.js:1015:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1035:10)
    at Module.load (internal/modules/cjs/loader.js:879:32)
    at Function.Module._load (internal/modules/cjs/loader.js:724:14)
    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:60:12) {
  code: 'MODULE_NOT_FOUND',

Attempting to run the binary directly from node_modules reveals the following error:

~/dev/project-dir/node_modules/odiff-bin/3_________________/i/odiff-b684a0b4/bin/ODiffBin: error while loading shared libraries: libpng12.so.0: cannot open shared object file: No such file or directory

I notice the windows instructions mention that libpng needs to be separately installed, is the same true on Linux? There doesn't appear to be a great candidate for a package in the standard Ubuntu repositories that will fix this missing dependency, is there something I'm missing?

Thanks very much.

[bug] Image comparaison issue

Hello Dmitriy,

Your project seems amazing and I would like to use it but I found an issue in image comparison.

It seems that odiff can't see the differences between this images.

rect

rect-new

Error saving diff png

Error: odiff: internal error, uncaught exception:
Failure("Can not write diff output. fopen error: Read-only file system")

Does not respect EXIF orientation

I have a huge database of photos and am trying to compare ones of the same name to discard duplicates. Some duplicates have a different orientation flag in the EXIF data, while others have already been rotated (I probably used some jpeg optimization software on them in the past which transformed for the orientation). When comparing both images that appear the same way in image viewers, a huge difference is reported because one stores the pixels in a horizontal sequence and the other in a vertical sequence.

odiff should apply the orientation flag when loading images and transform the data accordingly. I could preprocess all images that have non standard orientation, but that requires a recompression and potential loss of quality.

Seems like a trivial thing to implement and would avoid mismatches for the unaware.

Doesn't work inside azure function

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

const httpTrigger: AzureFunction = async function (context: Context, req: HttpRequest): Promise<void> {
    const actual = (req.query.actual || (req.body && req.body.actual));
    const expected = (req.query.expected || (req.body && req.body.expected));
  
    if (actual && expected) {
        try {
            temp.track();

            const actualPath = temp.path({ suffix: '.png' });
            await downloadFileFromUrl(actual, actualPath);
            
            const expectedPath = temp.path({ suffix: '.png' });
            await downloadFileFromUrl(expected, expectedPath);
            
            const { match, reason, diffPercentage } = await compare(
                actualPath,
                expectedPath
            );

            context.log(`Compare screenshots result: equal=${match}, reason="${reason}", diffPercentage=${diffPercentage}`)

            context.res = {
                body: {
                    equal: match,
                    reason,
                    diff: diffPercentage
                }
            };

        }
        catch (e) {
           context.log(`Error occured while comparing screenshots: ${e.message}`, e);     
        }
        finally {
            const cleanupResult = await temp.cleanup();
            context.log(`Cleaning up: files[${cleanupResult.files}], dirs[${cleanupResult.dirs}]`);
        }
    }
};

Error:

Error occured while comparing screenshots: Error at ChildProcess. (C:\home\site\wwwroot\node_modules\odiff-bin\odiff.js:134:13) at ChildProcess.emit (events.js:327:22) at maybeClose (internal/child_process.js:1048:16) at Socket. (internal/child_process.js:439:11) at Socket.emit (events.js:315:20) at Pipe. (net.js:673:12)

Any idea how to fix it?

Iterate over y-coordinates in outer loop

Had a quick look at this, and it appears the tool is iterating over x-coordinates in the outer loop.

If your image library's memory layout is anything like most others out there, this isn't the most CPU/memory friendly way to go about it.

Handle `no file or directory` UnhandledPromiseRejectionWarning

Hey. Thank you for the package. It's a great thing and an oportunity to reduce time to compare images.

Could you please add handling an error when no file found in the baseline directory?

For now I get UnhandledPromiseRejectionWarning, but I would be happy to get it via the result object. Something like this.

result: { match: false, reason: 'ENOENT: no such file or directory', details: filepath }

Update peer dependencies related Cypress

Right now the peerDependencies lists

"peerDependencies": {
"cypress": "10.0.3"
}
so there is a dependency warning if you are using a newer major version of cypress 10.7.0
I would propose changing it to ^n if there are no issues.

Awesome tool - thanks so much!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.