ক্যামেরা প্রিভিউ

দ্রষ্টব্য: এই পৃষ্ঠাটি Camera2 প্যাকেজকে বোঝায়। আপনার অ্যাপের Camera2 থেকে নির্দিষ্ট, নিম্ন-স্তরের বৈশিষ্ট্যের প্রয়োজন না হলে, আমরা CameraX ব্যবহার করার পরামর্শ দিই। CameraX এবং Camera2 উভয়ই Android 5.0 (API স্তর 21) এবং উচ্চতর সমর্থন করে।

অ্যান্ড্রয়েড ডিভাইসে ক্যামেরা এবং ক্যামেরা প্রিভিউ সবসময় একই অভিযোজনে থাকে না।

ডিভাইসটি ফোন, ট্যাবলেট বা কম্পিউটার যাই হোক না কেন ক্যামেরা একটি ডিভাইসে একটি স্থির অবস্থানে থাকে। ডিভাইসের অভিযোজন পরিবর্তিত হলে, ক্যামেরার অভিযোজন পরিবর্তিত হয়।

ফলস্বরূপ, ক্যামেরা অ্যাপগুলি সাধারণত ডিভাইসের ওরিয়েন্টেশন এবং ক্যামেরা প্রিভিউ এর আকৃতি অনুপাতের মধ্যে একটি স্থির সম্পর্ক অনুমান করে। যখন একটি ফোন পোর্ট্রেট ওরিয়েন্টেশনে থাকে, তখন ক্যামেরা প্রিভিউটি চওড়া হওয়ার চেয়ে লম্বা বলে ধরে নেওয়া হয়। যখন ফোন (এবং ক্যামেরা) ল্যান্ডস্কেপে ঘোরানো হয়, তখন ক্যামেরা প্রিভিউ লম্বা হওয়ার চেয়ে প্রশস্ত হবে বলে আশা করা হচ্ছে।

কিন্তু এই অনুমানগুলিকে নতুন ফর্ম ফ্যাক্টর দ্বারা চ্যালেঞ্জ করা হয়, যেমন ফোল্ডেবল ডিভাইস এবং ডিসপ্লে মোড যেমন মাল্টি-উইন্ডো এবং মাল্টি-ডিসপ্লে । ভাঁজযোগ্য ডিভাইসগুলি অভিযোজন পরিবর্তন না করেই প্রদর্শনের আকার এবং আকৃতির অনুপাত পরিবর্তন করে। মাল্টি-উইন্ডো মোড ক্যামেরা অ্যাপ্লিকেশানগুলিকে স্ক্রীনের একটি অংশে সীমাবদ্ধ করে, ডিভাইসের অভিযোজন নির্বিশেষে ক্যামেরার পূর্বরূপ স্কেল করে৷ মাল্টি-ডিসপ্লে মোড সেকেন্ডারি ডিসপ্লে ব্যবহার করতে সক্ষম করে যা প্রাথমিক ডিসপ্লের মতো একই ওরিয়েন্টেশনে নাও থাকতে পারে।

ক্যামেরা ওরিয়েন্টেশন

অ্যান্ড্রয়েড সামঞ্জস্যতার সংজ্ঞা নির্দিষ্ট করে যে একটি ক্যামেরা ইমেজ সেন্সর "অবশ্যই ওরিয়েন্টেড হতে হবে যাতে ক্যামেরার লম্বা ডাইমেনশন স্ক্রীনের লম্বা ডাইমেনশনের সাথে সারিবদ্ধ হয়। অর্থাৎ, যখন ডিভাইসটিকে ল্যান্ডস্কেপ ওরিয়েন্টেশনে রাখা হয়, ক্যামেরাগুলিকে অবশ্যই ল্যান্ডস্কেপ ওরিয়েন্টেশনে ছবি ক্যাপচার করতে হবে। এটি ডিভাইসের প্রাকৃতিক অভিযোজন নির্বিশেষে প্রযোজ্য, অর্থাৎ এটি ল্যান্ডস্কেপ-প্রাথমিক ডিভাইসের পাশাপাশি পোর্ট্রেট-প্রাথমিক ডিভাইসগুলিতে প্রযোজ্য৷"

ক্যামেরা টু স্ক্রিন বিন্যাস একটি ক্যামেরা অ্যাপে ক্যামেরা ভিউফাইন্ডারের ডিসপ্লে এরিয়াকে সর্বাধিক করে তোলে। এছাড়াও, ইমেজ সেন্সরগুলি সাধারণত ল্যান্ডস্কেপ অ্যাসপেক্ট রেশিওতে তাদের ডেটা আউটপুট করে, 4:3 সবচেয়ে সাধারণ।

ফোন এবং ক্যামেরা সেন্সর উভয়ই পোর্ট্রেট ওরিয়েন্টেশনে।
চিত্র 1. ফোন এবং ক্যামেরা সেন্সর অভিযোজনের সাধারণ সম্পর্ক।

ক্যামেরা সেন্সরের প্রাকৃতিক অভিযোজন হল ল্যান্ডস্কেপ। চিত্র 1-এ, অ্যান্ড্রয়েড সামঞ্জস্যের সংজ্ঞা মেনে চলার জন্য সামনের ক্যামেরার সেন্সর (ক্যামেরাটি ডিসপ্লের মতো একই দিকে নির্দেশ করে) ফোনের সাপেক্ষে 270 ডিগ্রি ঘোরানো হয়েছে।

