Можно ли сделать снимок IMG и заменить один точный цвет другим, скажем, #fff на #000, сохранив все остальные цвета без изменений? Возможно, поможет цветовая матрица из фильтров SVG?
Замените один цвет с помощью фильтров SVG
Ответы (1)
Это тривиально сделать с Canvas. Также можно сделать с SVG, но это запутанно. Следующий метод работает с обычными полностью непрозрачными изображениями. Во-первых, вы конвертируете каждое несовпадающее значение цвета в каждом канале в ноль, а каждое совпадающее значение цвета в 1 с помощью длинного ComponentTransfer (индекс единственной «1» в ваших 256-элементных массивах tableValues должен соответствовать вашим r, g и b заменить значение). Затем вы обнуляете альфа-канал всего, кроме результирующих белых пикселей, используя цветовую матрицу. Вы используете результат в качестве маски с feFlood вашего целевого цвета и накладываете результат поверх исходной графики. Например, следующий код заменяет определенный цвет — rgb(87, 78, 29) — синим.
<svg width="600px" height="600px" viewBox="0 0 600 600">
<defs>
<filter id="color-replace" color-interpolation-filters="sRGB">
<!-- Replace rgb(87,78,29) with blue. -->
<feComponentTransfer >
<feFuncR type="discrete" tableValues="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0"/>
<feFuncG type="discrete" tableValues="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0"/>
<feFuncB type="discrete" tableValues="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0"/>
</feComponentTransfer>
<feColorMatrix type="matrix" values="1 0 0 0 0
0 1 0 0 0
0 0 1 0 0
1 1 1 1 -3" result="selectedColor"/>
<feFlood flood-color="blue"/>
<feComposite operator="in" in2="selectedColor"/>
<feComposite operator="over" in2="SourceGraphic"/>
</filter>
</defs>
<g filter="url(#color-replace)">
<rect x="50" y="50" height="100" width="100" fill="rgb(86,77,28)"/>
<rect x="250" y="50" height="100" width="100" fill="rgb(86,77,29)"/>
<rect x="450" y="50" height="100" width="100" fill="rgb(86,78,29)"/>
<rect x="50" y="250" height="100" width="100" fill="rgb(87,77,29)"/>
<rect x="250" y="250" height="100" width="100" fill="rgb(87,78,29)"/>
<rect x="450" y="250" height="100" width="100" fill="rgb(87,78,30)"/>
<rect x="50" y="450" height="100" width="100" fill="rgb(88,78,30)"/>
<rect x="250" y="450" height="100" width="100" fill="rgb(88,79,29)"/>
<rect x="450" y="450" height="100" width="100" fill="rgb(88,79,30)"/>
</g>
</svg>
ОБНОВИТЬ:
Если вы хотите заменить исходный цвет цветом с непрозрачностью менее 1, вам нужно сделать дополнительный шаг — удалить выбранный цвет перед его заменой. Вы можете расширить фильтр таким образом, чтобы добиться этого.
<--snipping first half of filter -->
<feColorMatrix type="matrix" values="1 0 0 0 0
0 1 0 0 0
0 0 1 0 0
1 1 1 1 -3" result="selectedColor"/>
<feComposite operator="out" in="SourceGraphic" result="notSelectedColor"/>
<feFlood flood-color="blue" flood-opacity="0.5"/>
<feComposite operator="in" in2="selectedColor"/>
<feComposite operator="over" in2="notSelectedColor"/>
</filter>
flood-color="blue" flood-opacity="0.5"
не работает, равно как и установка 128 0 и 128 1 в <feFuncA/>
tableValues.
- person Todd Main; 08.10.2019
feComponentTransfer
, где tableValues
довольно странным образом интерпретируется Chrome.
- person Greegus; 23.10.2019