Mengambil foto dan mengontrol setelan kamera

Miguel Casas-Sanchez
Prancis Beaufort
François Beaufort

Pengambilan Gambar adalah API untuk mengambil gambar diam dan mengonfigurasi setelan hardware kamera. API ini tersedia di Chrome 59 pada Android dan desktop. Kami juga telah memublikasikan library polyfill ImageCapture.

API ini memungkinkan kontrol atas fitur-fitur kamera seperti zoom, kecerahan, kontras, ISO, dan white balance. Yang paling penting, Pengambilan Gambar memungkinkan Anda mengakses kemampuan resolusi penuh dari kamera perangkat atau webcam yang tersedia. Teknik pengambilan foto di Web sebelumnya telah menggunakan snapshot video, yang resolusinya lebih rendah daripada yang tersedia untuk gambar diam.

Objek ImageCapture dibuat dengan MediaStreamTrack sebagai sumber. API tersebut memiliki dua metode pengambilan takePhoto() dan grabFrame() serta cara mengambil kemampuan dan setelan kamera, serta untuk mengubah setelan tersebut.

Konstruksi

Image Capture API mendapatkan akses ke kamera melalui MediaStreamTrack yang diperoleh dari getUserMedia():

navigator.mediaDevices.getUserMedia({video: true})
    .then(gotMedia)
    .catch(error => console.error('getUserMedia() error:', error));

function gotMedia(mediaStream) {
    const mediaStreamTrack = mediaStream.getVideoTracks()[0];
    const imageCapture = new ImageCapture(mediaStreamTrack);
    console.log(imageCapture);
}

Anda dapat mencoba kode ini dari konsol DevTools.

Rekam

Mengambil gambar dapat dilakukan dengan dua cara: frame penuh dan snapshot cepat. takePhoto() menampilkan Blob, hasil dari satu eksposur fotografi, yang dapat didownload, disimpan oleh browser, atau ditampilkan di elemen <img>. Metode ini menggunakan resolusi kamera fotografi tertinggi yang tersedia. Contoh:

const img = document.querySelector('img');
// ...
imageCapture.takePhoto()
    .then(blob => {
    img.src = URL.createObjectURL(blob);
    img.onload = () => { URL.revokeObjectURL(this.src); }
    })
    .catch(error => console.error('takePhoto() error:', error));

grabFrame() menampilkan objek ImageBitmap, snapshot video live, yang dapat (misalnya) digambar di <canvas>, lalu diproses pasca-pemrosesan untuk mengubah nilai warna secara selektif. Perlu diketahui bahwa ImageBitmap hanya akan memiliki resolusi sumber video — yang biasanya lebih rendah daripada kemampuan gambar diam kamera. Contoh:

const canvas = document.querySelector('canvas');
// ...
imageCapture.grabFrame()
    .then(imageBitmap => {
    canvas.width = imageBitmap.width;
    canvas.height = imageBitmap.height;
    canvas.getContext('2d').drawImage(imageBitmap, 0, 0);
    })
    .catch(error => console.error('grabFrame() error:', error));

Kemampuan dan setelan

Ada sejumlah cara untuk memanipulasi setelan pengambilan, bergantung pada apakah perubahan akan tercermin dalam MediaStreamTrack atau hanya dapat dilihat setelah takePhoto(). Misalnya, perubahan level zoom segera diterapkan ke MediaStreamTrack, sedangkan pengurangan mata merah, jika disetel, hanya diterapkan saat foto diambil.

Kemampuan dan setelan kamera "live" dimanipulasi melalui pratinjau MediaStreamTrack: MediaStreamTrack.getCapabilities() menampilkan kamus MediaTrackCapabilities dengan kemampuan konkret yang didukung dan rentang atau nilai yang diizinkan, misalnya rentang zoom yang didukung atau mode white balance yang diizinkan. Sejalan dengan itu, MediaStreamTrack.getSettings() menampilkan MediaTrackSettings dengan setelan konkret saat ini. Zoom, kecerahan, dan mode senter termasuk dalam kategori ini, misalnya:

var zoomSlider = document.querySelector('input[type=range]');
// ...
const capabilities = mediaStreamTrack.getCapabilities();
const settings = mediaStreamTrack.getSettings();
if (capabilities.zoom) {
    zoomSlider.min = capabilities.zoom.min;
    zoomSlider.max = capabilities.zoom.max;
    zoomSlider.step = capabilities.zoom.step;
    zoomSlider.value = settings.zoom;
}

