צילום תמונות ושליטה בהגדרות המצלמה

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

צילום תמונות הוא ממשק API לצילום תמונות סטילס ולהגדיר את חומרת המצלמה הגדרות. ה-API הזה זמין בגרסה 59 של Chrome במכשירי Android ובמחשב. כמו כן פרסמה ספריית polyfill של ImageCapture polyfill.

ה-API מאפשר לשלוט בתכונות המצלמה כמו זום, בהירות ניגודיות, ISO ואיזון לבן. והכי חשוב, צילום תמונה מאפשר לך לגשת יכולות הרזולוציה המלאה של כל מצלמה או מצלמת אינטרנט זמינים במכשיר. בטכניקות קודמות לצילום תמונות באינטרנט נעשה שימוש בתמונות מצב של סרטונים, ברזולוציה נמוכה יותר מזו שזמינה לתמונות סטילס.

אובייקט ImageCapture בנוי עם MediaStreamTrack כמקור. לאחר מכן יש ל-API שתי שיטות תיעוד: takePhoto() ו-grabFrame(), ודרכים לאחזר את היכולות וההגדרות של המצלמה, וכדי לשנות אותן הגדרות.

בנייה

ה-API של צילום תמונות מקבל גישה למצלמה דרך אישור MediaStreamTrack מ-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);
}

אפשר לנסות את הקוד הזה במסוף כלי הפיתוח.

צילום

ניתן לצלם בשתי דרכים: פריים מלא ותמונת מצב מהירה. takePhoto() הפונקציה מחזירה Blob, תוצאה של חשיפה אחת בתמונה, שאותם ניתן להוריד, לאחסן בדפדפן או להציג בקובץ <img> לרכיב מסוים. בשיטה הזו נעשה שימוש ברזולוציית המצלמה הגבוהה ביותר הזמינה. לדוגמה:

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() מחזיר אובייקט ImageBitmap, תמונת מצב של וידאו בשידור חי, שניתן (לדוגמה) לצייר על <canvas> ואז מעובד לשנות באופן סלקטיבי את ערכי הצבעים. לתשומת ליבכם: 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));

יכולות והגדרות

יש כמה דרכים לשנות את הגדרות הצילום, בהתאם ל אם השינויים ישתקפו ב-MediaStreamTrack או יכולים להיות רק נראה אחרי takePhoto(). למשל, שינוי ברמת zoom מופיע מיד ל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) {
    zoomSlider.min = capabilities.zoom.min;
    zoomSlider.max = capabilities.zoom.max;
    zoomSlider.step = capabilities.zoom.step;
    zoomSlider.value = settings.zoom;
}

'לא פעיל' היכולות וההגדרות של המצלמה משתנות באמצעות אובייקט ImageCapture: ImageCapture.getPhotoCapabilities() מחזיר PhotoCapabilities שמספק גישה לפריט "לא פעיל" היכולות הזמינות של המצלמה. בהתאם, החל מ-Chrome 61, ImageCapture.getPhotoSettings() מחזירה PhotoSettings עם ההגדרות הממשיות הנוכחיות. רזולוציית התמונה, עין אדומה הפחתה ומצב הבהוב (למעט לפיד) שייכים לקטע הזה, לדוגמה:

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

מתבצעת הגדרה

'פעיל' אפשר לשנות את הגדרות המצלמה דרך התצוגה המקדימה. מכשיר applyConstraints() של MediaStreamTrack מגבלות , לדוגמה:

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

יכולות של מצלמה

אם תריצו את הקוד שלמעלה, תבחינו בהבדל בין המימדים grabFrame() ו-takePhoto() תוצאות.

השיטה takePhoto() מאפשרת גישה לרזולוציה המקסימלית של המצלמה.

grabFrame() פשוט לוקחת את הפעם הבאה של VideoFrame בMediaStreamTrack בתוך תהליך הרינדור, ואילו takePhoto() מפריע ל-MediaStream, מגדיר מחדש את המצלמה, מצלמת את התמונה (בדרך כלל בפורמט דחוס, כלומר Blob), ואז ממשיך את MediaStreamTrack. בעצם, ש-takePhoto() נותן גישה לרזולוציה המלאה של תמונת סטילס ביכולות של המצלמה. בעבר היה אפשר רק 'לצלם' לפי מפעילה את drawImage() ברכיב canvas, כאשר המקור הוא סרטון (בהתאם דוגמה כאן).

מידע נוסף זמין בקטע README.md.

בהדגמה הזו, המידות של <canvas> מוגדרות לרזולוציה של הסרטון ואילו הגודל הטבעי של <img> הוא הערך המקסימלי של תמונת סטילס. הרזולוציה של המצלמה. שירות CSS, כמובן, משמש להגדרת התצוגה בגודל של שניהם.

אפשר לקבל ולהגדיר את כל רזולוציות המצלמה הזמינות לתמונות סטילס באמצעות הערכים MediaSettingsRange עבור PhotoCapabilities.imageHeight imageWidth. שים לב שמגבלות המינימום והמקסימום של רוחב וגובה עבור getUserMedia() מיועדות לסרטון, והוא (כפי שהסברנו) עשוי להיות שונה מ- יכולות של המצלמה לתמונות סטילס. במילים אחרות, ייתכן שלא תוכלו גישה ליכולות הרזולוציה המלאה של המכשיר כאשר getUserMedia() לקנבס. הדגמת האילוצים לפתרון הבעיה של WebRTC מראה איך להגדיר אילוצים של getUserMedia() לצורך פתרון.

רוצה להוסיף עוד משהו?

  • Form Detection API עובד טוב עם צילום תמונה: אפשר לקרוא שוב ושוב אל grabFrame() ImageBitmaps ל-FaceDetector או ל-BarcodeDetector. מידע נוסף על API מתוך הפוסט בבלוג של פול קינלן.

  • אפשר לגשת אל הפלאש של המצלמה (האור במכשיר) דרך FillLightMode אינץ' PhotoCapabilities , אבל ניתן למצוא את מצב לפיד (הפלאש פועל כל הזמן) MediaTrackCapabilities.

הדגמות ודוגמאות קוד

תמיכה

  • Chrome 59 ב-Android ובמחשב.
  • Chrome Canary בגרסאות 59 ומטה של Android ומחשבים תכונות ניסיוניות של פלטפורמת האינטרנט הופעלו.

למידע נוסף