getPixel dari HTML Canvas?


111

Apakah mungkin untuk menanyakan objek Kanvas HTML untuk mendapatkan warna di lokasi tertentu?

Jawaban:


171

Ada bagian tentang manipulasi piksel dalam dokumentasi W3C.

Berikut contoh cara membalikkan gambar :

var context = document.getElementById('myCanvas').getContext('2d');

// Get the CanvasPixelArray from the given coordinates and dimensions.
var imgd = context.getImageData(x, y, width, height);
var pix = imgd.data;

// Loop over each pixel and invert the color.
for (var i = 0, n = pix.length; i < n; i += 4) {
    pix[i  ] = 255 - pix[i  ]; // red
    pix[i+1] = 255 - pix[i+1]; // green
    pix[i+2] = 255 - pix[i+2]; // blue
    // i+3 is alpha (the fourth element)
}

// Draw the ImageData at the given (x,y) coordinates.
context.putImageData(imgd, x, y);

Bagian manipulasi pixel sekarang tersedia di sini: w3.org/TR/2dcontext2/#pixel-manipulation
jtraulle

55

Sudahkah Anda mencoba metode getImageData?

var data = context.getImageData(x, y, 1, 1).data;
var rgb = [ data[0], data[1], data[2] ];

2
bukankah seharusnya ini menjadi context.getImageData () dan bukan canvas.getImageData ()?
Crashalot

2
@Crashalot bergantung pada isi var "canvas", itu bisa saja berupa konteks kanvas dengan nama var yang jelek.
tbleckert

1
Wow, sangat elegan! Saya berpikir untuk mencari poin dalam seluruh konteks, tapi ini jauh lebih pintar.
TheOne

5
Ini pintar, tetapi jika Anda akan sering memanggil getPixel, jauh lebih cepat untuk menyimpan objek ImageData untuk seluruh gambar (0,0, lebar, tinggi), dan kemudian menghitung indeks menggunakan idx = (y * width + x) * 4jawaban seperti Georg. Namun, jangan lupa menyegarkan objek yang di-cache itu setiap kali gambar berubah.
noio

2
Color()Konstruktor apa itu ? Tampaknya tidak ada di mana pun
fregante

12

Ya tentu, asalkan Anda memiliki konteksnya. Bagaimana cara mendapatkan konteks kanvas?

var imgData = context.getImageData(0,0,canvas.width,canvas.height);
// { data: [r,g,b,a,r,g,b,a,r,g,..], ... }

function getPixel(imgData, index) {
  var i = index*4, d = imgData.data;
  return [d[i],d[i+1],d[i+2],d[i+3]] // returns array [R,G,B,A]
}

// AND/OR

function getPixelXY(imgData, x, y) {
  return getPixel(imgData, y*imgData.width+x);
}



PS: Jika Anda berencana untuk mengubah data dan menggambarnya kembali di kanvas, Anda dapat menggunakansubarray

var
 a = getPixel(idt, 188411), // Array(4) [0, 251, 0, 255]
 b = idt.data.subarray(188411*4, 188411*4 + 4) // Uint8ClampedArray(4) [0, 251, 0, 255]

a[0] = 255 // does nothing
getPixel(idt, 188411), // Array(4) [0, 251, 0, 255]

b[0] = 255 // mutates the original imgData.data
getPixel(idt, 188411), // Array(4) [255, 251, 0, 255]

// or use it in the function
function getPixel(imgData, index) {
  var i = index*4, d = imgData.data;
  return imgData.data.subarray(index, index+4) // returns subarray [R,G,B,A]
}

Anda dapat bereksperimen dengan ini di http://qry.me/xyscope/ , kode untuk ini ada di sumbernya, cukup salin / tempel di konsol.


2
Yay! Terima kasih, ini bekerja dengan sangat baik dan lebih cepat daripada meneleponcontext.getImageData(x, y, 1, 1);
adelriosantiago

Memang lebih cepat. Terima kasih!
dmitru

9
function GetPixel(context, x, y)
{
    var p = context.getImageData(x, y, 1, 1).data; 
    var hex = "#" + ("000000" + rgbToHex(p[0], p[1], p[2])).slice(-6);  
    return hex;
}

function rgbToHex(r, g, b) {
    if (r > 255 || g > 255 || b > 255)
        throw "Invalid color component";
    return ((r << 16) | (g << 8) | b).toString(16);
}

4
ctx harus disetel sebagai atribut di GetPixel
Marcio

1
Pernyataan pengembalian rgbToHex yang bagus
Qwerty


6

Perhatikan bahwa getImageData mengembalikan snapshot. Implikasinya adalah:

  • Perubahan tidak akan berlaku hingga putImageData berikutnya
  • Panggilan getImageData dan putImageData relatif lambat

4
// Get pixel data 
var imageData = context.getImageData(x, y, width, height);
//color at (x,y) position
var color = [];
color['red'] = imageData.data[((y*(imageData.width*4)) + (x*4)) + 0];
color['green'] = imageData.data[((y*(imageData.width*4)) + (x*4)) + 1];
color['blue'] = imageData.data[((y*(imageData.width*4)) + (x*4)) + 2];
color['alpha'] = imageData.data[((y*(imageData.width*4)) + (x*4)) + 3];

0

Anda bisa menggunakan i << 2.

const data = context.getImageData(x, y, width, height).data;
const pixels = [];

for (let i = 0, dx = 0; dx < data.length; i++, dx = i << 2) {
    pixels.push({
        r: data[dx  ],
        g: data[dx+1],
        b: data[dx+2],
        a: data[dx+3]
    });
}

0

Satu baris piksel baca panjang yang praktis (gambar piksel di sini )

let rp=((s='.myCanvas',c=document.querySelector(s),ctx=c.getContext('2d')) => (x,y)=>Object.values(ctx.getImageData(x, y, 1, 1).data))();

rp(10,20) // rp(x,y) returns: [r,g,b,a] with values 0-255

Baris pertama adalah bagian awal tempat Anda dapat mengubah pemilih kanvas s='.myCanvas'. Oneliner yang praktis ini baik untuk menguji algoritma atau membuat bukti konsep tetapi untuk kode produksi lebih baik menggunakan kode lain yang lebih jelas dan dapat dibaca.


0

Jika Anda ingin mengekstrak warna tertentu dari piksel dengan meneruskan koordinat piksel ke dalam fungsi, ini akan berguna

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
function detectColor(x,y){
  data=ctx.getImageData(x,y,1,1).data;
  col={
    r:data[0],
    g:data[1],
    b:data[2]
  };
  return col;
}

x, yadalah koordinat yang ingin Anda filter warnanya.

var color=detectColor(x,y)

Warnanya objek, Anda akan mendapatkan nilai rgb oleh color.r, color.g, color.b.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.