Advertisement
  1. Web Design
  2. Web Development

Canvas dari awal: manipulasi Pixel

Scroll to top
Read Time: 11 min
This post is part of a series called Canvas From Scratch.
Canvas From Scratch: Transformations and Gradients

() translation by (you can also view the original English article)

Dalam artikel terakhir, Anda belajar semua tentang transformasi, bayangan, dan gradien. Hari ini, aku akan menunjukkan kepada Anda bagaimana untuk memanipulasi piksel di canvas; hanya mengakses nilai-nilai warna, untuk mengedit gambar dalam kanvas seperti editor foto.

Ini adalah yang mudah dan salah satu fitur yang paling powerful yang dibangun ke dalam canvas langsung, dan setelah Anda belajar ini, saya menjamin bahwa Anda akan memiliki berbagai macam ide-ide menarik.


Menyiapkan

Anda akan menggunakan template HTML yang sama dari artikel sebelumnya, sehingga membuka editor favorit Anda dan Salin kode berikut:

1
<!DOCTYPE html>
2
3
<html>
4
    <head>
5
        <title>Canvas from scratch</title>
6
        <meta charset="utf-8">
7
8
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
9
10
        <script>
11
            $(document).ready(function() {
12
                var canvas = document.getElementById("myCanvas");
13
                var ctx = canvas.getContext("2d");
14
            });
15
        </script>
16
    </head>
17
18
    <body>
19
        <canvas id="myCanvas" width="500" height="500">
20
            <!-- Insert fallback content here -->
21
        </canvas>
22
    </body>
23
</html>

Ini adalah tidak lebih dari halaman HTML dasar dengan canvas elemen dan beberapa JavaScript yang berjalan setelah DOM telah dimuat. Tidak ada yang gila.


Menempatkan gambar di Canvas

Anda dapat memanipulasi piksel dengan apa pun yang diambil ke canvas, tapi demi tutorial ini, Anda akan menggunakan gambar. Ini adalah sebagian karena hal itu penting untuk menunjukkan Anda bagaimana untuk memuat gambar keckanvas, tetapi juga karena kemampuan untuk melakukan manipulasi gambar (misalnya. mengedit foto) adalah titik plus besar teknologi ini.

Sebelum saya menunjukkan Anda bagaimana untuk mengakses nilai-nilai piksel, mari kita menempatkan gambar ke canvas. Merasa bebas untuk menggunakan gambar apapun yang Anda inginkan, tetapi untuk contoh ini, saya akan menggunakan salah satu foto saya sendiri dari Flickr.

One of my photos from FlickrOne of my photos from FlickrOne of my photos from Flickr

Anda memiliki izin untuk menggunakan foto ini jika Anda ingin, yang Anda dapat men-download dalam berbagai ukuran.

Memuat gambar ke dalam canvas memerlukan dua langkah. Yang pertama adalah untuk memuat gambar ke dalam elemen HTML image, yang dapat dilakukan menggunakan HTML atau dengan membuat sebuah elemen DOM yang baru secara langsung dalam JavaScript. Dalam contoh ini, Anda akan membuat sebuah elemen DOM yang baru--ini sangat sederhana:

1
var image = new Image();
2
image.src = "sample.jpg";
3
$(image).load(function() {
4
5
});

Semua yang Anda lakukan di sini adalah menciptakan sebuah elemen DOM Image baru dan menetapkan ke variabel. Anda kemudian gunakan variabel untuk memuat gambar Anda dengan menetapkan src atribut dari gambar ke path yang benar. Ini penting dicatat bahwa Anda dapat memuat gambar terpencil yang menggunakan teknik ini, tetapi hal ini menimbulkan beberapa masalah bagi kita lebih lanjut bawah garis sehingga kita akan tetap dengan gambar yang disimpan secara lokal untuk sekarang. Langkah terakhir adalah untuk mendengarkan event load yang akan dijalankan begitu gambar selesai diload dan tersedia untuk digunakan.

Setelah gambar telah dimuat, Anda dapat kemudian menempatkannya di canvas dalam satu langkah mudah. Semua yang perlu Anda lakukan adalah memasukan variable image yang baru Anda buat ke sebuah panggilan ke drawImage metode konteks rendering 2d. Tempatkan di dalam event load image, seperti:

1
$(image).load(function() {
2
    ctx.drawImage(image, 0, 0);
3
});

Dalam hal ini, metode drawImage mengambil tiga argumen; elemen gambar, serta x dan y koordinat nilai-nilai untuk menempatkan gambar di canvas. Ini akan menarik gambar pada ukuran penuh (500px untuk gambar ini) dan di posisi tertentu:

Placing an imagePlacing an imagePlacing an image

Namun, drawImage dapat benar-benar mengambil lagi dua argumen yang mendefinisikan lebar dan tinggi Menggambar Gambar, seperti:

1
ctx.drawImage(image, 0, 0, 250, 166);

Ini akan menggambar gambar di setengah ukuran aslinya (250px untuk gambar ini):

Placing and resizing an imagePlacing and resizing an imagePlacing and resizing an image

Anda bahkan dapat mengambil hal-hal satu langkah lebih lanjut dan penggunaan penuh sembilan argumen untuk drawImage menggambar hanya sebagian kecil dari gambar asli, seperti:

1
ctx.drawImage(image, 0, 0, 200, 200, 0, 0, 500, 500);

Ini akan mengambil 200px persegi dari kiri atas gambar dan menggambar di canvas di 500px persegi:

Placing only part of an imagePlacing only part of an imagePlacing only part of an image

Dalam pseudo kode, argumen drawImage penuh sembilan dapat digambarkan seperti begitu (s berarti sumber dan d berarti tujuan):

1
ctx.drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh);

Dan hasilnya divisualisasikan dalam ilustrasi berikut:

Taking drawImage to the extremeTaking drawImage to the extremeTaking drawImage to the extreme

Sederhana, benar? Di semua kejujuran, tidak ada di canvas yang yang rumit sekali Anda memecahnya dan melihat potongan-potongan individual.


Mengakses nilai-nilai piksel

Sekarang bahwa Anda memiliki gambar di canvas saatnya untuk mengakses piksel sehingga Anda dapat memanipulasi mereka. Namun, mari kita lupakan memanipulasi mereka untuk sekarang dan berkonsentrasi semata-mata pada mengakses mereka sebagai konsep mengambil sedikit waktu untuk mendapatkan kepala Anda di sekitar.

Masalah keamanan

Jika Anda ingin mengakses pixel menggunakan canvas Anda perlu menyadari keterbatasan keamanan yang terlibat. Keterbatasan ini hanya memungkinkan Anda untuk mengakses data dari gambar yang dimuat pada domain yang sama seperti JavaScript. Hal ini mencegah Anda dari mengakses gambar dari remote server dan kemudian menganalisis piksel yang, meskipun ada cara untuk berkeliling, semacam. Sayangnya tidak semua browser mengobati JavaScript dan gambar berjalan secara lokal dari sistem file (yaitu, tanpa nama domain) sebagai di bawah domain yang sama, sehingga Anda mungkin menerima error keamanan. Untuk melakukannya Anda perlu baik menjalankan sisa tutorial ini pada locla development environment (seperti MAMP, WAMP, atau XAMPP) atau remote Web server dan mengakses berkas menggunakan nama domain (seperti example.com).

Dengan itu keluar dari jalan, mari bongkat pada dan mendapatkan kita beberapa piksel!

Mengakses piksel adalah sedikit aneh

Seperti yang saya sebutkan di awal bagian ini, mengakses nilai-nilai piksel di canvas mengambil beberapa saat untuk mendapatkan kepala Anda di sekitar. Ini adalah karena cara bahwa pixel disimpan oleh canvas; mereka tidak sedang disimpan sebagai piksel seluruh sama sekali! Sebaliknya, piksel tersebut masing-masing dipecah menjadi empat nilai-nilai terpisah (merah, hijau, biru, dan alpha) dan nilai-nilai ini disimpan dalam sebuah dimensi array dengan semua nilai warna pixel lainnya. Karena ini Anda hanya tidak dapat meminta data dari sebuah pixel tertentu, setidaknya tidak secara default. Biarkan saya menjelaskan.

Untuk mengakses piksel di canvas Anda harus memanggil metode getImageData konteks rendering 2d, seperti:

1
var imageData = ctx.getImageData(x, y, width, height);

Metode ini mengambil empat argumen yang menggambarkan sebuah wilayah persegi panjang canvas yang Anda inginkan data pixel dari; x dan y asal, diikuti oleh width dan height. Mengembalikan CanvasPixelArray yang berisi semua nilai warna piksel dalam area yang didefinisikan. Hal pertama yang harus melihat dengan CanvasPixelArray adalah bahwa setiap pixel memiliki empat nilai-nilai warna, sehingga index dari nilai warna pertama untuk setiap pixel dalam array akan kelipatan 4 (0 nilai pertama pixel pertama, 4 untuk nilai pertama kedua dll):

Index values in the CanvasPixelArrayIndex values in the CanvasPixelArrayIndex values in the CanvasPixelArray

Apa yang menarik tentang ini array (atau mengganggu, tergantung pada bagaimana Anda melihatnya) adalah bahwa ada tidak ada konsep tentang (x, y) mengkoordinasikan posisi, berarti bahwa mengambil nilai warna untuk sebuah pixel tertentu sedikit lebih keras daripada mengakses array dua dimensi (misalnya. menggunakan pixelArray [0] [3] untuk mengakses pixel pada (1, 4)). Sebaliknya, Anda perlu menggunakan rumus yang sedikit yang benar-benar sangat mudah untuk memahami setelah itu dijelaskan dengan benar:

1
var redValueForPixel = ((y - 1) * (width * 4)) + ((x - 1) * 4);
Accessing a specific pixel from the CanvasPixelArrayAccessing a specific pixel from the CanvasPixelArrayAccessing a specific pixel from the CanvasPixelArray

Dapatkah Anda bekerja tahu apa yang terjadi di sini? Mari kita memecahnya dan berpura-pura bahwa kita ingin mendapatkan pixel nilai warna untuk pixel terdalam di kotak 3 x 3 pixel-pixel pada (2, 2).

Jika Anda melihat dua gambar sebelumnya Anda dapat melihat bahwa nilai-nilai warna untuk pixel akan dimulai pada index 16, tetapi untuk memperaktekan ini dengan kode Anda perlu untuk melakukan dua hal; pertama menghitung index di awal baris yang pixel (posisi y), dan kemudian tambahkan ke index jumlah nilai warna yang ada antara pixel dan awal baris (posisi x). Ini adalah sedikit mind-bender, tetapi tanggung dengan itu.

Bagian pertama mudah, Anda sudah tahu bahwa ada empat nilai-nilai warna setiap piksel, dan Anda sudah tahu lebar grid (3 piksel). Untuk menghitung index dari pixel pada baris y (2) Anda melewati nilai-nilai ini melalui bagian pertama dari formula, yang akan terlihat seperti:

1
((2 - 1) * (3 * 4))

Ini memberi Anda index 12, yang akan Anda lihat cocok dengan piksel pertama pada baris kedua dalam gambar sebelumnya. Sejauh ini baik-baik saja.

Langkah berikutnya adalah untuk menghitung jumlah nilai warna yang ada sebelum pixel yang Anda inginkan pada baris ini. Lakukan bahwa Anda hanya kalikan jumlah piksel sebelum Anda ingin oleh empat. Sederhana. Dalam hal ini bagian kedua dari rumus akan terlihat seperti ini:

1
((2 - 1) * 4)

Anda dapat bekerja itu semua jika Anda ingin, tapi jawabannya adalah 4, yang ketika ditambahkan ke nilai sebelumnya memberi Anda index 16. Keren, ey?

Aku tidak terlalu khawatir tentang memahaminya sepenuhnya, hanya tahu bahwa formula kecil yang menakjubkan ini ada sehingga Anda dapat dengan mudah mendapatkan index dari nilai warna merah untuk setiap pixel. Untuk mendapatkan index dari nilai warna lain dari sebuah pixel (hijau, biru, atau alpha), Anda hanya menambahkan 1, 2, atau 3 ke index dihitung masing-masing.

Memasukkan ini dalam praktek

Sekarang bahwa Anda tahu cara ambil setiap piksel yang Anda inginkan, mari kita menempatkan ini ke dalam praktek dan ambil nilai warna dari suatu gambar untuk mengubah warna latar belakang situs. Teknik semacam ini akan bekerja besar dengan color picker untuk aplikasi Web untuk mengedit foto.

Kode untuk contoh ini cukup sederhana, jadi mari kita menyerang semua dalam satu jalan:

1
var image = new Image();
2
image.src = "sample.jpg";
3
$(image).load(function() {
4
    ctx.drawImage(image, 0, 0);
5
});
6
7
$(canvas).click(function(e) {
8
    var canvasOffset = $(canvas).offset();
9
    var canvasX = Math.floor(e.pageX-canvasOffset.left);
10
    var canvasY = Math.floor(e.pageY-canvasOffset.top);
11
12
    var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
13
    var pixels = imageData.data;
14
    var pixelRedIndex = ((canvasY - 1) * (imageData.width * 4)) + ((canvasX - 1) * 4);
15
    var pixelcolor = "rgba("+pixels[pixelRedIndex]+", "+pixels[pixelRedIndex+1]+", "+pixels[pixelRedIndex+2]+", "+pixels[pixelRedIndex+3]+")";
16
17
    $("body").css("backgroundColor", pixelcolor);
18
});

Anda akan mengenali beberapa baris pertama dari contoh sebelumnya. Semua barang baru dicapai handler klik pada canvas elemen, yang menggunakan sedikit jQuery untuk memberitahu Anda Kapan canvas telah diklik.

Dalam handler klik Anda ingin mempraktekan pixel yang telah diklik mouse di atas canvas. Untuk melakukan ini Anda harus menghitung offset dalam pixel dari posisi kiri atas canvas dari tepi kiri atas jendela browser, Anda dapat menggunakan metode offset jQuery untuk ini. Anda kemudian dapat menyimpulkan dengan pixel yang diklik di canvas dengan mengurangi offset dari posisi mouse acara klik (pageX dan pageY). Anda pasti harus meluangkan waktu membaca pada acara klik JavaScript jika Anda ingin memahami hal ini lebih lanjut.

Empat baris berikut ambil CanvasPixelArray untuk canvas (getImageData), menyimpannya dalam variabel, menemukan index dari nilai warna merah untuk pixel diklik dengan menghitung menggunakan rumus bahwa Anda lihat sebelumnya, dan kemudian menyimpan nilai piksel warna CSS rgba string. Akhirnya, langkah terakhir adalah untuk mengatur warna latar belakang dari elemen body yang diklik pixel.

Creating a basic color pickerCreating a basic color pickerCreating a basic color picker

Dan dengan itu selesai. Mencobanya untuk diri Anda sendiri; Klik pada gambar di canvas dan menonton latar belakang website berubah warna. Jika tidak bekerja, pastikan bahwa Anda sedang menjalankan demo pada server dengan nama domain, seperti dijelaskan dalam bagian tentang masalah keamanan.

Sudah perjalanan panjang, tetapi Anda sekarang dapat dengan cepat dan mudah mengambil nilai-nilai warna setiap piksel pada canvas. Apakah saya memberitahu Anda bahwa Anda juga dapat mengubah nilai-nilai warna piksel pada canvas? Aku tidak? UPS! Mari kita lihat bahwa sekarang kemudian, itu benar keren.


Menerapkan efek ke gambar

Sekarang bahwa Anda dapat mengakses nilai-nilai piksel warna canvas, mengubah nilai-nilai tersebut sangat mudah. Pada kenyataannya, mengubah nilai-nilai warna tersebut yang sederhana seperti mengubah nilai-nilai di CanvasPixelArray dan kemudian menggambar kembali ke canvas. Mari kita lihat bagaimana untuk melakukannya.

Langkah pertama adalah untuk menyiapkan kode seperti yang Anda lakukan di bagian sebelumnya. Kode ini Load gambar, menarik ke canvas, dan kemudian meraih pixel data:

1
var image = new Image();
2
image.src = "sample.jpg";
3
$(image).load(function() {
4
    ctx.drawImage(image, 0, 0);
5
6
    var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
7
    var pixels = imageData.data;
8
    var numPixels = imageData.width * imageData.height;
9
});

Sejauh ini baik-baik saja. Langkah berikutnya adalah untuk loop melalui setiap pixel di canvas dan mengubah nilai-nilai warna. Dalam contoh ini Anda akan invert warna oleh deducting nilai saat ini warna (0 hingga 255) dari 255:

1
for (var i = 0; i < numPixels; i++) {
2
    pixels[i*4] = 255-pixels[i*4]; // Red

3
    pixels[i*4+1] = 255-pixels[i*4+1]; // Green

4
    pixels[i*4+2] = 255-pixels[i*4+2]; // Blue

5
};

Tidak ada yang gila terjadi di sini; Anda hanya mengalikan jumlah piksel (i) oleh 4 untuk mendapatkan index dari nilai warna merah itu pixel di CanvasPixelArray. Dengan menambahkan 1 atau 2 untuk jumlah itu, Anda bisa mendapatkan dan mengubah nilai-nilai warna hijau dan biru masing-masing.

Akhirnya, semua yang perlu Anda lakukan sekarang adalah untuk menghapus canvas (untuk menyingkirkan gambar normal), dan kemudian menggunakan metode putImageData konteks rendering 2d menggambar CanvasPixelArray disimpan ke canvas:

1
ctx.clearRect(0, 0, canvas.width, canvas.height);
2
ctx.putImageData(imageData, 0, 0);

Dan itu adalah jujur semua ada untuk itu; muat ulang peramban Anda dan melihat untuk diri sendiri. Keren, bukan?

Inverting the pixels of an imageInverting the pixels of an imageInverting the pixels of an image

Kesimpulan

Ada jauh lebih banyak untuk manipulasi pixel di canvas, tapi saya berharap bahwa Anda telah mengalami cukup dalam artikel ini untuk mendapatkan jus Anda mengalir. Saya mendorong Anda untuk menjelajahi daerah ini lebih lanjut dan melihat apa lagi yang dapat Anda lakukan dengan piksel. Mengapa? Karena semua teknik yang Anda bersandar tentang manipulasi pixel dapat digunakan untuk HTML5 video serta gambar. Sekarang itu keren!

Dalam artikel berikutnya, yang terakhir dalam seri ini, kami akan mengambil pandangan yang berbeda di canvas. Kali ini, Anda akan belajar cara menghidupkan pada canvas, yang akan memberi Anda dasar-dasar yang diperlukan untuk membuat kartun, animasi dan permainan. Ini benar-benar favorit saya dari canvas.

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Web Design tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.