অ্যাপ্লিকেশানগুলিতে সেন্সর ঘূর্ণন প্রকাশ করতে, camera2 API একটি SENSOR_ORIENTATION ধ্রুবক অন্তর্ভুক্ত করে৷ বেশিরভাগ ফোন এবং ট্যাবলেটের জন্য, ডিভাইসটি সামনের ক্যামেরাগুলির জন্য 270 ডিগ্রি এবং পিছনের দিকের ক্যামেরাগুলির জন্য 90 ডিগ্রি (ডিভাইসের পিছনের দৃষ্টিকোণ) একটি সেন্সর অভিযোজন রিপোর্ট করে, যা সেন্সরের দীর্ঘ প্রান্তকে সারিবদ্ধ করে ডিভাইসের দীর্ঘ প্রান্ত। ল্যাপটপ ক্যামেরা সাধারণত 0 বা 180 ডিগ্রি সেন্সর অভিযোজন রিপোর্ট করে।

যেহেতু ক্যামেরা ইমেজ সেন্সর তাদের ডেটা (একটি ইমেজ বাফার) সেন্সরের প্রাকৃতিক অভিযোজনে (ল্যান্ডস্কেপ) আউটপুট করে, তাই ডিভাইসের প্রাকৃতিক অভিযোজনে ক্যামেরা প্রিভিউটি সরাসরি দেখানোর জন্য ইমেজ বাফারটিকে SENSOR_ORIENTATION দ্বারা নির্দিষ্ট ডিগ্রির সংখ্যা ঘোরাতে হবে। সামনের দিকের ক্যামেরাগুলির জন্য, ঘূর্ণন ঘড়ির কাঁটার বিপরীতে হয়; পিছনের দিকের ক্যামেরার জন্য, ঘড়ির কাঁটার দিকে।

উদাহরণস্বরূপ, চিত্র 1-এ সামনের দিকের ক্যামেরার জন্য, ক্যামেরা সেন্সর দ্বারা উত্পাদিত চিত্র বাফারটি দেখতে এইরকম:

ক্যামেরা সেন্সরটি ল্যান্ডস্কেপ ওরিয়েন্টেশনে চিত্রের পাশে, উপরে বাম দিকে ঘোরানো হয়েছে।

চিত্রটিকে ঘড়ির কাঁটার বিপরীত দিকে 270 ডিগ্রি ঘোরাতে হবে যাতে পূর্বরূপের অভিযোজন ডিভাইসের অভিযোজনের সাথে মেলে:

পোর্ট্রেট ওরিয়েন্টেশনে ক্যামেরা সেন্সর ইমেজ খাড়া।

একটি পিছনের দিকের ক্যামেরা উপরের বাফারের মতো একই অভিযোজন সহ একটি চিত্র বাফার তৈরি করবে, তবে SENSOR_ORIENTATION হল 90 ডিগ্রি। ফলস্বরূপ, বাফারটি ঘড়ির কাঁটার দিকে 90 ডিগ্রি ঘোরানো হয়।

ডিভাইস ঘূর্ণন

ডিভাইস ঘূর্ণন একটি ডিভাইস তার স্বাভাবিক স্থিতিবিন্যাস থেকে ঘোরানো হয় ডিগ্রী সংখ্যা. উদাহরণস্বরূপ, ল্যান্ডস্কেপ ওরিয়েন্টেশনে একটি ফোনের ঘূর্ণনের দিকের উপর নির্ভর করে 90 বা 270 ডিগ্রির একটি ডিভাইস ঘূর্ণন থাকে।

একটি ক্যামেরা সেন্সর ইমেজ বাফারকে অবশ্যই ডিভাইসের ঘূর্ণন (সেন্সর ওরিয়েন্টেশনের ডিগ্রী ছাড়াও) একই সংখ্যক ডিগ্রী ঘোরাতে হবে যাতে ক্যামেরা প্রিভিউ সোজাভাবে দেখা যায়।

ওরিয়েন্টেশন গণনা

ক্যামেরা প্রিভিউয়ের সঠিক অভিযোজন সেন্সর ওরিয়েন্টেশন এবং ডিভাইসের ঘূর্ণন বিবেচনা করে।

সেন্সর ইমেজ বাফারের সামগ্রিক ঘূর্ণন নিম্নলিখিত সূত্র ব্যবহার করে গণনা করা যেতে পারে:

rotation = (sensorOrientationDegrees - deviceOrientationDegrees * sign + 360) % 360

যেখানে sign সামনের ক্যামেরার জন্য 1 , পিছনের দিকের ক্যামেরার জন্য -1

সামনের দিকের ক্যামেরাগুলির জন্য, ইমেজ বাফারটি ঘড়ির কাঁটার বিপরীত দিকে ঘোরানো হয় (সেন্সরের প্রাকৃতিক অভিযোজন থেকে)। পিছনের দিকের ক্যামেরার জন্য, সেন্সর ইমেজ বাফার ঘড়ির কাঁটার দিকে ঘোরানো হয়।

অভিব্যক্তি deviceOrientationDegrees * sign + 360 ডিভাইসের ঘূর্ণনকে ঘড়ির কাঁটার বিপরীত দিকে থেকে ঘড়ির কাঁটার দিকে রূপান্তর করে পিছনের দিকের ক্যামেরাগুলির জন্য (উদাহরণস্বরূপ, 270 ডিগ্রিকে ঘড়ির কাঁটার বিপরীতে 90 ডিগ্রিতে রূপান্তর করা)। মডুলো অপারেশন ফলাফলটিকে 360 ডিগ্রির কম স্কেল করে (উদাহরণস্বরূপ, ঘূর্ণনের 540 ডিগ্রি স্কেলিং 180)।

বিভিন্ন APIs ডিভাইস ঘূর্ণন ভিন্নভাবে রিপোর্ট করে:

  • Display#getRotation() ডিভাইসের ঘড়ির কাঁটার বিপরীতে ঘূর্ণন প্রদান করে (ব্যবহারকারীর দৃষ্টিকোণ থেকে)। এই মান উপরের সূত্রে প্লাগ করে।
  • OrientationEventListener#onOrientationChanged() ডিভাইসের ঘড়ির কাঁটার দিকে ঘোরানো (ব্যবহারকারীর দৃষ্টিকোণ থেকে) ফেরত দেয়। উপরের সূত্রে ব্যবহারের জন্য মানটি বাতিল করুন।

