اتجاهات الكاميرا

إذا كان تطبيق Android يستخدم الكاميرات، يجب مراعاة بعض الاعتبارات الخاصة عند التعامل مع اتجاهات الشاشة. يفترض هذا المستند أنّك على دراية بالمفاهيم الأساسية لواجهة برمجة التطبيقات camera2 في Android. يمكنك الاطّلاع على مشاركة المدونة أو الملخّص للحصول على نظرة عامة حول Camera2. ننصحك أيضًا بتجربة كتابة تطبيق كاميرا أولاً قبل الاطّلاع على هذا المستند.

الخلفية

إنّ التعامل مع اتجاهات العرض في تطبيقات الكاميرا على Android أمر معقّد ويجب مراعاة العوامل التالية:

  • الاتجاه الطبيعي: هو اتجاه العرض عندما يكون الجهاز في الوضع "العادي" لتصميم الجهاز، ويكون عادةً عموديًا للهواتف الجوّالة وأفقيًا لأجهزة الكمبيوتر المحمول.
  • اتجاه أداة الاستشعار: اتجاه أداة الاستشعار المثبَّتة فعليًا على الجهاز
  • دوران الشاشة: مقدار دوران الجهاز فعليًا عن الاتجاه الطبيعي
  • حجم عدسة الكاميرا: حجم عدسة الكاميرا المستخدَمة لعرض معاينة الكاميرا
  • حجم الصورة الناتج عن الكاميرا

تؤدي هذه العوامل مجتمعةً إلى توفير عدد كبير من إعدادات واجهة المستخدم والمعاينة المحتملة لتطبيقات الكاميرا. يهدف هذا المستند إلى توضيح كيفية تنقّل المطوّرين بين هذه الحالات والتعامل بشكل صحيح مع اتجاهات الكاميرا في تطبيقات Android.

لتسهيل الأمر قليلاً، افترض أنّ جميع الأمثلة تتضمّن كاميرا خلفية ما لم يُذكر خلاف ذلك. بالإضافة إلى ذلك، تمّت محاكاة جميع الصور التالية لجعل الرسوم التوضيحية أكثر وضوحًا.

لمحة عن الاتجاهات

الاتجاه الطبيعي

يتم تحديد الاتجاه الطبيعي على أنّه اتجاه العرض عندما يكون الجهاز في الوضع الذي يُتوقّع أن يكون فيه عادةً. بالنسبة إلى الهواتف، يكون الاتجاه الطبيعي غالبًا هو الوضع العمودي. بعبارة أخرى، تكون الهواتف أضيق وأطول. بالنسبة إلى أجهزة الكمبيوتر المحمول، يكون الاتجاه الطبيعي أفقيًا، ما يعني أنّ عرضها أطول من ارتفاعها. تختلف الأجهزة اللوحية عن ذلك، إذ يمكن استخدامها في الوضع العمودي أو الأفقي.

صورة توضيحية للاتجاه الطبيعي مع هاتف وكمبيوتر محمول وعنصر من جهة المراقب

اتجاه جهاز الاستشعار

من الناحية الفنية، يتم قياس اتجاه المستشعر بالدرجات التي يجب تدوير صورة الإخراج من المستشعر في اتجاه عقارب الساعة لتتطابق مع الاتجاه الطبيعي للجهاز. بعبارة أخرى، اتجاه المستشعر هو عدد الدرجات التي يتم تدوير المستشعر بها عكس اتجاه عقارب الساعة قبل تركيبه على الجهاز. عند النظر إلى الشاشة، يبدو أنّ الدوران يتم في اتجاه عقارب الساعة، وذلك لأنّ مستشعر الكاميرا الخلفية مثبّت على الجانب "الخلفي" من الجهاز.

وفقًا لتعريف التوافق مع نظام التشغيل Android 10، القسم 7.5.5 "اتجاه الكاميرا"، "يجب توجيه الكاميرات الأمامية والخلفية بحيث يتوافق البُعد الأطول للكاميرا مع البُعد الأطول للشاشة".

