कॉन्फ़िगरेशन विकल्प

CameraX के हर इस्तेमाल के उदाहरण को कॉन्फ़िगर किया जाता है, ताकि इस्तेमाल के उदाहरण की कार्रवाइयों के अलग-अलग पहलुओं को कंट्रोल किया जा सके.

उदाहरण के लिए, इमेज कैप्चर करने के लिए, टारगेट आसपेक्ट रेशियो और फ़्लैश मोड सेट किया जा सकता है. यहां दिए गए कोड में एक उदाहरण दिखाया गया है:

Kotlin

val imageCapture = ImageCapture.Builder()
    .setFlashMode(...)
    .setTargetAspectRatio(...)
    .build()

Java

ImageCapture imageCapture =
    new ImageCapture.Builder()
        .setFlashMode(...)
        .setTargetAspectRatio(...)
        .build();

कॉन्फ़िगरेशन के विकल्पों के अलावा, इस्तेमाल के कुछ उदाहरणों में एपीआई उपलब्ध कराए जाते हैं. इनकी मदद से, इस्तेमाल के उदाहरण बनाने के बाद सेटिंग को डाइनैमिक तरीके से बदला जा सकता है. इस्तेमाल के अलग-अलग उदाहरणों के हिसाब से कॉन्फ़िगरेशन के बारे में जानने के लिए, प्रीव्यू लागू करना, इमेज का विश्लेषण करना, और इमेज कैप्चर करना लेख पढ़ें.

CameraXConfig

CameraX में डिफ़ॉल्ट कॉन्फ़िगरेशन होते हैं, जैसे कि इंटरनल एक्ज़ीक्यूटर और हैंडलर. ये ज़्यादातर इस्तेमाल के उदाहरणों के लिए सही होते हैं. हालांकि, अगर आपके ऐप्लिकेशन की कुछ खास ज़रूरतें हैं या आपको उन कॉन्फ़िगरेशन को पसंद के मुताबिक बनाना है, तो CameraXConfig इंटरफ़ेस का इस्तेमाल करें.

CameraXConfig की मदद से, कोई ऐप्लिकेशन ये काम कर सकता है:

  • setAvailableCameraLimiter() की मदद से, स्टार्टअप में लगने वाले समय को ऑप्टिमाइज़ करें.
  • CameraX को ऐप्लिकेशन का एक्ज़ीक्यूटर setCameraExecutor() के साथ दें.
  • डिफ़ॉल्ट शेड्यूलर हैंडलर को setSchedulerHandler() से बदलें.
  • setMinimumLoggingLevel() की मदद से, लॉगिंग लेवल बदलें.

इस्तेमाल का मॉडल

CameraXConfig का इस्तेमाल करने का तरीका यहां बताया गया है:

  1. अपनी पसंद के मुताबिक कॉन्फ़िगरेशन के साथ CameraXConfig ऑब्जेक्ट बनाएं.
  2. अपने Application में CameraXConfig.Provider इंटरफ़ेस लागू करें. साथ ही, getCameraXConfig() में अपना CameraXConfig ऑब्जेक्ट दिखाएं.
  3. अपनी Application क्लास को अपनी AndroidManifest.xml फ़ाइल में जोड़ें. इसके बारे में यहां बताया गया है.

उदाहरण के लिए, यहां दिए गए कोड के सैंपल में, CameraX की लॉगिंग को सिर्फ़ गड़बड़ी के मैसेज तक सीमित किया गया है:

Kotlin

class CameraApplication : Application(), CameraXConfig.Provider {
   override fun getCameraXConfig(): CameraXConfig {
       return CameraXConfig.Builder.fromConfig(Camera2Config.defaultConfig())
           .setMinimumLoggingLevel(Log.ERROR).build()
   }
}

अगर आपके ऐप्लिकेशन को CameraX कॉन्फ़िगरेशन सेट करने के बाद इसकी जानकारी चाहिए, तो CameraXConfig ऑब्जेक्ट की एक लोकल कॉपी रखें.

कैमरा लिमिटर

ProcessCameraProvider.getInstance() को पहली बार शुरू करने पर, CameraX डिवाइस पर उपलब्ध कैमरों की विशेषताओं की गिनती करता है और उनके बारे में क्वेरी करता है. CameraX को हार्डवेयर कॉम्पोनेंट के साथ कम्यूनिकेट करना होता है. इसलिए, हर कैमरे के लिए इस प्रोसेस में कुछ समय लग सकता है. खास तौर पर, कम कॉन्फ़िगरेशन वाले डिवाइसों पर. अगर आपका ऐप्लिकेशन, डिवाइस पर सिर्फ़ कुछ कैमरों का इस्तेमाल करता है, तो CameraX को अन्य कैमरों को अनदेखा करने के लिए सेट किया जा सकता है. इससे, आपके ऐप्लिकेशन में इस्तेमाल किए जाने वाले कैमरों के चालू होने में लगने वाला समय कम हो सकता है. जैसे, डिफ़ॉल्ट तौर पर सेट किया गया फ्रंट कैमरा.

अगर CameraSelector से CameraXConfig.Builder.setAvailableCamerasLimiter() को पास किया गया कोई कैमरा फ़िल्टर हो जाता है, तो CameraX इस तरह काम करता है जैसे वह कैमरा मौजूद ही नहीं है. उदाहरण के लिए, यहां दिया गया कोड, ऐप्लिकेशन को सिर्फ़ डिवाइस के डिफ़ॉल्ट बैक कैमरे का इस्तेमाल करने की अनुमति देता है:

Kotlin

class MainApplication : Application(), CameraXConfig.Provider {
   override fun getCameraXConfig(): CameraXConfig {
       return CameraXConfig.Builder.fromConfig(Camera2Config.defaultConfig())
              .setAvailableCamerasLimiter(CameraSelector.DEFAULT_BACK_CAMERA)
              .build()
   }
}

थ्रेड

CameraX को बनाने के लिए इस्तेमाल किए गए कई प्लैटफ़ॉर्म एपीआई को, हार्डवेयर के साथ इंटरप्रोसेस कम्यूनिकेशन (आईपीसी) को ब्लॉक करने की ज़रूरत होती है. इसमें कभी-कभी सैकड़ों मिलीसेकंड लग सकते हैं. इस वजह से, CameraX सिर्फ़ बैकग्राउंड थ्रेड से इन एपीआई को कॉल करता है, ताकि मुख्य थ्रेड ब्लॉक न हो और यूज़र इंटरफ़ेस (यूआई) आसानी से काम करता रहे. CameraX, इन बैकग्राउंड थ्रेड को इंटरनल तौर पर मैनेज करता है, ताकि यह व्यवहार पारदर्शी दिखे. हालांकि, कुछ ऐप्लिकेशन के लिए थ्रेड को पूरी तरह से कंट्रोल करना ज़रूरी होता है. CameraXConfig की मदद से, कोई ऐप्लिकेशन बैकग्राउंड थ्रेड सेट कर सकता है. इनका इस्तेमाल CameraXConfig.Builder.setCameraExecutor() और CameraXConfig.Builder.setSchedulerHandler() के ज़रिए किया जाता है.

