কনফিগারেশন সংক্রান্ত বিকল্প

আপনি প্রতিটি CameraX ব্যবহারের ক্ষেত্রে কনফিগার করেন যাতে ব্যবহারের ক্ষেত্রে অপারেশনের বিভিন্ন দিক নিয়ন্ত্রণ করা যায়।

যেমন, ইমেজ ক্যাপচার ব্যবহারের ক্ষেত্রে, আপনি টার্গেট অ্যাস্পেক্ট রেশিও এবং ফ্ল্যাশ মোড সেট করতে পারেন। নিচের কোডটি একটি উদাহরণ দেখায়:

Kotlin

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

জাভা

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

কনফিগারেশন বিকল্প ছাড়াও, কিছু ব্যবহারের ক্ষেত্রে, ব্যবহারের ক্ষেত্র তৈরি করার পরে সেটিংস ডাইনামিকভাবে পরিবর্তন করার জন্য API প্রকাশ করে। স্বতন্ত্র ব্যবহারের ক্ষেত্রে নির্দিষ্ট কনফিগারেশন সম্পর্কে তথ্যের জন্য, প্রিভিউ প্রয়োগ করুন, ছবি বিশ্লেষণ করুন এবং ছবি ক্যাপচার করুন দেখুন।

CameraXConfig

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

CameraXConfig-এর মাধ্যমে, কোনও অ্যাপ্লিকেশন নিম্নলিখিত কাজগুলি করতে পারে:

  • setAvailableCameraLimiter()-এর মাধ্যমে স্টার্টআপ লেটেন্সি অপ্টিমাইজ করুন।
  • setCameraExecutor()-এর মাধ্যমে CameraX-এ অ্যাপ্লিকেশনের এক্সিকিউটর প্রদান করুন।
  • ডিফল্ট শিডিউলার হ্যান্ডলারের পরিবর্তে setSchedulerHandler() ব্যবহার করুন।
  • setMinimumLoggingLevel()-এর মাধ্যমে লগিং লেভেল পরিবর্তন করুন।

ব্যবহারের মডেল

নিম্নলিখিত পদ্ধতিতে CameraXConfig কীভাবে ব্যবহার করতে হয় তা বর্ণনা করা হয়েছে:

  1. আপনার কাস্টমাইজ করা কনফিগারেশন সহ একটি CameraXConfig অবজেক্ট তৈরি করুন।
  2. আপনার Application-এ CameraXConfig.Provider ইন্টারফেস প্রয়োগ করুন এবং getCameraXConfig()-এ আপনার CameraXConfig অবজেক্ট ফিরিয়ে দিন।
  3. AndroidManifest.xml ফাইলে আপনার Application ক্লাস যোগ করুন, এখানে যেমন বলা হয়েছে।

যেমন, নিম্নলিখিত কোড স্যাম্পেল CameraX লগিংকে শুধুমাত্র ত্রুটি মেসেজে সীমাবদ্ধ করে:

Kotlin

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

আপনার অ্যাপ্লিকেশনের CameraXConfig অবজেক্টের একটি লোকাল কপি রাখুন যদি আপনার অ্যাপ্লিকেশনকে সেট করার পরে CameraX কনফিগারেশন জানতে হয়।

ক্যামেরা লিমিটার

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 যে প্ল্যাটফর্ম API-এর উপর তৈরি করা হয়েছে তার মধ্যে অনেক API-এর ক্ষেত্রে হার্ডওয়্যারের সাথে ইন্টারপ্রসেস কমিউনিকেশন (IPC) ব্লক করার প্রয়োজন হয়, যার উত্তর দিতে কখনও কখনও কয়েকশো মিলিসেকেন্ড সময় লাগতে পারে। এই কারণে, CameraX শুধুমাত্র ব্যাকগ্রাউন্ড থ্রেড থেকে এইসব API কল করে, যাতে প্রধান থ্রেড ব্লক না হয় এবং UI তরল থাকে। CameraX ইন্টার্নালি এইসব ব্যাকগ্রাউন্ড থ্রেড ম্যানেজ করে যাতে এই আচরণ স্বচ্ছ বলে মনে হয়। তবে, কিছু অ্যাপ্লিকেশনের ক্ষেত্রে থ্রেড কঠোরভাবে নিয়ন্ত্রণ করতে হয়। CameraXConfig কোনও অ্যাপ্লিকেশনকে ব্যাকগ্রাউন্ড থ্রেড সেট করতে দেয় যা CameraXConfig.Builder.setCameraExecutor() এবং CameraXConfig.Builder.setSchedulerHandler()-এর মাধ্যমে ব্যবহার করা হয়।