تكون مخازن الإخراج المؤقتة من الكاميرات بحجم الوضع الأفقي. بما أنّ الاتجاه الطبيعي للهواتف هو عادةً الوضع العمودي، يكون اتجاه المستشعر عادةً 90 أو 270 درجة من الاتجاه الطبيعي ليتطابق الجانب الطويل من المخزن المؤقت للإخراج مع الجانب الطويل من الشاشة. يختلف اتجاه المستشعر للأجهزة التي يكون اتجاهها الطبيعي أفقيًا، مثل أجهزة Chromebook. في هذه الأجهزة، يتم وضع مستشعرات الصور مرة أخرى بحيث يتطابق الجانب الطويل من المخزن المؤقت للإخراج مع الجانب الطويل من الشاشة. بما أنّ كلتا الشاشتين بحجم أفقي، تتطابق الاتجاهات ويكون اتجاه المستشعر 0 أو 180 درجة.

صورة توضيحية للاتجاه الطبيعي مع هاتف وكمبيوتر محمول وعنصر من جهة المراقب

توضّح الرسومات التوضيحية التالية كيف تبدو الأشياء من وجهة نظر مراقب ينظر إلى شاشة الجهاز:

صورة توضيحية لاتجاه أداة الاستشعار مع هاتف وكمبيوتر محمول وعنصر من جهة المراقب

لنفترض المشهد التالي:

مشهد يضم تمثالاً صغيرًا لطيفًا لنظام التشغيل Android (bugdroid)

الهاتف كمبيوتر محمول
صورة توضيحية من خلال مستشعر الكاميرا الخلفية على هاتف صورة توضيحية من خلال مستشعر الكاميرا الخلفية على كمبيوتر محمول

بما أنّ اتجاه المستشعر يكون عادةً 90 أو 270 درجة على الهواتف، وبدون مراعاة اتجاه المستشعر، ستظهر الصور التي تحصل عليها على النحو التالي:

الهاتف كمبيوتر محمول
صورة توضيحية من خلال مستشعر الكاميرا الخلفية على هاتف صورة توضيحية من خلال مستشعر الكاميرا الخلفية على كمبيوتر محمول

لنفترض أنّ اتجاه أداة الاستشعار بعكس اتجاه عقارب الساعة مخزَّن في المتغيّر sensorOrientation. للتعويض عن اتجاه أداة الاستشعار، عليك تدوير مخازن البيانات المؤقتة للناتج بمقدار `sensorOrientation` في اتجاه عقارب الساعة لإعادة محاذاة الاتجاه مع الاتجاه الطبيعي للجهاز.

في نظام التشغيل Android، يمكن للتطبيقات استخدام TextureView أو SurfaceView لعرض معاينة الكاميرا. يمكن لكليهما التعامل مع اتجاه أجهزة الاستشعار إذا كانت التطبيقات تستخدمهما بشكل صحيح. سنشرح بالتفصيل في الأقسام التالية كيفية مراعاة اتجاه المستشعر.

تدوير شاشة العرض

يتم تحديد تدوير الشاشة رسميًا من خلال تدوير الرسومات المعروضة على الشاشة، وهو الاتجاه المعاكس للتدوير الفعلي للجهاز من اتجاهه الطبيعي. تفترض الأقسام التالية أنّ جميع عمليات تدوير الشاشة هي مضاعفات للرقم 90. إذا استرجعت دوران الشاشة بالدرجات المطلقة، قرِّبها إلى أقرب قيمة من {0, 90, 180, 270}.

يشير "اتجاه العرض" في الأقسام التالية إلى ما إذا كان الجهاز يتم حمله فعليًا في الوضع الأفقي أو الوضع الرأسي، وهو يختلف عن "تدوير الشاشة".

لنفترض أنّك أدرت الأجهزة بمقدار 90 درجة عكس اتجاه عقارب الساعة من مواضعها السابقة كما هو موضّح في الشكل التالي:

صورة توضيحية لتدوير الشاشة بمقدار 90 درجة مع هاتف وكمبيوتر محمول وعنصر من جهة المراقب

