Unlimited WordPress themes, graphics, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Code
  2. Web Development
Code

Изучение Canvas с нуля: работа с пикселями

by
Difficulty:IntermediateLength:LongLanguages:
This post is part of a series called Canvas From Scratch.
Canvas From Scratch: Transformations and Gradients

Russian (Pусский) translation by Nadia Gonzales (you can also view the original English article)

В предыдущем руководстве вы всесторонне изучили работу с трансформациями, тенями и градиентами. Сегодня я покажу вам, как работать с пикселями в Сanvas: от простого получения значений компонентов цвета до того редактирования изображений на «холсте», которое выполняем в редакторе изображений.

Это несомненно одна из наиболее мощных встроенных возможностей Canvas, и я вам гарантирую, что сразу после ее освоения у вас появится целый ряд потрясающих идей.


Подготавливаем страницу

Вы будете использовать тот же самый шаблон HTML, что и в предыдущем руководстве, поэтому откройте свой любимый редактор и скопируйте следующий код:

Это всего лишь базовая HTML-страница с элементом canvas и некоторым кодом JavaScript, который выполняется после загрузки модели DOM (* Document Object Model – Объектная модель документа. Тут и далее примеч. пер.). Ничего фантастического тут нет.


Размещаем изображение на «холсте»

Вы можете манипулировать значениями пикселей чего-угодно, что прорисовано на «холсте», однако для достижения целей этого руководства мы будем использовать изображения. Это так отчасти из-за того, что мне важно показать вам, как загружать изображения в canvas, а также потому, что способность выполнять манипуляции с изображениями (например редактирование изображений) – это большой плюс рассматриваемой технологии.

Перед тем, как я покажу вам, как получать значения пикселей, давайте разместим изображение на «холсте». Вы запросто можете использовать любое изображение, однако для достижения целей этого руководства я буду использовать одно из моих собственных с Flickr.

One of my photos from Flickr

При желании можете использовать это изображение, которое доступно для скачивания в различных размерах.

Загрузка изображения на «холст» выполняется в два этапа. Первый – загрузка изображения в элемент HTML image, что можно осуществить при помощи HTML или создания нового элемента DOM непосредственно в коде JavaScript. В нашем примере мы создадим новый элемент DOM – это чрезвычайно просто:

Здесь мы всего лишь создаем новый элемент DOM типа  Image и задаем его в качестве значения переменной. Далее мы используем эту переменную для загрузки вашего изображения, задавая в качестве значения атрибута src изображения необходимый путь к файлу (* чтобы  началась загрузка изображения, элемент не нужно добавлять к документу – оно начинает загружаться, как только задано значение свойства src). Стоит отметить, что при помощи этой техники мы бы могли загрузить изображение с удаленного компьютера, однако при этом позже у нас возникли бы некоторые проблемы, так что мы остановимся на использовании изображения с локального компьютера. Второй этап – прослушивание события load, которое будет сгенерировано, как только изображение загружено и готово к использованию.

Сразу после загрузки изображения мы можем разместить его на «холсте» одним махом. Для этого нам всего лишь необходимо передать переменную image, которую только что создали, в качестве аргумента метода drawImage 2-мерного контекста отображения. Разместите этот код в обработчике события загрузки для image следующим образом:

В данном случае метод drawImage принимает три аргумента: элемент с изображением и значения координат x и y для задания позиции изображения на «холсте». За счет этого кода изображение будет отображено в полном размере (ширина составляет 500px в нашем примере) и в указанной позиции:

Placing an image

Однако на самом деле drawImage может принимать еще два аргумента, за счет которых задаются значения ширины и высоты отображаемого изображения, следующим образом:

За счет этого кода изображение было бы отображено в половину своего изначального размера (ширина составляет 250px в нашем примере):

Placing and resizing an image

Вы можете пойти еще дальше и воспользоваться всеми девятью аргументами метода drawImage для прорисовывания только небольшой части изначального изображения вот так:

За счет этого кода будет выбран квадрат со значением стороны 200px вверху слева изображения и прорисован на «холсте» в квадрате со значением стороны 500px:

Placing only part of an image

В псевдокоде (* язык, напоминающий императивный язык программирования и используемый в качестве нотации для описания алгоритмов и/или структуры программы) все девять аргументов drawImage можно описать следующим образом (s – для обозначения источника (source) и d – для обозначения места назначения (destination)):

Результат приведен на следующей иллюстрации:

Taking drawImage to the extreme

Все просто, не так ли? По правде говоря, понимание любого аспекта работы Сanvas не вызывает трудностей, как только вы его проанализируете и рассмотрите каждый момент по отдельности.


Получаем значения компонентов цвета пикселей

