2016-09-05 8 views
2

Сегодня я ищу алгоритм, который преобразует цветное изображение в оттенках серого, а результат не долгих поисков я нашел следующую статьюПонять, как JavaScript Grayscale алгоритм работы (без использования JQuery)

3 Ways to Turn Web Images to Grayscale

Эта статья содержит следующий фрагмент кода

var imgObj = document.getElementById('js-image'); 

function gray(imgObj) { 
    var canvas = document.createElement('canvas'); 
    var canvasContext = canvas.getContext('2d'); 

    var imgW = imgObj.width; 
    var imgH = imgObj.height; 
    canvas.width = imgW; 
    canvas.height = imgH; 

    canvasContext.drawImage(imgObj, 0, 0); 
    var imgPixels = canvasContext.getImageData(0, 0, imgW, imgH); 

    for (var y = 0; y < imgPixels.height; y++) { 
     for (var x = 0; x < imgPixels.width; x++) { 
      var i = (y * 4) * imgPixels.width + x * 4; 
      var avg = (imgPixels.data[i] + imgPixels.data[i + 1] + imgPixels.data[i + 2])/3; 
      imgPixels.data[i] = avg; 
      imgPixels.data[i + 1] = avg; 
      imgPixels.data[i + 2] = avg; 
     } 
    } 
    canvasContext.putImageData(imgPixels, 0, 0, 0, 0, imgPixels.width, imgPixels.height); 
    return canvas.toDataURL(); 
} 

imgObj.src = gray(imgObj); 

Кроме того, в этой статье http://www.ajaxblender.com/howto-convert-image-to-grayscale-using-javascript.html в комментариях он был приглашен, чтобы заменить

for (var y = 0; y < imgPixels.height; y++) { 
    for (var x = 0; x < imgPixels.width; x++) { 
     var i = (y * 4) * imgPixels.width + x * 4; 
     var avg = (imgPixels.data[i] + imgPixels.data[i + 1] + imgPixels.data[i + 2])/3; 
     imgPixels.data[i] = avg; 
     imgPixels.data[i + 1] = avg; 
     imgPixels.data[i + 2] = avg; 
    } 
} 

с

for (var i = 0; i < imgPixels.data.length; i = i + 4) { 
    var avg = (imgPixels.data[i] + imgPixels.data[i + 1] + imgPixels.data[i + 2])/3; 
    imgPixels.data[i] = avg; 
    imgPixels.data[i + 1] = avg; 
    imgPixels.data[i + 2] = avg; 
} 

Demo на JSFiddle https://jsfiddle.net/n6q9a2c9/

И у меня есть некоторые проблемы с пониманием того, как работает этот алгоритм.

В этом фрагменте кода

for (var i = 0; i < imgPixels.data.length; i = i + 4) { 
    var avg = (imgPixels.data[i] + imgPixels.data[i + 1] + imgPixels.data[i + 2])/3; 
    imgPixels.data[i] = avg; 
    imgPixels.data[i + 1] = avg; 
    imgPixels.data[i + 2] = avg; 
} 

Я понимаю, что var avg = (imgPixels.data[i] + imgPixels.data[i + 1] + imgPixels.data[i + 2])/3 является формула (R + G + B)/3 ниже часть, которая сбивает с толку меня

for (var i = 0; i < imgPixels.data.length; i = i + 4) { 

Почему здесь мы увеличиваем на 4?

Буду благодарен за ответ, как работает этот алгоритм.

ответ

2

Данные холста предоставляются вам в формате RGBA (красный, зеленый, синий и прозрачный формат, называемый альфа-альфа). Каждому каналу нужен байт на пиксель, и у вас есть четыре канала, и есть четыре значения на пиксель. Так как каналы чередуются, вы увеличиваете на 4 пикселя.

Ссылки:

+0

спасибо за ваш ответ. После этого я попытался (в jsfiddle) использовать 'console.log (imgPixels)' и получить большие объемы массивов данных. И с 'console.log (imgPixels.data.length)' получите номер 666000. Как получить этот номер, если изображение было получено '500px * 333px' – Mikhail

+0

@Mikhail 500 * 333 * 4 = 666000 – Ouroborus

+1

Oh. Кажется, я понял. '500 * 333 = 166500', и поскольку для каждого пикселя он имеет 4 канала (RGBA) умножить' 166500 * 4 = 666000' – Mikhail