ক্যামেরা এক্সিকিউটর

ক্যামেরা এক্সিকিউটর সব ইন্টার্নাল ক্যামেরা প্ল্যাটফর্ম API কলের জন্য ব্যবহার করা হয়, পাশাপাশি এইসব API থেকে কলব্যাকের জন্যও ব্যবহার করা হয়। CameraX এইসব টাস্ক পারফর্ম করার জন্য একটি ইন্টার্নাল Executor বরাদ্দ ও ম্যানেজ করে। তবে, আপনার অ্যাপ্লিকেশনে থ্রেডের আরও কঠোর নিয়ন্ত্রণের প্রয়োজন হলে, CameraXConfig.Builder.setCameraExecutor() ব্যবহার করুন।

শিডিউলার হ্যান্ডলার

শিডিউলার হ্যান্ডলার নির্দিষ্ট বিরতিতে ইন্টার্নাল টাস্ক শিডিউল করতে ব্যবহার করা হয়, যেমন ক্যামেরা উপলভ্য না থাকলে সেটি খোলার জন্য আবার চেষ্টা করা। এই হ্যান্ডলার কাজ এক্সিকিউট করে না, শুধু ক্যামেরা এক্সিকিউটরে পাঠায়। এছাড়াও, এটি কখনও কখনও লিগ্যাসি API প্ল্যাটফর্মে ব্যবহার করা হয় যার জন্য কলব্যাকের জন্য একটি 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 আউটপুট তৈরি করে যাতে অ্যাপটি প্রিভিউতে আপনি যা দেখতে চান তার সাথে ম্যাচ করতে পারে। মাল্টি-ডিসপ্লে ডিভাইস সাপোর্ট করার জন্য আপনি রোটেশন পরিবর্তন করে কাস্টম ভ্যালু সেট করতে পারেন। এর জন্য, ইউজ কেস অবজেক্ট কনফিগার করার সময় বা সেগুলি তৈরি করার পরে ডায়নামিকালি বর্তমান ডিসপ্লে ওরিয়েন্টেশন পাস করতে হবে।

আপনার অ্যাপ কনফিগারেশন সেটিংস ব্যবহার করে টার্গেট রোটেশন সেট করতে পারে। এটি তারপর ব্যবহারের ক্ষেত্রে API (যেমন 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()
}

জাভা

@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 মেটাডেটা, বাফার অথবা বাফার ও মেটাডেটা, উভয়ই পরিবর্তন করা হয়। পরিবর্তিত মান HAL ইমপ্লিমেন্টেশনের উপর নির্ভর করে।

ক্রপ রেক্ট

ডিফল্ট হিসেবে, ক্রপ রেক্ট হল সম্পূর্ণ বাফার রেক্ট। আপনি এটি 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)

জাভা

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

জাভা

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]

জাভা

// 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-কে ছবির রেজোলিউশন সেট করার অনুমতি দিতে পারেন। বিকল্প হিসেবে, আপনি নির্দিষ্ট টার্গেট রেজোলিউশন বা নির্দিষ্ট অ্যাস্পেক্ট রেশিও সেট করতে পারেন, যা সেই কনফিগারেশনকে সাপোর্ট করে।

অটোমেটিক রেজোলিউশন

cameraProcessProvider.bindToLifecycle()-এ উল্লেখ করা ব্যবহারের কেসের উপর ভিত্তি করে CameraX অটোমেটিক সেরা রেজোলিউশন সেটিংস নির্ধারণ করতে পারে। যখনই সম্ভব, একটি bindToLifecycle() কলে একটি সেশনে একসাথে চালানোর জন্য প্রয়োজনীয় সমস্ত ব্যবহারের ক্ষেত্রে নির্দিষ্ট করুন। CameraX ডিভাইসের সমর্থিত হার্ডওয়্যার লেভেল বিবেচনা করে এবং ডিভাইস-নির্দিষ্ট বৈচিত্র্যের (যেখানে একটি ডিভাইস উপলভ্য স্ট্রিম কনফিগারেশন অতিক্রম করে বা পূরণ করে না) জন্য অ্যাকাউন্টিং করে আবদ্ধ ব্যবহারের ক্ষেত্রে সেটের উপর ভিত্তি করে রেজোলিউশন নির্ধারণ করে। উদ্দেশ্য হল ডিভাইস-নির্দিষ্ট কোড পাথ কমিয়ে বিভিন্ন ডিভাইসে অ্যাপ্লিকেশনটি চালানো।

