Какие элементы создают цвет в пикселе

Обновлено: 07.07.2024

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

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

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

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

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

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

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

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

One of my photos from Flickr
One of my photos from 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
Placing an image
Placing an image

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

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

Placing and resizing an image
Placing and resizing an image
Placing and resizing an image

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

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

Placing only part of an image
Placing only part of an image
Placing only part of an image

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

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

Taking drawImage to the extreme
Taking drawImage to the extreme
Taking drawImage to the extreme

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

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

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

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

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

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

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

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

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

Index values in the CanvasPixelArray
Index values in the CanvasPixelArray
Index values in the CanvasPixelArray

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

Accessing a specific pixel from the CanvasPixelArray
Accessing a specific pixel from the CanvasPixelArray
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
Creating a basic color picker
Creating a basic color picker

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

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

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

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

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

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

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

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

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

Inverting the pixels of an image
Inverting the pixels of an image
Inverting the pixels of an image

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

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

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

Рассмотрим, как можно записать (закодировать) графическую информацию. Как известно, все документы (графика, тексты, программы и т. п.) хранятся в компьютере в виде файлов – организованных записей. Изображения хранятся в файлах специальных графических форматов, которых сейчас насчитывается более десятка. Однако здесь мы не будем их рассматривать. Вместо этого мы создадим собственный графический формат (не для действительного хранения изображений на жестком диске компьютера, а исключительно как наглядное пособие, дающее ключ к пониманию устройства настоящих графических файлов). Назовем такой идеальный файл протофайлом.

Представим себе некоторое изображение и нанесем на него прямоугольную сетку с квадратными ячейками. Ячейки сетки могут быть маленькими или большими, сейчас это не важно. Каждой ячейке сетки соответствует элемент изображения, который в ней находится. Этот квадратный элемент называется графическим элементом (picture element) или, сокращенно, пикселом (pixel). Мы создали основу для разложения изображения на множество элементов – пикселов. Теперь нам надо определить способ описания одного пиксела, чтобы затем описать все изображение как совокупность описаний отдельных пикселов.

В каждой клетке сетки, нанесенной на изображение, может находиться какая-то часть нашего изображения. Клетка может быть заполнена полностью, либо частично. Заполнение может быть однородным, либо неоднородным по цвету. Требуется решить, что же содержит клетка. Уже сейчас сами собой напрашиваются правила определения этого решения. Например, мы можем считать, что клетка целиком заполнена красным цветом, если преимущественный цвет ее окраски является красным. Однако на данном этапе рассмотрения это не столь важно. Будем считать, что эти правила как-то определены. В результате их применения мы преобразуем исходное изображение в некоторое другое. На рисунке показаны простые черные кривые на белом фоне. Здесь нет ни вариаций цвета, ни даже градаций серого. Представьте, что получится, если, например, заменить все клетки, закрашенные черным менее чем наполовину, белыми клетками, а более чем "половину – черными. Ясно, что это будет другая картинка. Мы не думаем сейчас о том, будет ли она лучше или хуже. Важно лишь то, что картинка как-то изменится. Именно это новое изображение будет тем, которое мы и сохраним в нашем протофайле.


Рис. 13. Сетка на изображении. Каждая клетка соответствует пикселу. Требуется решить, какой цвет содержит каждый пиксел

Итак, основа протофайла создана. Это – описание цветов всех пикселов (клеток) сетки, нанесенной на исходное изображение. Как описать цвет пиксела, вы уже знаете из предыдущей главы. Описание цвета пиксела является, по существу, кодом цвета в соответствии с той или иной цветовой моделью. Например, в модели RGB каждый пиксел описывается тройкой чисел, соответствующих яркостям базовых составляющих. В модели CMYK пиксел описывается четверкой чисел. В моделях Lab и HSB пиксел описывается тройкой чисел, соответствующих значениям параметров этих моделей. Указание на цветовую модель нужно также включить в протофайл. Кроме того, в протофайл необходимо записать, сколько пикселов по ширине и высоте имеет наше изображение. Сведения о цветовой модели, габаритах изображения и, может быть, еще о чем-то (например, об авторе картинки) включаются в специальный раздел файла, обычно называемый заголовком. После заголовка в файле записываются друг за другом коды цветов (или параметров цветовой модели) отдельных пикселов, слева направо и сверху вниз. Наш идеальный графический файл готов! Напомним, что рассмотренная структура файла не используется на практике в точности. Однако файлы реального формата BMP имеют очень похожую структуру. Это не случайное совпадение и даже не упрошенное описание одного из существующих форматов. Дело в том, что простая, почти самоочевидная, идея описания графики, изложенная выше, нашла свое воплощение в одном из реально существующих (и, кстати, самых древних) форматов графических файлов. Простые идеи реализуются раньше других.

