Как получить цвет координаты x, y пикселя из изображения?


Ответы:


199

Основываясь на ответе Джеффа, вашим первым шагом будет создание холста для вашего PNG. Следующее создает внеэкранный холст той же ширины и высоты, что и ваше изображение, и на нем нарисовано изображение.

var img = document.getElementById('my-image');
var canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.height;
canvas.getContext('2d').drawImage(img, 0, 0, img.width, img.height);

После этого, когда пользователь щелкает, используйте event.offsetXи, event.offsetYчтобы получить позицию. Затем это можно использовать для получения пикселя:

var pixelData = canvas.getContext('2d').getImageData(event.offsetX, event.offsetY, 1, 1).data;

Поскольку вы захватываете только один пиксель, pixelData представляет собой массив из четырех записей, содержащий значения R, G, B и A пикселя. Для альфа-канала значение меньше 255 представляет некоторый уровень прозрачности, при этом 0 означает полную прозрачность.

Вот пример jsFiddle: http://jsfiddle.net/thirtydot/9SEMf/869/ Я использовал jQuery для удобства во всем этом, но это ни в коем случае не требуется.

Примечание. getImageData Подпадает под действие политики браузера с одинаковым происхождением для предотвращения утечки данных, что означает, что этот метод не сработает, если вы испачкаете холст изображением из другого домена или (я считаю, но некоторые браузеры могли решить эту проблему) SVG из любого домена. Это защищает от случаев, когда сайт обслуживает пользовательский ресурс изображения для вошедшего в систему пользователя, и злоумышленник хочет прочитать изображение для получения информации. Вы можете решить проблему, обслуживая изображение с того же сервера или реализуя совместное использование ресурсов из разных источников .


3
бум - классная работа. Я знал, что мне следовало сделать такую ​​скрипку, но был слишком толстым и ленивым. вы убили его здесь
Джефф Эскаланте

Чтобы это было правильно, вам необходимо установить координатное пространство холста, т.е. установить ширину и высоту в соответствии с размерами изображения. Ширина и высота CSS служат только для растягивания конечного холста для макета, что не помогает, когда это неотображаемый элемент. Попробуйте что-нибудь вроде $ ('<canvas width =' + img.width + 'height =' + img.height + '/>') ;. Или это как-то не касается закадровых полотен?
fabspro

@fabspro: Отличный момент. Поскольку рисование и чтение данных изображения выполняются через контекст, значения ширины и высоты не имеют смысла. Они не имеют никакого вредного воздействия, потому что искажается холст, а не контекст, и причина, по которой я не видел этого эффекта в моей демонстрации, заключается просто в том, что изображение меньше начальной ширины / высоты контекста. Я обновлю соответственно, хотя это безопаснее для доступа .widthи .heightна самом холсте, чем через конкатенацию.
Брайан Никель

4
Исправьте это для Firefox jsfiddle.net/9SEMf/622, используя этот stackoverflow.com/questions/11334452/event-offsetx-in-firefox
benoît

6
Вы не можете использовать это для удаленных изображений. «Невозможно получить данные изображения с холста, потому что холст был испорчен данными из разных источников. SecurityError: была сделана попытка нарушить политику безопасности пользовательского агента».
Karl Glaser

18

Canvas был бы отличным способом сделать это, как сказал @pst выше. Посмотрите этот ответ на хороший пример:

getPixel из HTML Canvas?

Некоторый код, который также подойдет вам конкретно:

var imgd = context.getImageData(x, y, width, height);
var pix = imgd.data;

for (var i = 0, n = pix.length; i < n; i += 4) {
  console.log pix[i+3]
}

Это будет идти строка за строкой, поэтому вам нужно будет преобразовать это в x, y и либо преобразовать цикл for в прямую проверку, либо запустить условное выражение внутри.

Читая ваш вопрос еще раз, похоже, вы хотите уловить суть, на которую нажимает человек. Это можно легко сделать с помощью события click jquery. Просто запустите приведенный выше код внутри обработчика кликов как такового:

$('el').click(function(e){
   console.log(e.clientX, e.clientY)
}

Они должны захватить ваши значения x и y.


Это не то, о чем спрашивал (похоже) комментатор, и вообще не отвечает на вопрос. Принятый ответ действительно работает. Я рекомендую удалить этот ответ ...
Агамемн

5

Два предыдущих ответа демонстрируют, как использовать Canvas и ImageData. Я хотел бы предложить ответ на работоспособном примере и с использованием фреймворка обработки изображений, поэтому вам не нужно обрабатывать данные пикселей вручную.

MarvinJ предоставляет метод image.getAlphaComponent (x, y) который просто возвращает значение прозрачности для пикселя в координатах x, y. Если это значение равно 0, пиксель полностью прозрачен, значения от 1 до 254 - уровни прозрачности, наконец, 255 - непрозрачный.

Для демонстрации я использовал изображение ниже (300x300) с прозрачным фоном и двумя пикселями в координатах (0,0) и (150,150) .

введите описание изображения здесь

Вывод в консоль:

(0,0): ПРОЗРАЧНЫЙ
(150,150): NOT_TRANSPARENT

image = new MarvinImage();
image.load("https://i.imgur.com/eLZVbQG.png", imageLoaded);

function imageLoaded(){
  console.log("(0,0): "+(image.getAlphaComponent(0,0) > 0 ? "NOT_TRANSPARENT" : "TRANSPARENT"));
  console.log("(150,150): "+(image.getAlphaComponent(150,150) > 0 ? "NOT_TRANSPARENT" : "TRANSPARENT"));
}
<script src="https://www.marvinj.org/releases/marvinj-0.7.js"></script>


1

С участием : i << 2

const data = context.getImageData(x, y, width, height).data;
const pixels = [];

for (let i = 0, dx = 0; dx < data.length; i++, dx = i << 2) {
    if (data[dx+3] <= 8)
        console.log("transparent x= " + i);
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.