Как применить фильтры и эффекты к изображению при помощи javascript и canvas?

sepia-filter-canvas

Элемент <canvas> (по-русски – холст) был добавлен в спецификацию html5 еще несколько лет назад. Поэтому он полностью поддерживается IE, начиная с 9-го. Canvas предназначен для создания и обработки различной растровой графики при помощи JavaScript. Кроме этого его можно использовать для работы с анимацииями и даже обработки видео в реальном времени.

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

js

// создаем или находим изображение
var img = document.getElementById('img');

img.onload = function() {
  // создаем или находим canvas
  var canvas = document.getElementById('canvas');
  // получаем его 2D контекст
  var context = canvas.getContext('2d');
  // помещаем изображение в контекст
  context.drawImage(img, 0, 0);
  // получаем объект, описывающий внутреннее состояние области контекста
  var imageData = context.getImageData(0, 0, 300, 300);
  // фильтруем
  imageDataFiltered = sepia(imageData);
  // кладем результат фильтрации обратно в canvas
  context.putImageData(imageDataFiltered, 0, 0);
}

img.src = 'img/girl.png';

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

js

var sepia = function (imageData) {
  // получаем одномерный массив, описывающий все пиксели изображения
  var pixels = imageData.data;
  // циклически преобразуем массив, изменяя значения красного, зеленого и синего каналов
  for (var i = 0; i < pixels.length; i += 4) {
    var r = pixels[i];
    var g = pixels[i + 1];
    var b = pixels[i + 2];
    pixels[i]     = (r * 0.393)+(g * 0.769)+(b * 0.189); // red
    pixels[i + 1] = (r * 0.349)+(g * 0.686)+(b * 0.168); // green
    pixels[i + 2] = (r * 0.272)+(g * 0.534)+(b * 0.131); // blue
  }
  return imageData;
};

Как мы уже упоминали, pixels – это одномерный массив в котором последовательно представлены значения красного, зеленого, синего канала, а так-же канала прозрачности для каждого пикселя изображения. Графически его можно представить так:

canvaspixels

Результат в демке

canvas фильтры

Готовые библиотеки и плагины:

… и еще 100500 библиотек, если немного погуглить.

Достоинства фильтрации с Canvas

  • поддерживается IE 9-ым и практически всеми мобильными браузерами.
  • множество готовых решений, библиотек, плагинов.
  • фильтры могут быть настолько сложными и нестандартными, насколько у вас хватит фантазии и насколько вы разбираетесь в цифровой обработке изображений :)

Недостатки фильтрации с Canvas

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

Tagged with: , , , ,
2 comments on “Как применить фильтры и эффекты к изображению при помощи javascript и canvas?
  1. Роман Дворнов пишет:

    Про недостатки:

    C других доменов, в общем смысле, конечно, нельзя обрабатывать ресурсы. Но для этого не всегда нужно проксирование – сервер может отдавать заголовки (CORS), которые разрешают конкретному сайту (домену) или всем использовать свои ресурсы. Тогда проблем с другим доменом не будет. Ведь мы можем хранить наши изображения в CDN и проксирование будет не эффективным. Так же конвертация в base64 и обратно – не быстрая операция. И при конвертации base64 -> image такому изображение ставится текущий домен в качестве origin (если не ошибаюсь). Это так же может помешать “смешать” два изображения с разных доменов.
    Для того, чтобы не было проблем с быстродействием, можно выносить обработку изображения в Web Worker’ы (например, http://blogs.msdn.com/b/eternalcoding/archive/2012/09/20/using-web-workers-to-improve-performance-of-image-manipulation.aspx). Если обработка не требует соседних пикселей (как серпия, например), то можно даже распараллелить обработку по нескольким worker’ам.

Оставить комментарий

Ваш email не будет опубликован. Обязательные поля отмечены *

To create code blocks or other preformatted text, indent by four spaces:

    This will be displayed in a monospaced font. The first four 
    spaces will be stripped off, but all other whitespace
    will be preserved.
    
    Markdown is turned off in code blocks:
     [This is not a link](http://example.com)

To create not a block, but an inline code span, use backticks:

Here is some inline `code`.

For more help see http://daringfireball.net/projects/markdown/syntax

*

* Copy This Password *

* Type Or Paste Password Here *

Проект создан в GanttPRO
Спасибо за лайк в FACEBOOK
Подписывайтесь на новости вконтакте
Последние статьи от html5.by