<返回更多

聊聊浏览器最新特性 ImageCapture?

2023-05-22  今日头条  高级前端进阶
加入收藏

1.什么是ImageCapture?

MediaStream Image Capture API 的 ImageCapture 接口提供了从相机或其他摄影设备捕获图像或照片的方法。 它提供了一个接口,用于从通过有效的 MediaStreamTrack 引用的摄影设备捕获图像。

什么是ImageCapture?图片来自https://www.freepik.com/的marcovector并加工

2.ImageCapture的API 机制

ImageCapture 对象是使用 MediaStreamTrack 作为源构建的。 API 有两个捕获方法 takePhoto() 和 grabFrame() 以及检索相机功能和设置,同时提供了更改设置的诸多方法。

2.1 takePhoto

takePhoto() 将单次摄影曝光的结果作为 Blob 返回,该 Blob 可以下载、由浏览器存储或显示在 img 元素中。 此方法使用可用的最高摄影相机分辨率。

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

注意:要在不同的摄像头之间进行选择,例如手机上的前置摄像头和后置摄像头,可以通过
navigator.mediaDevices.enumerateDevices() 方法获取可用设备列表,然后在 getUserMedia() 约束中设置 deviceId(具体查看文末链接代码)。如下调用takePhoto方法:

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

2.2 grabFrame

grabFrame() 将 theTrack 中的实时视频快照作为 ImageBitmap 对象返回,该对象可以绘制在画布上,然后进行后期处理以有选择地更改颜色值。

请注意,ImageBitmap 将仅具有视频轨道的分辨率,而通常低于相机的静止图像分辨率。

比如下面的示例代码:

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

3.ImageCapture照片设置和功能

照片的选项、设置与 theImageCapturer 或 MediaStreamTrack 相关联,具体取决于给定的功能/设置是否对 MediaStreamTrack 具有立即可识别的效果,即是否“实时”。 例如,更改缩放级别会立即反映在 MediaStreamTrack 上,而启用红眼消除功能则不会。

照片设置和功能

“实时”相机功能和设置通过预览 MediaStreamTrack 进行操作。
MediaStreamTrack.getCapabilities() 返回一个 MediaTrackCapabilities对象,包含具体支持的功能和范围或允许值。例如 支持的变焦范围或允许的白平衡模式。 相应地,MediaStreamTrack.getSettings() 返回具有具体当前设置的 MediaTrackSettings。 缩放、亮度和手电筒模式等,例如:

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

“非实时”相机功能和设置通过 ImageCapture 对象进行操作:
ImageCapture.getPhotoCapabilities() 返回一个 PhotoCapabilities 对象,该对象提供对“非实时”可用相机功能的访问。

var widthSlider = document.querySelector('input[type=range]');
// 获取目标DOM
imageCapture.getPhotoCapabilities()
    .then(function(photoCapabilities) {
  // 获取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));

“实时”相机设置可以通过 MediaStreamTrack 的 ApplyConstrAInts() constraints 配置,例如:

//applyConstraints设置实时属性
var zoomSlider = document.querySelector('input[type=range]');
mediaStreamTrack.applyConstraints({ advanced: [{ zoom: zoomSlider.value }]})
    .catch(error => console.error('Uh, oh, applyConstraints() error:', error));

“非实时”相机设置使用 takePhoto() 的可选 PhotoSettings 字典进行配置,例如:

var widthSlider = document.querySelector('input[type=range]');
//takePhoto方法参数设置非实时属性
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));

4.ImageCapture的浏览器支持与polyfill

如下图所示,Chrome从59版本、Edge从79版本开始已经支持ImageCapture,Firefox从35版本开始也作为试验属性添加。Safari依然是特例,即使最新的16.3版本也没有支持这个属性。

 

整体来看,浏览器支持大约75.06%。不可以可幸的是,对于不支持的浏览器来说google Chrome实验室提供了ImageCapture的polyfill,只需要按照如下方式集成项目即可。

npm install --save image-capture

安装项目后就可以直接在JS中使用:

let videoDevice;
let canvas = document.getElementById('canvas');
let photo = document.getElementById('photo');
navigator.mediaDevices.getUserMedia({video: true}).then(gotMedia).catch(failedToGetMedia);
function gotMedia(mediaStream) {
  // Extract video track.
  videoDevice = mediaStream.getVideoTracks()[0];
  // Check if this device supports a picture mode...
  let captureDevice = new ImageCapture(videoDevice);
  if (captureDevice) {
    captureDevice.takePhoto().then(processPhoto).catch(stopCamera);
    captureDevice.grabFrame().then(processFrame).catch(stopCamera);
  }
}
function processPhoto(blob) {
  photo.src = window.URL.createObjectURL(blob);
}
// 绘制到Canvas中
function processFrame(imageBitmap) {
  canvas.width = imageBitmap.width;
  canvas.height = imageBitmap.height;
  canvas.getContext('2d').drawImage(imageBitmap, 0, 0);
}
function stopCamera(error) {
  console.error(error);
  if (videoDevice) videoDevice.stop();  // turn off the camera
}
photo.addEventListener('load', function () {
  // 图片加载完成后,丢弃图片对象释放内存
  window.URL.revokeObjectURL(this.src);
});

5.本文总结

本文主要和大家介绍MediaStream Image Capture API 的 ImageCapture 接口,其提供了从相机或其他摄影设备捕获图像或照片的方法,文章没有就ImageCapture过多的展开。但是文末的参考资料提供了大量优秀文档以供学习,如果有兴趣可以自行阅读。如果大家有什么疑问欢迎在评论区留言。

 

参考资料

https://chromium.googlesource.com/chromium/src/third_party/+/master/blink/renderer/modules/imagecapture/README.md

https://developer.chrome.com/blog/imagecapture/

https://Github.com/GoogleChromeLabs/imagecapture-polyfill

https://webrtc.github.io/samples/src/content/devices/input-output/

声明:本站部分内容来自互联网,如有版权侵犯或其他问题请与我们联系,我们将立即删除或处理。
▍相关推荐
更多资讯 >>>