Maak foto's en bedien de camera-instellingen

Miguel Casas-Sanchez
François Beaufort
François Beaufort

Image Capture is een API om stilstaande beelden vast te leggen en camerahardware-instellingen te configureren. Deze API is beschikbaar in Chrome 59 voor Android en desktop. We hebben ook een ImageCapture polyfill-bibliotheek gepubliceerd.

De API biedt controle over camerafuncties zoals zoom, helderheid, contrast, ISO en witbalans. Bovendien geeft Image Capture je toegang tot de volledige resolutiemogelijkheden van elke beschikbare camera of webcam. Eerdere technieken voor het maken van foto's op internet maakten gebruik van videosnapshots, die een lagere resolutie hebben dan die van stilstaande beelden.

Een ImageCapture object wordt geconstrueerd met een MediaStreamTrack als bron. De API heeft vervolgens twee capture-methoden: takePhoto() en grabFrame() en manieren om de mogelijkheden en instellingen van de camera op te halen en te wijzigen.

Bouw

De Image Capture API krijgt toegang tot een camera via een MediaStreamTrack verkregen via 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);
}

U kunt deze code uitproberen vanuit de DevTools-console.

Vastlegging

Vastleggen kan op twee manieren: full frame en quick snapshot. takePhoto() retourneert een Blob , het resultaat van een enkele fotografische belichting , die kan worden gedownload, opgeslagen in de browser of weergegeven in een <img> -element. Deze methode maakt gebruik van de hoogst beschikbare resolutie van een fotocamera. Bijvoorbeeld:

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() retourneert een ImageBitmap object, een momentopname van live video , die (bijvoorbeeld) op een <canvas getekend kan worden en vervolgens nabewerkt kan worden om de kleurwaarden selectief te wijzigen. Houd er rekening mee dat de ImageBitmap alleen de resolutie van de videobron heeft – die meestal lager is dan de mogelijkheden van de camera voor stilstaande beelden. Bijvoorbeeld:

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

Mogelijkheden en instellingen

Er zijn verschillende manieren om de opname-instellingen te manipuleren, afhankelijk van of de wijzigingen worden weergegeven in de MediaStreamTrack of pas zichtbaar zijn na takePhoto() . Een wijziging in zoom wordt bijvoorbeeld direct doorgegeven aan de MediaStreamTrack , terwijl rode-ogenreductie, indien ingesteld, alleen wordt toegepast tijdens het maken van de foto.

De mogelijkheden en instellingen van de "live" camera worden gemanipuleerd via de preview MediaStreamTrack : MediaStreamTrack.getCapabilities() retourneert een MediaTrackCapabilities -woordenboek met de concreet ondersteunde mogelijkheden en de bereiken of toegestane waarden, bijvoorbeeld het ondersteunde zoombereik of de toegestane witbalansmodi. Overeenkomstig retourneert MediaStreamTrack.getSettings() een MediaTrackSettings met de concrete huidige instellingen. Zoom, helderheid en zaklampmodus behoren tot deze categorie, bijvoorbeeld:

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

De mogelijkheden en instellingen van de "niet-live" camera worden gemanipuleerd via het ImageCapture object: ImageCapture.getPhotoCapabilities() retourneert een PhotoCapabilities object dat toegang biedt tot de beschikbare "niet-live" cameramogelijkheden. Vanaf Chrome 61 retourneert ImageCapture.getPhotoSettings() een PhotoSettings object met de concrete huidige instellingen. De fotoresolutie, rode-ogenreductie en flitsmodus (behalve zaklamp) behoren tot deze sectie, bijvoorbeeld:

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

Configureren

Instellingen voor de livecamera kunnen worden geconfigureerd via de applyConstraints() beperkingen van de preview- MediaStreamTrack , bijvoorbeeld:

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

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

"Niet-live" camera-instellingen worden geconfigureerd met het optionele PhotoSettings woordenboek van takePhoto() , bijvoorbeeld:

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

Cameramogelijkheden

Als u de bovenstaande code uitvoert, zult u een verschil in afmetingen opmerken tussen de resultaten van grabFrame() en takePhoto() .

Met de takePhoto() -methode krijgt u toegang tot de maximale resolutie van de camera.

grabFrame() neemt gewoon het volgende beschikbare VideoFrame in de MediaStreamTrack binnen het renderproces, terwijl takePhoto() de MediaStream onderbreekt, de camera opnieuw configureert, de foto maakt (meestal in een gecomprimeerd formaat, vandaar de Blob ) en vervolgens de MediaStreamTrack hervat. In wezen betekent dit dat takePhoto() toegang geeft tot de volledige resolutiemogelijkheden van de camera voor stilstaande beelden. Voorheen was het alleen mogelijk om een ​​'foto te maken' door drawImage() aan te roepen op een canvas element, met een video als bron (zoals in het voorbeeld hier ).

Meer informatie vindt u in de README.md sectie .

In deze demo zijn de <canvas> -afmetingen ingesteld op de resolutie van de videostream, terwijl de natuurlijke grootte van de <img> de maximale resolutie van de camera is. Uiteraard wordt CSS gebruikt om de weergavegrootte van beide in te stellen.

Het volledige scala aan beschikbare cameraresoluties voor stilstaande beelden kan worden opgehaald en ingesteld met behulp van de MediaSettingsRange waarden voor PhotoCapabilities.imageHeight en imageWidth . Houd er rekening mee dat de minimale en maximale breedte- en hoogtebeperkingen voor getUserMedia() gelden voor video, wat (zoals besproken) kan afwijken van de cameramogelijkheden voor stilstaande beelden. Met andere woorden, u kunt mogelijk niet de volledige resolutiemogelijkheden van uw apparaat gebruiken wanneer u vanuit getUserMedia() opslaat op een canvas. De demo van de WebRTC-resolutiebeperking laat zien hoe u getUserMedia() -beperkingen voor resolutie instelt.

Nog iets anders?

Demo's en codevoorbeelden

Steun

  • Chrome 59 op Android en desktop.
  • Chrome Canary op Android en desktop vóór versie 59 met Experimental Web Platform -functies ingeschakeld.

Meer informatie