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

ميزة "التقاط الصور" هي واجهة برمجة تطبيقات لالتقاط الصور الثابتة وضبط إعدادات جهاز الكاميرا. تتوفّر واجهة برمجة التطبيقات هذه في الإصدار 59 من Chrome على أجهزة 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));

جارٍ الإعداد

يمكن ضبط إعدادات الكاميرا "البث المباشر" من خلال قيود 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 داخل عملية العرض، بينما يقاطع 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.

نماذج تجريبية وعينات تعليمات برمجية

الدعم

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

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