Конечно, нет необходимости использовать библиотеки. Это действительно просто через холсты .
img -> canvas -> magic -> canvas -> img
Что вам нужно, это:
- создать
<canvas>
- получить холст
context
- копия
img
на canvas
- получить холст
image data
(массив значений [r,g,b,a,r,g,b,a,r,g,..]
)
- do `The magic`®
- положить
image data
назад
- положить изменено
canvas
обратно на <img>
код для работы с холстом
var cvs = document.createElement('canvas'),
img = document.getElementsByTagName("img")[0]; // your image goes here
// img = $('#yourImage')[0]; // can use jquery for selection
cvs.width = img.width; cvs.height = img.height;
var ctx = cvs.getContext("2d");
ctx.drawImage(img,0,0,cvs.width,cvs.height);
var idt = ctx.getImageData(0,0,cvs.width,cvs.height);
// usage
getPixel(idt, 852); // returns array [red, green, blue, alpha]
getPixelXY(idt, 1,1); // same pixel using x,y
setPixelXY(idt, 1,1, 0,0,0,255); // a black pixel
6,7, изменить изображение ...
ctx.putImageData(idt, 0,0); // 0,0 is xy coordinates
img.src = cvs.toDataURL();
Интересно, где холст?
document.body.appendChild(cvs);
некоторые магические функции
Поскольку image data
- это массив последовательных значений r,g,b,a,r,g,..
, а один пиксель состоит из 4 значений, вам необходимо пересчитать индексы. Формула проста: data[(y*width + x)*4 + ch]
, где ch
находится между 0
и 3
для r,g,b,a
каналов.
Обратите внимание, что есть более краткое, а также более быстрое решение ниже.
function getPixel(imgData, index) {
var i = index*4, d = imgData.data;
return [d[i],d[i+1],d[i+2],d[i+3]] // [R,G,B,A]
}
function getPixelXY(imgData, x, y) {
return getPixel(imgData, y*imgData.width+x);
}
function setPixel(imgData, index, r, g, b, a) {
var i = index*4, d = imgData.data;
d[i] = r;
d[i+1] = g;
d[i+2] = b;
d[i+3] = a;
}
function setPixelXY(imgData, x, y, r, g, b, a) {
return setPixel(imgData, y*imgData.width+x, r, g, b, a);
}
обновление 2019 Uint8ClampedArray
Вы можете манипулировать данными пикселей непосредственно с помощью этого подмассива "view" .
subarray
отличается от slice
или от предыдущего примера тем, что он не создает поверхностную копию массива, а массив, который использует то же хранилище.
Подробнее на MDN: Uint8ClampedArray .
function getPixel(imgData, index) {
return imgData.data.subarray(index*4, index*4+4) // Uint8ClampedArray(4) [R,G,B,A]
}
let px = getPixelXY(idt, 0, 0)
px[0] = 255
// ctx.putImageData(idt,0,0); // makes the pixel reddish
или
function getPixel(imgData, index) {
return imgData.data.slice(index*4, index*4+4) // [R,G,B,A]
}
function setPixel(imgData, index, pixelData /*[R,G,B,A]*/) {
imgData.data.set(pixelData, index*4)
}