В браузерах, которые поддерживают это, вы можете использовать фильтры svg, чтобы сделать это:
Вот другой Q / A , который показывает интересный способ сделать это дляфиксированный цвет.
Здесь я сделал простую вспомогательную функцию, которая настроит для нас требуемый tableValues
с небольшим допуском, и я удалил <feFill>
, чтобы выбранный цвет стал прозрачным (<feFill>
испортил бы холст в Chrome).Если вы хотите заменить цвет, вы все равно можете добиться этого с помощью параметров компоновки холста (прокомментированный код ниже фрагмента).
const ctx = canvas.getContext('2d');
const img = new Image();
img.onload = e => {
canvas.width = img.width;
canvas.height = img.height;
// update our filter
updateChroma([76, 237, 0], 8);
// if you wish to replace the color, uncomment followings
// ctx.fillStyle = "your_replaceColor";
// ctx.fillRect(0,0,img.width,img.height);
ctx.filter = 'url(#chroma)';
ctx.drawImage(img, 0, 0);
ctx.filter = 'none';
// ctx.globalCompositeOperation = 'destination-in';
// ctx.drawImage(img, 0,0);
};
img.src = "https://i.stack.imgur.com/hZm8o.png";
function updateChroma(rgb, tolerance) {
const sels = ['R', 'G', 'B'];
rgb.forEach((value, ind) => {
const fe = document.querySelector('#chroma feFunc' + sels[ind]);
let vals = '';
if (!value) {
vals = '0'
} else {
for (let i = 0; i < 256; i++) {
vals += (Math.abs(value - i) <= tolerance) ? '1 ' : '0 ';
}
}
fe.setAttribute('tableValues', vals);
});
}
canvas {
background: ivory
}
<svg width="0" height="0" style="position:absolute;visibility:hidden">
<filter id="chroma" color-interpolation-filters="sRGB"x="0" y="0" height="100%" width="100%">
<feComponentTransfer>
<feFuncR type="discrete"/>
<feFuncG type="discrete"/>
<feFuncB type="discrete"/>
</feComponentTransfer>
<feColorMatrix type="matrix" values="1 0 0 0 0
0 1 0 0 0
0 0 1 0 0
1 1 1 1 -1" result="selected"/>
<feComposite in="SourceGraphic" in2="selected" operator="out"/>
</filter>
</svg>
<canvas id="canvas"></canvas>
Я не проводил обширные тесты на многих устройствах, но там, где аппаратное ускорение включено, это может работать лучше, чем любой пиксельный цикл, так каквсе должно быть сделано на графическом процессоре.
Но поддержка браузера все еще не так уж велика ...
Так что вам, возможно, придется в любом случае откатиться на пиксельные манипулы.
Здесь, в зависимости отна том, что вы делаете для цветности, вы можете пожертвовать немного качеством ради скорости.
Например, на видео вы можете выполнить цветность на холсте уменьшенного размера, а затем нарисовать его обратно с помощьюкомпозитинг на основной, выиграв несколько итераций за кадры.См. предыдущий Q / A для примера.