कैमरा मैनेजर

कैमरा एक्ज़ीक्यूटर का इस्तेमाल, Camera Platform API के सभी इंटरनल कॉल के लिए किया जाता है. साथ ही, इन एपीआई से मिलने वाले कॉलबैक के लिए भी इसका इस्तेमाल किया जाता है. CameraX, इन टास्क को पूरा करने के लिए, इंटरनल Executor को असाइन और मैनेज करता है. हालांकि, अगर आपके ऐप्लिकेशन को थ्रेड पर ज़्यादा कंट्रोल की ज़रूरत है, तो CameraXConfig.Builder.setCameraExecutor() का इस्तेमाल करें.

शेड्यूलर हैंडलर

शेड्यूलर हैंडलर का इस्तेमाल, तय समय पर इंटरनल टास्क शेड्यूल करने के लिए किया जाता है. जैसे, कैमरा उपलब्ध न होने पर उसे फिर से खोलने की कोशिश करना. यह हैंडलर, टास्क पूरे नहीं करता. यह सिर्फ़ उन्हें कैमरा एक्ज़ीक्यूटर को भेजता है. इसका इस्तेमाल कभी-कभी, एपीआई के उन पुराने प्लैटफ़ॉर्म पर भी किया जाता है जिनके लिए कॉलबैक के लिए Handler की ज़रूरत होती है. ऐसे मामलों में, कॉलबैक अब भी सिर्फ़ कैमरे के एक्ज़ीक्यूटर को भेजे जाते हैं. CameraX, इन टास्क को पूरा करने के लिए एक इंटरनल HandlerThread को असाइन और मैनेज करता है. हालांकि, CameraXConfig.Builder.setSchedulerHandler() का इस्तेमाल करके इसे बदला जा सकता है.

लॉग इन हो रहा है

CameraX लॉगिंग की सुविधा की मदद से, ऐप्लिकेशन logcat मैसेज को फ़िल्टर कर सकते हैं. ऐसा इसलिए, क्योंकि प्रोडक्शन कोड में ज़्यादा जानकारी वाले मैसेज से बचना एक अच्छा तरीका हो सकता है. CameraX में चार लॉगिंग लेवल होते हैं. इनमें सबसे ज़्यादा जानकारी देने वाले लेवल से लेकर सबसे गंभीर लेवल तक शामिल हैं:

  • Log.DEBUG (डिफ़ॉल्ट)
  • Log.INFO
  • Log.WARN
  • Log.ERROR

इन लॉग लेवल के बारे में ज़्यादा जानने के लिए, Android लॉग का दस्तावेज़ देखें. अपने ऐप्लिकेशन के लिए सही लॉगिंग लेवल सेट करने के लिए, CameraXConfig.Builder.setMinimumLoggingLevel(int) का इस्तेमाल करें.

अपने-आप चुने जाने की सुविधा

CameraX, आपके ऐप्लिकेशन को उस डिवाइस के हिसाब से अपने-आप सुविधाएं उपलब्ध कराता है जिस पर आपका ऐप्लिकेशन चल रहा है. उदाहरण के लिए, अगर आपने कोई रिज़ॉल्यूशन तय नहीं किया है या आपके तय किए गए रिज़ॉल्यूशन का इस्तेमाल नहीं किया जा सकता, तो CameraX अपने-आप सबसे सही रिज़ॉल्यूशन तय कर लेता है. इन सभी को लाइब्रेरी मैनेज करती है. इसलिए, आपको डिवाइस के हिसाब से कोड लिखने की ज़रूरत नहीं होती.

CameraX का मकसद, कैमरा सेशन को सही तरीके से शुरू करना है. इसका मतलब है कि CameraX, डिवाइस की क्षमता के आधार पर रिज़ॉल्यूशन और आसपेक्ट रेशियो से समझौता करता है. खाते से समझौता इन वजहों से हो सकता है:

  • डिवाइस पर, अनुरोध किया गया रिज़ॉल्यूशन काम नहीं करता.
  • डिवाइस में, साथ काम करने से जुड़ी समस्याएं हैं. जैसे, लेगसी डिवाइसों को ठीक से काम करने के लिए कुछ रिज़ॉल्यूशन की ज़रूरत होती है.
  • कुछ डिवाइसों पर, कुछ फ़ॉर्मैट सिर्फ़ कुछ आसपेक्ट रेशियो में उपलब्ध होते हैं.
  • इस डिवाइस में, JPEG या वीडियो एन्कोडिंग के लिए "nearest mod16" का इस्तेमाल किया जाता है. ज़्यादा जानकारी के लिए, SCALER_STREAM_CONFIGURATION_MAP देखें.

CameraX, सेशन बनाता है और उसे मैनेज करता है. हालांकि, अपने कोड में इस्तेमाल के उदाहरण के आउटपुट पर, दिखाई गई इमेज के साइज़ की हमेशा जांच करें और उसके मुताबिक बदलाव करें.

रोटेशन

डिफ़ॉल्ट रूप से, कैमरा रोटेशन को डिसप्ले के डिफ़ॉल्ट रोटेशन के हिसाब से सेट किया जाता है. ऐसा इस्तेमाल के उदाहरण बनाते समय किया जाता है. डिफ़ॉल्ट तौर पर, CameraX आउटपुट जनरेट करता है, ताकि ऐप्लिकेशन में आपको वही दिखे जो आपने झलक में देखा था. मल्टी-डिसप्ले डिवाइसों के साथ काम करने के लिए, रोटेशन को कस्टम वैल्यू में बदला जा सकता है. इसके लिए, इस्तेमाल के उदाहरण वाले ऑब्जेक्ट कॉन्फ़िगर करते समय या उन्हें बनाने के बाद, मौजूदा डिसप्ले ओरिएंटेशन पास करें.