সামনের দিকে ক্যামেরা

ক্যামেরা প্রিভিউ এবং সেন্সর উভয়ই ল্যান্ডস্কেপ ওরিয়েন্টেশনে, সেন্সর ডান পাশে রয়েছে।
চিত্র 2. ফোন সহ ক্যামেরা প্রিভিউ এবং সেন্সর ল্যান্ডস্কেপ ওরিয়েন্টেশনে 90 ডিগ্রি পরিণত হয়েছে।

চিত্র 2-এ ক্যামেরা সেন্সর দ্বারা উত্পাদিত চিত্র বাফারটি এখানে রয়েছে:

ল্যান্ডস্কেপ ওরিয়েন্টেশনে ক্যামেরা সেন্সর, ইমেজ খাড়া।

সেন্সর অভিযোজন সামঞ্জস্য করতে বাফারটিকে ঘড়ির কাঁটার বিপরীত দিকে 270 ডিগ্রি ঘোরাতে হবে (উপরে ক্যামেরার অভিযোজন দেখুন):

ক্যামেরা সেন্সরটি পোর্টেট অভিযোজনে চিত্রের পাশে, উপরে ডানদিকে ঘোরানো হয়েছে।

তারপরে ডিভাইস ঘূর্ণনের জন্য বাফারটিকে ঘড়ির কাঁটার বিপরীতে অতিরিক্ত 90 ডিগ্রি ঘোরানো হয়, যার ফলে চিত্র 2-এ ক্যামেরা প্রিভিউটির সঠিক স্থিতিবিন্যাস দেখা যায়:

ক্যামেরা সেন্সর ল্যান্ডস্কেপ ওরিয়েন্টেশনে ইমেজ সোজা রেখে ঘোরানো হয়েছে।

এখানে ক্যামেরাটি ল্যান্ডস্কেপ ওরিয়েন্টেশনের ডানদিকে ঘুরছে:

ল্যান্ডস্কেপ ওরিয়েন্টেশনে ক্যামেরা প্রিভিউ এবং সেন্সর উভয়ই, তবে সেন্সরটি উল্টোদিকে।
ছবি 3. ফোন সহ ক্যামেরা প্রিভিউ এবং সেন্সর ল্যান্ডস্কেপ ওরিয়েন্টেশনে 270 ডিগ্রি (বা -90 ডিগ্রি) হয়ে গেছে।

এখানে ইমেজ বাফার আছে:

ক্যামেরা সেন্সর ল্যান্ডস্কেপ ওরিয়েন্টেশনে ইমেজ উলটো করে ঘোরানো হয়েছে।

সেন্সর ওরিয়েন্টেশনের জন্য সামঞ্জস্য করতে বাফারটিকে ঘড়ির কাঁটার বিপরীতে 270 ডিগ্রি ঘোরাতে হবে:

ক্যামেরা সেন্সরকে পোর্ট্রেট অভিযোজনে রেট করা হয়েছে ছবির পাশে, উপরে বাম দিকে।

তারপরে ডিভাইস ঘূর্ণনের জন্য বাফারটিকে ঘড়ির কাঁটার বিপরীতে আরও 270 ডিগ্রি ঘোরানো হয়:

ক্যামেরা সেন্সর ল্যান্ডস্কেপ ওরিয়েন্টেশনে ইমেজ সোজা রেখে ঘোরানো হয়েছে।

পিছনের দিকের ক্যামেরা

পিছনের দিকের ক্যামেরাগুলিতে সাধারণত 90 ডিগ্রি সেন্সর অভিযোজন থাকে (ডিভাইসের পিছনের দিক থেকে দেখা যায়)। ক্যামেরা প্রিভিউকে অভিমুখী করার সময়, সেন্সর ইমেজ বাফারটি সেন্সর ঘূর্ণনের পরিমাণ দ্বারা ঘড়ির কাঁটার দিকে ঘোরানো হয় (সামনের ক্যামেরাগুলির মতো ঘড়ির কাঁটার বিপরীতে নয়), এবং তারপরে চিত্রের বাফারটি ডিভাইস ঘূর্ণনের পরিমাণ দ্বারা ঘড়ির কাঁটার বিপরীত দিকে ঘোরানো হয়।

ল্যান্ডস্কেপ ওরিয়েন্টেশনে ক্যামেরা প্রিভিউ এবং সেন্সর উভয়ই, তবে সেন্সরটি উল্টোদিকে।
চিত্র 4. ল্যান্ডস্কেপ ওরিয়েন্টেশনে ব্যাক-ফেসিং ক্যামেরা সহ ফোন (270 বা -90 ডিগ্রি হয়ে গেছে)।

চিত্র 4-এ ক্যামেরা সেন্সর থেকে চিত্র বাফারটি এখানে রয়েছে:

ক্যামেরা সেন্সর ল্যান্ডস্কেপ ওরিয়েন্টেশনে ইমেজ উলটো করে ঘোরানো হয়েছে।

সেন্সর অভিযোজনের জন্য সামঞ্জস্য করতে বাফারটি ঘড়ির কাঁটার দিকে 90 ডিগ্রি ঘোরানো আবশ্যক:

ক্যামেরা সেন্সরকে পোর্ট্রেট অভিযোজনে রেট করা হয়েছে ছবির পাশে, উপরে বাম দিকে।

তারপরে ডিভাইস ঘূর্ণনের জন্য বাফারটিকে ঘড়ির কাঁটার বিপরীতে 270 ডিগ্রি ঘোরানো হয়:

ক্যামেরা সেন্সর ল্যান্ডস্কেপ ওরিয়েন্টেশনে ইমেজ সোজা রেখে ঘোরানো হয়েছে।

আকৃতির অনুপাত

ডিসপ্লে অ্যাসপেক্ট রেশিও পরিবর্তিত হয় যখন ডিভাইসের অভিযোজন পরিবর্তিত হয় কিন্তু এছাড়াও যখন ফোল্ডেবল ভাঁজ করা হয় এবং উন্মোচন করা হয়, যখন মাল্টি-উইন্ডো পরিবেশে উইন্ডোর আকার পরিবর্তন করা হয় এবং যখন সেকেন্ডারি ডিসপ্লেতে অ্যাপগুলি খোলা হয়।

ক্যামেরা সেন্সর ইমেজ বাফারকে অবশ্যই ওরিয়েন্টেশন এবং স্কেল করতে হবে যাতে ভিউফাইন্ডার UI এলিমেন্টের ওরিয়েন্টেশন এবং অ্যাসপেক্ট রেশিওর সাথে মেলে কারণ UI গতিশীলভাবে ওরিয়েন্টেশন পরিবর্তন করে—ডিভাইস পরিবর্তনের ওরিয়েন্টেশন সহ বা ছাড়া।

নতুন ফর্ম ফ্যাক্টরগুলিতে বা মাল্টি-উইন্ডো বা মাল্টি-ডিসপ্লে পরিবেশে, যদি আপনার অ্যাপ ধরে নেয় যে ক্যামেরা প্রিভিউতে ডিভাইসের (পোর্ট্রেট বা ল্যান্ডস্কেপ) একই অভিযোজন আছে আপনার প্রিভিউ ভুলভাবে ভিত্তিক, ভুলভাবে স্কেল করা বা উভয়ই হতে পারে।

পোর্ট্রেট ক্যামেরা প্রিভিউ সহ উন্মোচন করা ভাঁজযোগ্য ডিভাইসটি পাশে ঘুরিয়ে দেওয়া হয়েছে।
চিত্র 5. ফোল্ডেবল ডিভাইস পোর্ট্রেট থেকে ল্যান্ডস্কেপ অ্যাসপেক্ট রেশিওতে রূপান্তরিত হয় কিন্তু ক্যামেরা সেন্সর পোর্ট্রেট ওরিয়েন্টেশনে থাকে।

চিত্র 5-এ, অ্যাপ্লিকেশনটি ভুলভাবে ধরে নিয়েছে যে ডিভাইসটি ঘড়ির কাঁটার বিপরীতে 90 ডিগ্রি ঘোরানো হয়েছে; এবং তাই, অ্যাপটি একই পরিমাণ প্রিভিউ ঘুরিয়েছে।

ক্যামেরা প্রিভিউ সহ ভাঁজ করা যোগ্য ডিভাইসটি সোজা কিন্তু ভুল স্কেলিং এর কারণে স্কোয়াশ করা হয়েছে।
চিত্র 6. ফোল্ডেবল ডিভাইস পোর্ট্রেট থেকে ল্যান্ডস্কেপ অ্যাসপেক্ট রেশিওতে রূপান্তরিত হয় কিন্তু ক্যামেরা সেন্সর পোর্ট্রেট ওরিয়েন্টেশনে থাকে।

চিত্র 6-এ, অ্যাপটি ক্যামেরা প্রিভিউ UI উপাদানের নতুন মাত্রার সাথে মানানসই করার জন্য এটিকে সঠিকভাবে স্কেল করতে সক্ষম করতে ইমেজ বাফারের আকৃতির অনুপাতকে সামঞ্জস্য করেনি।

ফিক্সড-অরিয়েন্টেশন ক্যামেরা অ্যাপগুলি সাধারণত ফোল্ডেবল এবং অন্যান্য বড় স্ক্রীন ডিভাইস যেমন ল্যাপটপগুলিতে সমস্যা অনুভব করে:

ল্যাপটপে ক্যামেরা প্রিভিউ খাড়া কিন্তু অ্যাপ UI পাশে থাকে।
চিত্র 7. ল্যাপটপ কম্পিউটারে ফিক্সড-অরিয়েন্টেশন পোর্ট্রেট অ্যাপ।

চিত্র 7-এ, ক্যামেরা অ্যাপের UI পাশে রয়েছে কারণ অ্যাপটির অভিযোজন শুধুমাত্র প্রতিকৃতিতে সীমাবদ্ধ। ভিউফাইন্ডার চিত্রটি ক্যামেরা সেন্সরের সাথে সম্পর্কিত সঠিকভাবে ভিত্তিক।

ইনসেট পোর্ট্রেট মোড

ক্যামেরা অ্যাপগুলি যেগুলি মাল্টি-উইন্ডো মোড সমর্থন করে না ( resizeableActivity="false" ) এবং তাদের অভিযোজন সীমাবদ্ধ করে ( screenOrientation="portrait" বা screenOrientation="landscape" ) ক্যামেরাকে সঠিকভাবে অভিমুখী করতে বড় স্ক্রীন ডিভাইসে ইনসেট পোর্ট্রেট মোডে রাখা যেতে পারে পূর্বরূপ

ইনসেট পোর্ট্রেট মোড লেটারবক্স (ইনসেট) পোর্ট্রেট-শুধুমাত্র অ্যাপ্লিকেশানগুলি পোর্ট্রেট ওরিয়েন্টেশনে, যদিও ডিসপ্লে অ্যাসপেক্ট রেশিও ল্যান্ডস্কেপ। ল্যান্ডস্কেপ-শুধুমাত্র অ্যাপ্লিকেশানগুলি ল্যান্ডস্কেপ ওরিয়েন্টেশনে লেটারবক্স করা হয় যদিও ডিসপ্লে অ্যাসপেক্ট রেশিও পোর্ট্রেট। ক্যামেরা ইমেজ অ্যাপ UI এর সাথে সারিবদ্ধ করতে ঘোরানো হয়, ক্যামেরা প্রিভিউ এর আকৃতির অনুপাতের সাথে মেলে ক্রপ করা হয় এবং তারপর প্রিভিউ পূরণ করতে স্কেল করা হয়।

