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

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

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

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

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

בנייה

ל-Image Capture 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);
}

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

צילום

אפשר לצלם בשתי דרכים: במסגרת מלאה ובתמונת מצב מהירה. הפונקציה 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));

הגדרות המצלמה מסוג 'לא בשידור חי' מוגדרות באמצעות המילון האופציונלי 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 בתוך תהליך ה-renderer, בעוד ש-takePhoto() משבש את MediaStream, מגדיר מחדש את המצלמה, מצלם את התמונה (בדרך כלל בפורמט דחוס, ולכן Blob) ואז ממשיך את MediaStreamTrack. במילים אחרות, takePhoto() מאפשרת גישה לכל רזולוציות התמונות הסטטיות של המצלמה. בעבר, אפשר היה 'לצלם תמונה' רק על ידי קריאה ל-drawImage() ברכיב canvas, באמצעות סרטון כמקור (כמו בדוגמה כאן).

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

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

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

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

  • Shape Detection API פועל היטב עם Image Capture: אפשר להפעיל את grabFrame() שוב ושוב כדי להזין ImageBitmap ל-FaceDetector או ל-BarcodeDetector. מידע נוסף על ה-API זמין בפוסט הזה בבלוג של Paul Kinlan.

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

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

תמיכה

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

למידע נוסף