Статьи

Создание редактора изображений с помощью CamanJS: применение основных фильтров

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

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

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

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

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

Библиотека поддерживает базовые эффекты, такие как яркость, контрастность и насыщенность. Это сэкономит время и позволит нам создавать более сложные фильтры на основе этих основных.

Название этой библиотеки основано на том факте, что она используется для выполнения (ca) nvas (man) ipulation в JavaScript (JS). Прежде чем вы сможете начать использовать различные функции библиотеки, вам нужно будет включить ее в свой проект. Это можно сделать, либо загрузив библиотеку и разместив ее самостоятельно, либо связавшись напрямую с CDN .

Есть два способа использования библиотеки. Первый вариант — использовать атрибут data-caman с элементами изображения. Этот атрибут может принимать комбинацию различных фильтров CamanJS в качестве значения. Например, если вы хотите увеличить яркость изображения на 20, а контрастность на 10, вы можете использовать следующий HTML-код:

1
2
<img src=»path/to/image.jpg»
    data-caman=»brightness(20) contrast(10)»>

Точно так же вы можете применять другие фильтры, такие как насыщенность, экспозиция, шум, сепия и т. Д. Помимо основных фильтров, CamanJS также предоставляет вам доступ к некоторым более сложным фильтрам из коробки. Эти фильтры могут быть применены к изображению аналогичным образом. Чтобы применить фильтр sunrise , вы можете просто использовать следующий HTML:

1
2
<img src=»path/to/image.jpg»
    data-caman=»sunrise()»>

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

1
2
3
4
5
Caman(‘#canvas-id’, function () {
    this.brightness(20);
    this.contrast(10);
    this.render();
});

В этой серии мы будем использовать JavaScript-способ для создания нашего редактора изображений.

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

Давайте начнем с HTML-кода, необходимого для добавления холста и кнопок загрузки / выгрузки:

01
02
03
04
05
06
07
08
09
10
11
<div class=»preview-wrapper»>
    <canvas id=»canvas»></canvas>
    <p class=»process-message»></p>
</div>
 
<div class=»editor-buttons»>
    <input type=»file» id=»upload-file» placeholder=»Upload a Picture» />
    <label for=»upload-file»>Upload a Picture</label>
    <button id=»download-btn»>Download Image</button>
    <br/>
</div>

Вот код для реализации основных функций загрузки изображений:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
var img = new Image();
var canvas = document.getElementById(‘canvas’);
var ctx = canvas.getContext(‘2d’);
var fileName = »;
 
$(«#upload-file»).on(«change», function(){
    var file = document.querySelector(‘#upload-file’).files[0];
    var reader = new FileReader();
    if (file) {
        fileName = file.name;
        reader.readAsDataURL(file);
    }
    reader.addEventListener(«load», function () {
        img = new Image();
        img.src = reader.result;
        img.onload = function () {
            canvas.width = img.width;
            canvas.height = img.height;
            ctx.drawImage(img, 0, 0, img.width, img.height);
            $(«#canvas»).removeAttr(«data-caman-id»);
        }
    }, false);
});

Мы начинаем с создания некоторых переменных для хранения имени файла изображения, выбранного пользователем, и контекста для нашего холста. После этого мы пишем код для получения файла изображения из файла input после его события change . Файлы, выбранные пользователем, хранятся в FileList , и мы можем получить первый файл из списка, используя .files[0] .

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

Внутри обработчика события onload для объекта FileReader мы создаем экземпляр HTMLImageElement с помощью конструктора Image() . Атрибут src изображения затем устанавливается в значение свойства result нашего FileReader .

Как только изображение успешно загрузилось, мы устанавливаем ширину и высоту нашего холста равными width и height изображения, выбранного пользователем. После этого мы рисуем изображение на холсте и удаляем атрибут data-caman-id с холста.

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

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

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

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
$(‘#download-btn’).on(‘click’, function (e) {
    var fileExtension = fileName.slice(-4);
    if (fileExtension == ‘.jpg’ || fileExtension == ‘.png’) {
        var actualName = fileName.substring(0, fileName.length — 4);
    }
    download(canvas, actualName + ‘-edited.jpg’);
});
 
