Skip to content

Commit 42565bf

Browse files
committed
Improve API and add documentation
1 parent d342037 commit 42565bf

27 files changed

+620
-13
lines changed

Diff for: README.md

+152
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,27 @@ Please also refer to the **[Documentation](https://prior99.github.io/native-imag
1515
* [Table of contents](#table-of-contents)
1616
* [Supported environments](#supported-environments)
1717
* [Usage](#usage)
18+
* [Basic example](#basic-example)
19+
* [Usage with node-libpng](#usage-with-node-libpng)
20+
* [The resulting values explained](#the-resulting-values-explained)
21+
* [Antialiasing Detection](#antialiasing-detection)
22+
* [Color threshold](#color-threshold)
1823
* [Contributing](#contributing)
1924
* [Contributors](#contributors)
2025

2126
## Usage
2227

28+
More sophisticated, fully working examples can be found [here](example/):
29+
30+
* [Simple example](example/src/simple.js)
31+
* [Antialiasing Detection](example/src/antialiasing-detection.js)
32+
* [Generate no diff image](example/src/no-diff-image.js)
33+
* [Color Threshold comparison](example/src/color-threshold.js)
34+
35+
### Basic example
36+
37+
A basic example of how to use this library can look like this:
38+
2339
```typescript
2440
import { diffImages } from "native-image-diff";
2541

@@ -47,6 +63,142 @@ const { image, pixels, totalDelta } = diffImages(image1, image2);
4763
// the most different and `0` being total equal.
4864
```
4965

66+
The two buffers in `image1` and `image2` are expected to contain an RGB or RGBA encoded 8bit image. In the above example an RGB image was used.
67+
68+
Both images will be compared pixel-per-pixel and the result as well as a visualization of the difference is returned.
69+
70+
This library does not provide any way to read or write images. Take a look at [usage with node-libpng](#usage-with-node-libpng) for an idea.
71+
72+
With these input images:
73+
74+
![](images/pixels-example-ya.png) ![](images/pixels-example-yay.png)
75+
76+
The generate diff image will look like this:
77+
78+
![](images/pixels-example-diff.png)
79+
80+
### Usage with node-libpng
81+
82+
This library is API-compatible with [node-libpng](https://www.npmjs.com/package/node-libpng). It's simple to use decoded images as well as encoding them:
83+
84+
```typescript
85+
import { diffImages } from "native-image-diff";
86+
import { readPngFileSync, writePngFileSync } from "node-libpng";
87+
88+
const { image, pixels } = diffImages(readPngFileSync("./image1.png"), readPngFileSync("./image2.png"));
89+
console.log(`Compared both images. ${pixels} were different.`);
90+
91+
writePngFileSync("./diff.png", image.data, { width: image.width, height: image.height });
92+
// In JS this can be even shorter: `writePngFileSync("./diff.png", image.data, image);`.
93+
```
94+
95+
### The resulting values explained
96+
97+
A result might look like this:
98+
99+
```js
100+
{
101+
pixels: 286,
102+
totalDelta: 3434604.5,
103+
image: {
104+
width: 100,
105+
height: 100,
106+
data: <Buffer 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ... >
107+
}
108+
}
109+
```
110+
111+
#### pixels
112+
113+
This represents the total amount of pixels differing between both images.
114+
115+
#### totalDelta
116+
117+
This is the summed up total perceived difference of all pixels. It grows with the color difference of every unmatched pixel.
118+
119+
In comparison to the [pixels](https://prior99.github.io/native-image-diff/docs/interfaces/diffresult.html#pixels) property this property also represents how different all colors were. Comparing a white image
120+
with a black image would yield a higher difference as comparing an orange with a red image.
121+
122+
It doesn't feature any specific unit and should be used for relative comparisons only.
123+
124+
#### image
125+
126+
This property is only generate if [generateDiffImage](https://prior99.github.io/native-image-diff/docs/interfaces/diffimagesarguments.html#generatediffimage) is set to `true` (default).
127+
128+
It's properties `width` and `height` represent the dimensions of the generated image in pixels and `data` holds a RGBA buffer
129+
of raw image data showing the visual difference between both input images. Different pixels are drawn in red and pixels which
130+
only differed between both images because of antialiasing will be drawn in yellow. This is only true if [detectAntialiasing](https://prior99.github.io/native-image-diff/docs/interfaces/diffimagesarguments.html#detectantialiasing)
131+
is set to `true` (default).
132+
133+
### Antialiasing Detection
134+
135+
By default this library will try to detect whether a pixel was part of antialiasing and ignore the respective change.
136+
This works ~90% of the time:
137+
138+
These images (one with and one without antialiasing):
139+
140+
![](images/antialiasing-example-no-antialiasing.png) ![](images/antialiasing-example-with-antialiasing.png)
141+
142+
Will look like this with detection enabled:
143+
144+
![](images/antialiasing-example-diff-detection-enabled.png)
145+
146+
The yellow pixels represent detected antialiasing will not be included in the [pixels](https://prior99.github.io/native-image-diff/docs/interfaces/diffresult.html#pixels)
147+
property of the result.
148+
149+
And like this with detection disabled:
150+
151+
![](images/antialiasing-example-diff-detection-disabled.png)
152+
153+
Disable the detection by providing `false` as [detectAntialiasing](https://prior99.github.io/native-image-diff/docs/interfaces/diffimagesarguments.html#detectantialiasing).
154+
155+
### Color threshold
156+
157+
It's possible to specify a different [colorThreshold](https://prior99.github.io/native-image-diff/docs/interfaces/diffimagesarguments.html#colorthreshold).
158+
159+
The color threshold ranges from `0` to `1` with `1` permitting all changes and `0` permitting none.
160+
It influences the allowed per-pixel color difference.
161+
162+
The following example shows the visual difference between a gradient and a red rectangle with different thresholds:
163+
164+
Input images:
165+
166+
![](images/red-rectangle-example-red.png) ![](images/red-rectangle-example-gradient.png)
167+
168+
Thresholds from 0.0 to 0.7:
169+
170+
*0.0: (2826 pixels different)*
171+
172+
![](images/red-rectangle-example-0-diff.png)
173+
174+
*0.1: (2413 pixels different)*
175+
176+
![](images/red-rectangle-example-10-diff.png)
177+
178+
*0.2: (1986 pixels different)*
179+
180+
![](images/red-rectangle-example-20-diff.png)
181+
182+
*0.3: (1570 pixels different)*
183+
184+
![](images/red-rectangle-example-30-diff.png)
185+
186+
*0.4: (1142 pixels different)*
187+
188+
![](images/red-rectangle-example-40-diff.png)
189+
190+
*0.5: (731 pixels different)*
191+
192+
![](images/red-rectangle-example-50-diff.png)
193+
194+
*0.6: (300 pixels different)*
195+
196+
![](images/red-rectangle-example-60-diff.png)
197+
198+
*0.7: (0 pixels different)*
199+
200+
![](images/red-rectangle-example-70-diff.png)
201+
50202
## Supported environments
51203

52204
This is a native Addon to NodeJS which delivers prebuilt binaries. Only some environments are supported:

Diff for: example/package.json

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"name": "native-image-diff-example",
3+
"dependencies": {
4+
"native-image-diff": "file:..",
5+
"node-libpng": "^0.2.0"
6+
}
7+
}

Diff for: example/src/antialiasing-detection.js

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
const NodeLibpng = require("node-libpng");
2+
const NativeImageDiff = require("native-image-diff");
3+
4+
// Read the images from PNG images on the disk.
5+
const imageNoAntialiasing =
6+
NodeLibpng.readPngFileSync(`${__dirname}/../../images/antialiasing-example-no-antialiasing.png`);
7+
const imageAntialiasing =
8+
NodeLibpng.readPngFileSync(`${__dirname}/../../images/antialiasing-example-with-antialiasing.png`);
9+
10+
// Compare both images with antialiasing detection enabled.
11+
const resultDetectionEnabled = NativeImageDiff.diffImages({
12+
image1: imageNoAntialiasing,
13+
image2: imageAntialiasing,
14+
// This can be omitted; It's `true` by default.
15+
detectAntialiasing: true,
16+
});
17+
console.log(`Antialiasing detection enabled: ${resultDetectionEnabled.pixels} pixels were different.`);
18+
// Write the diff image to the disk.
19+
NodeLibpng.writePngFileSync(
20+
`${__dirname}/../../images/antialiasing-example-diff-detection-enabled.png`,
21+
resultDetectionEnabled.image.data,
22+
resultDetectionEnabled.image,
23+
);
24+
25+
// Compare both images with antialiasing detection disabled.
26+
const resultDetectionDisabled = NativeImageDiff.diffImages({
27+
image1: imageNoAntialiasing,
28+
image2: imageAntialiasing,
29+
detectAntialiasing: false,
30+
});
31+
console.log(`Antialiasing detection disabled: ${resultDetectionDisabled.pixels} pixels were different.`);
32+
// Write the diff image to the disk.
33+
NodeLibpng.writePngFileSync(
34+
`${__dirname}/../../images/antialiasing-example-diff-detection-disabled.png`,
35+
resultDetectionDisabled.image.data,
36+
resultDetectionDisabled.image,
37+
);

Diff for: example/src/color-threshold.js

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
const NodeLibpng = require("node-libpng");
2+
const NativeImageDiff = require("native-image-diff");
3+
4+
// Read the images from PNG images on the disk.
5+
const imageRed = NodeLibpng.readPngFileSync(`${__dirname}/../../images/red-rectangle-example-red.png`);
6+
const imageGradient = NodeLibpng.readPngFileSync(`${__dirname}/../../images/red-rectangle-example-gradient.png`);
7+
8+
// Compare the images with different color thresholds.
9+
for (let colorThreshold = 0; colorThreshold <= 0.7; colorThreshold += 0.1) {
10+
const result = NativeImageDiff.diffImages({
11+
image1: imageRed,
12+
image2: imageGradient,
13+
colorThreshold,
14+
detectAntialiasing: false,
15+
});
16+
const percent = Math.floor(colorThreshold * 100);
17+
// Log the result for this threshold.
18+
console.log(`Color threshold ${percent}%: ${result.pixels} pixels were different.`);
19+
// Write the diff image.
20+
NodeLibpng.writePngFileSync(
21+
`${__dirname}/../../images/red-rectangle-example-${percent}-diff.png`,
22+
result.image.data,
23+
result.image,
24+
);
25+
}

Diff for: example/src/no-diff-image.js

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
const NodeLibpng = require("node-libpng");
2+
const NativeImageDiff = require("native-image-diff");
3+
4+
// Read the images from PNG images on the disk.
5+
const imageA = NodeLibpng.readPngFileSync(`${__dirname}/../../images/pixels-example-ya.png`);
6+
const imageB = NodeLibpng.readPngFileSync(`${__dirname}/../../images/pixels-example-yay.png`);
7+
// Compare both images. Don't generate a diff image.
8+
const result = NativeImageDiff.diffImages({
9+
image1: imageA,
10+
image2: imageB,
11+
generateDiffImage: false,
12+
});
13+
// Log the result.
14+
console.log(`${result.pixels} pixels were different.`);

Diff for: example/src/simple.js

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
const NodeLibpng = require("node-libpng");
2+
const NativeImageDiff = require("native-image-diff");
3+
4+
// Read the images from PNG images on the disk.
5+
const imageA = NodeLibpng.readPngFileSync(`${__dirname}/../../images/pixels-example-ya.png`);
6+
const imageB = NodeLibpng.readPngFileSync(`${__dirname}/../../images/pixels-example-yay.png`);
7+
// Compare both images.
8+
const result = NativeImageDiff.diffImages(imageA, imageB);
9+
// Log the result.
10+
console.log(`${result.pixels} pixels were different.`);
11+
// Write the diff image to the disk.
12+
NodeLibpng.writePngFileSync(`${__dirname}/../../images/pixels-example-diff.png`, result.image.data, result.image);

Diff for: example/yarn-error.log

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
Arguments:
2+
/home/prior/.nvm/versions/node/v8.9.3/bin/node /home/prior/.nvm/versions/node/v8.9.3/bin/yarn add file:..
3+
4+
PATH:
5+
/home/prior/.nvm/versions/node/v8.9.3/bin:/home/prior/.cargo/bin:/home/prior/.cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/bin:/opt/android-sdk/platform-tools:/opt/android-sdk/tools:/opt/cuda/bin:/usr/lib/emscripten:/usr/lib/jvm/default/bin:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl
6+
7+
Yarn version:
8+
1.3.2
9+
10+
Node version:
11+
8.9.3
12+
13+
Platform:
14+
linux x64
15+
16+
npm manifest:
17+
{
18+
"name": "native-image-diff-example",
19+
"main": "src/index.js"
20+
}
21+
22+
yarn manifest:
23+
No manifest
24+
25+
Lockfile:
26+
No lockfile
27+
28+
Trace:
29+
Error: https://registry.yarnpkg.com/node-fetch: ETIMEDOUT
30+
at Timeout._onTimeout (/home/prior/.nvm/versions/node/v8.9.3/lib/node_modules/yarn/lib/cli.js:123749:19)
31+
at ontimeout (timers.js:475:11)
32+
at tryOnTimeout (timers.js:310:5)
33+
at Timer.listOnTimeout (timers.js:270:5)

0 commit comments

Comments
 (0)