Chụp ảnh và kiểm soát chế độ cài đặt của máy ảnh

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

Chụp ảnh là một API để chụp ảnh tĩnh và định cấu hình các chế độ cài đặt phần cứng máy ảnh. API này có trong Chrome 59 trên Android và máy tính. Chúng tôi cũng đã phát hành thư viện polyfill ImageCapture.

API này cho phép kiểm soát các tính năng của máy ảnh, chẳng hạn như thu phóng, độ sáng, độ tương phản, ISO và cân bằng trắng. Hơn hết, tính năng Image Capture cho phép bạn truy cập vào khả năng phân giải đầy đủ của mọi máy ảnh hoặc webcam trên thiết bị hiện có. Các kỹ thuật chụp ảnh trên web trước đây sử dụng ảnh chụp nhanh video. Đây là những kỹ thuật có độ phân giải thấp hơn so với ảnh tĩnh.

Đối tượng ImageCapture được tạo bằng MediaStreamTrack làm nguồn. Sau đó, API có 2 phương thức chụp takePhoto()grabFrame(), cũng như các cách để truy xuất các chức năng và chế độ cài đặt của máy ảnh, cũng như để thay đổi các chế độ cài đặt đó.

Công trường

API Chụp ảnh có quyền truy cập vào máy ảnh thông qua MediaStreamTrack lấy từ 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);
}

Bạn có thể thử mã này từ bảng điều khiển Công cụ cho nhà phát triển.

Quay hình

Bạn có thể chụp theo 2 cách: toàn bộ khung hình và chụp nhanh nhanh. takePhoto() trả về Blob, kết quả của một lần phơi sáng ảnh, có thể được tải xuống, lưu trữ bởi trình duyệt hoặc hiển thị trong phần tử <img>. Phương thức này sử dụng độ phân giải cao nhất của máy ảnh chụp được. Ví dụ:

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() trả về một đối tượng ImageBitmap, bản tổng quan nhanh của video trực tiếp, có thể được vẽ (ví dụ) trên <canvas>, sau đó được xử lý sau để thay đổi các giá trị màu có chọn lọc. Xin lưu ý rằng ImageBitmap sẽ chỉ có độ phân giải của nguồn video, thường sẽ thấp hơn khả năng hình ảnh tĩnh của máy ảnh. Ví dụ:

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

Chức năng và chế độ cài đặt

Có một số cách để điều chỉnh chế độ cài đặt chụp, tuỳ thuộc vào việc các thay đổi sẽ được phản ánh trong MediaStreamTrack hay chỉ có thể xem sau takePhoto(). Ví dụ: sự thay đổi về mức zoom sẽ được áp dụng ngay lập tức đến MediaStreamTrack trong khi tính năng giảm mắt đỏ (khi được đặt) sẽ chỉ được áp dụng khi chụp ảnh.

Các chức năng và chế độ cài đặt của máy ảnh "Live" được điều chỉnh thông qua bản xem trước MediaStreamTrack: MediaStreamTrack.getCapabilities() trả về một từ điển MediaTrackCapabilities với các tính năng được hỗ trợ cụ thể và các phạm vi hoặc các giá trị được cho phép, ví dụ: phạm vi thu phóng được hỗ trợ hoặc các chế độ cân bằng trắng được cho phép. Tương ứng, MediaStreamTrack.getSettings() sẽ trả về một MediaTrackSettings với chế độ cài đặt cụ thể hiện tại. Thu phóng, độ sáng và chế độ đèn pin thuộc danh mục này, ví dụ:

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

Các chức năng và chế độ cài đặt của máy ảnh "Không phát trực tiếp" được điều chỉnh thông qua đối tượng ImageCapture: ImageCapture.getPhotoCapabilities() trả về một đối tượng PhotoCapabilities cung cấp quyền truy cập vào các tính năng hiện có của máy ảnh ở chế độ "Không trực tiếp". Tương ứng, kể từ Chrome 61, ImageCapture.getPhotoSettings() sẽ trả về đối tượng PhotoSettings kèm theo chế độ cài đặt cụ thể hiện tại. Độ phân giải ảnh, chế độ giảm mắt đỏ và chế độ đèn flash (ngoại trừ đèn pin) thuộc phần này, ví dụ:

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

