Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 | 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 148008x 148008x 148008x 148008x 148008x 148008x 148008x 148008x 148008x 148008x 148008x 148008x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 148022x 148022x 148022x 148013x 5x 5x 5x 148013x 148017x 148017x 148017x 148017x 9x 9x 9x 148017x 148017x 148017x 148017x 148017x 148022x 92268x 92268x 92268x 92268x 92268x 92268x 92268x 92268x 92268x 92268x 92268x 92268x 92268x 92268x 92268x 92268x 92268x 92268x 92268x 148017x 148017x 148017x 55749x 55749x 55749x 148017x 2x 2x 2x 2x 2x 2x | import { colorBlend } from './color-blend.js' import { distYIQ, distCIEDE2000, distRGB, distRieRGB, distYIQBrightness } from './color-metrics.js' /** @param {number} num - number to round */ const rounded = (num) => +num.toFixed(5) export const maxDelta = { YIQ: rounded(distYIQ(0, 0, 0, 255, 255, 255)), RGB: rounded(distRGB(0, 0, 0, 255, 255, 255)), RieRGB: rounded(distRieRGB(0, 0, 0, 255, 255, 255)), CIEDE2000: rounded(distCIEDE2000(0, 0, 0, 255, 255, 255)), Brightness: rounded(Math.abs(distYIQBrightness(0, 0, 0, 255, 255, 255))), } export const validAlgorithms = Object.freeze(/** @type {const} */(['YIQ', 'CIEDE2000', 'RGB', 'RieRGB', 'Brightness'])) /** @typedef {(typeof validAlgorithms)[number]} Algorithm */ /** * * @param {Uint8Array | Uint8ClampedArray} img1 - original image * @param {Uint8Array | Uint8ClampedArray} img2 - image to compare * @param {number} posImg1 - pixel position on `img1` * @param {number} posImg2 - pixel position on `img2` * @param {Algorithm} algorithm - algorithm used to calculate delta defaults to CIEDE2000 * @returns {colorDelta} color delta result */ export function colorDeltaImgPosition (img1, img2, posImg1, posImg2, algorithm) { const r1 = img1[posImg1 + 0] const g1 = img1[posImg1 + 1] const b1 = img1[posImg1 + 2] const a1 = img1[posImg1 + 3] const r2 = img2[posImg2 + 0] const g2 = img2[posImg2 + 1] const b2 = img2[posImg2 + 2] const a2 = img2[posImg2 + 3] return colorDelta(r1, g1, b1, a1, r2, g2, b2, a2, algorithm) } /** * calculate color difference according to the paper "Measuring perceived color difference * using YIQ NTSC transmission color space in mobile applications" by Y. Kotsarenko and F. Ramos * @param {number} r1 - color 1 rgba red value * @param {number} g1 - color 1 rgba green value * @param {number} b1 - color 1 rgba blue value * @param {number} a1 - color 1 rgba alpha value * @param {number} r2 - color 2 rgba red value * @param {number} g2 - color 2 rgba green value * @param {number} b2 - color 2 rgba blue value * @param {number} a2 - color 2 rgba alpha value * @param {Algorithm} algorithm - algorithm used to calculate delta defaults to CIEDE2000 * @returns {colorDelta} color delta result */ export function colorDelta (r1, g1, b1, a1, r2, g2, b2, a2, algorithm) { algorithm = Object.hasOwn(maxDelta, algorithm) ? algorithm : 'CIEDE2000' if (a1 === a2 && r1 === r2 && g1 === g2 && b1 === b2) { return { delta: 0, maxDelta: maxDelta[algorithm], } } const algorithmFunction = (() => { switch (algorithm) { case 'YIQ': return distYIQ case 'RGB': return distRGB case 'RieRGB': return distRieRGB case 'Brightness': return distYIQBrightness case 'CIEDE2000': default: return distCIEDE2000 } })() if (a1 < 255 || a2 < 255) { const rgb1Light = colorBlend(r1, g1, b1, a1, 255, 255, 255) const rgb2Light = colorBlend(r2, g2, b2, a2, 255, 255, 255) const deltaLightBlend = rounded(algorithmFunction( rgb1Light.R, rgb1Light.G, rgb1Light.B, rgb2Light.R, rgb2Light.G, rgb2Light.B )) const rgb1Dark = colorBlend(r1, g1, b1, a1, 0, 0, 0) const rgb2Dark = colorBlend(r2, g2, b2, a2, 0, 0, 0) const deltaDarkBlend = rounded(algorithmFunction( rgb1Dark.R, rgb1Dark.G, rgb1Dark.B, rgb2Dark.R, rgb2Dark.G, rgb2Dark.B )) return { delta: Math.max(deltaLightBlend, deltaDarkBlend), maxDelta: maxDelta[algorithm], } } const delta = rounded(algorithmFunction(r1, g1, b1, r2, g2, b2)) return { delta, maxDelta: maxDelta[algorithm], } } /** * @typedef {object} colorDelta * @property {number} delta - color delta result * @property {number} maxDelta - max possible result value */ |