بافتراض أنّه تم تدوير مخازن الإخراج المؤقتة استنادًا إلى اتجاه أداة الاستشعار، ستحصل بعد ذلك على مخازن الإخراج المؤقتة التالية:

الهاتف كمبيوتر محمول
صورة توضيحية من خلال مستشعر الكاميرا الخلفية على هاتف صورة توضيحية من خلال مستشعر الكاميرا الخلفية على كمبيوتر محمول

إذا تم تخزين دوران الشاشة في المتغيّر displayRotation، للحصول على الصورة الصحيحة، عليك تدوير مخازن الإخراج المؤقتة بمقدار displayRotation عكس اتجاه عقارب الساعة.

بالنسبة إلى الكاميرات الأمامية، يعمل تدوير الشاشة على مخازن الصور المؤقتة في الاتجاه المعاكس بالنسبة إلى الشاشة. إذا كنت تتعامل مع كاميرا أمامية، عليك تدوير المخازن المؤقتة بمقدار displayRotatation في اتجاه عقارب الساعة.

المحاذير

يقيس دوران شاشة العرض مقدار دوران الجهاز عكس اتجاه عقارب الساعة. ولا ينطبق ذلك على جميع واجهات برمجة التطبيقات الخاصة بالاتجاه/التدوير.

على سبيل المثال:

من المهم ملاحظة أنّ تدوير الشاشة يرتبط بالاتجاه الطبيعي. على سبيل المثال، إذا أدرت الهاتف بزاوية 90 أو 270 درجة، ستحصل على شاشة على شكل أفقي. في المقابل، ستحصل على شاشة عمودية الشكل إذا أدرت جهاز كمبيوتر محمولًا بالمقدار نفسه. ويجب أن تضع التطبيقات ذلك في اعتبارها دائمًا وألا تفترض أبدًا الاتجاه الطبيعي للجهاز.

أمثلة

لنستخدِم الأشكال السابقة لتوضيح ما هي الاتجاهات وعمليات التدوير.

صورة توضيحية للاتجاهات المدمجة مع هاتف وجهاز كمبيوتر محمول غير مُدارَين وكائن

الهاتف كمبيوتر محمول
الاتجاه الطبيعي = عمودي الاتجاه الطبيعي = أفقي
Sensor Orientation = 90 Sensor Orientation = 0
Display Rotation = 0 Display Rotation = 0
اتجاه العرض = عمودي اتجاه العرض = أفقي

صورة توضيحية للاتجاهات المدمجة مع هاتف وجهاز كمبيوتر محمول غير مُدارَين وكائن

الهاتف كمبيوتر محمول
الاتجاه الطبيعي = عمودي الاتجاه الطبيعي = أفقي
Sensor Orientation = 90 Sensor Orientation = 0
Display Rotation = 90 Display Rotation = 90
اتجاه العرض = أفقي اتجاه العرض = عمودي

حجم عدسة الكاميرا

يجب أن تغيّر التطبيقات حجم عدسة الكاميرا دائمًا استنادًا إلى الاتجاه والتدوير ودقة الشاشة. بشكل عام، يجب أن تجعل التطبيقات اتجاه عدسة الكاميرا مطابقًا لاتجاه العرض الحالي. بعبارة أخرى، يجب أن تتطابق الحافة الطويلة لنافذة العرض مع الحافة الطويلة للشاشة.

حجم إخراج الصورة حسب الكاميرا

عند اختيار حجم إخراج الصورة للمعاينة، يجب اختيار حجم يساوي حجم "نافذة العرض" أو أكبر منه قليلاً كلما أمكن ذلك. بشكل عام، لا تريد أن يتم توسيع نطاق مخازن الإخراج المؤقتة، لأنّ ذلك سيؤدي إلى تشوّه الصورة. لا ننصحك أيضًا باختيار حجم كبير جدًا لأنّ ذلك قد يقلّل من الأداء ويستهلك المزيد من طاقة البطارية.

اتجاه JPEG

