Bagaimana cara mendapatkan warna koordinat x, y piksel dari sebuah gambar?

124

Apakah ada cara untuk memeriksa apakah titik (x, y) yang dipilih dari gambar PNG transparan?

Danny Fox
sumber
1
Bisakah gambar dimuat pada elemen Canvas?
Jika tidak ada cara lain, maka
Danny Fox

Jawaban:

199

Berdasarkan jawaban Jeff, langkah pertama Anda adalah membuat representasi kanvas PNG Anda. Berikut ini akan membuat kanvas di luar layar dengan lebar dan tinggi yang sama dengan gambar Anda dan memiliki gambar yang digambar di atasnya.

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

Setelah itu, saat pengguna mengklik, gunakan event.offsetXdan event.offsetYuntuk mendapatkan posisi. Ini kemudian dapat digunakan untuk mendapatkan piksel:

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

Karena Anda hanya mengambil satu piksel, pikselData adalah larik empat entri yang berisi nilai R, G, B, dan A. piksel. Untuk alfa, apa pun yang kurang dari 255 mewakili beberapa tingkat transparansi dengan 0 yang sepenuhnya transparan.

Berikut adalah contoh jsFiddle: http://jsfiddle.net/thirtydot/9SEMf/869/ Saya menggunakan jQuery untuk kenyamanan dalam semua ini, tetapi sama sekali tidak diperlukan.

Catatan: getImageData termasuk dalam kebijakan browser asal yang sama untuk mencegah kebocoran data, yang berarti teknik ini akan gagal jika Anda mengotori kanvas dengan gambar dari domain lain atau (saya yakin, tetapi beberapa browser mungkin telah menyelesaikannya) SVG dari domain mana pun. Ini melindungi dari kasus ketika situs menyajikan aset gambar khusus untuk pengguna yang masuk dan penyerang ingin membaca gambar untuk mendapatkan informasi. Anda dapat mengatasi masalah ini dengan menyajikan gambar dari server yang sama atau menerapkan berbagi sumber daya lintas sumber .

Brian Nickel
sumber
3
booming - pekerjaan luar biasa. Saya tahu saya seharusnya membuat biola seperti ini tetapi terlalu gemuk dan malas. Anda membunuhnya di sini
Jeff Escalante
Agar ini benar, Anda perlu mengatur ruang koordinat kanvas yaitu mengatur lebar dan tinggi agar sesuai dengan dimensi gambar. Lebar dan tinggi CSS hanya berfungsi untuk meregangkan kanvas akhir untuk tata letak, yang tidak membantu jika itu adalah elemen yang tidak ditampilkan. Coba sesuatu seperti $ ('<canvas width =' + img.width + 'height =' + img.height + '/>') ;. Atau apakah ini entah bagaimana tidak berlaku dengan kanvas di luar layar?
fabspro
@fabspro: Itu poin yang sangat bagus. Karena menggambar dan membaca data gambar dilakukan melalui konteks, nilai lebar dan tinggi tidak ada artinya. Mereka tidak memiliki efek buruk karena kanvas bukan konteks yang berkerut dan alasan saya tidak melihat efek ini pada demo saya hanya karena gambar lebih kecil dari lebar / tinggi awal konteks. Saya akan memperbarui sesuai, meskipun lebih aman untuk mengakses .widthdan .heightdi kanvas itu sendiri daripada melalui penggabungan.
Brian Nickel
6
Anda tidak dapat menggunakan ini untuk gambar jarak jauh. "Tidak dapat memperoleh data gambar dari kanvas karena kanvas telah tercemar oleh data lintas sumber. SecurityError: Upaya telah dilakukan untuk menerobos kebijakan keamanan agen pengguna."
Karl Glaser
18

Kanvas akan menjadi cara yang bagus untuk melakukan ini, seperti yang dikatakan @pst di atas. Lihat jawaban ini untuk contoh yang bagus:

getPixel dari HTML Canvas?

Beberapa kode yang akan melayani Anda secara khusus juga:

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

Ini akan berjalan baris demi baris, jadi Anda harus mengubahnya menjadi x, y dan mengubah perulangan for menjadi pemeriksaan langsung atau menjalankan bagian dalam bersyarat.

Membaca pertanyaan Anda lagi, sepertinya Anda ingin mendapatkan poin yang diklik orang tersebut. Ini dapat dilakukan dengan mudah dengan event klik jquery. Jalankan saja kode di atas di dalam handler klik seperti:

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

Itu harus mengambil nilai x dan y Anda.

Jeff Escalante
sumber
Ini bukanlah yang ditanyakan oleh pemberi komentar (tampaknya), dan tidak menjawab pertanyaan tersebut sama sekali. Jawaban yang diterima berhasil. Saya sarankan menghapus jawaban ini ...
Agamemnus
5

Dua jawaban sebelumnya menunjukkan cara menggunakan Canvas dan ImageData. Saya ingin mengajukan jawaban dengan contoh runnable dan menggunakan kerangka kerja pemrosesan gambar, jadi Anda tidak perlu menangani data piksel secara manual.

MarvinJ menyediakan metode image.getAlphaComponent (x, y) yang hanya mengembalikan nilai transparansi piksel dalam koordinat x, y. Jika nilai ini 0, piksel benar-benar transparan, nilai antara 1 dan 254 adalah tingkat transparansi, akhirnya 255 buram.

Untuk mendemonstrasikan saya telah menggunakan gambar di bawah (300x300) dengan latar belakang transparan dan dua piksel pada koordinat (0,0) dan (150.150) .

masukkan deskripsi gambar di sini

Keluaran konsol:

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

Gabriel Ambrósio Archanjo
sumber
2

Dengan: 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);
}
A-312
sumber