आपका ऐप्लिकेशन, कॉन्फ़िगरेशन सेटिंग का इस्तेमाल करके टारगेट रोटेशन सेट कर सकता है. इसके बाद, यह इस्तेमाल के उदाहरण वाले एपीआई (जैसे कि ImageAnalysis.setTargetRotation()) के तरीकों का इस्तेमाल करके, रोटेशन की सेटिंग को अपडेट कर सकता है. ऐसा तब भी किया जा सकता है, जब लाइफ़साइकल चालू हो. इस सुविधा का इस्तेमाल तब किया जा सकता है, जब ऐप्लिकेशन को पोर्ट्रेट मोड में लॉक किया गया हो. ऐसे में, डिवाइस को घुमाने पर कोई बदलाव नहीं होता. हालांकि, फ़ोटो या विश्लेषण के इस्तेमाल के उदाहरण के लिए, डिवाइस के मौजूदा रोटेशन के बारे में पता होना ज़रूरी है. उदाहरण के लिए, रोटेशन की जानकारी की ज़रूरत पड़ सकती है, ताकि चेहरे की पहचान करने के लिए चेहरों को सही तरीके से ओरिएंट किया जा सके या फ़ोटो को लैंडस्केप या पोर्ट्रेट मोड में सेट किया जा सके.

कैप्चर की गई इमेज का डेटा, रोटेशन की जानकारी के बिना सेव किया जा सकता है. Exif डेटा में रोटेशन की जानकारी होती है, ताकि गैलरी ऐप्लिकेशन इमेज को सेव करने के बाद सही ओरिएंटेशन में दिखा सकें.

झलक डेटा को सही ओरिएंटेशन में दिखाने के लिए, Preview.PreviewOutput() से मिले मेटाडेटा का इस्तेमाल करके ट्रांसफ़ॉर्म बनाए जा सकते हैं.

यहां दिए गए कोड के सैंपल में, ओरिएंटेशन इवेंट पर रोटेशन सेट करने का तरीका बताया गया है:

Kotlin

override fun onCreate() {
    val imageCapture = ImageCapture.Builder().build()

    val orientationEventListener = object : OrientationEventListener(this as Context) {
        override fun onOrientationChanged(orientation : Int) {
            // Monitors orientation values to determine the target rotation value
            val rotation : Int = when (orientation) {
                in 45..134 -> Surface.ROTATION_270
                in 135..224 -> Surface.ROTATION_180
                in 225..314 -> Surface.ROTATION_90
                else -> Surface.ROTATION_0
            }

            imageCapture.targetRotation = rotation
        }
    }
    orientationEventListener.enable()
}

Java

@Override
public void onCreate() {
    ImageCapture imageCapture = new ImageCapture.Builder().build();

    OrientationEventListener orientationEventListener = new OrientationEventListener((Context)this) {
       @Override
       public void onOrientationChanged(int orientation) {
           int rotation;

           // Monitors orientation values to determine the target rotation value
           if (orientation >= 45 && orientation < 135) {
               rotation = Surface.ROTATION_270;
           } else if (orientation >= 135 && orientation < 225) {
               rotation = Surface.ROTATION_180;
           } else if (orientation >= 225 && orientation < 315) {
               rotation = Surface.ROTATION_90;
           } else {
               rotation = Surface.ROTATION_0;
           }

           imageCapture.setTargetRotation(rotation);
       }
    };

    orientationEventListener.enable();
}

सेट किए गए रोटेशन के आधार पर, हर इस्तेमाल के उदाहरण में इमेज डेटा को सीधे तौर पर रोटेट किया जाता है. इसके अलावा, रोटेट न किए गए इमेज डेटा के उपभोक्ताओं को रोटेशन मेटाडेटा उपलब्ध कराया जाता है.

  • झलक: मेटाडेटा आउटपुट दिया जाता है, ताकि Preview.getTargetRotation() का इस्तेमाल करके टारगेट रिज़ॉल्यूशन के रोटेशन के बारे में पता चल सके.
  • ImageAnalysis: मेटाडेटा आउटपुट दिया जाता है, ताकि इमेज बफ़र के कोऑर्डिनेट, डिसप्ले के कोऑर्डिनेट के हिसाब से पता चल सकें.
  • ImageCapture: रोटेशन की सेटिंग को नोट करने के लिए, इमेज के Exif मेटाडेटा, बफ़र या बफ़र और मेटाडेटा, दोनों में बदलाव किया जाता है. बदली गई वैल्यू, एचएएल लागू करने के तरीके पर निर्भर करती है.

क्रॉप रेक्ट

डिफ़ॉल्ट रूप से, क्रॉप रेक्ट, पूरा बफ़र रेक्ट होता है. इसे ViewPort और UseCaseGroup की मदद से अपनी पसंद के मुताबिक बनाया जा सकता है. इस्तेमाल के उदाहरणों को ग्रुप करके और व्यूपोर्ट सेट करके, CameraX यह पक्का करता है कि ग्रुप में मौजूद इस्तेमाल के सभी उदाहरणों के क्रॉप रेक्ट, कैमरा सेंसर में एक ही जगह पर पॉइंट करें.

नीचे दिए गए कोड स्निपेट में, इन दोनों क्लास का इस्तेमाल करने का तरीका बताया गया है:

Kotlin

val viewPort =  ViewPort.Builder(Rational(width, height), display.rotation).build()
val useCaseGroup = UseCaseGroup.Builder()
    .addUseCase(preview)
    .addUseCase(imageAnalysis)
    .addUseCase(imageCapture)
    .setViewPort(viewPort)
    .build()
cameraProvider.bindToLifecycle(lifecycleOwner, cameraSelector, useCaseGroup)

Java

ViewPort viewPort = new ViewPort.Builder(
         new Rational(width, height),
         getDisplay().getRotation()).build();
UseCaseGroup useCaseGroup = new UseCaseGroup.Builder()
    .addUseCase(preview)
    .addUseCase(imageAnalysis)
    .addUseCase(imageCapture)
    .setViewPort(viewPort)
    .build();
cameraProvider.bindToLifecycle(lifecycleOwner, cameraSelector, useCaseGroup);

ViewPort से, असली उपयोगकर्ताओं को दिखने वाले बफ़र रेक्ट का पता चलता है. इसके बाद, CameraX, व्यूपोर्ट की प्रॉपर्टी और अटैच किए गए इस्तेमाल के उदाहरणों के आधार पर, सबसे बड़े संभावित क्रॉप रेक्ट का हिसाब लगाता है. आम तौर पर, WYSIWYG इफ़ेक्ट पाने के लिए, झलक देखने के इस्तेमाल के उदाहरण के आधार पर व्यूपोर्ट को कॉन्फ़िगर किया जा सकता है. व्यूपोर्ट पाने का आसान तरीका PreviewView का इस्तेमाल करना है.

यहां दिए गए कोड स्निपेट से पता चलता है कि ViewPort ऑब्जेक्ट कैसे मिलता है:

Kotlin

val viewport = findViewById<PreviewView>(R.id.preview_view).viewPort

Java

ViewPort viewPort = ((PreviewView)findViewById(R.id.preview_view)).getViewPort();