لنبدأ بموقف شائع، وهو التقاط صورة بتنسيق JPEG. في واجهة برمجة التطبيقات camera2، يمكنك تمرير JPEG_ORIENTATION في طلب الالتقاط لتحديد مقدار التدوير المطلوب لملفات JPEG الناتجة في اتجاه عقارب الساعة.

إليك ملخصًا سريعًا لما ذكرناه:

  • للتعامل مع اتجاه المستشعر، عليك تدوير مخزن الصور المؤقت بزاوية sensorOrientation درجة في اتجاه عقارب الساعة.
  • للتعامل مع تدوير الشاشة، عليك تدوير المخزن المؤقت بمقدار displayRotation عكس اتجاه عقارب الساعة للكاميرات الخلفية، وفي اتجاه عقارب الساعة للكاميرات الأمامية.

بإضافة العاملَين، يصبح مقدار التدوير في اتجاه عقارب الساعة

  • sensorOrientation - displayRotation للكاميرات الخلفية
  • sensorOrientation + displayRotation للكاميرات الأمامية

يمكنك الاطّلاع على نموذج الرمز البرمجي لهذه المنطق في مستندات JPEG_ORIENTATION. يُرجى العِلم أنّ deviceOrientation في نموذج الرمز البرمجي الخاص بالمستندات يستخدم دوران الجهاز في اتجاه عقارب الساعة. وبالتالي، تكون إشارات تدوير الشاشة معكوسة.

معاينة

ماذا عن معاينة الكاميرا؟ هناك طريقتان رئيسيتان يمكن للتطبيق من خلالهما عرض معاينة للكاميرا: SurfaceView وTextureView. ويتطلّب كل منهما أساليب مختلفة للتعامل مع الاتجاه بشكل صحيح.

SurfaceView

يُنصح عمومًا باستخدام SurfaceView لمعاينات الكاميرا، شرط ألا تحتاج إلى معالجة مخازن المعاينة المؤقتة أو تحريكها. وهي أكثر فعالية وأقل استهلاكًا للموارد من TextureView.

يسهل أيضًا ترتيب SurfaceView نسبيًا. ما عليك سوى الاهتمام بنسبة العرض إلى الارتفاع في SurfaceView الذي تعرض عليه معاينة الكاميرا.

المصدر

تحت SurfaceView، يدير نظام التشغيل Android مخازن الإخراج المؤقتة لتتطابق مع اتجاه العرض للجهاز. وبعبارة أخرى، يأخذ في الاعتبار كلاً من اتجاه المستشعر وتدوير الشاشة. بشكل أبسط، عندما تكون شاشة العرض أفقية، نحصل على معاينة أفقية أيضًا، والعكس صحيح بالنسبة إلى الوضع العمودي.

يوضّح الجدول التالي ذلك. من المهم أن تتذكّر هنا أنّ تدوير الشاشة وحده لا يحدّد اتجاه المصدر.

تدوير شاشة العرض الهاتف (الاتجاه الطبيعي = عمودي) كمبيوتر محمول (الاتجاه الطبيعي = أفقي)
0 صورة عمودية يظهر فيها رأس Bugdroid متّجهًا للأعلى صورة أفقية يظهر فيها رأس bugdroid متّجهًا للأعلى
90 صورة أفقية يظهر فيها رأس bugdroid متّجهًا للأعلى صورة عمودية يظهر فيها رأس Bugdroid متّجهًا للأعلى
180 صورة عمودية يظهر فيها رأس Bugdroid متّجهًا للأعلى صورة أفقية يظهر فيها رأس bugdroid متّجهًا للأعلى
270 صورة أفقية يظهر فيها رأس bugdroid متّجهًا للأعلى صورة عمودية يظهر فيها رأس Bugdroid متّجهًا للأعلى

التنسيق