ইমেজ ক্যাপচার ও ইমেজ বিশ্লেষণ ব্যবহারের ক্ষেত্রে ডিফল্ট অ্যাস্পেক্ট রেশিও হল ৪:৩।

ব্যবহারের ক্ষেত্রে কনফিগার করা যায় এমন অ্যাস্পেক্ট রেশিও থাকে যাতে অ্যাপ্লিকেশন UI ডিজাইনের উপর ভিত্তি করে পছন্দসই অ্যাস্পেক্ট রেশিও নির্দিষ্ট করতে পারে। ডিভাইস যতটা সাপোর্ট করে তার সাথে যতটা সম্ভব কাছাকাছি অ্যাস্পেক্ট রেশিও ম্যাচ করার জন্য CameraX আউটপুট তৈরি করা হয়। যদি কোনও সম্পূর্ণ ম্যাচ করা রেজোলিউশন কাজ না করে, তাহলে যে রেজোলিউশনটি সবচেয়ে বেশি শর্ত পূরণ করে সেটি বেছে নেওয়া হয়। তাই, অ্যাপে ক্যামেরা কীভাবে দেখা যাবে তা অ্যাপ্লিকেশন নির্ধারণ করে এবং বিভিন্ন ডিভাইসে সেই অনুযায়ী ক্যামেরা রেজোলিউশনের সেরা সেটিংস CameraX নির্ধারণ করে।

যেমন, কোনও অ্যাপ নিম্নলিখিত যেকোনও একটি কাজ করতে পারে:

  • কোনও ব্যবহারের ক্ষেত্রে ৪:৩ বা ১৬:৯ টার্গেট রেজোলিউশন নির্দিষ্ট করুন
  • একটি কাস্টম রেজোলিউশন নির্দিষ্ট করুন, যা CameraX সবচেয়ে কাছাকাছি মিল খুঁজে বের করার চেষ্টা করে
  • ImageCapture-এর জন্য ক্রপ করার অ্যাস্পেক্ট রেশিও উল্লেখ করুন

CameraX অটোমেটিক ইন্টার্নাল Camera2 সারফেস রেজোলিউশন বেছে নেয়। নিচের সারণীতে রেজোলিউশন দেখানো হয়েছে:

ব্যবহারের উদাহরণ ইন্টার্নাল সারফেস রেজোলিউশন আউটপুট ডেটা রেজোলিউশন
প্রিভিউ অ্যাস্পেক্ট রেশিও: যে রেজোলিউশন সেটিংয়ের সাথে টার্গেটকে সবচেয়ে ভালোভাবে ফিট করে। ইন্টার্নাল সারফেস রেজোলিউশন। টার্গেট অ্যাস্পেক্ট রেশিওর জন্য ভিউ ক্রপ, স্কেল ও রোটেট করতে মেটাডেটা প্রদান করা হয়।
ডিফল্ট রেজোলিউশন: সর্বোচ্চ প্রিভিউ রেজোলিউশন অথবা প্রিভিউয়ের অ্যাস্পেক্ট রেশিওর সাথে ম্যাচ করে এমন ডিভাইস-প্রেফার্ড রেজোলিউশন।
সর্বাধিক রেজোলিউশন: প্রিভিউ সাইজ, যা ডিভাইসের স্ক্রিন রেজোলিউশনের সাথে সবচেয়ে ভালো সাইজ ম্যাচ করে অথবা 1080p (1920x1080), যেটি ছোট।
ছবি বিশ্লেষণ অ্যাস্পেক্ট রেশিও: যে রেজোলিউশন টার্গেটের সাথে সবচেয়ে ভালোভাবে ফিট করে সেটিং। ইন্টার্নাল সারফেস রেজোলিউশন।
ডিফল্ট রেজোলিউশন: ডিফল্ট টার্গেট রেজোলিউশন সেটিং হল ৬৪০x৪৮০। টার্গেট রেজোলিউশন ও সংশ্লিষ্ট অ্যাস্পেক্ট রেশিও অ্যাডজাস্ট করলে সবচেয়ে ভালো রেজোলিউশন পাওয়া যায়।
সর্বাধিক রেজোলিউশন: ক্যামেরা ডিভাইসের সর্বাধিক আউটপুট রেজোলিউশন YUV_420_888 ফর্ম্যাট যা StreamConfigurationMap.getOutputSizes() থেকে পাওয়া যায়। টার্গেট রেজোলিউশন ডিফল্ট হিসেবে ৬৪০x৪৮০ সেট করা থাকে, তাই আপনি যদি ৬৪০x৪৮০-এর চেয়ে বেশি রেজোলিউশন চান, তাহলে আপনাকে অবশ্যই setTargetResolution() এবং setTargetAspectRatio() ব্যবহার করতে হবে যাতে আপনি কাজ চালানোর মতো রেজোলিউশন পেতে পারেন।
ইমেজ ক্যাপচার অ্যাস্পেক্ট রেশিও: সেটিংয়ের সাথে সবচেয়ে মানানসই অ্যাস্পেক্ট রেশিও। ইন্টার্নাল সারফেস রেজোলিউশন।
ডিফল্ট রেজোলিউশন: উপলভ্য সর্বোচ্চ রেজোলিউশন বা ডিভাইসের জন্য সবচেয়ে উপযুক্ত সর্বোচ্চ রেজোলিউশন যা ImageCapture-এর অ্যাস্পেক্ট রেশিওর সাথে মেলে।
সর্বাধিক রেজোলিউশন: JPEG ফর্ম্যাটে ক্যামেরা ডিভাইসের সর্বাধিক আউটপুট রেজোলিউশন। এটি ফিরিয়ে আনতে StreamConfigurationMap.getOutputSizes() ব্যবহার করুন।