Kemampuan dan setelan kamera "Non-Live" dimanipulasi melalui objek ImageCapture: ImageCapture.getPhotoCapabilities() menampilkan objek PhotoCapabilities yang memberikan akses ke kemampuan kamera yang tersedia "Non-Live". Sejalan dengan itu, mulai Chrome 61, ImageCapture.getPhotoSettings() menampilkan objek PhotoSettings dengan setelan konkret saat ini. Resolusi foto, pengurangan mata merah, dan mode flash (kecuali flash) termasuk dalam bagian ini, misalnya:

var widthSlider = document.querySelector('input[type=range]');
// ...
imageCapture.getPhotoCapabilities()
    .then(function(photoCapabilities) {
    widthSlider.min = photoCapabilities.imageWidth.min;
    widthSlider.max = photoCapabilities.imageWidth.max;
    widthSlider.step = photoCapabilities.imageWidth.step;
    return imageCapture.getPhotoSettings();
    })
    .then(function(photoSettings) {
    widthSlider.value = photoSettings.imageWidth;
    })
    .catch(error => console.error('Error getting camera capabilities and settings:', error));

Mengonfigurasi

Setelan kamera "langsung" dapat dikonfigurasi melalui batasan applyConstraints() MediaStreamTrack pratinjau, misalnya:

var zoomSlider = document.querySelector('input[type=range]');

mediaStreamTrack.applyConstraints({ advanced: [{ zoom: zoomSlider.value }]})
    .catch(error => console.error('Uh, oh, applyConstraints() error:', error));

Setelan kamera "Non-Live" dikonfigurasi dengan kamus PhotoSettings opsional takePhoto(), misalnya:

var widthSlider = document.querySelector('input[type=range]');
imageCapture.takePhoto({ imageWidth : widthSlider.value })
    .then(blob => {
    img.src = URL.createObjectURL(blob);
    img.onload = () => { URL.revokeObjectURL(this.src); }
    })
    .catch(error => console.error('Uh, oh, takePhoto() error:', error));

Kemampuan kamera

Jika menjalankan kode di atas, Anda akan melihat perbedaan dimensi antara hasil grabFrame() dan takePhoto().

Metode takePhoto() memberikan akses ke resolusi maksimum kamera.

grabFrame() hanya mengambil VideoFrame berikutnya yang tersedia di MediaStreamTrack dalam proses perender, sedangkan takePhoto() mengganggu MediaStream, mengonfigurasi ulang kamera, mengambil foto (biasanya dalam format terkompresi, sehingga Blob), lalu melanjutkan MediaStreamTrack. Pada dasarnya, ini berarti bahwa takePhoto() memberikan akses ke kemampuan resolusi gambar diam penuh kamera. Sebelumnya, Anda hanya dapat 'mengambil foto' dengan memanggil drawImage() pada elemen canvas, menggunakan video sebagai sumber (seperti contoh di sini).

Informasi selengkapnya dapat ditemukan di bagian README.md.

Dalam demo ini, dimensi <canvas> disetel ke resolusi streaming video, sedangkan ukuran alami <img> adalah resolusi gambar diam maksimum kamera. Tentu saja, CSS digunakan untuk menyetel ukuran tampilan keduanya.

Berbagai resolusi kamera yang tersedia untuk gambar diam bisa didapatkan dan ditetapkan menggunakan nilai MediaSettingsRange untuk PhotoCapabilities.imageHeight dan imageWidth. Perhatikan bahwa batasan lebar dan tinggi minimum dan maksimum untuk getUserMedia() adalah untuk video, yang (seperti yang telah dibahas) mungkin berbeda dengan kemampuan kamera untuk gambar diam. Dengan kata lain, Anda mungkin tidak dapat mengakses kemampuan resolusi penuh perangkat saat menyimpan dari getUserMedia() ke kanvas. Demo batasan resolusi WebRTC menunjukkan cara menetapkan batasan getUserMedia() untuk resolusi.

Ada lagi?

Demo dan contoh kode

Dukungan

  • Chrome 59 di Android dan desktop.
  • Chrome Canary di Android dan desktop sebelum versi 59 dengan fitur Platform Web Eksperimental diaktifkan.

Cari tahu selengkapnya