كما ترى، تعالج SurfaceView بعض الأمور الصعبة نيابةً عنّا. ولكن عليك الآن مراعاة حجم عدسة الكاميرا، أو حجم المعاينة التي تريدها على الشاشة. تغيّر SurfaceView حجم المخزن المؤقت المصدر تلقائيًا ليتناسب مع أبعاده. عليك التأكّد من أنّ نسبة العرض إلى الارتفاع في عدسة الكاميرا هي نفسها نسبة العرض إلى الارتفاع في sourcebuffer. على سبيل المثال، إذا حاولت ملاءمة معاينة على شكل صورة شخصية في SurfaceView على شكل أفقي، سيظهر لك شيء مشوّه على النحو التالي:

صورة توضيحية تعرض bugdroid ممدودًا نتيجة ملاءمة معاينة بشكل عمودي في إطار عرض بشكل أفقي

بشكل عام، يجب أن تكون نسبة العرض إلى الارتفاع (أي العرض/الارتفاع) في عدسة الكاميرا مماثلة لنسبة العرض إلى الارتفاع في المصدر. إذا كنت لا تريد قص الصورة في عدسة الكاميرا (أي إزالة بعض وحدات البكسل لإصلاح العرض)، هناك حالتان يجب أخذهما في الاعتبار، وهما عندما يكون aspectRatioActivity أكبر من aspectRatioSource وعندما يكون أصغر من أو يساوي aspectRatioSource

aspectRatioActivity > aspectRatioSource

يمكنك التفكير في الحالة على أنّ النشاط "أوسع نطاقًا". في ما يلي مثال على نشاط بنسبة عرض إلى ارتفاع تبلغ 16:9 ومصدر بنسبة عرض إلى ارتفاع تبلغ 4:3.

aspectRatioActivity = 16/9 ≈ 1.78
aspectRatioSource = 4/3 ≈ 1.33

أولاً، يجب أن تكون نسبة العرض إلى الارتفاع في عدسة الكاميرا 4:3 أيضًا. بعد ذلك، عليك ضبط المصدر ونافذة العرض في النشاط على النحو التالي:

صورة توضيحية لنشاط تكون نسبة العرض إلى الارتفاع فيه أكبر من نسبة العرض إلى الارتفاع في عدسة الكاميرا الداخلية

في هذه الحالة، يجب أن يتطابق ارتفاع شاشة العرض مع ارتفاع النشاط، مع جعل نسبة العرض إلى الارتفاع لشاشة العرض مماثلة لنسبة العرض إلى الارتفاع للمصدر. الرمز الزائف هو كما يلي:

viewfinderHeight = activityHeight;
viewfinderWidth = activityHeight * aspectRatioSource;
aspectRatioActivity ≤ aspectRatioSource

الحالة الأخرى هي عندما يكون النشاط "أضيق" أو "أطول". يمكننا إعادة استخدام المثال السابق، باستثناء أنّك في المثال التالي ستدوّر الجهاز بمقدار 90 درجة، ما يجعل نسبة العرض إلى الارتفاع للنشاط 9:16 وللمصدر 3:4.

aspectRatioActivity = 9/16 = 0.5625
aspectRatioSource = 3/4 = 0.75

في هذه الحالة، عليك ملاءمة المصدر ونافذة العرض في النشاط على النحو التالي:

صورة توضيحية لنشاط تكون نسبة العرض إلى الارتفاع فيه أقل من نسبة العرض إلى الارتفاع في عدسة الكاميرا الداخلية

يجب أن يتطابق عرض إطار العرض مع عرض النشاط (بدلاً من الارتفاع في الحالة السابقة) مع الحرص على أن تكون نسبة العرض إلى الارتفاع لإطار العرض مماثلة لنسبة العرض إلى الارتفاع للمصدر. الرمز الزائف:

viewfinderWidth = activityWidth;
viewfinderHeight = activityWidth / aspectRatioSource;
القص

تتجاوز السمة AutoFitSurfaceView.kt (github) من نماذج Camera2 السمة SurfaceView وتتعامل مع نسب العرض إلى الارتفاع غير المتطابقة باستخدام صورة تساوي حجم النشاط أو "أكبر منه قليلاً" في كلا البُعدَين، ثم تقص المحتوى الذي يتجاوز الحجم. ويكون ذلك مفيدًا للتطبيقات التي تريد أن تغطي المعاينة النشاط بأكمله أو أن تملأ تمامًا عرضًا بأبعاد ثابتة، بدون تشويه الصورة.