রেজোলিউশন উল্লেখ করুন

setTargetResolution(Size resolution) পদ্ধতি ব্যবহার করে ব্যবহারের কেস তৈরি করার সময় আপনি নির্দিষ্ট রেজোলিউশন সেট করতে পারেন, যেমনটি নিম্নলিখিত কোড স্যাম্পেলে দেখানো হয়েছে:

Kotlin

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

জাভা

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

একই ব্যবহারের ক্ষেত্রে আপনি টার্গেট অ্যাস্পেক্ট রেশিও এবং টার্গেট রেজোলিউশন, দুটিই সেট করতে পারবেন না। এটি করলে, কনফিগারেশন অবজেক্ট তৈরি করার সময় IllegalArgumentException দেখায়।

টার্গেট রোটেশন অনুযায়ী কাজ করে এমন সাইজ ঘোরানোর পরে কোঅর্ডিনেট ফ্রেমে রেজোলিউশন Size প্রকাশ করুন। যেমন, কোনও ডিভাইস যদি পোর্ট্রেট ন্যাচারাল ওরিয়েন্টেশনে ন্যাচারাল টার্গেট রোটেশনে পোর্ট্রেট ইমেজ অনুরোধ করে, তাহলে সেটি ৪৮০x৬৪০ উল্লেখ করতে পারে এবং একই ডিভাইস ৯০ ডিগ্রি ঘোরানো হলে এবং ল্যান্ডস্কেপ ওরিয়েন্টেশন টার্গেট করলে ৬৪০x৪৮০ উল্লেখ করতে পারে।

টার্গেট রেজোলিউশন ছবির রেজোলিউশনের জন্য একটি ন্যূনতম সীমা নির্ধারণ করার চেষ্টা করে। আসল ছবির রেজোলিউশন হল সাইজে উপলভ্য সবচেয়ে কাছাকাছি রেজোলিউশন যা টার্গেট রেজোলিউশনের চেয়ে ছোট নয়, যেমনটা ক্যামেরা ইমপ্লিমেন্টেশন দ্বারা নির্ধারিত হয়।

তবে, টার্গেট রেজোলিউশনের সমান বা তার থেকে বড় কোনও রেজোলিউশন না থাকলে, টার্গেট রেজোলিউশনের থেকে ছোট, সবচেয়ে কাছাকাছি উপলভ্য রেজোলিউশন বেছে নেওয়া হয়। প্রদান করা Size-এর মতো একই অ্যাস্পেক্ট রেশিও সহ রেজোলিউশনকে অন্য অ্যাস্পেক্ট রেশিওর রেজোলিউশনের চেয়ে বেশি অগ্রাধিকার দেওয়া হয়।