Теперь, когда у вас имеется изображение на «холсте», пришло время получить значения компонентов цвета пикселей, благодаря чему вы сможете ими манипулировать.Однако давайте сейчас забудем о манипулировании и сосредоточимся исключительно на получении значений компонентов цвета пикселей, поскольку для понимания этой концепции необходимо некоторое время.

Вопросы безопасности

Если вы хотите получить значения компонентов цвета пикселей при помощи canvas, то должны быть в курсе об имеющихся ограничениях, связанных с безопасностью. Согласно им вы можете получать данные только изображений, загруженных с того же домена, что и JavaScript. Из-за этого вы не можете получать изображения с удаленного сервера с дальнейшим анализом значений компонентов цвета его пикселей, хотя имеется что-то вроде обходного пути этого ограничения. К сожалению, не во всех браузерах код JavaScript и изображения, загружаемые локально из файловой системы (то есть без использования доменного имени), рассматриваются в качестве файлов, получаемых с одного и того же домена, так что у вас могут возникнуть ошибки, связанные с нарушением безопасности. Чтобы избежать этого вам необходимо либо запускать оставшуюся часть кода руководства при помощи серверного программного обеспечения на вашем локальном компьютере (вроде MAMP, WAMP или XAMPP) или удаленного веб-сервера и получать файлы при помощи доменного имени (например example.com).

Разобравшись с этим, давайте продолжим и получим некоторые значения компонентов цвета пикселей!

Способ получения значений компонентов цвета пикселей странноватый

Как я уже упомянул в начале данного раздела, для понимания способа получения значений компонентов цвета пикселя «холста» необходимо некоторое время.  Это так из-за способа, согласно которому пиксели сохраняются в Сanvas; они вовсе не хранятся как цельные пиксели. Вместо этого каждый пиксель разбивается на четыре отдельных компонента (красный, зеленый, синий и альфа (* в компьютерной графике - четвёртый компонент цвета, используемый для контроля смешивания цветов с фоном или нижележащим объектом. При этом его значение 1,0 означает полную непрозрачность, а 0,0 - полную прозрачность объекта)), и эти значения сохраняются в одномерном массиве со всеми значениями компонентов цвета для других пикселей. Поэтому вы не можете просто запросить данные из определенного пикселя, по крайней мере по умолчанию. Давайте поясню.

Для получения значений компонентов цвета пикселей вам необходимо вызвать метод getImageData 2-мерного контекста отображения следующим образом:

Этот метод принимает четыре аргумента, при помощи которых задается прямоугольная область «холста», значения пикселей которой вы хотите получить: координаты x и y начала отсчета, за которыми следуют значения ширины и высоты. Этот метод возвращает массив CanvasPixelArray, в котором содержатся все значения компонентов цвета пикселей заданной области. Первое, на что следует обратить внимание при работе с CanvasPixelArray, – это то, что для каждого пикселя задается четыре значения компонентов цвета, так что индексом первого компонента цвета каждого пикселя массива будет кратное 4 число (0 для первого значения первого пикселя, 4 для первого значения второго пикселя и т.д.):

Index values in the CanvasPixelArray

Интересно (или раздражает, в зависимости от того, как вы смотрите на массив) то, что тут не используется концепция позиции координат (x, y), из-за чего получить значения компонентов цвета для определенного пикселя немного тяжелее, чем получить определенное значение двухмерного массива (например используя pixelArray[0][3] для получения значения пикселя в координате (1, 4)). Вместо этого вы должны использовать небольшую формулу, которая в действительности очень проста для понимания, если правильно объяснена:

Accessing a specific pixel from the CanvasPixelArray

Можете разобраться, что тут происходит? Давайте проанализируем формулу и представим, что мы хотим получить значения компонентов цвета для внутреннего пикселя в таблице пикселей 3x3 – пиксель в координате (2, 2).

Если вы посмотрите на предыдущие два изображения, то увидите, что значения компонентов цвета для этого пикселя начинаются с индекса 16, и для реализации этого в коде вам необходимо выполнить два шага: первый – вычислить индекс необходимого пикселя (координату y) в начале ряда, и затем добавить к этому индексу количество значений компонентов цвета между пикселем и началом ряда (координата х). Прозвучало немного запутанно, но проявите терпение.

Первая часть формулы проста: вы уже знаете, что на один пиксель приходится четыре значения цвета, а также что ширина таблицы составляет 3 пикселя. Для вычисления индекса пикселя в ряду у (2) вы подставляете эти значения в первую часть формулы, которая при этом будет выглядеть следующим образом:

В результате вы получаете значение индекса 12, которое соответствует индексу первого пикселя второго ряда в предыдущем изображении. Пока все должно быть понятно.

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

