التقاط الصور والتحكّم في إعدادات الكاميرا

ميغيل كاساس سانشيز
فرانسوا بوفورت
فرانسوا بوفورت

إنّ ميزة "التقاط الصور" هي واجهة برمجة تطبيقات لالتقاط صور ثابتة وضبط إعدادات أجهزة الكاميرا. تتوفّر واجهة برمجة التطبيقات هذه في Chrome 59 على أجهزة Android وأجهزة الكمبيوتر المكتبي. كذلك نشرنا مكتبة polyfill ImageCapture.

تتيح واجهة برمجة التطبيقات التحكم في ميزات الكاميرا مثل التكبير/التصغير والسطوع والتباين وISO وتوازن اللون الأبيض. وأفضل ما في الأمر هو أن ميزة "التقاط الصور" تتيح لك الوصول إلى إمكانات الدقة الكاملة لأي كاميرا أو كاميرا ويب متاحة في الجهاز. استخدمت التقنيات السابقة لالتقاط الصور على الويب لقطات فيديو بدرجة دقة أقل من تلك المتاحة للصور الثابتة.

يتم إنشاء الكائن ImageCapture باستخدام MediaStreamTrack كمصدر. وعندئذٍ تتضمن واجهة برمجة التطبيقات طريقتين للالتقاط takePhoto() وgrabFrame() بالإضافة إلى طرق لاسترداد إمكانيات وإعدادات الكاميرا وتغيير تلك الإعدادات.

أشغال

يمكن لواجهة برمجة تطبيقات التقاط الصور الوصول إلى كاميرا من خلال 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));

جارٍ الإعداد

يمكن ضبط إعدادات الكاميرا "مباشر" من خلال MediaStreamTrack's applyConstraints() القيود في المعاينة، على سبيل المثال:

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 داخل عملية العرض، في حين يقاطع takePhoto() عنصر MediaStream ويعيد ضبط الكاميرا ويلتقط الصورة (بتنسيق مضغوط عادةً، وبالتالي Blob) ثم يستأنف تشغيل MediaStreamTrack. وهذا يعني في الواقع أنّ takePhoto() يتيح الوصول إلى إمكانات دقة الصور الثابتة الكاملة في الكاميرا. في السابق، لم يكن بالإمكان "التقاط صورة" سوى من خلال استدعاء drawImage() على عنصر canvas، واستخدام فيديو كمصدر (كما في المثال هنا).

ويمكن العثور على مزيد من المعلومات في القسم README.md.

في هذا العرض التوضيحي، يتم ضبط الأبعاد <canvas> على درجة دقة الفيديو المضمّن، في حين يمثّل الحجم الطبيعي لـ <img> الحدّ الأقصى لدقة الصور الثابتة للكاميرا. يتم استخدام CSS بالطبع لتعيين حجم العرض لكليهما.

يمكن الحصول على النطاق الكامل لدرجات الدقة المتاحة في الكاميرا للصور الثابتة وضبطه باستخدام قيمتَي MediaSettingsRange للسمتَين PhotoCapabilities.imageHeight وimageWidth. يُرجى العِلم أنّ الحدّ الأدنى والحد الأقصى لقيود العرض والارتفاع في getUserMedia() يتناسبان مع الفيديو، وقد تختلف (كما ناقشنا سابقًا) عن إمكانات الكاميرا للصور الثابتة. بمعنى آخر، قد لا تتمكّن من الاستفادة من إمكانات الدقة الكاملة لجهازك عند حفظ عناصر من getUserMedia() على لوحة صورة مطبوعة. يعرض العرض التوضيحي لقيود حلّ مشكلة WebRTC كيفية ضبط قيود getUserMedia() لحلّ المشكلة.

هل من خطوات أخرى تريد تنفيذها؟

  • تعمل Shape Detection API بشكل جيد مع ميزة "التقاط الصور": يمكن طلب grabFrame() بشكل متكرر لخلاصة ImageBitmap إلى FaceDetector أو BarcodeDetector. تعرّف على مزيد من المعلومات حول واجهة برمجة التطبيقات من خلال مشاركة مدونة "بول كينلان".

  • يمكن الوصول إلى فلاش الكاميرا (ضوء الجهاز) من خلال FillLightMode في PhotoCapabilities ، ولكنّ وضع الكشاف (الفلاش مشغَّل باستمرار) يمكنك العثور عليه في MediaTrackCapabilities.

العروض التوضيحية وعيّنات التعليمات البرمجية

الدعم

  • Chrome 59 على Android وأجهزة الكمبيوتر المكتبي.
  • Chrome Canary على أجهزة Android والكمبيوتر المكتبي التي تسبق الإصدار 59 مع تفعيل ميزات الإصدار التجريبي للنظام الأساسي للويب.

التعرف على المزيد