অনুরোধের উপর ভিত্তি করে CameraX সবচেয়ে উপযুক্ত রেজোলিউশন প্রয়োগ করে। যদি প্রাথমিক প্রয়োজন হয় অ্যাস্পেক্ট রেশিও পূরণ করা, তাহলে শুধুমাত্র setTargetAspectRatio উল্লেখ করুন, এবং CameraX ডিভাইসের উপর ভিত্তি করে উপযুক্ত একটি নির্দিষ্ট রেজোলিউশন নির্ধারণ করে। ইমেজ প্রসেসিং আরও দক্ষ করে তোলার জন্য (যেমন, ডিভাইসের প্রসেসিং ক্ষমতার উপর ভিত্তি করে ছোট বা মাঝারি সাইজের ছবি) রেজোলিউশন নির্দিষ্ট করা যদি অ্যাপের প্রাথমিক প্রয়োজন হয়, তাহলে setTargetResolution(Size resolution) ব্যবহার করুন।

আপনার অ্যাপের জন্য সঠিক রেজোলিউশন প্রয়োজন হলে, প্রতিটি হার্ডওয়্যার লেভেলে সর্বাধিক কত রেজোলিউশন কাজ করে তা নির্ধারণ করতে createCaptureSession() -এর মধ্যে থাকা টেবিল দেখুন। বর্তমান ডিভাইসে কাজ করে এমন নির্দিষ্ট রেজোলিউশন চেক করতে, StreamConfigurationMap.getOutputSizes(int) দেখুন।

আপনার অ্যাপ Android 10 বা তার পরবর্তী যেকোনও ভার্সনে রান করলে, আপনি isSessionConfigurationSupported() ব্যবহার করে নির্দিষ্ট SessionConfiguration যাচাই করতে পারবেন।

ক্যামেরা আউটপুট নিয়ন্ত্রণ করুন

প্রতিটি স্বতন্ত্র ব্যবহারের ক্ষেত্রে প্রয়োজন অনুযায়ী ক্যামেরা আউটপুট কনফিগার করার পাশাপাশি, 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

জাভা

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() ০ থেকে ১.০ পর্যন্ত লিনিয়ার জুম ভ্যালু সহ বর্তমান জুম সেট করে।

    লিনিয়ার জুমের সুবিধা হল যে এটি জুমের পরিবর্তনের সাথে ফিল্ড অফ ভিউ (FOV) স্কেল করে। এটি Slider ভিউয়ের সাথে ব্যবহার করার জন্য আদর্শ।

CameraInfo.getZoomState() বর্তমান জুম স্টেট সংক্রান্ত LiveData রিটার্ন করে। ক্যামেরা শুরু হলে বা setZoomRatio() অথবা setLinearZoom() ব্যবহার করে জুম লেভেল সেট করা হলে মান পরিবর্তিত হয়। যেকোনও পদ্ধতি কল করলে, ZoomState.getZoomRatio() এবং ZoomState.getLinearZoom()-এর ভ্যালু ব্যাকআপ সেট হয়ে যায়। আপনি স্লাইডারের পাশাপাশি জুম অনুপাত টেক্সট দেখাতে চাইলে এটি সহায়ক হবে। কনভার্সন না করেই দুটি আপডেট করতে শুধু ZoomState LiveData দেখুন।

দুটি API-এর মাধ্যমে রিটার্ন করা 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 দেখায়। এটি একটি স্বাভাবিক ফর্মে স্টোর করা হয় যাতে এটি সহজেই AF/AE/AWB অঞ্চলগুলি নির্দিষ্ট করার জন্য সেন্সর কোঅর্ডিনেটে রূপান্তরিত হতে পারে।

MeteringPoint-এর সাইজ ০ থেকে ১-এর মধ্যে হয়, যার ডিফল্ট সাইজ হল ০.১৫f। 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 প্যারামিটার সেট করে।

যেহেতু সব ডিভাইসে AF/AE/AWB এবং একাধিক অঞ্চল কাজ করে না, তাই CameraX FocusMeteringAction-কে যথাসাধ্য কার্যকর করে। CameraX সর্বাধিক সংখ্যক MeteringPoints ব্যবহার করে, যে ক্রমে পয়েন্ট যোগ করা হয়েছে সেই ক্রমে। সর্বাধিক MeteringPoints-এর পরে যোগ করা সমস্ত MeteringPoints উপেক্ষা করা হয়। যেমন, কোনও FocusMeteringAction-এ ৩টি মিটারিং পয়েন্ট থাকলে এবং প্ল্যাটফর্মটি মাত্র ২টি মিটারিং পয়েন্ট সাপোর্ট করলে, প্রথম ২টি মিটারিং পয়েন্ট ব্যবহার করা হয়। CameraX শেষ MeteringPoint এড়িয়ে যায়।

এক্সপোজার নিয়ন্ত্রণ

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

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 আলোচনা গ্রুপ