Можете посчитать и получите 4, что в сумме с предыдущим значением дает значение индекса 16. Круто, да?

Я бы особо не переживал о полном ее понимании, просто знайте, что эта потрясающая небольшая формула существует и позволяет вам легко получить индекс значения красной компоненты цвета для любого пикселя. Для получения индекса значений остальных компонентов цвета пикселя (зеленый, синий или альфа) вы просто добавляете 1, 2 или 3 к вычисленному индексу соответственно.

Начинаем применять полученные знания

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

Код для нашего примера довольно ясный, так что давайте напишем его весь сразу:

Вы узнаете первые несколько строк из предыдущих примеров. Новый код располагается в обработчике события click для canvas, который реализуется при помощи небольшого количества кода jQuery, чтобы сообщить вам, когда произошло нажатие по «холсту».

Внутри обработчика мы хотим определить пиксель, по которому было выполнено нажатие на «холсте». Для этого нам необходимо для начала вычислить смещение в пикселях верхней левой координаты «холста» относительно верхнего левого угла окна браузера; для этого можно воспользоваться методом offset jQuery. Далее мы можем определить пиксель, по которому было выполнено нажатие на «холсте», путем вычитания значения смещения из значений координат, содержащихся в объекте для события click (pageX и pageY). Вам несомненно стоит потратить немного времени на освоение информации о событии click JavaScript для углубления своих познаний о нем. 

В следующих четырех строках происходит получение CanvasPixelArray для «холста» (getImageData), его сохранение в переменной, нахождение индекса значения красной компоненты цвета пикселя, по которому было выполнено нажатие, путем его вычисления при помощи ранее виденной вами формулы, и затем сохранение значений компонентов цвета пикселя в виде строки rgba CSS. Наконец, последний этап – установление в качестве значений компонентов цвета фона элемента body значений компонентов цвета пикселя, по которому было выполнено нажатие.

Creating a basic color picker

И после этого все готово. Протестируйте результат самостоятельно; нажмите по изображению на «холсте» и пронаблюдайте, как изменяется цвет фона веб-сайта. Если не работает, то убедитесь, что вы запустили демоверсию на сервере с доменным именем, как описано в разделе, посвященном вопросам безопасности.

Мы многое рассмотрели, и теперь вы умеете быстро и легко получать значения компонентов цвета любого пикселя на «холсте». Упоминал ли я, что вы также можете изменять значения компонентов цвета пикселей на «холсте». Нет? Ой! Тогда давайте теперь рассмотрим этот прием; с его помощью создаются очень крутые эффекты.


Добавляем к изображениям эффекты

Теперь, когда вы умеете получать значения цвета пикселей «холста», их изменение не должно составить особого труда. По сути, изменение этих значений цвета сводится к изменению значений в CanvasPixelArray и их дальнейшему прорисовыванию обратно на «холст». Давайте рассмотрим, как это осуществить.

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

Пока все должно быть понятно. Далее необходимо перебрать каждый пиксель «холста» и изменить значения компонентов его цвета. В нашем примере вы переставите значения компонентов цветов путем вычитания текущего значения компонента цвета (от 0 до 255) из 255:

Тут не происходит ничего фантастического; вы просто перемножаете номер пикселя (i) на 4 для получения индекса значения красного компонента цвета для текущего пикселя в CanvasPixelArray. За счет добавления 1 или 2 к этому числу вы можете получить и изменить значения зеленого и синего компонентов цвета соответственно.

И, наконец, все, что вам теперь осталось, так это очистить «холст» (чтобы избавиться от изначального изображения) и затем воспользоваться методом putImageData 2-мерного контекста отображения для прорисовывания сохраненного CanvasPixelArray на «холст»:

И на этом, собственно, все; перезагрузите ваш браузер и взгляните. Круто, правда ведь?

Inverting the pixels of an image

Подведение итогов

Мы рассмотрели лишь некоторые аспекты работы с пикселями, однако я надеюсь, что в этом руководстве вы почерпнули достаточно информации для получения вдохновения. Я настоятельно рекомендую вам копнуть в этом вопросе поглубже и посмотреть, что еще вы можете делать с пикселями. Почему? Потому что все техники по работе с пикселями можно также применить к видео HTML5 и изображениям. Теперь вы поняли, какие возможности открываются перед вами за счет умения манипулировать пикселями.

В следующем руководстве, последнем в этой серии, мы будем рассматривать другие аспекты Canvas. Вы узнаете, как анимировать фигуры на «холсте», после чего у вас будет база, необходимая для создания мультипликаций, анимаций и игр. Это, бесспорно, мой любимый вариант использования Canvas.

Advertisement
Advertisement
Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.