ইনসেট পোর্ট্রেট মোড ট্রিগার হয় যখন ক্যামেরা ইমেজ সেন্সরের আকৃতির অনুপাত এবং অ্যাপ্লিকেশনের প্রাথমিক কার্যকলাপের আকৃতির অনুপাত মেলে না।

ল্যাপটপে সঠিক পোর্ট্রেট অভিযোজনে ক্যামেরা প্রিভিউ এবং অ্যাপ UI।             ওয়াইড প্রিভিউ ইমেজ স্কেল করা হয়েছে এবং পোর্ট্রেট ওরিয়েন্টেশনের সাথে মানানসই করা হয়েছে।
চিত্র 8. ল্যাপটপে ইনসেট পোর্ট্রেট মোডে ফিক্সড-অরিয়েন্টেশন পোর্ট্রেট অ্যাপ।

চিত্র 8-এ, শুধুমাত্র পোর্ট্রেট-ক্যামেরা অ্যাপটিকে ল্যাপটপের ডিসপ্লেতে UI সরাসরি প্রদর্শনের জন্য ঘোরানো হয়েছে। পোর্ট্রেট অ্যাপ এবং ল্যান্ডস্কেপ ডিসপ্লের মধ্যে আকৃতির অনুপাতের পার্থক্যের কারণে অ্যাপটি লেটারবক্সযুক্ত। অ্যাপের UI ঘূর্ণনের জন্য (ইনসেট পোর্ট্রেট মোডের কারণে) ক্ষতিপূরণ দিতে ক্যামেরা প্রিভিউ ইমেজটি ঘোরানো হয়েছে, এবং চিত্রটিকে ক্রপ করা হয়েছে এবং পোর্ট্রেট ওরিয়েন্টেশনের সাথে মানানসই করার জন্য স্কেল করা হয়েছে, দৃশ্যের ক্ষেত্রকে হ্রাস করে।

ঘোরান, ক্রপ, স্কেল

একটি ল্যান্ডস্কেপ আকৃতির অনুপাত আছে এমন একটি ডিসপ্লেতে একটি পোর্ট্রেট-শুধু ক্যামেরা অ্যাপের জন্য ইনসেট পোর্ট্রেট মোড চালু করা হয়েছে:

ল্যাপটপে ক্যামেরা প্রিভিউ খাড়া কিন্তু অ্যাপ UI পাশে থাকে।
চিত্র 9. ল্যাপটপে ফিক্সড-অরিয়েন্টেশন পোর্ট্রেট অ্যাপ।

অ্যাপটি পোর্ট্রেট অভিযোজনে লেটারবক্সযুক্ত:

অ্যাপটি পোর্ট্রেট ওরিয়েন্টেশন এবং লেটারবক্সে ঘোরানো হয়েছে। ইমেজ সাইডওয়ে, উপরে ডানদিকে.

অ্যাপটির পুনর্বিন্যাসের জন্য সামঞ্জস্য করতে ক্যামেরা চিত্রটি 90 ডিগ্রি ঘোরানো হয়েছে:

সেন্সর ইমেজ 90 ডিগ্রী ঘোরে যাতে এটি খাড়া হয়।

ছবিটি ক্যামেরা প্রিভিউয়ের আকৃতির অনুপাতের সাথে ক্রপ করা হয়, তারপর প্রিভিউ পূরণ করতে স্কেল করা হয় (দর্শনের ক্ষেত্র হ্রাস করা হয়):

ক্যামেরা প্রিভিউ পূরণ করতে ক্রপ করা ক্যামেরার ছবি স্কেল করা হয়েছে।

ভাঁজযোগ্য ডিভাইসগুলিতে, ক্যামেরা সেন্সরের অভিযোজন পোর্ট্রেট হতে পারে যখন ডিসপ্লের আকৃতির অনুপাত ল্যান্ডস্কেপ হয়:

ক্যামেরা প্রিভিউ এবং অ্যাপ UI চওড়া, খোলামেলা ডিসপ্লের পাশে ঘুরিয়ে দিয়েছে।
চিত্র 10. শুধুমাত্র পোর্ট্রেট-ক্যামেরা অ্যাপ এবং ক্যামেরা সেন্সর এবং ডিসপ্লের বিভিন্ন আকৃতির অনুপাত সহ খোলা ডিভাইস।

যেহেতু ক্যামেরা প্রিভিউটি সেন্সর ওরিয়েন্টেশনের জন্য সামঞ্জস্য করার জন্য ঘোরানো হয়, তাই ছবিটি ভিউফাইন্ডারে সঠিকভাবে ভিত্তিক, কিন্তু পোর্ট্রেট-শুধু অ্যাপটি পাশে থাকে।

ইনসেট পোর্ট্রেট মোডের জন্য শুধুমাত্র অ্যাপটিকে পোর্ট্রেট ওরিয়েন্টেশনে লেটারবক্স করতে হবে অ্যাপ এবং ক্যামেরা প্রিভিউকে সঠিকভাবে ওরিয়েন্ট করতে:

ফোল্ডেবল ডিভাইসে ক্যামেরা প্রিভিউ সহ পোর্টেট ওরিয়েন্টেশনে লেটারবক্সড অ্যাপ।

API

অ্যান্ড্রয়েড 12 (API লেভেল 31) অ্যাপগুলি CaptureRequest ক্লাসের SCALER_ROTATE_AND_CROP প্রপার্টির মাধ্যমে ইনসেট পোর্ট্রেট মোডকে স্পষ্টভাবে নিয়ন্ত্রণ করতে পারে।