Caveat

يحاول المثال السابق الاستفادة إلى أقصى حد من مساحة الشاشة من خلال جعل المعاينة أكبر قليلاً من النشاط حتى لا تترك أي مساحة غير مملوءة. يعتمد ذلك على حقيقة أنّ الأجزاء المتجاوزة يتم قصّها بواسطة التصميم الرئيسي (أو ViewGroup) تلقائيًا. يتوافق السلوك مع RelativeLayout وLinearLayout، ولكن ليس مع ConstraintLayout. قد تعيد ConstraintLayout تغيير حجم طرق العرض الفرعية لتلائم التنسيق، ما يؤدي إلى إيقاف تأثير "القص من الوسط" المقصود وتشويه المعاينات. يمكنك الرجوع إلى هذا التعديل كمرجع.

TextureView

تمنح TextureView أكبر قدر من التحكّم في محتوى معاينة الكاميرا، ولكنّها تتطلّب أداءً عاليًا. ويتطلّب أيضًا المزيد من العمل لعرض معاينة الكاميرا بشكل صحيح تمامًا.

المصدر

تحت TextureView، يدير نظام التشغيل Android مخازن الإخراج المؤقتة وفقًا لاتجاه المستشعر لتتطابق مع الاتجاه الطبيعي للجهاز. على الرغم من أنّ TextureView يتعامل مع اتجاه أداة الاستشعار، إلا أنّه لا يتعامل مع عمليات تدوير الشاشة. تعمل هذه السمة على محاذاة مخازن الإخراج المؤقتة مع الاتجاه الطبيعي للجهاز، ما يعني أنّه عليك التعامل مع عمليات تدوير الشاشة بنفسك.

يوضّح الجدول التالي ذلك. جرِّب تدوير الأشكال حسب دوران شاشة العرض المقابل، وستحصل في الواقع على الأشكال نفسها في SurfaceView.

تدوير شاشة العرض الهاتف (الاتجاه الطبيعي = عمودي) كمبيوتر محمول (الاتجاه الطبيعي = أفقي)
0 صورة عمودية يظهر فيها رأس Bugdroid متّجهًا للأعلى صورة أفقية يظهر فيها رأس bugdroid متّجهًا للأعلى
90 صورة بشكل عمودي يظهر فيها رأس Bugdroid متّجهًا إلى اليسار صورة أفقية يظهر فيها رأس Bugdroid متّجهًا إلى اليسار
180 صورة أفقية يظهر فيها رأس bugdroid متّجهًا للأعلى صورة عمودية يظهر فيها رأس Bugdroid متّجهًا للأعلى
270 صورة أفقية يظهر فيها رأس bugdroid متّجهًا للأعلى صورة عمودية يظهر فيها رأس Bugdroid متّجهًا للأعلى

التنسيق

قد يكون التنسيق معقّدًا بعض الشيء في حالة TextureView. لقد تم اقتراح استخدام مصفوفة تحويل لـ TextureView في السابق، ولكن هذه الطريقة لا تعمل على جميع الأجهزة. نقترح عليك اتّباع الخطوات الموضّحة هنا بدلاً من ذلك.

في ما يلي الخطوات الثلاث اللازمة لتحديد موضع المعاينات بشكل صحيح على TextureView:

  1. اضبط حجم TextureView ليكون مطابقًا لحجم المعاينة الذي تم اختياره.
  2. يمكنك إعادة ضبط حجم TextureView الذي قد يكون ممتدًا إلى الأبعاد الأصلية للمعاينة.
  3. تدوير TextureView بمقدار displayRotation عكس اتجاه عقارب الساعة

لنفترض أنّ لديك هاتفًا يمكن تدوير شاشته بمقدار 90 درجة.

صورة توضيحية لهاتف تم تدوير شاشته بمقدار 90 درجة، ويظهر عليه كائن

1. اضبط حجم TextureView ليكون مطابقًا لحجم المعاينة الذي تم اختياره