Đang định cấu hình

Bạn có thể định cấu hình chế độ cài đặt "Live" cho máy ảnh thông qua bản xem trước applyConstraints() các ràng buộc của MediaStreamTrack , ví dụ:

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

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

Chế độ cài đặt máy ảnh "Không phát trực tiếp" được định cấu hình bằng từ điển PhotoSettings không bắt buộc của takePhoto(), ví dụ:

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

Các chức năng của camera

Nếu chạy mã ở trên, bạn sẽ thấy sự khác biệt về kích thước giữa kết quả grabFrame()takePhoto().

Phương thức takePhoto() cấp quyền truy cập vào độ phân giải tối đa của máy ảnh.

grabFrame() chỉ lấy VideoFrame có sẵn tiếp theo trong MediaStreamTrack bên trong quá trình kết xuất đồ hoạ, trong khi takePhoto() làm gián đoạn MediaStream, định cấu hình lại máy ảnh, chụp ảnh (thường ở định dạng nén, do đó Blob) rồi tiếp tục MediaStreamTrack. Về cơ bản, điều này có nghĩa là takePhoto() cấp quyền truy cập vào khả năng phân giải đầy đủ hình ảnh tĩnh của máy ảnh. Trước đây, bạn chỉ có thể "chụp ảnh" bằng cách gọi drawImage() trên phần tử canvas, sử dụng video làm nguồn (như ví dụ tại đây).

Bạn có thể xem thêm thông tin trong phần README.md.

Trong bản minh hoạ này, kích thước <canvas> được đặt thành độ phân giải của luồng video, trong khi kích thước tự nhiên của <img> là độ phân giải hình ảnh tĩnh tối đa của máy ảnh. Tất nhiên, CSS được dùng để đặt kích thước hiển thị của cả hai.

Bạn có thể lấy và thiết lập đầy đủ độ phân giải máy ảnh có sẵn cho hình ảnh tĩnh bằng cách sử dụng các giá trị MediaSettingsRange cho PhotoCapabilities.imageHeightimageWidth. Xin lưu ý rằng các giới hạn chiều rộng và chiều cao tối thiểu và tối đa của getUserMedia() dành cho video (như đã thảo luận) có thể khác với khả năng của máy ảnh đối với hình ảnh tĩnh. Nói cách khác, có thể bạn sẽ không truy cập được độ phân giải đầy đủ của thiết bị khi lưu từ getUserMedia() vào canvas. Bản minh hoạ điều kiện ràng buộc về độ phân giải của WebRTC cho biết cách đặt các quy tắc ràng buộc đối với getUserMedia() để giải quyết vấn đề.

Gợi ý thêm cho bạn

  • API Phát hiện hình dạng hoạt động tốt với tính năng Chụp ảnh: grabFrame() có thể được gọi nhiều lần để cấp ImageBitmap cho FaceDetector hoặc BarcodeDetector. Hãy tìm hiểu thêm về API trong bài đăng trên blog của Paul Kinlan.

  • Bạn có thể truy cập vào Đèn flash của máy ảnh (đèn thiết bị) thông qua FillLightMode trong PhotoCapabilities, nhưng bạn có thể tìm thấy Chế độ đèn pin (bật đèn flash liên tục) trong MediaTrackCapabilities.

Bản minh hoạ và mã mẫu

Hỗ trợ

  • Chrome 59 trên Android và máy tính.
  • Chrome Canary trên Android và máy tính để bàn cũ phiên bản 59 và bật các tính năng của Nền tảng web thử nghiệm.

Tìm hiểu thêm