ডিফল্ট মান হল SCALER_ROTATE_AND_CROP_AUTO , যা সিস্টেমকে ইনসেট পোর্ট্রেট মোড চালু করতে সক্ষম করে৷ SCALER_ROTATE_AND_CROP_90 হল উপরে বর্ণিত ইনসেট পোর্ট্রেট মোডের আচরণ৷

সমস্ত ডিভাইস সমস্ত SCALER_ROTATE_AND_CROP মান সমর্থন করে না৷ সমর্থিত মানগুলির একটি তালিকা পেতে, CameraCharacteristics#SCALER_AVAILABLE_ROTATE_AND_CROP_MODES

ক্যামেরাএক্স

জেটপ্যাক ক্যামেরাএক্স লাইব্রেরি একটি ক্যামেরা ভিউফাইন্ডার তৈরি করে যা সেন্সর ওরিয়েন্টেশন এবং ডিভাইস ঘূর্ণন একটি সহজ কাজ মিটমাট করে।

PreviewView লেআউট উপাদানটি একটি ক্যামেরা পূর্বরূপ তৈরি করে, স্বয়ংক্রিয়ভাবে সেন্সর অভিযোজন, ডিভাইস ঘূর্ণন এবং স্কেলিং এর জন্য সামঞ্জস্য করে। PreviewView FILL_CENTER স্কেল টাইপ প্রয়োগ করে ক্যামেরা ছবির আকৃতির অনুপাত বজায় রাখে, যা ছবিটিকে কেন্দ্র করে কিন্তু PreviewView এর মাত্রার সাথে মেলে এটি ক্রপ করতে পারে। ক্যামেরা ইমেজ লেটারবক্স করতে, স্কেল টাইপ FIT_CENTER এ সেট করুন।

PreviewView দিয়ে একটি ক্যামেরা প্রিভিউ তৈরির মূল বিষয়গুলি শিখতে, একটি প্রিভিউ বাস্তবায়ন দেখুন।

একটি সম্পূর্ণ নমুনা বাস্তবায়নের জন্য, GitHub-এ CameraXBasic সংগ্রহস্থল দেখুন।

ক্যামেরা ভিউফাইন্ডার

পূর্বরূপ ব্যবহারের ক্ষেত্রে অনুরূপ, CameraViewfinder লাইব্রেরি একটি ক্যামেরা প্রিভিউ তৈরিকে সহজ করার জন্য সরঞ্জামগুলির একটি সেট সরবরাহ করে। এটি CameraX Core-এর উপর নির্ভর করে না, তাই আপনি এটিকে আপনার বিদ্যমান Camera2 কোডবেসে নির্বিঘ্নে সংহত করতে পারেন।

সরাসরি Surface ব্যবহার করার পরিবর্তে, আপনি Camera2 এর জন্য ক্যামেরা ফিড প্রদর্শন করতে CameraViewfinder উইজেট ব্যবহার করতে পারেন।

ক্যামেরা ফিড প্রদর্শন করতে CameraViewfinder অভ্যন্তরীণভাবে একটি TextureView বা SurfaceView ব্যবহার করে এবং ভিউফাইন্ডারকে সঠিকভাবে প্রদর্শন করার জন্য প্রয়োজনীয় রূপান্তরগুলি প্রয়োগ করে। এতে তাদের আকৃতির অনুপাত, স্কেল এবং ঘূর্ণন সংশোধন করা জড়িত।

CameraViewfinder বস্তু থেকে পৃষ্ঠের অনুরোধ করতে, আপনাকে একটি ViewfinderSurfaceRequest তৈরি করতে হবে।

এই অনুরোধে সারফেস রেজোলিউশন এবং CameraCharacteristics থেকে ক্যামেরা ডিভাইসের তথ্যের প্রয়োজনীয়তা রয়েছে।

requestSurfaceAsync() কল করলে সারফেস প্রদানকারীর কাছে অনুরোধ পাঠানো হয়, যেটি হয় একটি TextureView বা SurfaceView এবং একটি ListenableFuture of Surface পায়।

markSurfaceSafeToRelease() কল করা পৃষ্ঠ প্রদানকারীকে সূচিত করে যে পৃষ্ঠের প্রয়োজন নেই এবং সম্পর্কিত সংস্থান প্রকাশ করা যেতে পারে।

কোটলিন


fun startCamera(){
    val previewResolution = Size(width, height)
    val viewfinderSurfaceRequest =
        ViewfinderSurfaceRequest(previewResolution, characteristics)
    val surfaceListenableFuture =
        cameraViewfinder.requestSurfaceAsync(viewfinderSurfaceRequest)

    Futures.addCallback(surfaceListenableFuture, object : FutureCallback<Surface> {
        override fun onSuccess(surface: Surface) {
            /* create a CaptureSession using this surface as usual */
        }
        override fun onFailure(t: Throwable) { /* something went wrong */}
    }, ContextCompat.getMainExecutor(context))
}

জাভা


    void startCamera(){
        Size previewResolution = new Size(width, height);
        ViewfinderSurfaceRequest viewfinderSurfaceRequest =
                new ViewfinderSurfaceRequest(previewResolution, characteristics);
        ListenableFuture<Surface> surfaceListenableFuture =
                cameraViewfinder.requestSurfaceAsync(viewfinderSurfaceRequest);

        Futures.addCallback(surfaceListenableFuture, new FutureCallback<Surface>() {
            @Override
            public void onSuccess(Surface result) {
                /* create a CaptureSession using this surface as usual */
            }
            @Override public void onFailure(Throwable t) { /* something went wrong */}
        },  ContextCompat.getMainExecutor(context));
    }

সারফেসভিউ