function download(canvas, filename) {
    var e;
    var lnk = document.createElement(‘a’);
     
    lnk.download = filename;
    lnk.href = canvas.toDataURL(«image/jpeg», 0.8);
     
    if (document.createEvent) {
        e = document.createEvent(«MouseEvents»);
        e.initMouseEvent(«click», true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
        lnk.dispatchEvent(e);
    }
    else if (lnk.fireEvent) {
        lnk.fireEvent(«onclick»);
    }
}

Мы используем метод jQuery .on() для выполнения фрагмента кода каждый раз, когда вызывается событие click для кнопки загрузки. Этот код удаляет расширение файла из имени файла изображения, выбранного пользователем, и заменяет его суффиксом -edited.jpg . Затем это имя передается в функцию download вместе со ссылкой на холст, на котором мы рендерили и редактировали изображение.

Функция загрузки создает ссылку и устанавливает свой атрибут download в filename . Атрибут href содержит URI данных для отредактированного изображения. После установки значения этих двух атрибутов мы программно запускаем событие click для нашей вновь созданной ссылки. Этот щелчок запускает загрузку отредактированного изображения.

Как я упоминал в начале урока, CamanJS поставляется с базовыми встроенными фильтрами. Таким образом, вы можете напрямую применить яркость, контраст, сепию, насыщенность, экспозицию, шум, резкость, вибрацию и оттенок. Некоторые фильтры, такие как яркость и контрастность, могут иметь как отрицательное, так и положительное значение.

Вы можете сделать значения такими же высокими или низкими, как вы хотите, но разумным выбором будет оставить их между -100 и 100. Например, изображение становится белым, когда вы устанавливаете яркость на 100. Таким образом, любое значение выше 100 будет быть бесполезным Точно так же изображение станет полностью серым, если вы установите значение контрастности -100.

Другие фильтры, такие как сепия, шум, резкость и размытие, будут принимать только положительные значения. Имейте в виду, что фильтр оттенков покрывает полный круг с углом обзора 360 градусов, значения которого находятся в диапазоне от 0 до 100. Изображение будет выглядеть точно так же, если вы установите оттенок на 0 или 100.

Вот HTML-код для добавления кнопок для нашего редактора изображений:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
<div class=»filter-buttons»>
    <div class=»filter-group»>
        <button id=»brightness-dec»>-</button>
        <span class=»filter-name»>Brightness
        <button id=»brightness-inc»>+</button>
    </div>
    <!— More Such Buttons —>
    <div class=»filter-group»>
        <button id=»gamma-dec» class=»disabled»>-</button>
        <span class=»filter-name»>Gamma
        <button id=»gamma-inc»>+</button>
    </div>
</div>
<div class=»editor-buttons»>
    <input type=»file» id=»upload-file» placeholder=»Upload a Picture» />
    <label for=»upload-file»>Upload a Picture</label>
    <button id=»download-btn»>Download Image</button>
    <br/>
    <button id=»vintage-btn»>Vintage</button>
    <!— More Such Buttons —>
    <button id=»lomo-btn»>Lomo</button>
</div>

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

Мы будем применять соответствующие фильтры на основе кнопки, нажатой с помощью следующего JavaScript.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/* Similar Code for All Other Buttons */
 
$(‘#brightness-inc’).on(‘click’, function (e) {
    Caman(‘#canvas’, img, function () {
        this.brightness(10).render();
    });
});
 
$(‘#brightness-dec’).on(‘click’, function (e) {
    Caman(‘#canvas’, img, function () {
        this.brightness(-10).render();
    });
});
 
 
/* Similar Code for All Inbuilt Filters */
 
$(‘#nostalgia-btn’).on(‘click’, function (e) {
    Caman(‘#canvas’, img, function () {
        this.nostalgia().render();
    });
});
 
$(‘#majestic-btn’).on(‘click’, function (e) {
    Caman(‘#canvas’, img, function () {
        this.herMajesty().render();
    });
});

Для кнопок увеличения и уменьшения сила фильтра зависит от того, как масштабируется его эффект. Например, яркость и контрастность увеличиваются на 10, но значение гаммы увеличивается только на 0,1 после каждого клика.

Следующая демонстрационная программа CodePen показывает редактор изображений CamanJS, который мы создали в действии.

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

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

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