getPixel từ HTML Canvas?


111

Có thể truy vấn đối tượng HTML Canvas để lấy màu tại một vị trí cụ thể không?

Câu trả lời:


171

Có một phần về thao tác pixel trong tài liệu W3C.

Đây là một ví dụ về cách đảo ngược hình ảnh :

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);

Phần thao tác trên Pixel hiện có sẵn tại đây: w3.org/TR/2dcontext2/#pixel-manipulation
jtraulle

55

Bạn đã thử phương thức getImageData chưa?

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

2
Đây không phải là context.getImageData () và không phải canvas.getImageData ()?
Crashalot

2
@Crashalot phụ thuộc vào những gì var "canvas" chứa, nó có thể đơn giản là ngữ cảnh của canvas với tên var khó hiểu.
báo trước

1
Wow, rất thanh lịch! Tôi đã nghĩ đến việc tìm kiếm điểm trong toàn bộ bối cảnh, nhưng điều này thông minh hơn nhiều.
TheOne

5
Điều này thật thông minh, nhưng nếu bạn định gọi getPixel nhiều, thì việc lưu vào bộ nhớ cache đối tượng ImageData cho toàn bộ hình ảnh (0,0, width, height) sẽ nhanh hơn nhiều , rồi tính toán chỉ mục bằng cách sử dụng idx = (y * width + x) * 4như câu trả lời của Georg. Tuy nhiên, đừng quên làm mới đối tượng được lưu trong bộ nhớ cache mỗi khi hình ảnh thay đổi.
noio

2
Hàm tạo đó là Color()gì? Đó dường như không tồn tại bất cứ nơi nào
fregante

12

Có chắc chắn, miễn là bạn có ngữ cảnh của nó. Làm thế nào để lấy bối cảnh canvas?

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);
}



Tái bút: Nếu bạn định thay đổi dữ liệu và vẽ chúng trở lại trên canvas, bạn có thể sử dụngsubarray

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]
}

Bạn có thể thử nghiệm điều này trên http://qry.me/xyscope/ , mã cho điều này là trong nguồn, chỉ cần sao chép / dán nó vào bảng điều khiển.


2
Yay! Nhờ nó hoạt động rất tốt và nó là waay nhanh hơn gọicontext.getImageData(x, y, 1, 1);
adelriosantiago

Nó thực sự nhanh hơn. Cảm ơn!
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
Tuy nhiên, ctx nên được đặt làm thuộc tính trong GetPixel
Marcio

1
Lệnh return đẹp rgbToHex
Qwerty


6

Lưu ý rằng getImageData trả về một ảnh chụp nhanh. Hàm ý là:

  • Các thay đổi sẽ không có hiệu lực cho đến khi putImageData tiếp theo
  • Các cuộc gọi getImageData và putImageData tương đối chậm

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

Bạn có thể sử dụng 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

Oneliner pixel đọc dài tiện dụng (vẽ pixel tại đây )

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

Dòng đầu tiên là phần ban đầu nơi bạn có thể thay đổi bộ chọn canvas s='.myCanvas'. Oneliner tiện dụng này tốt cho các thuật toán thử nghiệm hoặc tạo bằng chứng về khái niệm nhưng đối với mã sản xuất thì tốt hơn nên sử dụng mã khác rõ ràng và dễ đọc hơn.


0

Nếu bạn muốn trích xuất màu cụ thể của pixel bằng cách chuyển tọa độ của pixel vào hàm, điều này sẽ hữu ích

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, ylà tọa độ bạn muốn lọc ra màu.

var color=detectColor(x,y)

Màu sắc là đối tượng, bạn sẽ nhận được giá trị rgb bởi color.r, color.g, color.b.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.