SurfaceView হল একটি ক্যামেরা প্রিভিউ তৈরি করার একটি সহজ পদ্ধতি যদি প্রিভিউটির প্রক্রিয়াকরণের প্রয়োজন না হয় এবং অ্যানিমেটেড না হয়।

SurfaceView স্বয়ংক্রিয়ভাবে ক্যামেরা সেন্সর ইমেজ বাফারকে ডিসপ্লে ওরিয়েন্টেশনের সাথে মেলে, সেন্সর ওরিয়েন্টেশন এবং ডিভাইস রোটেশন উভয়ের জন্যই অ্যাকাউন্টিং করে। যাইহোক, আকৃতির অনুপাত বিবেচনা না করেই SurfaceView মাত্রার সাথে মানানসই করার জন্য চিত্রের বাফারটি স্কেল করা হয়েছে।

আপনাকে অবশ্যই নিশ্চিত করতে হবে যে ইমেজ বাফারের আকৃতির অনুপাত SurfaceView এর অনুপাতের সাথে মেলে, যা আপনি কম্পোনেন্টের onMeasure() পদ্ধতিতে SurfaceView এর বিষয়বস্তু স্কেল করে সম্পন্ন করতে পারেন:

( computeRelativeRotation() সোর্স কোডটি নিচের আপেক্ষিক ঘূর্ণনে রয়েছে।)

কোটলিন

override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
    val width = MeasureSpec.getSize(widthMeasureSpec)
    val height = MeasureSpec.getSize(heightMeasureSpec)

    val relativeRotation = computeRelativeRotation(characteristics, surfaceRotationDegrees)

    if (previewWidth > 0f && previewHeight > 0f) {
        /* Scale factor required to scale the preview to its original size on the x-axis. */
        val scaleX =
            if (relativeRotation % 180 == 0) {
                width.toFloat() / previewWidth
            } else {
                width.toFloat() / previewHeight
            }
        /* Scale factor required to scale the preview to its original size on the y-axis. */
        val scaleY =
            if (relativeRotation % 180 == 0) {
                height.toFloat() / previewHeight
            } else {
                height.toFloat() / previewWidth
            }

        /* Scale factor required to fit the preview to the SurfaceView size. */
        val finalScale = min(scaleX, scaleY)

        setScaleX(1 / scaleX * finalScale)
        setScaleY(1 / scaleY * finalScale)
    }
    setMeasuredDimension(width, height)
}

জাভা

@Override
void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    int width = MeasureSpec.getSize(widthMeasureSpec);
    int height = MeasureSpec.getSize(heightMeasureSpec);

    int relativeRotation = computeRelativeRotation(characteristics, surfaceRotationDegrees);

    if (previewWidth > 0f && previewHeight > 0f) {

        /* Scale factor required to scale the preview to its original size on the x-axis. */
        float scaleX = (relativeRotation % 180 == 0)
                       ? (float) width / previewWidth
                       : (float) width / previewHeight;

        /* Scale factor required to scale the preview to its original size on the y-axis. */
        float scaleY = (relativeRotation % 180 == 0)
                       ? (float) height / previewHeight
                       : (float) height / previewWidth;

        /* Scale factor required to fit the preview to the SurfaceView size. */
        float finalScale = Math.min(scaleX, scaleY);

        setScaleX(1 / scaleX * finalScale);
        setScaleY(1 / scaleY * finalScale);
    }
    setMeasuredDimension(width, height);
}

একটি ক্যামেরা প্রিভিউ হিসাবে SurfaceView প্রয়োগ করার বিষয়ে আরও বিশদ বিবরণের জন্য, ক্যামেরার অভিযোজন দেখুন।

টেক্সচারভিউ

TextureView SurfaceView -এর চেয়ে কম পারফরম্যান্স — এবং আরও বেশি কাজ — তবে TextureView আপনাকে ক্যামেরা প্রিভিউয়ের সর্বাধিক নিয়ন্ত্রণ দেয়৷

TextureView সেন্সর অভিযোজনের উপর ভিত্তি করে সেন্সর ইমেজ বাফার ঘোরায় কিন্তু ডিভাইস ঘূর্ণন বা পূর্বরূপ স্কেলিং পরিচালনা করে না।

একটি ম্যাট্রিক্স রূপান্তরে স্কেলিং এবং ঘূর্ণন এনকোড করা যেতে পারে। TextureView কীভাবে সঠিকভাবে স্কেল করা যায় এবং ঘোরানো যায় তা জানতে, আপনার ক্যামেরা অ্যাপে সাপোর্ট রিসাইজযোগ্য সারফেস দেখুন

আপেক্ষিক ঘূর্ণন

ক্যামেরা সেন্সরের আপেক্ষিক ঘূর্ণন হল ক্যামেরা সেন্সর আউটপুটকে ডিভাইসের ওরিয়েন্টেশনের সাথে সারিবদ্ধ করার জন্য প্রয়োজনীয় ঘূর্ণনের পরিমাণ।

পূর্বরূপ চিত্রের জন্য x এবং y স্কেলিং ফ্যাক্টর নির্ধারণ করতে SurfaceView এবং TextureView এর মতো উপাদান দ্বারা আপেক্ষিক ঘূর্ণন ব্যবহার করা হয়। এটি সেন্সর ইমেজ বাফারের ঘূর্ণন নির্দিষ্ট করতেও ব্যবহৃত হয়।

CameraCharacteristics এবং Surface ক্লাসগুলি ক্যামেরা সেন্সরের আপেক্ষিক ঘূর্ণনের গণনা সক্ষম করে:

কোটলিন

/**
 * Computes rotation required to transform the camera sensor output orientation to the
 * device's current orientation in degrees.
 *
 * @param characteristics The CameraCharacteristics to query for the sensor orientation.
 * @param surfaceRotationDegrees The current device orientation as a Surface constant.
 * @return Relative rotation of the camera sensor output.
 */