لنفترض أنّ حجم المعاينة الذي اخترته هو previewWidth × previewHeight حيث previewWidth > previewHeight (يكون ناتج المستشعر على شكل أفقي بطبيعته). عند ضبط جلسة تسجيل، يجب استدعاء SurfaceTexture#setDefaultBufferSize(int width, height) لتحديد حجم المعاينة (previewWidth × previewHeight).

قبل استدعاء setDefaultBufferSize، من المهم ضبط حجم TextureView على `previewWidth × previewHeight` باستخدام View#setLayoutParams(android.view.ViewGroup.LayoutParams). والسبب في ذلك هو أنّ TextureView يستدعي SurfaceTexture#setDefaultBufferSize(int width, height) مع العرض والارتفاع اللذين تم قياسهما. إذا لم يتم ضبط حجم TextureView بشكلٍ صريح مسبقًا، قد يؤدي ذلك إلى حدوث حالة سباق. ويمكن الحدّ من ذلك من خلال ضبط حجم TextureView بشكل صريح أولاً.

قد لا يتطابق TextureView الآن مع أبعاد المصدر. في حالة الهواتف، يكون المصدر على شكل عمودي، في حين أنّ TextureView يكون على شكل أفقي بسبب layoutParams الذي تم ضبطه للتو. سيؤدي ذلك إلى عرض معاينات ممدودة، كما هو موضّح هنا:

صورة توضيحية لمعاينة على شكل صورة شخصية تمّ تمديدها لتناسب TextureView بالحجم نفسه الذي تمّ اختياره لحجم المعاينة

2. تغيير حجم TextureView الذي قد يكون ممدودًا إلى الأبعاد الأصلية للمعاينة

يجب مراعاة ما يلي لتغيير حجم المعاينة الممدّدة إلى أبعاد المصدر.

سمات المستند المصدر (sourceWidth × sourceHeight) هي:

  • previewHeight × previewWidth، إذا كان الاتجاه الطبيعي عموديًا أو عموديًا معكوسًا (يكون اتجاه المستشعر 90 أو 270 درجة)
  • previewWidth × previewHeight، إذا كان الاتجاه الطبيعي أفقيًا أو أفقيًا معكوسًا (يكون اتجاه جهاز الاستشعار 0 أو 180 درجة)

إصلاح مشكلة التمدّد باستخدام View#setScaleX(float) وView#setScaleY(float)

  • setScaleX(sourceWidth / previewWidth)
  • setScaleY(sourceHeight / previewHeight)

صورة توضيحية تعرض إجراء إعادة معاينة الصورة الممدّدة إلى أبعادها الأصلية

3. تدوير المعاينة بمقدار `displayRotation` عكس اتجاه عقارب الساعة

كما ذكرنا سابقًا، يجب تدوير المعاينة بمقدار displayRotation عكس عقارب الساعة للتعويض عن تدوير الشاشة.

يمكنك إجراء ذلك من خلال View#setRotation(float)

  • setRotation(-displayRotation)، لأنّها تُجري عملية تدوير في اتجاه عقارب الساعة.

صورة توضيحية تعرض إجراء تدوير المعاينة لتتطابق مع اتجاه عرض الجهاز

عيّنة
  • تعالج PreviewView من camerax في Jetpack تخطيط TextureView كما هو موضّح سابقًا. يضبط هذا الإجراء عملية التحويل باستخدام PreviewCorrector.

ملاحظة: إذا كنت قد استخدمت مصفوفة التحويل في TextureView في الرمز البرمجي، قد لا تبدو المعاينة صحيحة على جهاز أفقي بشكل طبيعي، مثل أجهزة Chromebook. من المحتمل أنّ مصفوفة التحويل تفترض بشكل غير صحيح أنّ اتجاه المستشعر هو 90 أو 270 درجة. يمكنك الرجوع إلى هذا التعديل على GitHub للحصول على حلّ بديل، ولكن ننصحك بشدة بنقل تطبيقك لاستخدام الطريقة الموضّحة هنا بدلاً من ذلك.