画像からピクセルのX、Y座標の色を取得する方法は?


回答:


198

ジェフの答えに基づいて、最初のステップは、PNGのキャンバス表現を作成することです。次の例では、画像と同じ幅と高さで、画像が描画されたオフスクリーンキャンバスを作成します。

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

その後、ユーザーがクリックしたときに、event.offsetXおよびevent.offsetYを使用して位置を取得します。次に、これを使用してピクセルを取得できます。

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

1つのピクセルしか取得していないため、pixelDataは、ピクセルのR、G、B、Aの値を含む4エントリの配列です。アルファの場合、255未満はある程度の透明度を表し、0は完全に透明になります。

:ここではjsFiddle例があるhttp://jsfiddle.net/thirtydot/9SEMf/869/ 私はこのすべての便宜上のjQueryを使用しますが、それは必要とされるものではありません。

注: getImageDataデータリークを防ぐためにブラウザーの同一生成元ポリシーに該当します。つまり、別のドメインからの画像または(一部のブラウザーはこれを解決している可能性があります)ドメインからのSVGでキャンバスをダーティにすると、この手法は失敗します。これは、サイトがログインしているユーザーにカスタム画像アセットを提供し、攻撃者がその画像を読み取って情報を取得しようとするケースから保護します。同じサーバーからイメージを提供するか、クロスオリジンリソースシェアリングを実装することにより、問題を解決できます。


3
ブーム-素晴らしい仕事。私はこのようなバイオリンを作るべきであると知っていましたが、太りすぎで怠惰でした。あなたはここでそれを殺しました
ジェフ・エスカランテ2012年

これを正しく行うには、キャンバスの座標空間を設定する必要があります。つまり、画像の寸法に一致するように幅と高さを設定します。CSSの幅と高さは、レイアウト用の最終的なキャンバスを引き伸ばすためだけに機能します。これは、表示されていない要素の場合は役に立ちません。$( '<canvas width =' + img.width + 'height =' + img.height + '/>');のようなものを試してください。または、これはどういうわけか画面外のキャンバスには適用されませんか?
fabspro

@fabspro:それは素晴らしい点です。画像データの描画と読み取りはコンテキストを介して行われるため、幅と高さの値は意味がありません。コンテキストではなくキャンバスが歪んでいるため、悪影響はありません。デモでこの効果が見られなかったのは、画像がコンテキストの初期の幅/高さよりも小さいためです。それに応じて更新しますが.width.height連結よりもキャンバス自体にアクセスする方が安全です。
ブライアンニッケル


6
これをリモートイメージに使用することはできません。「キャンバスがクロスオリジンデータによって汚染されているため、キャンバスから画像データを取得できません。SecurityError:ユーザーエージェントのセキュリティポリシーを突破しようとしました。」
Karl Glaser

18

@pstが前述したように、Canvasはこれを行うための優れた方法です。良い例については、この答えをチェックしてください:

HTML CanvasのgetPixel?

具体的にも役立ついくつかのコード:

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

これは行ごとに行われるため、それをx、yに変換し、forループを直接チェックに変換するか、内部で条件付きで実行する必要があります。

あなたの質問をもう一度読んで、あなたがその人がクリックするポイントを取得できるようにしたいようです。これは、jqueryのクリックイベントでかなり簡単に実行できます。クリックハンドラ内で上記のコードを実行するだけです。

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

それらはあなたのxとyの値をつかむはずです。


これは、コメント者が(一見)尋ねた質問ではなく、質問にまったく答えていません。受け入れられた答えは機能します。この回答を削除することをお勧めします...
Agamemnus

5

前の2つの回答は、CanvasとImageDataの使用方法を示しています。実行可能な例と画像処理フレームワークを使用して回答を提案したいので、ピクセルデータを手動で処理する必要はありません。

MarvinJが提供するメソッドimage.getAlphaComponent(x、y)は、x、y座標でピクセルの透明度の値を返すだけです。この値が0の場合、ピクセルは完全に透明であり、1〜254の値は透明度レベルであり、最後に255は不透明です。

以下の画像(300x300)を使用して、背景が透明で、座標(0,0)(150,150)に 2ピクセルを使用していることを示しています。

ここに画像の説明を入力してください

コンソール出力:

(0,0):透明
(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

と: 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);
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.