Как было отмечено выше, цвет пиксела описывается несколькими числами. Эти числа еще называют каналами. В случае моделей RGB, CMYK и Lab эти каналы называют также цветовыми каналами. Числа можно представлять в различных системах счисления. В обычной практике мы используем десятичную систему, в которой для записи чисел применяются 10 цифр (0, 1, 2,…, 9). В программировании часто используется шестнадцатеричная система счисления 0, 1, 2,…, 9, А, В, С, D, Е, F). Работа компьютеров основана на двоичной системе с двумя цифрами – 0 и 1. Двоичную цифру называют битом. Бит может принимать только одно из двух возможных значений. Количество бит, отводимое на каждый пиксел для представления цветовой информации, называют цветовой глубиной (color depth) или битовой глубиной цвета (bit depth).

Цветовая глубина определяет, как много цветов может быть представлено пикселом. Например, если цветовая глубина равна 1 бит, то пиксел может представлять только один из двух возможных цветов – белый или черный. Если цветовая глубина равна 8 бит, то количество возможных цветов равно 2 8 = 256. При глубине цвета 24 бит количество цветов превышает 16 млн. Иногда под цветовой глубиной понимают максимальное количество цветов, которые можно представить. Очевидно: чем больше цветовая глубина, тем больше объем файла, содержащего описание изображения.

Изображения в системах RGB, CMYK, Lab и оттенках серого (gray scale) обычно содержат 8 бит на один цветовой канал. Поскольку в RGB и Lab три цветовых канала, глубина цвета в этих режимах равна 8x3 = 24. В CMYK четыре канала и поэтому цветовая глубина равна 8x4 = 32. В полутоновых изображениях только один канал, следовательно, его цветовая глубина равна 8. Однако Photoshop может воспринимать RGB, CMYK, Lab и изображения в оттенках серого, содержащие 16 бит на канал.

Во время использования фотошопа, вашим главным оружием будет инструмент «Карандаш» (клавиша В), который является альтернативой инструменту «Кисть». Карандаш позволяет вам разукрашивать отдельные пиксели, избегая наложения цветов.

Нам пригодятся ещё два инструмента: «Выделение» (клавиша М) и «Волшебная палочка» (клавиша W) для того, чтобы выбирать и перетаскивать, или же копировать и вставлять. Помните, что, зажав клавишу Alt или Shift во время выделения, вы можете добавить выделенные объекты или же исключить их из текущего списка выделенных. Это необходимо кстати, когда нужно выбирать неровные объекты.

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

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

Дизеринг

Сохранение цветов – вот на что создателям пиксель арт действительно нужно обратить внимание. Ещё один способ получить больше теней без использования большего количества цветов называется «дизеринг». Также как в традиционной живописи используется «штриховка» и «перекрестная штриховка», то есть вы, в прямом смысле, получаете что-то среднее из двух цветов.

Простой пример

Вот простой пример того, как, посредством дизеринга, из двух цветов можно создать четыре варианта шейдинга.

Продвинутый пример

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

Применение

Применение

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

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

II. Создание персонажа

Шаг 1

И вот теперь, когда все настроено, мы можем приступить непосредственно к рисованию персонажа.

Сделайте эскиз вашего персонажа с четким контуром, стараясь, при этом, не перегружать его мелкими деталями. На данном этапе цвет не имеет никакого значения, главное, чтобы контур был четко прорисован, и вы понимали, как будет выглядеть персонаж. Вот такой эскиз был подготовлен специально для этого урока.

Шаг 2

Шаг 2

Уменьшите масштаб эскиза до 60 пикселей в высоту, используя комбинацию клавиш Control+T, или команду Edit > Free Transform.