ऊपर दिए गए उदाहरण में, ImageAnalysis और ImageCapture से ऐप्लिकेशन को मिलने वाला डेटा, असली उपयोगकर्ता को PreviewView में दिखने वाले डेटा से मेल खाता है. ऐसा तब होता है, जब PreviewView के स्केल टाइप को डिफ़ॉल्ट FILL_CENTER पर सेट किया गया हो. आउटपुट बफ़र में काटने के आयत और रोटेशन को लागू करने के बाद, इस्तेमाल के सभी उदाहरणों में इमेज एक जैसी होती है. हालांकि, ऐसा हो सकता है कि उनके रिज़ॉल्यूशन अलग-अलग हों. ट्रांसफ़ॉर्मेशन की जानकारी लागू करने के तरीके के बारे में ज़्यादा जानने के लिए, transformOutput देखें.

कैमरा चुनना

CameraX, आपके ऐप्लिकेशन की ज़रूरतों और इस्तेमाल के उदाहरणों के लिए, सबसे अच्छा कैमरा डिवाइस अपने-आप चुन लेता है. अगर आपको उस डिवाइस के बजाय किसी दूसरे डिवाइस का इस्तेमाल करना है जिसे आपके लिए चुना गया है, तो आपके पास ये विकल्प हैं:

  • CameraSelector.DEFAULT_FRONT_CAMERA का इस्तेमाल करके, सामने वाले डिफ़ॉल्ट कैमरे का अनुरोध करें.
  • CameraSelector.DEFAULT_BACK_CAMERA का इस्तेमाल करके, पीछे की ओर लगे डिफ़ॉल्ट कैमरे का अनुरोध करें.
  • उपलब्ध डिवाइसों की सूची को उनके CameraCharacteristics के हिसाब से फ़िल्टर करें. इसके लिए, आपको CameraSelector.Builder.addCameraFilter() की ज़रूरत होगी.

यहां दिए गए कोड के सैंपल में, डिवाइस चुनने की प्रोसेस पर असर डालने के लिए CameraSelector बनाने का तरीका बताया गया है:

Kotlin

fun selectExternalOrBestCamera(provider: ProcessCameraProvider):CameraSelector? {
   val cam2Infos = provider.availableCameraInfos.map {
       Camera2CameraInfo.from(it)
   }.sortedByDescending {
       // HARDWARE_LEVEL is Int type, with the order of:
       // LEGACY < LIMITED < FULL < LEVEL_3 < EXTERNAL
       it.getCameraCharacteristic(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL)
   }

   return when {
       cam2Infos.isNotEmpty() -> {
           CameraSelector.Builder()
               .addCameraFilter {
                   it.filter { camInfo ->
                       // cam2Infos[0] is either EXTERNAL or best built-in camera
                       val thisCamId = Camera2CameraInfo.from(camInfo).cameraId
                       thisCamId == cam2Infos[0].cameraId
                   }
               }.build()
       }
       else -> null
    }
}

// create a CameraSelector for the USB camera (or highest level internal camera)
val selector = selectExternalOrBestCamera(processCameraProvider)
processCameraProvider.bindToLifecycle(this, selector, preview, analysis)

एक साथ कई कैमरे चुनना

CameraX 1.3 से, एक साथ कई कैमरे भी चुने जा सकते हैं. उदाहरण के लिए, फ़्रंट और बैक कैमरे को एक साथ इस्तेमाल किया जा सकता है, ताकि दोनों कैमरों से एक साथ फ़ोटो ली जा सकें या वीडियो रिकॉर्ड किए जा सकें.

एक साथ दो कैमरे इस्तेमाल करने की सुविधा का इस्तेमाल करते समय, डिवाइस एक साथ दो कैमरों को चालू कर सकता है. इन कैमरों के लेंस अलग-अलग दिशाओं में हो सकते हैं. इसके अलावा, डिवाइस एक साथ दो बैक कैमरे भी चालू कर सकता है. यहां दिए गए कोड ब्लॉक में बताया गया है कि bindToLifecycle को कॉल करते समय, दो कैमरे कैसे सेट किए जाते हैं. साथ ही, यह भी बताया गया है कि ConcurrentCamera ऑब्जेक्ट से दोनों Camera ऑब्जेक्ट कैसे पाए जाते हैं.

Kotlin

// Build ConcurrentCameraConfig
val primary = ConcurrentCamera.SingleCameraConfig(
    primaryCameraSelector,
    useCaseGroup,
    lifecycleOwner
)

val secondary = ConcurrentCamera.SingleCameraConfig(
    secondaryCameraSelector,
    useCaseGroup,
    lifecycleOwner
)

val concurrentCamera = cameraProvider.bindToLifecycle(
    listOf(primary, secondary)
)

val primaryCamera = concurrentCamera.cameras[0]
val secondaryCamera = concurrentCamera.cameras[1]

Java

// Build ConcurrentCameraConfig
SingleCameraConfig primary = new SingleCameraConfig(
    primaryCameraSelector,
    useCaseGroup,
    lifecycleOwner
);

SingleCameraConfig secondary = new SingleCameraConfig(
    primaryCameraSelector,
    useCaseGroup,
    lifecycleOwner
);

ConcurrentCamera concurrentCamera =  
    mCameraProvider.bindToLifecycle(Arrays.asList(primary, secondary));

Camera primaryCamera = concurrentCamera.getCameras().get(0);
Camera secondaryCamera = concurrentCamera.getCameras().get(1);

कैमरे का रिज़ॉल्यूशन

आपके पास यह चुनने का विकल्प होता है कि CameraX, इमेज का रिज़ॉल्यूशन सेट करे. इसके लिए, वह डिवाइस की क्षमताओं, डिवाइस के साथ काम करने वाले हार्डवेयर लेवल, इस्तेमाल के उदाहरण, और दिए गए आसपेक्ट रेशियो (लंबाई-चौड़ाई का अनुपात) को ध्यान में रखता है. इसके अलावा, उन मामलों में टारगेट रिज़ॉल्यूशन या पहलू का खास अनुपात सेट किया जा सकता है जिनमें इस कॉन्फ़िगरेशन का इस्तेमाल किया जा सकता है.

समस्या अपने-आप ठीक होने की सुविधा

