Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Transparent is not white #142

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 15 additions & 11 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -184,20 +184,24 @@ function colorDelta(img1, img2, k, m, yOnly) {
let b2 = img2[m + 2];
let a2 = img2[m + 3];

if (a1 === a2 && r1 === r2 && g1 === g2 && b1 === b2) return 0;
if (a1 === a2 && r1 === r2 && g1 === g2 && b1 === b2 && a1 === a2) return 0;
NathanMOlson marked this conversation as resolved.
Show resolved Hide resolved

const rBackground = 48 + 159 * (k % 2);
const gBackground = 48 + 159 * (Math.floor(k / 1.616) % 2);
const bBackground = 48 + 159 * (Math.floor(k / 2.612) % 2);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, left a comment here but it disappeared somewhere... Can you describe how these specific values / coefficients were picked, and maybe show a screenshot of how this looks?

Copy link

@HarelM HarelM Oct 21, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think one of the tests shows that - for me it looked like how the color picker looks, and I guess the coefficients came from there...

Copy link
Author

@NathanMOlson NathanMOlson Oct 21, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is what the background looks like:
background

There are a million choices for what the background image could look like. Here are my considerations when creating this background image:

  1. The background should not be a uniform color.
  2. The background should not contain large areas of uniform color.
  3. The background should have a large amount of perceptual variability.
  4. The background should be deterministic.
  5. The background color should be easy to compute.
  6. The background color should be a function of pixel index only (not x,y), because that is what was already available in colorDelta().
  7. The background should not contain "common colors" (particularly white and black).
  8. The background should not contain lines.
  9. The background image should not contain anything we would expect to appear in test images.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The 48 and 159 were picked to give large color variability, while avoiding white, black, and fully saturated colors.

The 1.616 and 2.612 were picked to keep the pattern from degenerating into lines at certain integer image widths. I've added some digits to make sure theses coefficients preserve their irrationality for very large images :)


if (a1 < 255) {
a1 /= 255;
r1 = blend(r1, a1);
g1 = blend(g1, a1);
b1 = blend(b1, a1);
r1 = blend(r1, rBackground, a1);
g1 = blend(g1, gBackground, a1);
b1 = blend(b1, bBackground, a1);
}

if (a2 < 255) {
a2 /= 255;
r2 = blend(r2, a2);
g2 = blend(g2, a2);
b2 = blend(b2, a2);
r2 = blend(r2, rBackground, a2);
g2 = blend(g2, gBackground, a2);
b2 = blend(b2, bBackground, a2);
}

const y1 = rgb2y(r1, g1, b1);
Expand All @@ -219,9 +223,9 @@ function rgb2y(r, g, b) { return r * 0.29889531 + g * 0.58662247 + b * 0.1144822
function rgb2i(r, g, b) { return r * 0.59597799 - g * 0.27417610 - b * 0.32180189; }
function rgb2q(r, g, b) { return r * 0.21147017 - g * 0.52261711 + b * 0.31114694; }

// blend semi-transparent color with white
function blend(c, a) {
return 255 + (c - 255) * a;
// blend semi-transparent color with background
function blend(c, cBackground, a) {
return cBackground + (c - cBackground) * a;
}

function drawPixel(output, pos, r, g, b) {
Expand All @@ -235,6 +239,6 @@ function drawGrayPixel(img, i, alpha, output) {
const r = img[i + 0];
const g = img[i + 1];
const b = img[i + 2];
const val = blend(rgb2y(r, g, b), alpha * img[i + 3] / 255);
const val = blend(rgb2y(r, g, b), 255, alpha * img[i + 3] / 255);
drawPixel(output, i, val, val, val);
}
Binary file modified test/fixtures/5diff.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added test/fixtures/8a.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added test/fixtures/8diff.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 2 additions & 1 deletion test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,11 @@ diffTest('2a', '2b', '2diff', {
}, 12437);
diffTest('3a', '3b', '3diff', options, 212);
diffTest('4a', '4b', '4diff', options, 36049);
diffTest('5a', '5b', '5diff', options, 0);
diffTest('5a', '5b', '5diff', options, 1);
diffTest('6a', '6b', '6diff', options, 51);
diffTest('6a', '6a', '6empty', {threshold: 0}, 0);
diffTest('7a', '7b', '7diff', {diffColorAlt: [0, 255, 0]}, 2448);
diffTest('8a', '5b', '8diff', options, 32896);

test('throws error if image sizes do not match', () => {
assert.throws(() => match(new Uint8Array(8), new Uint8Array(9), null, 2, 1), 'Image sizes do not match');
Expand Down