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

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

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

Kotlin

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

Java

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

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

CameraXConfig

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

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

  • setAvailableCameraLimiter() की मदद से, स्टार्टअप लेटेंसी को ऑप्टिमाइज़ करें.
  • setCameraExecutor() का इस्तेमाल करके, CameraX को ऐप्लिकेशन का एक्ज़ीक्यूटर उपलब्ध कराएं.
  • डिफ़ॉल्ट शेड्यूलर हैंडलर को 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 को अन्य कैमरों को अनदेखा करने के लिए सेट किया जा सकता है. इससे, आपके ऐप्लिकेशन के इस्तेमाल किए जाने वाले कैमरों के लिए, स्टार्टअप लेटेंसी कम हो सकती है.

अगर CameraXConfig.Builder.setAvailableCamerasLimiter() को पास किया गया CameraSelector किसी कैमरे को फ़िल्टर करता है, तो 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 एपीआई कॉल के साथ-साथ इन एपीआई से मिलने वाले कॉलबैक के लिए भी किया जाता है. 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 या वीडियो एन्कोडिंग के लिए, "सबसे नज़दीकी 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 पर सेट किया गया हो. आउटपुट बफ़र में क्रॉप रेक्ट और रोटेशन लागू करने के बाद, सभी इस्तेमाल के उदाहरणों से मिलने वाली इमेज एक जैसी होती है. हालांकि, हो सकता है कि उनके रिज़ॉल्यूशन अलग-अलग हों. ट्रांसफ़ॉर्मेशन की जानकारी को लागू करने के तरीके के बारे में ज़्यादा जानने के लिए, आउटपुट को ट्रांसफ़ॉर्म करना लेख पढ़ें.

कैमरा चुनने की सुविधा

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

यहां दिए गए कोड सैंपल में, डिवाइस चुनने पर असर डालने के लिए 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 ऑब्जेक्ट से दोनों कैमरा ऑब्जेक्ट कैसे पाए जाते हैं.

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 के साथ, कैमरे की ये सुविधाएं काम करती हैं:

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

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 दिखाता है.

ज़ूम करें

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 के आधार पर, एएफ़/एई/एडब्ल्यूबी मीटरिंग रीजन सेट करके, ऑटोफ़ोकस और एक्सपोज़र मीटरिंग को ट्रिगर करता है. इसका इस्तेमाल अक्सर कई कैमरा ऐप्लिकेशन में, “टैप करके फ़ोकस करें” सुविधा को लागू करने के लिए किया जाता है.

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 लेता है, जिसमें एएफ़/एई/एडब्ल्यूबी के लिए एक MeteringPoint होता है मीटरिंग रीजन और सिर्फ़ एएफ़ और एई के लिए एक और MeteringPoint.

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

हर डिवाइस में एएफ़/एई/एडब्ल्यूबी और कई इलाकों की सुविधा काम नहीं करती. इसलिए, CameraX FocusMeteringAction को बेहतर तरीके से लागू करता है. CameraX, MeteringPoints की ज़्यादा से ज़्यादा संख्या का इस्तेमाल करता है. यह संख्या, पॉइंट जोड़ने के क्रम में होती है. तय संख्या से ज़्यादा जोड़े गए सभी MeteringPoints को अनदेखा कर दिया जाता है. उदाहरण के लिए, अगर किसी FocusMeteringAction को ऐसे प्लैटफ़ॉर्म पर तीन MeteringPoints के साथ उपलब्ध कराया जाता है जो सिर्फ़ दो MeteringPoints के साथ काम करता है, तो सिर्फ़ पहले दो 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