CameraX, cameraProcessProvider.bindToLifecycle() में बताए गए इस्तेमाल के उदाहरणों के आधार पर, सबसे सही रिज़ॉल्यूशन सेटिंग अपने-आप तय कर सकता है. जब भी मुमकिन हो, एक ही सेशन में एक साथ चलाने के लिए ज़रूरी इस्तेमाल के सभी उदाहरणों को एक ही bindToLifecycle() कॉल में शामिल करें. CameraX, रिज़ॉल्यूशन का पता लगाता है. इसके लिए, वह इस्तेमाल के उन मामलों के सेट का इस्तेमाल करता है जो डिवाइस के साथ काम करने वाले हार्डवेयर लेवल को ध्यान में रखकर तय किए जाते हैं. साथ ही, वह डिवाइस के हिसाब से अंतर को भी ध्यान में रखता है. इस अंतर में, यह देखा जाता है कि कोई डिवाइस स्ट्रीम कॉन्फ़िगरेशन के उपलब्ध विकल्पों से ज़्यादा या कम है. इसका मकसद, ऐप्लिकेशन को अलग-अलग तरह के डिवाइसों पर चलाना है. साथ ही, डिवाइस के हिसाब से कोड पाथ को कम करना है.

इमेज कैप्चर करने और इमेज का विश्लेषण करने के इस्तेमाल के उदाहरणों के लिए, डिफ़ॉल्ट आसपेक्ट रेशियो 4:3 होता है.

इस्तेमाल के उदाहरणों में, कॉन्फ़िगर किया जा सकने वाला आसपेक्ट रेशियो (चौड़ाई-ऊंचाई का अनुपात) होता है. इससे ऐप्लिकेशन, यूज़र इंटरफ़ेस (यूआई) डिज़ाइन के आधार पर, मनचाहा आसपेक्ट रेशियो तय कर सकता है. CameraX का आउटपुट, अनुरोध किए गए आसपेक्ट रेशियो से मेल खाने के लिए तैयार किया जाता है. हालांकि, यह डिवाइस के हिसाब से तय होता है. अगर सटीक मिलान वाले रिज़ॉल्यूशन का इस्तेमाल नहीं किया जा सकता, तो उस रिज़ॉल्यूशन को चुना जाता है जो ज़्यादातर शर्तों को पूरा करता है. इसलिए, ऐप्लिकेशन यह तय करता है कि कैमरे को ऐप्लिकेशन में कैसे दिखाया जाए. साथ ही, CameraX अलग-अलग डिवाइसों पर कैमरे के रिज़ॉल्यूशन की सबसे अच्छी सेटिंग तय करता है, ताकि ऐप्लिकेशन की ज़रूरतें पूरी की जा सकें.

उदाहरण के लिए, कोई ऐप्लिकेशन इनमें से कोई भी काम कर सकता है:

  • इस्तेमाल के किसी उदाहरण के लिए, 4:3 या 16:9 का टारगेट रिज़ॉल्यूशन तय करना
  • कस्टम रिज़ॉल्यूशन तय करें. CameraX, इसके सबसे मिलते-जुलते रिज़ॉल्यूशन का पता लगाने की कोशिश करता है
  • ImageCapture के लिए, काटने का आसपेक्ट रेशियो (लंबाई-चौड़ाई का अनुपात) तय करें

CameraX, Camera2 के इंटरनल सर्फ़ेस रिज़ॉल्यूशन को अपने-आप चुनता है. इस टेबल में रिज़ॉल्यूशन दिखाए गए हैं:

इस्तेमाल का उदाहरण इंटरनल डिसप्ले का रिज़ॉल्यूशन आउटपुट डेटा रिज़ॉल्यूशन
झलक देखें आसपेक्ट रेशियो: यह टारगेट के लिए सबसे सही रिज़ॉल्यूशन होता है. इंटरनल सर्फ़ेस रिज़ॉल्यूशन. मेटाडेटा इसलिए दिया जाता है, ताकि टारगेट आसपेक्ट रेशियो के हिसाब से व्यू को काटा, छोटा-बड़ा, और घुमाया जा सके.
डिफ़ॉल्ट रिज़ॉल्यूशन: झलक का सबसे ज़्यादा रिज़ॉल्यूशन या डिवाइस के हिसाब से सबसे अच्छा रिज़ॉल्यूशन, जो झलक के आसपेक्ट रेशियो से मेल खाता हो.
ज़्यादा से ज़्यादा रिज़ॉल्यूशन: झलक का साइज़. यह डिवाइस के स्क्रीन रिज़ॉल्यूशन या 1080p (1920x1080) के हिसाब से सबसे सही साइज़ होता है. हालांकि, इनमें से जो भी साइज़ छोटा होता है उसे चुना जाता है.
इमेज का विश्लेषण करना आसपेक्ट रेशियो: वह रिज़ॉल्यूशन जो टारगेट आसपेक्ट रेशियो सेटिंग के लिए सबसे सही हो. इंटरनल सर्फ़ेस रिज़ॉल्यूशन.
डिफ़ॉल्ट रिज़ॉल्यूशन: डिफ़ॉल्ट रूप से, टारगेट रिज़ॉल्यूशन की सेटिंग 640x480 पर सेट होती है. टारगेट रिज़ॉल्यूशन और उससे जुड़े आसपेक्ट रेशियो (चौड़ाई-ऊंचाई का अनुपात), दोनों को अडजस्ट करने पर सबसे सही रिज़ॉल्यूशन मिलता है.
ज़्यादा से ज़्यादा रिज़ॉल्यूशन: यह कैमरा डिवाइस के YUV_420_888 फ़ॉर्मैट का ज़्यादा से ज़्यादा आउटपुट रिज़ॉल्यूशन होता है. इसे StreamConfigurationMap.getOutputSizes() से वापस पाया जाता है. डिफ़ॉल्ट रूप से, टारगेट रिज़ॉल्यूशन 640x480 पर सेट होता है. इसलिए, अगर आपको 640x480 से ज़्यादा रिज़ॉल्यूशन चाहिए, तो आपको setTargetResolution() और setTargetAspectRatio() का इस्तेमाल करना होगा, ताकि आपको सपोर्ट किए गए रिज़ॉल्यूशन में से सबसे सही रिज़ॉल्यूशन मिल सके.
इमेज कैप्चर करने की सुविधा आसपेक्ट रेशियो: ऐसा आसपेक्ट रेशियो जो सेटिंग के हिसाब से सबसे सही हो. इंटरनल सर्फ़ेस रिज़ॉल्यूशन.
डिफ़ॉल्ट रिज़ॉल्यूशन: उपलब्ध सबसे ज़्यादा रिज़ॉल्यूशन या डिवाइस के लिए सबसे अच्छा रिज़ॉल्यूशन, जो ImageCapture के आसपेक्ट रेशियो से मेल खाता हो.
ज़्यादा से ज़्यादा रिज़ॉल्यूशन: कैमरा डिवाइस का ज़्यादा से ज़्यादा आउटपुट रिज़ॉल्यूशन, JPEG फ़ॉर्मैट में होता है. इसे वापस पाने के लिए, StreamConfigurationMap.getOutputSizes() का इस्तेमाल करें.

