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

צילום תמונות הוא ממשק 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 שמספק גישה ליכולות המצלמה שזמינות במצב 'לא בשידור חי'. במקביל, החל מגרסה 61 של Chrome, האובייקט 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));

הגדרות המצלמה של "Non-Live" נקבעות באמצעות המילון האופציונלי PhotoSettings של takePhoto(), לדוגמה:

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 במכשירי Android ובמחשבים מגרסה 59 ומטה, כאשר תכונות של פלטפורמת אינטרנט ניסיונית מופעלות.

פרטים נוספים