public fun computeRelativeRotation(
    characteristics: CameraCharacteristics,
    surfaceRotationDegrees: Int
): Int {
    val sensorOrientationDegrees =
        characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION)!!

    // Reverse device orientation for back-facing cameras.
    val sign = if (characteristics.get(CameraCharacteristics.LENS_FACING) ==
        CameraCharacteristics.LENS_FACING_FRONT
    ) 1 else -1

    // Calculate desired orientation relative to camera orientation to make
    // the image upright relative to the device orientation.
    return (sensorOrientationDegrees - surfaceRotationDegrees * sign + 360) % 360
}

জাভা

/**
 * Computes rotation required to transform the camera sensor output orientation to the
 * device's current orientation in degrees.
 *
 * @param characteristics The CameraCharacteristics to query for the sensor orientation.
 * @param surfaceRotationDegrees The current device orientation as a Surface constant.
 * @return Relative rotation of the camera sensor output.
 */
public int computeRelativeRotation(
    CameraCharacteristics characteristics,
    int surfaceRotationDegrees
){
    Integer sensorOrientationDegrees =
        characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);

    // Reverse device orientation for back-facing cameras.
    int sign = characteristics.get(CameraCharacteristics.LENS_FACING) ==
        CameraCharacteristics.LENS_FACING_FRONT ? 1 : -1;

    // Calculate desired orientation relative to camera orientation to make
    // the image upright relative to the device orientation.
    return (sensorOrientationDegrees - surfaceRotationDegrees * sign + 360) % 360;
}

উইন্ডো মেট্রিক্স

ক্যামেরা ভিউফাইন্ডারের মাত্রা নির্ধারণ করতে পর্দার আকার ব্যবহার করা উচিত নয়; ক্যামেরা অ্যাপটি হয়ত মোবাইল ডিভাইসে মাল্টি-উইন্ডো মোডে অথবা ChromeOS-এ ফ্রি-ফ্রম মোডে, স্ক্রিনের একটি অংশে চলছে।

WindowManager#getCurrentWindowMetrics() (এপিআই লেভেল 30 এ যোগ করা হয়েছে) স্ক্রিনের আকারের পরিবর্তে অ্যাপ্লিকেশন উইন্ডোর আকার প্রদান করে। Jetpack WindowManager লাইব্রেরি পদ্ধতি WindowMetricsCalculator#computeCurrentWindowMetrics() এবং WindowInfoTracker#currentWindowMetrics() API স্তর 14-এ পশ্চাদগামী সামঞ্জস্যের সাথে অনুরূপ সমর্থন প্রদান করে।

180 ডিগ্রি ঘূর্ণন

একটি ডিভাইসের একটি 180 ডিগ্রি ঘূর্ণন (উদাহরণস্বরূপ, প্রাকৃতিক অভিযোজন থেকে প্রাকৃতিক অভিযোজন উল্টো দিকে) onConfigurationChanged() কলব্যাককে ট্রিগার করে না। ফলস্বরূপ, ক্যামেরা প্রিভিউ উল্টে যেতে পারে।

একটি 180 ডিগ্রি ঘূর্ণন সনাক্ত করতে, একটি DisplayListener প্রয়োগ করুন এবং onDisplayChanged() কলব্যাকে Display#getRotation() এ একটি কল দিয়ে ডিভাইসের ঘূর্ণন পরীক্ষা করুন৷

একচেটিয়া সম্পদ

অ্যান্ড্রয়েড 10-এর আগে, একটি মাল্টি-উইন্ডো পরিবেশে শুধুমাত্র শীর্ষস্থানীয় দৃশ্যমান কার্যকলাপ RESUMED অবস্থায় ছিল। এটি ব্যবহারকারীদের জন্য বিভ্রান্তিকর ছিল কারণ সিস্টেমটি কোন ক্রিয়াকলাপ পুনরায় শুরু করা হয়েছে তার কোনও ইঙ্গিত দেয়নি৷

অ্যান্ড্রয়েড 10 (এপিআই লেভেল 29) মাল্টি-রিজুমে চালু করেছে যেখানে সমস্ত দৃশ্যমান ক্রিয়াকলাপগুলি RESUMED অবস্থায় রয়েছে। দৃশ্যমান ক্রিয়াকলাপগুলি এখনও PAUSED অবস্থায় প্রবেশ করতে পারে যদি, উদাহরণস্বরূপ, ক্রিয়াকলাপের উপরে একটি স্বচ্ছ কার্যকলাপ থাকে বা কার্যকলাপটি ফোকাসযোগ্য না হয়, যেমন পিকচার-ইন -পিকচার মোডে (ছবিতে ছবি সমর্থন দেখুন)।

ক্যামেরা, মাইক্রোফোন, বা API স্তর 29 বা উচ্চতর কোনো এক্সক্লুসিভ বা সিঙ্গলটন রিসোর্স ব্যবহার করে একটি অ্যাপ্লিকেশন মাল্টি-রিজুমে সমর্থন করবে। উদাহরণস্বরূপ, যদি তিনটি পুনরায় শুরু করা কার্যকলাপ ক্যামেরা ব্যবহার করতে চায়, শুধুমাত্র একজন এই একচেটিয়া সম্পদ অ্যাক্সেস করতে সক্ষম। প্রতিটি ক্রিয়াকলাপকে একটি উচ্চ অগ্রাধিকার ক্রিয়াকলাপের মাধ্যমে ক্যামেরায় প্রিমম্পটিভ অ্যাক্সেস সম্পর্কে সচেতন থাকার জন্য একটি onDisconnected() কলব্যাক প্রয়োগ করতে হবে।

আরও তথ্যের জন্য, মাল্টি-রিজুমে দেখুন।

অতিরিক্ত সম্পদ