रिज़ॉल्यूशन तय करना

setTargetResolution(Size resolution) तरीके का इस्तेमाल करके, इस्तेमाल के उदाहरण बनाते समय खास रिज़ॉल्यूशन सेट किए जा सकते हैं. यहां दिए गए कोड के सैंपल में दिखाया गया है:

Kotlin

val imageAnalysis = ImageAnalysis.Builder()
    .setTargetResolution(Size(1280, 720))
    .build()

Java

ImageAnalysis imageAnalysis =
  new ImageAnalysis.Builder()
    .setTargetResolution(new Size(1280, 720))
    .build();

एक ही इस्तेमाल के मामले में, टारगेट आसपेक्ट रेशियो (लंबाई-चौड़ाई का अनुपात) और टारगेट रिज़ॉल्यूशन, दोनों को सेट नहीं किया जा सकता. ऐसा करने पर, कॉन्फ़िगरेशन ऑब्जेक्ट बनाते समय IllegalArgumentException दिखता है.

टारगेट रोटेशन के हिसाब से, काम करने वाले साइज़ को घुमाने के बाद, कोऑर्डिनेट फ़्रेम में रिज़ॉल्यूशन Size दिखाएं. उदाहरण के लिए, अगर किसी डिवाइस को पोर्ट्रेट मोड में रखा गया है और वह पोर्ट्रेट इमेज का अनुरोध कर रहा है, तो वह 480x640 डाइमेंशन तय कर सकता है. वहीं, अगर उसी डिवाइस को 90 डिग्री घुमाकर लैंडस्केप मोड में रखा गया है, तो वह 640x480 डाइमेंशन तय कर सकता है.

टारगेट रिज़ॉल्यूशन, इमेज के रिज़ॉल्यूशन के लिए कम से कम सीमा तय करता है. इमेज का असल रिज़ॉल्यूशन, साइज़ के हिसाब से सबसे नज़दीकी उपलब्ध रिज़ॉल्यूशन होता है. यह टारगेट रिज़ॉल्यूशन से छोटा नहीं होता. इसका फ़ैसला, कैमरा लागू करने वाले व्यक्ति या कंपनी करती है.

हालांकि, अगर टारगेट रिज़ॉल्यूशन के बराबर या उससे ज़्यादा रिज़ॉल्यूशन वाला कोई वीडियो उपलब्ध नहीं है, तो टारगेट रिज़ॉल्यूशन से कम रिज़ॉल्यूशन वाला सबसे नज़दीकी वीडियो चुना जाता है. दिए गए Size के आसपेक्ट रेशियो वाले रिज़ॉल्यूशन को, अलग-अलग आसपेक्ट रेशियो वाले रिज़ॉल्यूशन की तुलना में ज़्यादा प्राथमिकता दी जाती है.

CameraX, अनुरोधों के आधार पर सबसे सही रिज़ॉल्यूशन लागू करता है. अगर आपकी मुख्य ज़रूरत आसपेक्ट रेशियो (लंबाई-चौड़ाई का अनुपात) को पूरा करना है, तो सिर्फ़ setTargetAspectRatio तय करें. इसके बाद, CameraX डिवाइस के हिसाब से सही रिज़ॉल्यूशन तय करेगा. अगर ऐप्लिकेशन की मुख्य ज़रूरत इमेज प्रोसेसिंग को ज़्यादा असरदार बनाने के लिए रिज़ॉल्यूशन तय करना है (उदाहरण के लिए, डिवाइस की प्रोसेसिंग क्षमता के आधार पर छोटी या मीडियम साइज़ की इमेज), तो setTargetResolution(Size resolution) का इस्तेमाल करें.

अगर आपके ऐप्लिकेशन के लिए सटीक रिज़ॉल्यूशन की ज़रूरत है, तो createCaptureSession() में दी गई टेबल देखें. इससे आपको पता चलेगा कि हर हार्डवेयर लेवल पर, ज़्यादा से ज़्यादा कितने रिज़ॉल्यूशन काम करते हैं. मौजूदा डिवाइस पर काम करने वाले रिज़ॉल्यूशन देखने के लिए, StreamConfigurationMap.getOutputSizes(int) पर जाएं.

अगर आपका ऐप्लिकेशन Android 10 या इसके बाद के वर्शन पर काम करता है, तो किसी SessionConfiguration की पुष्टि करने के लिए, isSessionConfigurationSupported() का इस्तेमाल किया जा सकता है.

कैमरे के आउटपुट को कंट्रोल करना

CameraX, आपको हर इस्तेमाल के उदाहरण के लिए, ज़रूरत के मुताबिक कैमरा आउटपुट कॉन्फ़िगर करने की सुविधा देता है. साथ ही, यह बाइंड किए गए सभी इस्तेमाल के उदाहरणों के लिए, कैमरा ऑपरेशन को सपोर्ट करने के लिए इन इंटरफ़ेस को भी लागू करता है:

  • CameraControl की मदद से, कैमरे की सामान्य सुविधाओं को कॉन्फ़िगर किया जा सकता है.
  • CameraInfo की मदद से, कैमरे की उन सामान्य सुविधाओं की स्थितियों के बारे में क्वेरी की जा सकती है.

CameraControl के साथ काम करने वाली कैमरे की सुविधाएं ये हैं:

  • Zoom
  • टॉर्च
  • फ़ोकस और मीटरिंग (टैप-टू-फ़ोकस)
  • एक्सपोज़र कंपंसेशन

CameraControl और CameraInfo के इंस्टेंस पाना

ProcessCameraProvider.bindToLifecycle() से मिले Camera ऑब्जेक्ट का इस्तेमाल करके, CameraControl और CameraInfo के इंस्टेंस पाएं. यहां दिए गए कोड में एक उदाहरण दिखाया गया है:

Kotlin

val camera = processCameraProvider.bindToLifecycle(lifecycleOwner, cameraSelector, preview)

// For performing operations that affect all outputs.
val cameraControl = camera.cameraControl
// For querying information and states.
val cameraInfo = camera.cameraInfo

Java

Camera camera = processCameraProvider.bindToLifecycle(lifecycleOwner, cameraSelector, preview)

// For performing operations that affect all outputs.
CameraControl cameraControl = camera.getCameraControl()
// For querying information and states.
CameraInfo cameraInfo = camera.getCameraInfo()

उदाहरण के लिए, bindToLifecycle() को कॉल करने के बाद, ज़ूम करने और अन्य CameraControl कार्रवाइयां की जा सकती हैं. कैमरे के इंस्टेंस को बाइंड करने के लिए इस्तेमाल की गई गतिविधि को रोकने या बंद करने के बाद, CameraControl अब कार्रवाइयां नहीं कर सकता. साथ ही, ListenableFuture के तौर पर 'कार्रवाई पूरी नहीं की जा सकी' मैसेज दिखाता है.