Размер объекта отображается на информационной панели. Обратите внимание, чтобы настройки интерполяции были такими же, как мы делали в шаге 4.

Шаг 3

Шаг 3

Приблизьте эскиз на 300-400%, чтобы было легче работать, и уменьшите прозрачность слоя. Затем создайте новый слой и обрисуйте контуры эскиза, используя Pencil Tool. Если персонаж симметричный, как в нашем случае, можно обрисовать только половину, а затем продублировать и отразить нарисованное зеркально (Edit > Transform > Flip Horizontal).

Ритм: Чтобы нарисовать сложные элементы разбивайте

Ритм: Чтобы нарисовать сложные элементы разбивайте их на части. Когда пикселы (точки) в линии образуют «ритм», например, 1-2-3, или 1-1-2-2-3-3, набросок выглядит более гладко для человеческого глаза. Но, если того требует форма, этот ритм может быть нарушен.

Шаг 4

Шаг 4

Когда контур будет готов, можно выбрать основные цвета и раскрасить большие формы. Делайте это на отдельном слое под контуром.

Шаг 5

Шаг 5

Сгладьте контур, дорисовывая тень по внутреннему краю.

Продолжайте добавлять тени. Как вы могли заметить

Шаг 6

Шаг 6

Создайте новый слой для бликов.

Выберите режим наложения Overlay из выпадающего списка на панели слоев. Нарисуйте светлым цветом над теми областями, которые хотите подсветить. Затем сгладьте блик, применив фильтр Filter > Blur > Blur.

Дорисуйте картинку, а затем скопируйте и отзеркальте готовую половинку рисунка, после чего объедините слои с половинками, чтобы получился цельный рисунок.

Шаг 7

Шаг 7

Теперь космонавту нужно добавить контрастности. С помощью настроек уровней (Image > Adjustments > Levels) сделайте его ярче, а затем отрегулируйте оттенок с помощью опции Color Balance (Image > Adjustments > Color Balance).

4.1. Элемент управления для вставки рисунка (Image)


При создании приложений нередко возникает необходимость украсить их графическим изображением. В этом случае можно воспользоваться компонентом Image (изображение) . На панели компонентов Additional компонент изображение представлен в виде , имя объекта Image. Компонент Image, помещенный на форму, получает имя ImageN, где N — номер 1, 2, 3… (пример 4.1).

Некоторые свойства компонента Image приведены в таблице (пример 4.2).

Используя cвойство Picture, можно выбрать и загрузить изображение на этапе проектирования приложения. Изображение может быть выбрано в окне редактора изображений (кнопка около свойства Picture в окне инспектора объектов). В этом случае рисунок сохраняется в файле формы и для работы приложения отдельного файла с рисунком не требуется.

Компонент поддерживает вставку рисунков в форматах JPEG, PNG, BMP. Если требуется обработка изображения (любые изменения рисунка), то рисунок должен быть сохранен в формате BMP. Для рисунков формата PNG с прозрачным фоном при загрузке сохраняется прозрачность.

Свойство Picture компонента Image обладает методами LoadFromFile и SaveToFile, которые используются для загрузки и сохранения изображения. Метод LoadFromFile может быть использован для загрузки изображения при открытии приложения. В этом случае файл с рисунком должен находиться в папке проекта (или нужно прописать полный путь к файлу).

Пример 4.3. Создать проект, в которо м на форме разместить фоновое изображение. При нажатии на кнопку поверх фонового изображения должно появиться другое изображение.

Этапы выполнения задания

  1. Поместить на форму два компонента Image и кнопку.
  2. Загрузить в компонент Image1 фоновое изображение. Задайте размеры Image1: Height = 370, Width = 550. Свойство Stretch = True.
  3. Для компонента Image2 установить значения для свойства Visible = False (изображение невидимо при запуске приложения). Размеры Height = 120, Width = 200. Свойство Stretch = True.
  4. Загрузить изображение в компонент Image2. Изображение может быть формата PNG с прозрачным фоном или формата BMP с фоном однородного цвета (в этом случае значение свойства Transparent = True).
  5. Написать обработчик события OnClick для компонента Button1.

Пример 4.1. Компонент Image (изображение) на форме:


Пример 4.2. Некоторые свойства компонента Image (изображение).

