Scattare foto e controllare le impostazioni della fotocamera

Miguel Casas-Sanchez
Francesco Beaufort
François Beaufort

Image Capture è un'API che consente di acquisire immagini fisse e configurare le impostazioni dell'hardware della fotocamera. Questa API è disponibile in Chrome 59 su Android e computer. Abbiamo pubblicato anche una libreria di polyfill Image Capture.

L'API consente di controllare funzionalità della fotocamera come zoom, luminosità, contrasto, ISO e bilanciamento del bianco. E soprattutto, l'acquisizione di immagini ti consente di accedere alle funzionalità alla massima risoluzione di qualsiasi fotocamera o webcam del dispositivo disponibile. Le tecniche precedenti per scattare foto sul web utilizzavano le istantanee video, con una risoluzione inferiore rispetto a quella disponibile per le immagini statiche.

Viene creato un oggetto ImageCapture con MediaStreamTrack come origine. L'API dispone quindi di due metodi di acquisizione, takePhoto() e grabFrame(), e di modi per recuperare le funzionalità e le impostazioni della fotocamera e per modificarle.

Lavori in corso

L'API Image Capture ottiene l'accesso a una fotocamera tramite un MediaStreamTrack ottenuto da 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);
}

Puoi provare questo codice dalla console DevTools.

Acquisisci

Puoi acquisire immagini in due modi: a tutto frame e a un'istantanea rapida. takePhoto() restituisce Blob, il risultato di una singola esposizione fotografica, che può essere scaricata, memorizzata dal browser o visualizzata in un elemento <img>. Questo metodo utilizza la massima risoluzione disponibile per la fotocamera. Ad esempio:

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() restituisce un oggetto ImageBitmap, un'istantanea di un video in diretta, che potrebbe (ad esempio) essere disegnata su un <canvas> e poi post-elaborata per modificare selettivamente i valori dei colori. Tieni presente che ImageBitmap avrà solo la risoluzione dell'origine video, che in genere sarà inferiore rispetto alle funzionalità delle immagini fisse della fotocamera. Ad esempio:

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

Funzionalità e impostazioni

Esistono diversi modi per manipolare le impostazioni di acquisizione, a seconda che le modifiche si riflettano nell'MediaStreamTrack o siano visibili solo dopo il giorno takePhoto(). Ad esempio, una modifica nel livello zoom viene immediatamente propagata al livello MediaStreamTrack, mentre la riduzione degli occhi rossi, se impostata, viene applicata solo quando la foto viene scattata.

Le funzionalità e le impostazioni della fotocamera "in diretta" vengono modificate tramite l'anteprima MediaStreamTrack: MediaStreamTrack.getCapabilities() restituisce un dizionario MediaTrackCapabilities con le funzionalità effettive supportate e gli intervalli o i valori consentiti, ad esempio intervallo di zoom supportato o modalità di bilanciamento del bianco consentite. Analogamente, MediaStreamTrack.getSettings() restituisce MediaTrackSettings con le effettive impostazioni correnti. Zoom, luminosità e modalità torcia appartengono a questa categoria, ad esempio:

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

Le funzionalità e le impostazioni della fotocamera "Non dal vivo" vengono modificate tramite l'oggetto ImageCapture: ImageCapture.getPhotoCapabilities() restituisce un oggetto PhotoCapabilities che fornisce l'accesso alle funzionalità della fotocamera disponibili "Non dal vivo". Analogamente, a partire da Chrome 61, ImageCapture.getPhotoSettings() restituisce un oggetto PhotoSettings con le impostazioni attuali effettive. La risoluzione della foto, la riduzione occhi rossi e la modalità flash (tranne la torcia) appartengono a questa sezione, ad esempio:

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

Configurazione in corso…

Le impostazioni della fotocamera "In diretta" possono essere configurate tramite i vincoli applyConstraints() dell'anteprima, ad esempio:MediaStreamTrack

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

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

Le impostazioni della videocamera "Non in diretta" sono configurate con il dizionario facoltativo PhotoSettings di takePhoto(), ad esempio:

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

Funzionalità della fotocamera

Se esegui il codice riportato sopra, noterai una differenza di dimensioni tra i risultati grabFrame() e takePhoto().

Il metodo takePhoto() consente di accedere alla risoluzione massima della fotocamera.

grabFrame() prende semplicemente il successivo VideoFrame disponibile nell'MediaStreamTrack all'interno del processo di rendering, mentre takePhoto() interrompe MediaStream, riconfigura la fotocamera, scatta la foto (di solito in un formato compresso, da qui il Blob) e poi ripristina MediaStreamTrack. In sostanza, questo significa che takePhoto() concede l'accesso a tutte le funzionalità di risoluzione delle immagini fisse della videocamera. In precedenza, era possibile "scattare una foto" solo chiamando drawImage() su un elemento canvas, utilizzando un video come fonte (come da esempio qui).

Ulteriori informazioni sono disponibili nella sezione README.md.

In questa demo, le dimensioni <canvas> sono impostate sulla risoluzione dello stream video, mentre la dimensione naturale di <img> è la risoluzione massima delle immagini fisse della videocamera. CSS, ovviamente, serve per impostare le dimensioni di visualizzazione di entrambi.

Puoi recuperare e impostare l'intera gamma di risoluzioni della fotocamera disponibili per le immagini statiche utilizzando i valori MediaSettingsRange per PhotoCapabilities.imageHeight e imageWidth. Tieni presente che i limiti minimi e massimi di larghezza e altezza di getUserMedia() si applicano ai video, che (come discusso) potrebbero essere diversi dalle funzionalità della fotocamera per le immagini statiche. In altre parole, potresti non riuscire ad accedere alle funzionalità di massima risoluzione del dispositivo quando salvi da getUserMedia() su una tela. La demo dei vincoli di risoluzione di WebRTC mostra come impostare i vincoli getUserMedia() per la risoluzione.

Altro?

  • L'API Shape Detection funziona bene con l'acquisizione di immagini: grabFrame() può essere chiamato ripetutamente per inviare ImageBitmap a FaceDetector o BarcodeDetector. Per saperne di più sull'API, leggi il post del blog di Paul Kinlan.

  • È possibile accedere al Flash della fotocamera (spia del dispositivo) tramite FillLightMode in PhotoCapabilities , mentre la modalità torcia (lampeggia costantemente) è disponibile in MediaTrackCapabilities.

Demo ed esempi di codice

Assistenza

  • Chrome 59 su Android e computer.
  • Chrome Canary su Android e computer precedenti alla 59 con funzionalità sperimentali della piattaforma web abilitate.

Scopri di più