Zoom

CameraControl में, ज़ूम लेवल बदलने के लिए दो तरीके उपलब्ध हैं:

  • setZoomRatio() ज़ूम रेशियो के हिसाब से ज़ूम सेट करता है.

    अनुपात, CameraInfo.getZoomState().getValue().getMinZoomRatio() और CameraInfo.getZoomState().getValue().getMaxZoomRatio() के बीच होना चाहिए. ऐसा न होने पर, फ़ंक्शन फ़ेल होने की स्थिति ListenableFuture दिखाता है.

  • setLinearZoom() इस विकल्प से, ज़ूम की मौजूदा वैल्यू सेट की जाती है. इसकी वैल्यू 0 से 1.0 के बीच होती है.

    लीनियर ज़ूम का फ़ायदा यह है कि इससे ज़ूम में होने वाले बदलावों के साथ-साथ, फ़ील्ड ऑफ़ व्यू (एफ़ओवी) भी बदलता है. इसलिए, इसका इस्तेमाल Slider व्यू के साथ किया जा सकता है.

CameraInfo.getZoomState() ज़ूम की मौजूदा स्थिति का LiveData दिखाता है. कैमरा शुरू होने पर या setZoomRatio() या setLinearZoom() का इस्तेमाल करके ज़ूम लेवल सेट करने पर, वैल्यू बदल जाती है. इनमें से किसी भी तरीके को कॉल करने पर, ZoomState.getZoomRatio() और ZoomState.getLinearZoom() की वैल्यू सेट हो जाती हैं. अगर आपको स्लाइडर के साथ ज़ूम रेशियो का टेक्स्ट दिखाना है, तो यह विकल्प आपके लिए मददगार है. दोनों को अपडेट करने के लिए, ZoomState LiveData को देखें. इसके लिए, आपको कन्वर्ज़न करने की ज़रूरत नहीं है.

दोनों एपीआई से मिले ListenableFuture से, ऐप्लिकेशन को यह विकल्प मिलता है कि जब तय की गई ज़ूम वैल्यू के साथ बार-बार किए जाने वाले अनुरोध पूरे हो जाएं, तो उन्हें सूचना मिल जाए. इसके अलावा, अगर पिछले ऑपरेशन के चालू रहने के दौरान ज़ूम की नई वैल्यू सेट की जाती है, तो पिछले ज़ूम ऑपरेशन का ListenableFuture तुरंत बंद हो जाता है.

टॉर्च

CameraControl.enableTorch(boolean) इससे टॉर्च (इसे फ़्लैशलाइट भी कहा जाता है) चालू या बंद होती है.

CameraInfo.getTorchState() का इस्तेमाल, टॉर्च की मौजूदा स्थिति के बारे में क्वेरी करने के लिए किया जा सकता है. CameraInfo.hasFlashUnit() से मिली वैल्यू देखकर पता लगाया जा सकता है कि टॉर्च उपलब्ध है या नहीं. अगर ऐसा नहीं होता है, तो CameraControl.enableTorch(boolean) को कॉल करने पर, ListenableFuture तुरंत पूरा हो जाता है और टॉर्च की स्थिति TorchState.OFF पर सेट हो जाती है.

टॉर्च चालू होने पर, फ़ोटो और वीडियो कैप्चर करने के दौरान यह चालू रहती है. भले ही, flashMode की सेटिंग कुछ भी हो. ImageCapture में मौजूद flashMode सिर्फ़ तब काम करता है, जब टॉर्च बंद हो.

फ़ोकस और मीटरिंग

CameraControl.startFocusAndMetering() से, फ़ोकस और एक्सपोज़र मेज़रमेंट ट्रिगर होता है. इसके लिए, FocusMeteringAction के आधार पर AF/AE/AWB मेज़रमेंट रीजन सेट किए जाते हैं. इसका इस्तेमाल अक्सर कई कैमरा ऐप्लिकेशन में “टैप करके फ़ोकस करें” सुविधा को लागू करने के लिए किया जाता है.

MeteringPoint

शुरू करने के लिए, MeteringPointFactory.createPoint(float x, float y, float size) का इस्तेमाल करके MeteringPoint बनाएं. MeteringPoint, कैमरे पर मौजूद एक पॉइंट Surface को दिखाता है. इसे सामान्य किए गए फ़ॉर्म में सेव किया जाता है, ताकि इसे सेंसर के कोऑर्डिनेट में आसानी से बदला जा सके. इससे एएफ़/एई/एडब्ल्यूबी क्षेत्रों के बारे में जानकारी दी जा सकती है.

MeteringPoint का साइज़ 0 से 1 के बीच होता है. इसका डिफ़ॉल्ट साइज़ 0.15f होता है. MeteringPointFactory.createPoint(float x, float y, float size) को कॉल करने पर, CameraX, दिए गए size के लिए, (x, y) पर एक आयताकार क्षेत्र बनाता है.

यहां दिए गए कोड में, MeteringPoint बनाने का तरीका बताया गया है:

Kotlin