Свойство

Назначение

Используется для отображения изображений

При значении true размер компонента будет автоматически подгоняться под размер помещенной в него картинки

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

При значении true рисунок будет отцентрирован относительно компонента

Значение true показывает, что фон изображения становится прозрачным. Это можно использовать для наложения изображений друг на друга (действует только для файлов .bmp)

Значение true показывает, что при изменении размеров изображения будут сохраняться пропорции

Пример 4.3. Форма на этапе конструирования:


Обработчик события OnClick для Button1.

procedure TForm1.Button1Click(Sender: TObject);
begin
Image2.Top := 220 ;
Image2.Left := Random( 300 );
Image2.Visible := True ;
end ;

До нажатия на кнопку:


После нажатия на кнопку:


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

4.2. Построение графиков функций

Некоторые компоненты в Delphi, такие как форма, компонент Image и др., имеют свойство Canvas (канва, холст). Канва представляет собой область, на которой можно рисовать или выводить на нее растровые изображения. Система координат у канвы такая же, как и для любого компонента в Delphi — точка с координатами (0, 0) расположена в верхнем левом углу, ось ОY направлена вниз. Каждая точка имеет координаты X и Y. Координаты измеряются в пикселях. Важнейшее свойство пикселя — его цвет. Цвет пикселя канвы определяется значением свойства Pixels. Это свойство представляет собой двумерный массив, в котором хранится цвет каждого пикселя. Для задания цвета в Delphi можно воспользоваться несколькими способами (пример 4.4).

Пример 4.5. Создать проект, в котором построить график функции y = xsinx на промежутке, заданном пользователем.

Этапы выполнения задания

  1. Поместить на форму компоненты: Image, два компонента Label, два компонента Edit и компонент Button.
  2. Изменить свойства Caption у компонентов Label1, Label2 на x0 и xn соответственно.
  3. Изменить свойства Text у компонентов Edit1 и Edit2 на — 20 и 20 соответственно.
  4. Изменить свойства Caption у компонента Button1 на «Построить график».
  5. Написать обработчик события OnClick для компонента Button1, график функции по точкам.

5.1. Нарисовать оси координат в виде двух перпендикулярных линий, пересекающихся в центре компонента Image.
5.2. Ч тобы получить видимость сплошной линии, количество точек, которые образуют график функции, должно быть не менее 10000 (n = 10000 ).
5.3. Шаг изменения значения x определяется как
5.4. При построении нужно учитывать масштаб: ширина компонента Image должна соответствовать длине заданного промежутка. Тогда масштабный коэффициент можно рассчитать по формуле 5.5. Поскольку расположение осей координат на экране не совпадает с расположением осей, принятым в математике, то нужно преобразовать координаты: точке (0; 0) должна соответствовать точка в центре компонента Image. Для этого полученное значение x нужно увеличить на значение cx = Image1.Widt div2, а значение у на c y = Image 1.Height div 2 . Так как ось Y направлена вниз, а не вверх, то значение нужно изменить, поменяв знак на противоположный. На канве будет закрашиваться точка с координатами ( xekr = x · k + cx, y ekr = –y · k + c y ).
5.6. Необходимо учитывать, что при вычислении значения x и y будут вещественными, а значения координат на канве могут быть только целыми. Поэтому перед прорисовкой точки нужно преобразовать вещественные числа в целые с помощью функции trunc.

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

Пример 4.4. Способы задания цвета в Delphi:

  1. Задание цвета с помощью констант. Значения констант начинаются на буквосочетание cl. Далее может следовать имя цвета (например, clSkyBlue — небесно-синий, clRed — красный) или элементов Windows, цвет которых зависит от настроек пользователя (clBtnFace — цвет поверхности кнопки, clActivCaption — цвет строки заголовка активного окна). Список возможных значений можно посмотреть в инспекторе объектов у любого компонента, обладающего свойством Color или посмотреть в приложении.
  2. Задание цвета с помощью шестнадцатеричных чисел. Пары цифр шестнадцатеричного числа задают интенсивность синего, зеленого и красного цветов соответственно. Например, $FF0000 — синий цвет, $00FF00 — зеленый, $000000 — черный, $FFFFFF — белый.
  3. Шестнадцатеричные числа можно перевести в десятичную систему счисления и пользоваться этими значениями.
  4. Для задания цвета можно воспользоваться функцией RGB, три параметра которой задают интенсивность красного, синего и зеленого цветов соответственно. Значения параметров могут изменяться от 0 до 255.

