Изображения всегда был самый тяжелый компонент веб-сайтов.Даже если высокоскоростного доступа в Интернет становится дешевле и более доступны, веб-сайты получит тяжелые быстрее.Если вы действительно заботитесь о своих посетителях, то потратить некоторое время на выбор между хорошим качеством изображения, которые больше по размеру и худшего качества изображения, которые скачивают быстрее.И имейте в виду, что современные браузеры имеют достаточно сил, чтобы улучшать изображения прямо на computer.В этой статье я покажу одну из возможных solution.
Обратимся к изображению, которое я наткнулся недавно в моей работе.Как вы можете видеть, этот образ стадии шторы и имеет некоторые (преднамеренное) света шум:
Оптимизация изображения, как это было бы реальной боли, потому что он содержит много красного (которая вызывает больше артефакты в JPEG) и шума (который создает ужасную артефакты JPEG и это плохо для упаковки PNG).Лучше оптимизации я мог бы получить для этого изображения было 330 KB JPEG, который является довольно много для одного изображения.Итак, я решил сделать некоторые эксперименты с улучшения изображения прямо в профиль browser.
Если вы внимательно посмотрите на эту картинку, вы увидите, что он состоит из двух слоев: шум и стадии шторы.Если убрать шум, то изображение сжимается до 70 KB в JPEG, который действительно хорош.Таким образом, нашей целью становится проходят бесшумные изображения для пользователя, а затем добавить шум на изображение прямо в веб-browser.Это позволит значительно сократить время загрузки и делать веб-страницы выполнить better.
В Photoshop, создавая монохроматический шум очень легко: просто зайдите на Filter
→ Noise
→ Add Noise
.Но в исходном изображении, шум на самом деле темнеет некоторых пикселей (т.е. нет белых точек).Это приносит новые проблемы:. применять шума слой с “Multiply” режим смешивания на сцене image
HTML5 Canvas
Все современные веб-браузеры поддерживают холсте element.В то время как ранние реализации холст предлагается только рисование API, современных реализаций позволяют авторам анализировать и обрабатывать каждый пиксель изображения.Это может быть сделано с ImageData интерфейсе, который представляет собой данные изображения, ширина, высота и массив pixels.
Массив пикселей холсте это обычный массив, содержащий RGBa каждого пикселя обработки данных.Вот то, что массив данных выглядит следующим образом:
pixelData = [pixel1_red, pixel1_green, pixel1_blue, pixel1_alpha, pixel2_red, pixel2_green, pixel2_blue, pixel2_alpha, …];
Таким образом, массив данных изображения содержит total_pixels×4
элементов.Например,200× 100 изображение будет содержать 200× 100× 4 = 80,000 элементов в этой array.
Для анализа и управления отдельными пикселями холст, мы должны получить изображение из него данные, а затем изменить массив пикселей, а затем поместить данные обратно в холст:
// Coordinates of image pixel that we will modify var x = 10, y = 20; // Create a new canvas var canvas = document.createElement('canvas'); canvas.width = canvas.height = 100; document.body.appendChild(canvas); // Get drawing context var ctx = canvas.getContext('2d'); // Get image data var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); // Calculate offset for pixel var offset = (x - 1 + (y - 1) * canvas.width) * 4; // Set pixel color to opaque orange imageData.data[offset] = 255; // red channel imageData.data[offset + 1] = 127; // green channel imageData.data[offset + 2] = 0; // blue channel imageData.data[offset + 3] = 255; // alpha channel // Put image data back into canvas ctx.putImageData(imageData, 0, 0);
Генерирующая Noise
Как только мы знаем, как управлять отдельными пикселями холст, мы можем легко создавать шум слой.Простая функция, которая генерирует монохроматическое шум может выглядеть следующим образом:
function addNoise(canvas) { var ctx = canvas.getContext('2d'); // Get canvas pixels var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); var pixels = imageData.data; for (var i = 0, il = pixels.length; i < il; i += 4) { var color = Math.round(Math.random() * 255); // Because the noise is monochromatic, we should put the same value in the R, G and B channels pixels[i] = pixels[i + 1] = pixels[i + 2] = color; // Make sure pixels are opaque pixels[i + 3] = 255; } // Put pixels back into canvas ctx.putImageData(imageData, 0, 0); } // Set up canvas var canvas = document.createElement('canvas'); canvas.width = canvas.height = 200; document.body.appendChild(canvas); addNoise(canvas);
Результат может выглядеть следующим образом:
Довольно хорошо для начала.Но мы не можем просто создать шум слой и поместите его над сценой изображения.Напротив, мы должны смешайте его в “Multiply” mode.
Смесь Modes
Любой, кто работал с Adobe Photoshop или любой другой продвинутый редактор изображений знает, что режимы смешивания являются:
Некоторые люди считают режимов изображения смесь как своего рода ракетостроение, но в большинстве случаев алгоритмы за ними довольно просто.Например, вот что алгоритм смешивания Multiply выглядит следующим образом:
(colorA * colorB) / 255
То есть, мы должны умножить два цвета (стоимость каждого канала) и разделите его на 255.
Давайте изменим из фрагмента кода: загрузить изображение, создавать шум и применять его с помощью “Multiply” Blend Mode:
// Load image. Waiting for onload event is important var img = new Image; img.onload = function() { addNoise(img); }; img.src = "stage-bg.jpg"; function addNoise(img) { var canvas = document.createElement('canvas'); canvas.width = img.width; canvas.height = img.height; var ctx = canvas.getContext('2d'); // Draw image on canvas to get its pixel data ctx.drawImage(img, 0, 0); // Get image pixels var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); var pixels = imageData.data; for (var i = 0, il = pixels.length; i < il; i += 4) { // generate "noise" pixel var color = Math.random() * 255; // Apply noise pixel with Multiply blending mode for each color channel pixels[i] = pixels[i] * color / 255; pixels[i + 1] = pixels[i + 1] * color / 255; pixels[i + 2] = pixels[i + 2] * color / 255; } ctx.putImageData(imageData, 0, 0); document.body.appendChild(canvas); }
Результат будет выглядеть так:
Выглядит хорошо, но шум очень грубый.Мы должны применить прозрачность к it.
Alpha Compositing
Процесс объединения двух цветов с прозрачностью называется “. Альфа композиции« В простейшем случае композиции, алгоритм будет выглядеть следующим образом:
colorA * alpha + colorB * (1 - alpha)
Здесь alpha
является композиция коэффициент (прозрачности) от 0 до 1.Выбор, какой цвет будет фоном (colorB
) и который будет наложение (colorA
) имеет важное значение.В этом случае фон будет занавески изображение, и звук будет overlay.
Давайте добавим еще один аргумент в пользу addNoise()
функция, которая будет контролировать альфа-смешения и изменить основные функции соблюдать прозрачность в то время как смешивание изображений:
var img = new Image; img.onload = function() { addNoise(img, 0.2); // pass 'alpha' argument }; img.src = "stage-bg.jpg"; function addNoise(img, alpha) { // new 'alpha' argument var canvas = document.createElement('canvas'); canvas.width = img.width; canvas.height = img.height; var ctx = canvas.getContext('2d'); ctx.drawImage(img, 0, 0); var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); var pixels = imageData.data, r, g, b; for (var i = 0, il = pixels.length; i < il; i += 4) { // generate "noise" pixel var color = Math.random() * 255; // Calculate the target color in Multiply blending mode without alpha composition r = pixels[i] * color / 255; g = pixels[i + 1] * color / 255; b = pixels[i + 2] * color / 255; // alpha compositing pixels[i] = r * alpha + pixels[i] * (1 - alpha); pixels[i + 1] = g * alpha + pixels[i + 1] * (1 - alpha); pixels[i + 2] = b * alpha + pixels[i + 2] * (1 - alpha); } ctx.putImageData(imageData, 0, 0); document.body.appendChild(canvas); }
В результате именно то, что мы хотим: шум слой, нанесенный на фоновое изображение в режим смешивания Multiply с прозрачностью 20%:
Optimization
В то время как полученное изображение выглядит идеально, выполнение этого сценария является довольно бедным.На моем компьютере, она занимает около 300 миллисекунд (мс).На компьютере среднестатистического пользователя, это может занять еще больше времени.Таким образом, мы должны оптимизировать этот сценарий.Половина код использует браузер API вызовов, например, для создания холста, получение данных изображения и отправка его обратно, поэтому мы не можем сделать счто.Другая половина основного цикла для применения шум на сцене образ, и он может быть совершенно optimized.
Наш тест размер изображения 1293× 897, что прив …
Если вы хотите прочитать полностью статью, посетите сайт наших спонсоров