Làm thế nào để lấy màu tọa độ x, y của pixel từ một hình ảnh?


124

Có cách nào để kiểm tra xem một điểm (x, y) đã chọn của ảnh PNG có trong suốt không?


1
Bằng cách nào đó, hình ảnh có thể được tải trên một phần tử Canvas không?

Nếu không có cách nào khác, sau đó
Danny Fox

Câu trả lời:


199

Dựa trên câu trả lời của Jeff, bước đầu tiên của bạn sẽ là tạo một biểu diễn canvas cho PNG của bạn. Sau đây tạo một canvas ngoài màn hình có cùng chiều rộng và chiều cao với hình ảnh của bạn và có hình ảnh được vẽ trên đó.

var img = document.getElementById('my-image');
var canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.height;
canvas.getContext('2d').drawImage(img, 0, 0, img.width, img.height);

Sau đó, khi người dùng nhấp vào, hãy sử dụng event.offsetXevent.offsetYđể có được vị trí. Sau đó, điều này có thể được sử dụng để lấy pixel:

var pixelData = canvas.getContext('2d').getImageData(event.offsetX, event.offsetY, 1, 1).data;

Bởi vì bạn chỉ lấy một pixel, pixelData là một mảng bốn mục nhập chứa các giá trị R, G, B và A của pixel. Đối với alpha, bất kỳ thứ gì nhỏ hơn 255 đại diện cho một số mức độ minh bạch với 0 là hoàn toàn trong suốt.

Đây là một ví dụ về jsFiddle: http://jsfiddle.net/thirtydot/9SEMf/869/ Tôi đã sử dụng jQuery để thuận tiện trong tất cả những điều này, nhưng nó không bắt buộc.

Lưu ý: getImageData thuộc chính sách cùng nguồn gốc của trình duyệt để ngăn rò rỉ dữ liệu, nghĩa là kỹ thuật này sẽ không thành công nếu bạn làm bẩn canvas bằng một hình ảnh từ miền khác hoặc (tôi tin rằng, nhưng một số trình duyệt có thể đã giải quyết được điều này) SVG từ bất kỳ miền nào. Điều này bảo vệ khỏi các trường hợp một trang web cung cấp nội dung hình ảnh tùy chỉnh cho người dùng đã đăng nhập và kẻ tấn công muốn đọc hình ảnh để lấy thông tin. Bạn có thể giải quyết vấn đề bằng cách cung cấp hình ảnh từ cùng một máy chủ hoặc thực hiện chia sẻ tài nguyên nguồn gốc chéo .


3
bùng nổ - công việc tuyệt vời. Tôi biết tôi nên làm một trò chơi như thế này nhưng quá béo và lười biếng. bạn giết nó ở đây
Jeff Escalante

Để điều này được chính xác, bạn cần thiết lập không gian tọa độ của canvas tức là thiết lập chiều rộng và chiều cao phù hợp với kích thước hình ảnh. Chiều rộng và chiều cao CSS chỉ phục vụ để kéo căng canvas cuối cùng cho bố cục, điều này không hữu ích khi nó là một phần tử không hiển thị. Hãy thử một cái gì đó như $ ('<canvas width =' + img.width + 'height =' + img.height + '/>') ;. Hay điều này bằng cách nào đó không áp dụng với các bức tranh ngoài màn hình?
fabspro 12/12/12

@fabspro: Đó là một điểm tuyệt vời. Vì việc vẽ và đọc dữ liệu hình ảnh được thực hiện thông qua ngữ cảnh, các giá trị chiều rộng và chiều cao là vô nghĩa. Chúng không có bất kỳ hiệu ứng xấu nào vì canvas không phải bối cảnh bị biến dạng và lý do tôi không thấy hiệu ứng này trên bản trình diễn của mình đơn giản là vì hình ảnh nhỏ hơn chiều rộng / chiều cao ban đầu của bối cảnh. Tôi sẽ cập nhật tương ứng, mặc dù việc truy cập .width.heighttrên chính canvas sẽ an toàn hơn là thông qua nối.
Brian Nickel

4
Khắc phục sự cố cho Firefox jsfiddle.net/9SEMf/622 bằng cách sử dụng stackoverflow.com/questions/11334452/event-offsetx-in-firefox
benoît

6
Bạn không thể sử dụng điều này cho hình ảnh từ xa. "Không thể lấy dữ liệu hình ảnh từ canvas vì canvas đã bị làm bẩn bởi dữ liệu có nguồn gốc chéo. SecurityError: Đã cố gắng phá vỡ chính sách bảo mật của tác nhân người dùng."
Karl Glaser

18

Canvas sẽ là một cách tuyệt vời để làm điều này, như @pst đã nói ở trên. Hãy xem câu trả lời này để biết một ví dụ điển hình:

getPixel từ HTML Canvas?

Một số mã cũng sẽ phục vụ bạn cụ thể:

var imgd = context.getImageData(x, y, width, height);
var pix = imgd.data;

for (var i = 0, n = pix.length; i < n; i += 4) {
  console.log pix[i+3]
}

Điều này sẽ diễn ra theo từng hàng, vì vậy bạn cần chuyển đổi thành x, y và chuyển đổi vòng lặp for thành kiểm tra trực tiếp hoặc chạy điều kiện bên trong.

Đọc lại câu hỏi của bạn, có vẻ như bạn muốn có được điểm mà người đó nhấp vào. Điều này có thể được thực hiện khá dễ dàng với sự kiện nhấp chuột của jquery. Chỉ cần chạy mã trên bên trong trình xử lý nhấp chuột như sau:

$('el').click(function(e){
   console.log(e.clientX, e.clientY)
}

Chúng sẽ lấy các giá trị x và y của bạn.


Đây không phải là những gì người bình luận hỏi (dường như) và hoàn toàn không trả lời câu hỏi. Câu trả lời được chấp nhận không hoạt động. Tôi khuyên bạn nên xóa câu trả lời này ...
Agamemnus

5

Hai câu trả lời trước giải thích cách sử dụng Canvas và ImageData. Tôi muốn đề xuất một câu trả lời với ví dụ có thể chạy được và sử dụng khung xử lý hình ảnh, vì vậy bạn không cần phải xử lý dữ liệu pixel theo cách thủ công.

MarvinJ cung cấp phương thức image.getAlphaComponent (x, y) chỉ trả về giá trị trong suốt cho pixel theo tọa độ x, y. Nếu giá trị này là 0, pixel hoàn toàn trong suốt, các giá trị từ 1 đến 254 là mức trong suốt, cuối cùng 255 là không trong suốt.

Để minh họa, tôi đã sử dụng hình ảnh bên dưới (300x300) với nền trong suốt và hai pixel ở tọa độ (0,0)(150,150) .

nhập mô tả hình ảnh ở đây

Đầu ra bảng điều khiển:

(0,0): TRANSPARENT
(150,150): NOT_TRANSPARENT

image = new MarvinImage();
image.load("https://i.imgur.com/eLZVbQG.png", imageLoaded);

function imageLoaded(){
  console.log("(0,0): "+(image.getAlphaComponent(0,0) > 0 ? "NOT_TRANSPARENT" : "TRANSPARENT"));
  console.log("(150,150): "+(image.getAlphaComponent(150,150) > 0 ? "NOT_TRANSPARENT" : "TRANSPARENT"));
}
<script src="https://www.marvinj.org/releases/marvinj-0.7.js"></script>


2

Với : 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) {
    if (data[dx+3] <= 8)
        console.log("transparent x= " + i);
}
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.