Пример 4.5. Форма на этапе конструирования:


Обработчик события OnClick для компонента Button1.

procedure TForm1.Button1Click(Sender: TObject);
var x0, xn, x, y, h, k :real;
x_ekr, y_ekr, c_x, c_y, n, i :integer;
begin
// количество точек
n := 10000 ;
// концы промежутка
x0 := StrToFloat(Edit1.Text);
xn := StrToFloat(Edit2.Text);
// центр области построения
c _ x := Image 1. Width div 2 ;
c_y := Image1.Height div 2 ;
// масштабный коэффициент
k := Image1.Width / (xn - x0);
// шаг
h := (xn - x0) / n;
// оси
Image1.Canvas.MoveTo(0, c_y);
Image1.Canvas.LineTo(2*c_x, c_y);
Image1.Canvas.MoveTo(c_x, 0);
Image1.Canvas.LineTo(c_x, 2*c_y);
x := x0;
for i := 1 to n do
begin
y := x * sin(x);
//преобразование координат
x _ ekr := trunc ( x * k ) + c _ x ;
y_ekr := trunc(-y * k) + c_y;
// построение точки синим цветом
Image1.Canvas.Pixels[x_ekr, y_ekr] := clBlue;
//следующая точка
x := x + h;
end ;
end ;


Пример 4.6. Изменение начальных значений концов промежутка:


Константа Nil, имеет значение «ничего». Формально — это значение указателя, который не ссылается ни на какой объект.

4.3. Построение диаграмм

Основные принципы построения гистограмм и круговых диаграмм разбирались в 10-м классе (примеры 4.6 и 6.8). Используя аналогичные методы канвы диаграммы можно построить в Delphi.

Пример 4.7. Создать проект, в котором построить гистограмму по данным массива из n элементов (n = 10). Массив описать с константными данными или добавить данные в массив случайным образом.

1. Поместить на форму компоненты: изображение (Image), и два компонента Button.

2. Изменить свойства Caption у компонента Button1 на «Диаграмма с константными данными».

3. Изменить свойства Caption у компонента Button2 на «Диаграмма со случайными данными».

4. Написать обработчик события OnClick для компонента Button1, в котором диаграмма строится с помощью прямоугольников.

4.1. Найти максимальный элемент в массиве — max.
4.2. Рассчитать масштабный коэффициент: .
4.3. В цикле строить n прямоугольников одинаковой ширины. Ширина прямоугольника .

5. Обработчик для компонента Button2 будет отличаться от обработчика для компонента Button1 только способом получения элементов массива.

5.1. Массив должен быть описан в разделе
var a: array [1..10] of integer;
5.2. Элементы массива со значениями от 20 до 100 можно получать следующим образом:

randomize;
for i := 1 to n do
a[i] := random( 80 ) + 20 ;

Пример 4.7. Форма на этапе конструирования:


Обработчик события OnClick для компонента Button1:

procedure
TForm1.Button1Click(Sender: TObject);
const a: array [ 1..10 ] of integer =
( 10, 14, 22, 75, 63, 12, 37, 61, 42, 48 );
n = 10 ;
var max, x, y1, y2, h, i, cr, cg, cb : integer;
m :real;
begin
max := a[ 1 ];
for i := 2 to n do
if a[i] > max then
max := a[i];
h:= trunc(Image1.Width/( 2 *n+ 1 ));
m:= Image1.Height / max;
x:= h;
for i := 1 to n do
begin
cr := random( 256 );
cg := random( 256 );
cb := random( 256 );
Image1.Canvas.Brush.Color := RGB(cr, cg, cb);
y1 := Image1.Height;
y2 := y1 - trunc(a[i] * m);
Image1.Canvas.Rectangle(x, y1, x+h, y2);
x := x + 2 * h;
end ;
end ;


4.4. Анимация

Эффект анимации достигается за счет того, что перед взглядом пользователя происходит быстрая смена изображений. Каждый из кадров анимации остается на экране очень небольшой промежуток времени.