// Use PreviewView.getMeteringPointFactory if PreviewView is used for preview.
previewView.setOnTouchListener((view, motionEvent) ->  {
val meteringPoint = previewView.meteringPointFactory
    .createPoint(motionEvent.x, motionEvent.y)

}

// Use DisplayOrientedMeteringPointFactory if SurfaceView / TextureView is used for
// preview. Please note that if the preview is scaled or cropped in the View,
// it’s the application's responsibility to transform the coordinates properly
// so that the width and height of this factory represents the full Preview FOV.
// And the (x,y) passed to create MeteringPoint might need to be adjusted with
// the offsets.
val meteringPointFactory = DisplayOrientedMeteringPointFactory(
     surfaceView.display,
     camera.cameraInfo,
     surfaceView.width,
     surfaceView.height
)

// Use SurfaceOrientedMeteringPointFactory if the point is specified in
// ImageAnalysis ImageProxy.
val meteringPointFactory = SurfaceOrientedMeteringPointFactory(
     imageWidth,
     imageHeight,
     imageAnalysis)

startFocusAndMetering और FocusMeteringAction

startFocusAndMetering() को चालू करने के लिए, ऐप्लिकेशन को FocusMeteringAction बनाना होगा. इसमें MeteringPoints के साथ-साथ FLAG_AF, FLAG_AE, और FLAG_AWB से मीटरिंग मोड के एक या उससे ज़्यादा कॉम्बिनेशन शामिल होते हैं. इस कोड में, इस सुविधा के इस्तेमाल के बारे में बताया गया है:

Kotlin

val meteringPoint1 = meteringPointFactory.createPoint(x1, x1)
val meteringPoint2 = meteringPointFactory.createPoint(x2, y2)
val action = FocusMeteringAction.Builder(meteringPoint1) // default AF|AE|AWB
      // Optionally add meteringPoint2 for AF/AE.
      .addPoint(meteringPoint2, FLAG_AF | FLAG_AE)
      // The action is canceled in 3 seconds (if not set, default is 5s).
      .setAutoCancelDuration(3, TimeUnit.SECONDS)
      .build()

val result = cameraControl.startFocusAndMetering(action)
// Adds listener to the ListenableFuture if you need to know the focusMetering result.
result.addListener({
   // result.get().isFocusSuccessful returns if the auto focus is successful or not.
}, ContextCompat.getMainExecutor(this)

ऊपर दिए गए कोड में दिखाया गया है कि startFocusAndMetering(), FocusMeteringAction लेता है. इसमें AF/AE/AWB के लिए एक MeteringPoint और सिर्फ़ AF और AE के लिए एक और MeteringPoint शामिल है.

CameraX, इसे Camera2 MeteringRectangles में बदलता है और कैप्चर करने के अनुरोध के लिए, इससे जुड़े CONTROL_AF_REGIONS / CONTROL_AE_REGIONS / CONTROL_AWB_REGIONS पैरामीटर सेट करता है.

हर डिवाइस पर एएफ़/एई/एडब्ल्यूबी और एक से ज़्यादा क्षेत्रों की सुविधा काम नहीं करती. इसलिए, CameraX सबसे सही तरीके से FocusMeteringAction को लागू करता है. CameraX, ज़्यादा से ज़्यादा MeteringPoints का इस्तेमाल करता है. इन पॉइंट को उसी क्रम में इस्तेमाल किया जाता है जिस क्रम में इन्हें जोड़ा गया था. तय सीमा के बाद जोड़े गए सभी MeteringPoints को अनदेखा कर दिया जाता है. उदाहरण के लिए, अगर किसी ऐसे प्लैटफ़ॉर्म पर 3 MeteringPoints वाला FocusMeteringAction उपलब्ध कराया जाता है जो सिर्फ़ 2 MeteringPoints के साथ काम करता है, तो सिर्फ़ पहले 2 MeteringPoints का इस्तेमाल किया जाता है. CameraX, आखिरी MeteringPoint को अनदेखा करता है.

एक्सपोज़र कंपंसेशन

एक्सपोज़र कंपंसेशन तब काम आता है, जब ऐप्लिकेशन को ऑटो एक्सपोज़र (एई) के आउटपुट नतीजे से ज़्यादा, एक्सपोज़र वैल्यू (ईवी) को बेहतर बनाना होता है. मौजूदा इमेज की स्थितियों के लिए ज़रूरी एक्सपोज़र का पता लगाने के लिए, एक्सपोज़र कॉम्पन्सेशन की वैल्यू को इस तरह से जोड़ा जाता है:

Exposure = ExposureCompensationIndex * ExposureCompensationStep

CameraX, एक्सपोज़र कंपंसेशन को इंडेक्स वैल्यू के तौर पर सेट करने के लिए Camera.CameraControl.setExposureCompensationIndex() फ़ंक्शन उपलब्ध कराता है.

पॉज़िटिव इंडेक्स वैल्यू से इमेज की चमक बढ़ती है, जबकि नेगेटिव वैल्यू से इमेज की चमक कम होती है. ऐप्लिकेशन, CameraInfo.ExposureState.exposureCompensationRange() में बताई गई रेंज के बारे में क्वेरी कर सकते हैं. इसके बारे में अगले सेक्शन में बताया गया है. अगर वैल्यू का इस्तेमाल किया जा सकता है, तो कैप्चर करने के अनुरोध में वैल्यू के चालू होने पर, लौटाया गया ListenableFuture पूरा हो जाता है. अगर तय किया गया इंडेक्स, इस्तेमाल की जा सकने वाली सीमा से बाहर है, तो setExposureCompensationIndex() की वजह से, लौटाया गया ListenableFuture तुरंत पूरा हो जाता है और नतीजे के तौर पर गड़बड़ी दिखती है.

CameraX, सिर्फ़ सबसे हाल ही के setExposureCompensationIndex() अनुरोध को सेव रखता है. साथ ही, पिछले अनुरोध के पूरा होने से पहले इस फ़ंक्शन को कई बार कॉल करने पर, पिछला अनुरोध रद्द हो जाता है.

नीचे दिए गए स्निपेट में, एक्सपोज़र कॉम्पन्सेशन इंडेक्स सेट किया गया है. साथ ही, एक्सपोज़र बदलने का अनुरोध पूरा होने पर कॉल करने के लिए एक कॉलबैक रजिस्टर किया गया है:

Kotlin

camera.cameraControl.setExposureCompensationIndex(exposureCompensationIndex)
   .addListener({
      // Get the current exposure compensation index, it might be
      // different from the asked value in case this request was
      // canceled by a newer setting request.
      val currentExposureIndex = camera.cameraInfo.exposureState.exposureCompensationIndex
      
   }, mainExecutor)
  • Camera.CameraInfo.getExposureState() मौजूदा ExposureState की जानकारी देता है. इसमें ये शामिल हैं:

    • एक्सपोज़र कंपंसेशन कंट्रोल की सुविधा काम करती है या नहीं.
    • मौजूदा एक्सपोज़र कंपंसेशन इंडेक्स.
    • एक्सपोज़र कंपंसेशन इंडेक्स की रेंज.
    • एक्सपोज़र कंपंसेशन की वैल्यू कैलकुलेट करने के लिए, एक्सपोज़र कंपंसेशन के इस चरण का इस्तेमाल किया जाता है.

उदाहरण के लिए, यहां दिया गया कोड, मौजूदा ExposureState वैल्यू के साथ, किसी इंप्रेशन SeekBar के लिए सेटिंग को शुरू करता है:

Kotlin

val exposureState = camera.cameraInfo.exposureState
binding.seekBar.apply {
   isEnabled = exposureState.isExposureCompensationSupported
   max = exposureState.exposureCompensationRange.upper
   min = exposureState.exposureCompensationRange.lower
   progress = exposureState.exposureCompensationIndex
}

अन्य संसाधन

CameraX के बारे में ज़्यादा जानने के लिए, यहां दिए गए अतिरिक्त संसाधन देखें.

कोडलैब (कोड बनाना सीखना)

  • CameraX का इस्तेमाल शुरू करना
  • कोड सैंपल

  • CameraX के सैंपल ऐप्लिकेशन
  • डेवलपर कम्यूनिटी

    Android CameraX Discussion Group