ध्यान दें: इस पेज पर Camera2 पैकेज के बारे में बताया गया है. अगर आपके ऐप्लिकेशन को Camera2 की खास और लो-लेवल सुविधाओं की ज़रूरत नहीं है, तो हमारा सुझाव है कि आप CameraX का इस्तेमाल करें. CameraX और Camera2, दोनों ही Android 5.0 (एपीआई लेवल 21) और इसके बाद के वर्शन पर काम करते हैं.
Android डिवाइसों पर, कैमरे और कैमरे की झलक हमेशा एक ही ओरिएंटेशन में नहीं होती हैं.
कैमरा, डिवाइस पर एक तय जगह पर होता है. इससे कोई फ़र्क़ नहीं पड़ता कि डिवाइस फ़ोन, टैबलेट या कंप्यूटर है. डिवाइस का ओरिएंटेशन बदलने पर, कैमरे का ओरिएंटेशन बदल जाता है.
इस वजह से, कैमरा ऐप्लिकेशन आम तौर पर यह मान लेते हैं कि डिवाइस के ओरिएंटेशन और कैमरे की झलक के आसपेक्ट रेशियो (लंबाई-चौड़ाई का अनुपात) के बीच एक तय संबंध होता है. जब कोई फ़ोन पोर्ट्रेट ओरिएंटेशन में होता है, तो कैमरे की झलक चौड़ाई से ज़्यादा लंबी दिखती है. जब फ़ोन (और कैमरे) को लैंडस्केप मोड में घुमाया जाता है, तो कैमरे की झलक, लंबाई के मुकाबले चौड़ाई में ज़्यादा दिखती है.
हालांकि, डिवाइस के नए नाप या आकार की वजह से, इन अनुमानों को चुनौती मिलती है. जैसे, फ़ोल्ड किए जा सकने वाले डिवाइस और डिसप्ले मोड, जैसे कि मल्टी-विंडो और मल्टी-डिसप्ले. फ़ोल्ड किए जा सकने वाले डिवाइस, ओरिएंटेशन बदले बिना डिसप्ले का साइज़ और आसपेक्ट रेशियो (लंबाई-चौड़ाई का अनुपात) बदल देते हैं. मल्टी-विंडो मोड, कैमरा ऐप्लिकेशन को स्क्रीन के एक हिस्से तक सीमित कर देता है. इससे कैमरे की झलक को स्केल किया जाता है, भले ही डिवाइस का ओरिएंटेशन कुछ भी हो. मल्टी-डिसप्ले मोड की मदद से, सेकंडरी डिसप्ले का इस्तेमाल किया जा सकता है. ऐसा हो सकता है कि सेकंडरी डिसप्ले का ओरिएंटेशन, प्राइमरी डिसप्ले के ओरिएंटेशन से अलग हो.
कैमरा एडजस्ट करें
Android कंपैटबिलिटी डेफ़िनिशन में बताया गया है कि कैमरे के इमेज सेंसर को इस तरह से ओरिएंट किया जाना चाहिए कि कैमरे का लंबा डाइमेंशन, स्क्रीन के लंबे डाइमेंशन के साथ अलाइन हो. इसका मतलब है कि जब डिवाइस को लैंडस्केप ओरिएंटेशन में पकड़ा जाता है, तो कैमरे को लैंडस्केप ओरिएंटेशन में इमेज कैप्चर करनी चाहिए. यह डिवाइस के नैचुरल ओरिएंटेशन पर निर्भर नहीं करता. इसका मतलब है कि यह लैंडस्केप-प्राइमरी डिवाइसों के साथ-साथ पोर्ट्रेट-प्राइमरी डिवाइसों पर भी लागू होता है."
कैमरे से स्क्रीन तक की व्यवस्था, कैमरा ऐप्लिकेशन में कैमरे के व्यूफ़ाइंडर के डिसप्ले एरिया को बढ़ाती है. साथ ही, इमेज सेंसर आम तौर पर अपने डेटा को लैंडस्केप आसपेक्ट रेशियो (लंबाई-चौड़ाई का अनुपात) में आउटपुट करते हैं. इनमें 4:3 सबसे आम है.
कैमरा सेंसर का नैचुरल ओरिएंटेशन लैंडस्केप होता है. इमेज 1 में, सामने वाले कैमरे (डिसप्ले की दिशा में मौजूद कैमरा) के सेंसर को फ़ोन के हिसाब से 270 डिग्री घुमाया गया है, ताकि Android के साथ काम करने की परिभाषा का पालन किया जा सके.
ऐप्लिकेशन को सेंसर के रोटेशन की जानकारी देने के लिए, camera2 एपीआई में 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 डिग्री पर स्केल करना.
अलग-अलग एपीआई, डिवाइस के रोटेशन की जानकारी अलग-अलग तरीके से देते हैं:
Display#getRotation(), उपयोगकर्ता के हिसाब से डिवाइस को घड़ी की उलटी दिशा में घुमाने की जानकारी देता है. यह वैल्यू, पहले बताए गए फ़ॉर्मूला में सीधे तौर पर इस्तेमाल की जाती है.OrientationEventListener#onOrientationChanged()डिवाइस के घड़ी की सुई की दिशा में घूमने की जानकारी देता है (उपयोगकर्ता के नज़रिए से). पिछले फ़ॉर्मूले में इस्तेमाल करने के लिए, वैल्यू को नेगेटिव बनाएं.
फ़्रंट कैमरा
यहां इमेज 4 में, कैमरा सेंसर से जनरेट किया गया इमेज बफ़र दिखाया गया है:
सेंसर के ओरिएंटेशन को अडजस्ट करने के लिए, बफ़र को घड़ी की उलटी दिशा में 270 डिग्री घुमाना होगा (ऊपर कैमरे का ओरिएंटेशन देखें):
इसके बाद, बफ़र को घड़ी की उलटी दिशा में 90 डिग्री और घुमाया जाता है, ताकि डिवाइस के रोटेशन को अडजस्ट किया जा सके. इससे, इमेज 4 में कैमरे की झलक सही ओरिएंटेशन में दिखती है:
यहां कैमरे को दाईं ओर घुमाकर, लैंडस्केप ओरिएंटेशन में दिखाया गया है:
इमेज बफ़र यहां दिया गया है:
सेंसर ओरिएंटेशन में बदलाव करने के लिए, बफ़र को घड़ी की उल्टी दिशा में 270 डिग्री घुमाना होगा:
इसके बाद, बफ़र को घड़ी की उलटी दिशा में 270 डिग्री और घुमाया जाता है, ताकि डिवाइस के रोटेशन को अडजस्ट किया जा सके:
बैक कैमरे
बैक-फ़ेसिंग कैमरों में आम तौर पर, सेंसर का ओरिएंटेशन 90 डिग्री होता है. इसे डिवाइस के पीछे से देखा जाता है. कैमरे की झलक को ओरिएंट करते समय, सेंसर इमेज बफ़र को सेंसर के रोटेशन की मात्रा के हिसाब से घड़ी की सुई की दिशा में घुमाया जाता है. यह सामने वाले कैमरे की तरह घड़ी की उलटी दिशा में नहीं घूमता. इसके बाद, इमेज बफ़र को डिवाइस के रोटेशन की मात्रा के हिसाब से घड़ी की उलटी दिशा में घुमाया जाता है.
यहां इमेज 12 में, कैमरा सेंसर से इमेज बफ़र दिखाया गया है:
सेंसर के ओरिएंटेशन में बदलाव करने के लिए, बफ़र को घड़ी की सुई की दिशा में 90 डिग्री घुमाना होगा:
इसके बाद, बफ़र को घड़ी की उल्टी दिशा में 270 डिग्री घुमाया जाता है, ताकि डिवाइस के रोटेशन को अडजस्ट किया जा सके:
आसपेक्ट रेशियो
डिवाइस का ओरिएंटेशन बदलने पर, डिसप्ले का आसपेक्ट रेशियो (लंबाई-चौड़ाई का अनुपात) बदल जाता है. इसके अलावा, फ़ोल्ड किए जा सकने वाले डिवाइसों को फ़ोल्ड और अनफ़ोल्ड करने, मल्टी-विंडो एनवायरमेंट में विंडो का साइज़ बदलने, और सेकंडरी डिसप्ले पर ऐप्लिकेशन खोलने पर भी आसपेक्ट रेशियो बदल जाता है.
कैमरा सेंसर इमेज बफ़र को ओरिएंट और स्केल किया जाना चाहिए, ताकि वह व्यूफ़ाइंडर यूज़र इंटरफ़ेस (यूआई) एलिमेंट के ओरिएंटेशन और आसपेक्ट रेशियो (लंबाई-चौड़ाई का अनुपात) से मैच करे. ऐसा इसलिए, क्योंकि यूज़र इंटरफ़ेस (यूआई) डाइनैमिक तरीके से ओरिएंटेशन बदलता है. भले ही, डिवाइस का ओरिएंटेशन बदला जाए या नहीं.
नए डिवाइस साइज़ या मल्टी-विंडो या मल्टी-डिसप्ले वाले एनवायरमेंट में, अगर आपके ऐप्लिकेशन को लगता है कि कैमरे की झलक का ओरिएंटेशन, डिवाइस के ओरिएंटेशन (पोर्ट्रेट या लैंडस्केप) जैसा ही है, तो हो सकता है कि आपकी झलक का ओरिएंटेशन गलत हो, उसे गलत तरीके से स्केल किया गया हो या दोनों ही गलत हों.
इमेज 16 में, ऐप्लिकेशन ने गलती से यह मान लिया कि डिवाइस को घड़ी की उल्टी दिशा में 90 डिग्री घुमाया गया है. इसलिए, ऐप्लिकेशन ने झलक को भी उसी हिसाब से घुमा दिया.
इमेज 17 में, ऐप्लिकेशन ने इमेज बफ़र के आसपेक्ट रेशियो (लंबाई-चौड़ाई का अनुपात) में बदलाव नहीं किया. इस वजह से, कैमरे की झलक दिखाने वाले यूज़र इंटरफ़ेस (यूआई) एलिमेंट के नए डाइमेंशन के हिसाब से, इमेज को सही तरीके से स्केल नहीं किया जा सका.
फ़ोल्ड किए जा सकने वाले डिवाइसों और लैपटॉप जैसे बड़ी स्क्रीन वाले अन्य डिवाइसों पर, आम तौर पर फ़िक्स्ड-ओरिएंटेशन वाले कैमरा ऐप्लिकेशन इस्तेमाल करने में समस्याएं आती हैं:
इमेज 18 में, कैमरा ऐप्लिकेशन का यूज़र इंटरफ़ेस (यूआई) साइडवेज़ है, क्योंकि ऐप्लिकेशन का ओरिएंटेशन सिर्फ़ पोर्ट्रेट मोड पर सेट है. व्यूफ़ाइंडर की इमेज, कैमरा सेंसर के हिसाब से सही तरीके से ओरिएंट की गई है.
इनसेट पोर्ट्रेट मोड
कैमरे की झलक को सही तरीके से दिखाने के लिए, बड़ी स्क्रीन वाले डिवाइसों पर, कैमरे वाले ऐसे ऐप्लिकेशन को इनसेट पोर्ट्रेट मोड में रखा जा सकता है जो मल्टी-विंडो मोड (resizeableActivity="false") के साथ काम नहीं करते और अपने ओरिएंटेशन (screenOrientation="portrait" या screenOrientation="landscape") को सीमित करते हैं.
इनसेट पोर्ट्रेट मोड, सिर्फ़ पोर्ट्रेट मोड में काम करने वाले ऐप्लिकेशन को पोर्ट्रेट ओरिएंटेशन में लेटरबॉक्स (इनसेट) करता है. भले ही, डिसप्ले का आसपेक्ट रेशियो (लंबाई-चौड़ाई का अनुपात) लैंडस्केप हो. सिर्फ़ लैंडस्केप मोड में काम करने वाले ऐप्लिकेशन, लैंडस्केप ओरिएंटेशन में लेटरबॉक्स किए जाते हैं. भले ही, डिसप्ले का आसपेक्ट रेशियो (लंबाई-चौड़ाई का अनुपात) पोर्ट्रेट हो. कैमरे की इमेज को ऐप्लिकेशन के यूज़र इंटरफ़ेस (यूआई) के साथ अलाइन करने के लिए घुमाया जाता है. साथ ही, कैमरे की झलक के आसपेक्ट रेशियो (लंबाई-चौड़ाई का अनुपात) से मैच करने के लिए, इमेज को काटा जाता है. इसके बाद, झलक को भरने के लिए इमेज को स्केल किया जाता है.
इन्सेट पोर्ट्रेट मोड तब ट्रिगर होता है, जब कैमरे के इमेज सेंसर का आसपेक्ट रेशियो (लंबाई-चौड़ाई का अनुपात) और ऐप्लिकेशन की मुख्य गतिविधि का आसपेक्ट रेशियो मैच नहीं होता.
इमेज 19 में, सिर्फ़ पोर्ट्रेट मोड में काम करने वाले कैमरा ऐप्लिकेशन को घुमाया गया है, ताकि लैपटॉप के डिसप्ले पर यूज़र इंटरफ़ेस (यूआई) को सीधा दिखाया जा सके. ऐप्लिकेशन को लेटरबॉक्स किया गया है, क्योंकि पोर्ट्रेट ऐप्लिकेशन और लैंडस्केप डिसप्ले के आसपेक्ट रेशियो (लंबाई-चौड़ाई का अनुपात) में अंतर है. कैमरे की झलक वाली इमेज को घुमाया गया है, ताकि ऐप्लिकेशन के यूज़र इंटरफ़ेस (यूआई) के रोटेशन की भरपाई की जा सके. ऐसा इनसेट पोर्ट्रेट मोड की वजह से हुआ है. साथ ही, इमेज को पोर्ट्रेट ओरिएंटेशन में फ़िट करने के लिए, उसे काटा गया है और उसका साइज़ बदला गया है. इससे फ़ील्ड ऑफ़ व्यू (कैमरे से दिख रहा व्यू) कम हो गया है.
घुमाना, काटना, और स्केल करना
इन्सेट पोर्ट्रेट मोड, लैंडस्केप आसपेक्ट रेशियो (लंबाई-चौड़ाई का अनुपात) वाले डिसप्ले पर, सिर्फ़ पोर्ट्रेट मोड में काम करने वाले कैमरा ऐप्लिकेशन के लिए चालू किया जाता है:
ऐप्लिकेशन को पोर्ट्रेट ओरिएंटेशन में लेटरबॉक्स किया गया है:
ऐप्लिकेशन के ओरिएंटेशन में बदलाव करने के लिए, कैमरे की इमेज को 90 डिग्री घुमाया जाता है:
इमेज को कैमरे की झलक के आसपेक्ट रेशियो (लंबाई-चौड़ाई का अनुपात) के हिसाब से काटा जाता है. इसके बाद, झलक को भरने के लिए उसे स्केल किया जाता है. इससे फ़ील्ड ऑफ़ व्यू (कैमरे से दिख रहा व्यू) कम हो जाता है:
फ़ोल्ड किए जा सकने वाले डिवाइसों पर, कैमरा सेंसर का ओरिएंटेशन पोर्ट्रेट हो सकता है, जबकि डिसप्ले का आसपेक्ट रेशियो (लंबाई-चौड़ाई का अनुपात) लैंडस्केप हो सकता है:
कैमरे की झलक को सेंसर ओरिएंटेशन के हिसाब से अडजस्ट करने के लिए घुमाया जाता है. इसलिए, व्यूफ़ाइंडर में इमेज सही ओरिएंटेशन में दिखती है. हालांकि, सिर्फ़ पोर्ट्रेट मोड में काम करने वाला ऐप्लिकेशन, साइडवेज़ में दिखता है.
इन्सेट पोर्ट्रेट मोड में, ऐप्लिकेशन को पोर्ट्रेट ओरिएंटेशन में लेटरबॉक्स करने की ज़रूरत होती है, ताकि ऐप्लिकेशन और कैमरे की झलक को सही तरीके से ओरिएंट किया जा सके:
एपीआई
Android 12 (एपीआई लेवल 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 देखें.
CameraX
Jetpack CameraX लाइब्रेरी की मदद से, कैमरे का व्यूफ़ाइंडर बनाना आसान हो जाता है. यह व्यूफ़ाइंडर, सेंसर ओरिएंटेशन और डिवाइस के रोटेशन के हिसाब से काम करता है.
PreviewView लेआउट एलिमेंट, कैमरे की झलक दिखाता है. यह सेंसर ओरिएंटेशन, डिवाइस के रोटेशन, और स्केलिंग के लिए अपने-आप अडजस्ट हो जाता है.
PreviewView, FILL_CENTER स्केल टाइप लागू करके, कैमरे की इमेज के आसपेक्ट रेशियो (लंबाई-चौड़ाई का अनुपात) को बनाए रखता है. इससे इमेज बीच में आ जाती है, लेकिन PreviewView के डाइमेंशन से मैच करने के लिए, इसे काटा जा सकता है. कैमरे से ली गई इमेज को लेटरबॉक्स करने के लिए, स्केल टाइप को FIT_CENTER पर सेट करें.
PreviewView की मदद से कैमरे की झलक बनाने की बुनियादी बातें जानने के लिए, झलक लागू करें लेख पढ़ें.
लागू करने के तरीके का पूरा सैंपल देखने के लिए, GitHub पर CameraXBasic रिपॉज़िटरी देखें.
CameraViewfinder
झलक के इस्तेमाल के उदाहरण की तरह ही, CameraViewfinder लाइब्रेरी में टूल का एक सेट होता है. इससे कैमरे की झलक को आसानी से बनाया जा सकता है. यह CameraX Core पर निर्भर नहीं करता. इसलिए, इसे अपने मौजूदा Camera2 कोड बेस में आसानी से इंटिग्रेट किया जा सकता है.
Surface का सीधे तौर पर इस्तेमाल करने के बजाय, CameraViewfinder विजेट का इस्तेमाल करके, Camera2 के लिए कैमरा फ़ीड दिखाया जा सकता है.
CameraViewfinder, कैमरा फ़ीड दिखाने के लिए, TextureView या SurfaceView का इस्तेमाल करता है. साथ ही, व्यूफ़ाइंडर को सही तरीके से दिखाने के लिए, उन पर ज़रूरी बदलाव लागू करता है. इसमें, आसपेक्ट रेशियो (लंबाई-चौड़ाई का अनुपात),
स्केल, और रोटेशन को ठीक करना शामिल है.
CameraViewfinder ऑब्जेक्ट से सरफ़ेस का अनुरोध करने के लिए, आपको ViewfinderSurfaceRequest बनाना होगा.
इस अनुरोध में, CameraCharacteristics से ली गई, कैमरे के रिज़ॉल्यूशन और कैमरे की जानकारी शामिल है.
requestSurfaceAsync() को कॉल करने पर, अनुरोध को सरफेस प्रोवाइडर को भेजा जाता है. यह या तो TextureView होता है या SurfaceView. इसके बाद, Surface का ListenableFuture मिलता है.
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))
}
SurfaceView
अगर झलक को प्रोसेस करने की ज़रूरत नहीं है और वह ऐनिमेटेड नहीं है, तो कैमरे की झलक बनाने के लिए 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) }
कैमरे की झलक के तौर पर SurfaceView को लागू करने के बारे में ज़्यादा जानकारी के लिए, कैमरे के ओरिएंटेशन देखें.
TextureView
TextureView, SurfaceView के मुकाबले कम बेहतर तरीके से काम करता है. साथ ही, इसमें ज़्यादा मेहनत लगती है. हालांकि, TextureView की मदद से कैमरे की झलक को ज़्यादा बेहतर तरीके से कंट्रोल किया जा सकता है.
TextureView, सेंसर के ओरिएंटेशन के आधार पर सेंसर इमेज बफ़र को घुमाता है. हालांकि, यह डिवाइस के रोटेशन या झलक की स्केलिंग को मैनेज नहीं करता.
स्केलिंग और रोटेशन को मैट्रिक्स ट्रांसफ़ॉर्मेशन में एन्कोड किया जा सकता है.
TextureView को सही तरीके से स्केल करने और घुमाने का तरीका जानने के लिए, अपने कैमरा ऐप्लिकेशन में, साइज़ बदलने लायक सरफ़ेस के साथ काम करने की सुविधा लेख पढ़ें.
रिलेटिव रोटेशन
कैमरा सेंसर के रिलेटिव रोटेशन का मतलब है कि कैमरा सेंसर के आउटपुट को डिवाइस के ओरिएंटेशन के साथ अलाइन करने के लिए, उसे कितना घुमाना ज़रूरी है.
रिलेटिव रोटेशन का इस्तेमाल, SurfaceView और TextureView जैसे कॉम्पोनेंट करते हैं. इससे झलक वाली इमेज के लिए, x और y स्केलिंग फ़ैक्टर तय किए जाते हैं. इसका इस्तेमाल, सेंसर इमेज बफ़र के रोटेशन की जानकारी देने के लिए भी किया जाता है.
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) ?: 0 // 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 }
विंडो मेट्रिक
कैमरे के व्यूफ़ाइंडर के डाइमेंशन तय करने के लिए, स्क्रीन के साइज़ का इस्तेमाल नहीं किया जाना चाहिए. ऐसा हो सकता है कि कैमरा ऐप्लिकेशन, स्क्रीन के किसी हिस्से में चल रहा हो. जैसे, फ़ोन या टैबलेट पर मल्टी-विंडो मोड में या ChromeOS पर फ़्री-फ़ॉर्म मोड में.
WindowManager#getCurrentWindowMetrics()
(एपीआई लेवल 30 में जोड़ा गया) स्क्रीन के साइज़ के बजाय, ऐप्लिकेशन विंडो का साइज़ दिखाता है. Jetpack WindowManager लाइब्रेरी के तरीके
WindowMetricsCalculator#computeCurrentWindowMetrics()
और WindowInfoTracker#currentWindowMetrics()
एपीआई लेवल 14 के साथ पुराने सिस्टम के साथ काम करने की सुविधा देते हैं.
180 डिग्री का घुमाव
किसी डिवाइस को 180 डिग्री घुमाने पर, onConfigurationChanged() कॉलबैक ट्रिगर नहीं होता. उदाहरण के लिए, नैचुरल ओरिएंटेशन से नैचुरल ओरिएंटेशन को उल्टा करने पर. इस वजह से, कैमरे की झलक उल्टी दिख सकती है.
180 डिग्री के रोटेशन का पता लगाने के लिए, DisplayListener लागू करें. साथ ही, onDisplayChanged() कॉलबैक में Display#getRotation() को कॉल करके, डिवाइस के रोटेशन की जांच करें.
खास संसाधन
Android 10 से पहले, मल्टी-विंडो एनवायरमेंट में सबसे ऊपर दिखने वाली गतिविधि ही RESUMED स्थिति में होती थी. इससे उपयोगकर्ताओं को भ्रम होता था, क्योंकि सिस्टम यह नहीं बताता था कि कौनसी गतिविधि फिर से शुरू की गई है.
Android 10 (एपीआई लेवल 29) में, दो या इससे ज़्यादा ऐप्लिकेशन का एक साथ इस्तेमाल करने की सुविधा जोड़ी गई. इसमें स्क्रीन पर दिखने वाली सभी गतिविधियां, RESUMED स्टेट में होती हैं. दिखने वाली गतिविधियां अब भी PAUSED स्थिति में जा सकती हैं. उदाहरण के लिए, अगर कोई पारदर्शी गतिविधि, गतिविधि के ऊपर है या गतिविधि पर फ़ोकस नहीं किया जा सकता, जैसे कि पिक्चर में पिक्चर मोड में (पिक्चर में पिक्चर मोड के लिए सहायता देखें).
एपीआई लेवल 29 या इसके बाद के वर्शन पर, कैमरे, माइक्रोफ़ोन या किसी खास या सिंगलटन रिसॉर्स का इस्तेमाल करने वाले ऐप्लिकेशन में, दो या इससे ज़्यादा ऐप्लिकेशन का एक साथ इस्तेमाल करने की सुविधा होनी चाहिए. उदाहरण के लिए, अगर फिर से शुरू की गई तीन गतिविधियां कैमरे का इस्तेमाल करना चाहती हैं, तो सिर्फ़ एक गतिविधि ही इस खास संसाधन को ऐक्सेस कर पाएगी. हर गतिविधि को onDisconnected() कॉलबैक लागू करना चाहिए, ताकि ज़्यादा प्राथमिकता वाली गतिविधि के लिए कैमरे के प्रीएम्प्टिव ऐक्सेस के बारे में जानकारी मिलती रहे.
ज़्यादा जानकारी के लिए, दो या इससे ज़्यादा ऐप्लिकेशन का एक साथ इस्तेमाल देखें.
अन्य संसाधन
- Camera2 का सैंपल देखने के लिए, GitHub पर Camera2Basic ऐप्लिकेशन देखें.
- CameraX की झलक देखने के बारे में जानने के लिए, CameraX झलक लागू करें देखें.
- CameraX कैमरे की झलक दिखाने वाले सैंपल को लागू करने के लिए, GitHub पर CameraXBasic रिपॉज़िटरी देखें.
- ChromeOS पर कैमरे की झलक के बारे में जानकारी पाने के लिए, कैमरे का ओरिएंटेशन देखें.
- फ़ोल्ड किए जा सकने वाले डिवाइसों के लिए ऐप्लिकेशन डेवलप करने के बारे में जानने के लिए, फ़ोल्ड किए जा सकने वाले डिवाइसों के बारे में जानें.