Для замера интервалов времени можно использовать компонент таймер. Он расположен на панели System и представлен в виде . Компонент Timer, помещенный на форму, получает имя TimerN, где N — номер 1, 2, 3… (пример 4.8).

Некоторые свойства компонента Timer приведены в таблице (пример 4.9).

Компонент имеет единственный обработчик — OnTimer, в котором описываются действия, происходящие по истечении интервала срабатывания таймера.

Пример 4.10. Создать проект, в котором самолет будет пролетать над городом.

Этапы выполнения задания

  1. Поместить на форму два компонента Image, компоненты Timer и Button.
  2. Загрузить изображение города в компонент Image1.
  3. Написать обработчик события OnCreate для формы, и описать начальное положение самолета, указав координаты верхнего левого угла Image2 за пределами формы. Загрузить в Image2 изображение из файла (файл должен быть размещен в папке . \Win32\Debug).
  4. Изменить свойства Caption у компонента Button1 на «Полетели!».
  5. Установить значение False у свойства таймера Enabled в инспекторе объектов.
  6. Установить в инспекторе объектов время срабатывания таймера равным 10.
  7. Написать обработчик события OnClick для компонента Button1, в котором запустить таймер.
  8. В инспекторе объектов установить прозрачность для компонента Image2 (Transparent = True).
  9. Написать обработчик события OnTimer, и менять в нем значение свойства Left у компонента Image2. Если самолет вылетел за границу, то вернуть его в начальное положение.

Пример 4.8. Компонент таймер на форме:


Компонент Timer не виден при работе приложения, поэтому место его размещения на форме не имеет значения.

Пример 4.9. Некоторые свойства компонента таймер.

Свойство

Назначение

Значение True обозначает, что таймер запущен

Время в миллисекундах, через которое происходит срабатывание таймера и вызов обработчика OnTimer

Пример 4.10. Форма на этапе конструирования:


Обработчик события OnCreate для формы:

procedure
TForm1.FormCreate(Sender: TObject);
begin


Image2.Picture.LoadFromFile ( 'plane.bmp' );

Обработчик события OnClick для компонента Button1:

procedure TForm1.Button1Click(Sender: TObject);
begin
Timer1.Enabled := True ;
end ;

Обработчик события OnTimer для компонента Timer1:

procedure TForm1.Timer1Timer(Sender: TObject);
begin
x := x + 1 ;
Image2.Left := x;
if Image2.Left >
Image1.Width + Image2.Width
then
x := - Image 2. Width ;
end ;


Вопросы к параграфу

1. Какой компонент используется для размещения изображений?

2. Какое свойство позволяет загрузить готовое изображение в компонент Image?

3. С помощью какого свойства можно установить прозрачный фон для изображения?

4. Что такое канва?

5. Какой метод канвы позволяет закрасить пиксель?

6. Какой компонент используется для отсчета времени?

Упражнения



1. Добавьте в проект из примера 4.4. еще одно животное (например, белку). Для размещения белки нужно добавить еще одну кнопку. Местоположение определить случайным образом в верхушке какого-либо дерева.

2. Добавьте в проект 4.5 перечисленные возможности.

2.1. Оси координат со стрелками и подписями.
2.2. Единичный отрезок на оси X.
2.3. График функции y = 0.3x 2 – 4x + 2, в той же системе координат, красным цветом.


3. Измените проект из примера 4.8 так, чтобы строилась линейчатая диаграмма (столбики расположены горизонтально).

4*. Измените проект из примера 4.8 так, чтобы значения в массив можно было вводить. Для этого числа необходимо записывать в компонент Edit, считывать строку из чисел и пробелов, выделять цифры и преобразовывать их в числовые значения.

5. Изменить проект из примера 4.10. Заменить самолет на вертолет и добавить кнопку «Стоп», при нажатии на которую вертолет остановится. *После остановки вертолета должен появиться парашют с грузом, который опустится вниз.

6*. Создайте анимацию движения Луны вокруг Земли. Для расчета координат верхнего левого угла Image2, содержащего Луну, можно воспользоваться параметрическим уравнением окружности: x = Rsin(t), y = Rcos ( t ) , где R — радиус, t — параметр, изменяющий свое значение от 0 до 2 π .

Читайте также: