Chrome mendukung createImageBitmap() di Chrome 50

Mendekode gambar untuk digunakan dengan kanvas cukup umum, baik untuk memungkinkan pengguna menyesuaikan avatar, memangkas gambar, atau hanya memperbesar gambar. Masalah dengan decoding gambar adalah dapat menggunakan CPU secara intensif, dan terkadang dapat menyebabkan jank atau checkerboarding. Mulai Chrome 50 (dan di Firefox 42+) Anda kini memiliki opsi lain: createImageBitmap(). Dengan ini, Anda dapat mendekode gambar di latar belakang, dan mendapatkan akses ke primitif ImageBitmap baru, yang dapat Anda gambar ke kanvas dengan cara yang sama seperti elemen <img>, kanvas lain, atau video.

Menggambar blob dengan createImageBitmap()

Misalnya Anda mendownload gambar blob dengan fetch() (atau XHR), dan Anda ingin menggambarnya menjadi kanvas. Tanpa createImageBitmap(), Anda harus membuat elemen gambar dan URL Blob untuk mendapatkan gambar dalam format yang dapat Anda gunakan. Dengannya, Anda mendapatkan rute yang jauh lebih langsung untuk melukis:

fetch(url)
    .then(response => response.blob())
    .then(blob => createImageBitmap(blob))
    .then(imageBitmap => ctx.drawImage(imageBitmap, 0, 0));

Pendekatan ini juga akan berfungsi dengan gambar yang disimpan sebagai blob di IndexedDB, sehingga blob menjadi format perantara yang praktis. Chrome 50 juga mendukung metode .toBlob() pada elemen kanvas, yang berarti Anda dapat -- misalnya -- membuat blob dari elemen kanvas.

Menggunakan createImageBitmap() di pekerja web

Salah satu fitur terbaik createImageBitmap() adalah fitur ini juga tersedia di pekerja, yang berarti Anda kini dapat mendekode gambar di mana pun Anda mau. Jika Anda memiliki banyak gambar yang perlu didekode dan dianggap tidak penting, Anda akan mengirimkan URL-nya ke Web Worker, yang akan mendownload dan mendekodenya sesuai waktu yang tersedia. Kemudian, kode ini akan mentransfernya kembali ke thread utama untuk menggambar ke kanvas.

Aliran data dengan createImageBitmap dan pekerja web.

Kode untuk melakukannya mungkin terlihat seperti ini:

// In the worker.
fetch(imageURL)
    .then(response => response.blob())
    .then(blob => createImageBitmap(blob))
    .then(imageBitmap => {
    // Transfer the imageBitmap back to main thread.
    self.postMessage({ imageBitmap }, [imageBitmap]);
    }, err => {
    self.postMessage({ err });
    });

// In the main thread.
worker.onmessage = (evt) => {
    if (evt.data.err)
    throw new Error(evt.data.err);

    canvasContext.drawImage(evt.data.imageBitmap, 0, 0);
}

Saat ini, jika Anda memanggil createImageBitmap() di thread utama, decoding akan dilakukan di sana. Namun, rencananya adalah membuat Chrome melakukan dekode secara otomatis di thread lain, sehingga membantu mengurangi beban kerja thread utama. Namun, sementara itu, Anda harus berhati-hati saat melakukan decoding di thread utama, karena ini adalah pekerjaan intensif yang dapat memblokir tugas penting lainnya, seperti JavaScript, penghitungan gaya, tata letak, gambar, atau komposisi.

Library bantuan

Untuk memudahkan, saya telah membuat library helper yang menangani decoding pada worker, dan mengirimkan kembali gambar yang telah didekode ke thread utama, serta menggambarnya ke dalam kanvas. Tentu saja, Anda harus merekayasa baliknya dan menerapkan model tersebut ke aplikasi Anda sendiri. Manfaat utamanya adalah lebih banyak kontrol, tetapi (seperti biasa) hal itu disertai dengan lebih banyak kode, lebih banyak yang harus di-debug, dan lebih banyak kasus ekstrem yang harus dipertimbangkan daripada menggunakan elemen <img>.

Jika Anda memerlukan kontrol lebih besar dengan decoding gambar, createImageBitmap() adalah teman baru Anda. Coba di Chrome 50, dan beri tahu kami hasilnya.