কনফিগারেশন অপশন

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

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

কোটলিন

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

জাভা

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

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

CameraXConfig

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

CameraXConfig এর সাথে, একটি অ্যাপ্লিকেশন নিম্নলিখিতগুলি করতে পারে:

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

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

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

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

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

কোটলিন

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 এমন আচরণ করে যেন সেই ক্যামেরাটি নেই। উদাহরণস্বরূপ, নিম্নলিখিত কোডটি অ্যাপ্লিকেশনটিকে শুধুমাত্র ডিভাইসের ডিফল্ট ব্যাক ক্যামেরা ব্যবহার করতে সীমাবদ্ধ করে:

কোটলিন

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

থ্রেড

অনেক প্ল্যাটফর্ম API যার উপর CameraX তৈরি করা হয়েছে তাদের হার্ডওয়্যার সহ আন্তঃপ্রসেস কমিউনিকেশন (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() দিয়ে এটিকে ওভাররাইড করতে পারেন।

লগিং

ক্যামেরাএক্স লগিং অ্যাপ্লিকেশনগুলিকে লগক্যাট বার্তাগুলিকে ফিল্টার করতে দেয়, কারণ এটি আপনার উত্পাদন কোডে ভার্বোস বার্তাগুলি এড়াতে ভাল অনুশীলন হতে পারে৷ ক্যামেরাএক্স চারটি লগিং স্তরকে সমর্থন করে, সবচেয়ে ভার্বস থেকে সবচেয়ে গুরুতর পর্যন্ত:

  • Log.DEBUG (ডিফল্ট)
  • Log.INFO
  • Log.WARN
  • Log.ERROR

এই লগ স্তরগুলির বিশদ বিবরণের জন্য Android লগ ডকুমেন্টেশন পড়ুন৷ আপনার অ্যাপ্লিকেশনের জন্য উপযুক্ত লগিং স্তর সেট করতে CameraXConfig.Builder.setMinimumLoggingLevel(int) ব্যবহার করুন।

স্বয়ংক্রিয় নির্বাচন

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

CameraX এর লক্ষ্য হল সফলভাবে একটি ক্যামেরা সেশন শুরু করা। এর মানে ক্যামেরাএক্স ডিভাইসের ক্ষমতার উপর ভিত্তি করে রেজোলিউশন এবং আকৃতির অনুপাতের সাথে আপস করে। আপস ঘটতে পারে কারণ:

  • ডিভাইসটি অনুরোধ করা রেজোলিউশন সমর্থন করে না।
  • ডিভাইসটির সামঞ্জস্যের সমস্যা রয়েছে, যেমন লিগ্যাসি ডিভাইসগুলির সঠিকভাবে কাজ করার জন্য নির্দিষ্ট রেজোলিউশনের প্রয়োজন।
  • কিছু ডিভাইসে, নির্দিষ্ট ফর্ম্যাটগুলি শুধুমাত্র নির্দিষ্ট আকৃতির অনুপাতগুলিতে উপলব্ধ।
  • ডিভাইসটিতে JPEG বা ভিডিও এনকোডিংয়ের জন্য "নিকটতম mod16" এর জন্য একটি পছন্দ রয়েছে৷ আরও তথ্যের জন্য, SCALER_STREAM_CONFIGURATION_MAP দেখুন।

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

ঘূর্ণন

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

আপনার অ্যাপ কনফিগারেশন সেটিংস ব্যবহার করে লক্ষ্য ঘূর্ণন সেট করতে পারে। এটি তারপর ব্যবহার কেস API (যেমন ImageAnalysis.setTargetRotation() ) থেকে পদ্ধতি ব্যবহার করে ঘূর্ণন সেটিংস আপডেট করতে পারে, এমনকি জীবনচক্র চলমান অবস্থায় থাকা অবস্থায়। আপনি এটি ব্যবহার করতে পারেন যখন অ্যাপটি পোর্ট্রেট মোডে লক করা থাকে—এবং তাই ঘূর্ণনে কোনও পুনঃকনফিগারেশন ঘটে না-কিন্তু ফটো বা বিশ্লেষণ ব্যবহারের ক্ষেত্রে ডিভাইসের বর্তমান ঘূর্ণন সম্পর্কে সচেতন হওয়া প্রয়োজন৷ উদাহরণস্বরূপ, ঘূর্ণন সচেতনতার প্রয়োজন হতে পারে যাতে মুখ সনাক্তকরণের জন্য মুখগুলি সঠিকভাবে ভিত্তিক হয়, বা ফটোগুলি ল্যান্ডস্কেপ বা প্রতিকৃতিতে সেট করা হয়।

ক্যাপচার করা ছবিগুলির ডেটা ঘূর্ণন তথ্য ছাড়াই সংরক্ষণ করা যেতে পারে। Exif ডেটাতে ঘূর্ণন তথ্য রয়েছে যাতে গ্যালারি অ্যাপ্লিকেশনগুলি সংরক্ষণ করার পরে সঠিক অভিযোজনে চিত্রটি দেখাতে পারে।

সঠিক অভিযোজন সহ পূর্বরূপ তথ্য প্রদর্শন করতে, রূপান্তর তৈরি করতে আপনি Preview.PreviewOutput() থেকে মেটাডেটা আউটপুট ব্যবহার করতে পারেন।

নিম্নলিখিত কোড নমুনা দেখায় কিভাবে একটি ওরিয়েন্টেশন ইভেন্টে ঘূর্ণন সেট করতে হয়:

কোটলিন

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() ব্যবহার করে জানা যায়।
  • ইমেজ অ্যানালাইসিস : মেটাডেটা আউটপুট প্রদান করা হয় যাতে ইমেজ বাফার স্থানাঙ্কগুলি প্রদর্শন স্থানাঙ্কের সাথে সম্পর্কিত হয়।
  • ইমেজ ক্যাপচার : ইমেজ এক্সিফ মেটাডেটা, বাফার, বা বাফার এবং মেটাডেটা উভয়ই ঘূর্ণন সেটিং নোট করার জন্য পরিবর্তিত হয়। পরিবর্তিত মান HAL বাস্তবায়নের উপর নির্ভর করে।

ক্রপ রেক্ট

ডিফল্টরূপে, ক্রপ রেক্ট হল সম্পূর্ণ বাফার রেক্ট। আপনি এটিকে ViewPort এবং UseCaseGroup দিয়ে কাস্টমাইজ করতে পারেন। ব্যবহারের কেসগুলিকে গোষ্ঠীবদ্ধ করে এবং ভিউপোর্ট সেট করার মাধ্যমে, CameraX গ্যারান্টি দেয় যে গ্রুপের সমস্ত ব্যবহারের ক্ষেত্রে ক্রপ রেক্ট ক্যামেরা সেন্সরে একই এলাকায় নির্দেশ করে৷

নিম্নলিখিত কোড স্নিপেট দেখায় কিভাবে এই দুটি ক্লাস ব্যবহার করতে হয়:

কোটলিন

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 অবজেক্ট পেতে হয়:

কোটলিন

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 তৈরি করতে হয়:

কোটলিন

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 অবজেক্ট থেকে উভয় ক্যামেরা অবজেক্ট কিভাবে পেতে হয়।

কোটলিন

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

ইমেজ ক্যাপচার এবং ইমেজ বিশ্লেষণ ব্যবহারের ক্ষেত্রে ডিফল্ট অনুপাত হল 4:3।

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

কোটলিন

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

জাভা

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

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

লক্ষ্য ঘূর্ণন দ্বারা সমর্থিত আকারগুলি ঘোরানোর পরে স্থানাঙ্ক ফ্রেমে রেজোলিউশনের Size প্রকাশ করুন। উদাহরণস্বরূপ, প্রাকৃতিক লক্ষ্য ঘূর্ণনে প্রতিকৃতির প্রাকৃতিক অভিযোজন সহ একটি ডিভাইস একটি প্রতিকৃতি চিত্রের জন্য অনুরোধ করে 480x640 নির্দিষ্ট করতে পারে এবং একই ডিভাইস, 90 ডিগ্রি ঘোরানো এবং ল্যান্ডস্কেপ অভিযোজন 640x480 নির্দিষ্ট করতে পারে।

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

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

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

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

যদি আপনার অ্যাপটি Android 10 বা উচ্চতর সংস্করণে চলছে, তাহলে আপনি একটি নির্দিষ্ট SessionConfiguration যাচাই করতে isSessionConfigurationSupported() ব্যবহার করতে পারেন।

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

আপনাকে প্রতিটি পৃথক ব্যবহারের ক্ষেত্রে প্রয়োজনীয় ক্যামেরা আউটপুট কনফিগার করতে দেওয়ার পাশাপাশি, CameraX সমস্ত আবদ্ধ ব্যবহারের ক্ষেত্রে সাধারণ ক্যামেরা অপারেশনগুলিকে সমর্থন করার জন্য নিম্নলিখিত ইন্টারফেসগুলিও প্রয়োগ করে:

  • CameraControl আপনাকে সাধারণ ক্যামেরা বৈশিষ্ট্যগুলি কনফিগার করতে দেয়।
  • CameraInfo আপনাকে সেই সাধারণ ক্যামেরা বৈশিষ্ট্যগুলির রাজ্যগুলি জিজ্ঞাসা করতে দেয়৷

এইগুলি ক্যামেরা কন্ট্রোলের সাথে সমর্থিত ক্যামেরা বৈশিষ্ট্যগুলি:

  • জুম
  • টর্চ
  • ফোকাস এবং মিটারিং (ফোকাস করতে ট্যাপ করুন)
  • এক্সপোজার ক্ষতিপূরণ

CameraControl এবং CameraInfo এর উদাহরণ পান

ProcessCameraProvider.bindToLifecycle() দ্বারা প্রত্যাবর্তিত Camera অবজেক্ট ব্যবহার করে CameraControl এবং CameraInfo এর উদাহরণ পুনরুদ্ধার করুন। নিম্নলিখিত কোড একটি উদাহরণ দেখায়:

কোটলিন

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 ফেরত দেয়।

জুম

ক্যামেরা কন্ট্রোল জুম স্তর পরিবর্তন করার জন্য দুটি পদ্ধতি অফার করে:

  • setZoomRatio() জুম অনুপাত দ্বারা জুম সেট করে।

    অনুপাতটি অবশ্যই CameraInfo.getZoomState().getValue().getMinZoomRatio() এবং CameraInfo.getZoomState().getValue().getMaxZoomRatio() এর সীমার মধ্যে হতে হবে। অন্যথায় ফাংশনটি একটি ব্যর্থ ListenableFuture প্রদান করে।

  • setLinearZoom() 0 থেকে 1.0 পর্যন্ত রৈখিক জুম মান সহ বর্তমান জুম সেট করে।

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

CameraInfo.getZoomState() বর্তমান জুম অবস্থার একটি লাইভ ডেটা প্রদান করে। ক্যামেরা শুরু হলে মান পরিবর্তন হয় অথবা setZoomRatio() বা setLinearZoom() ব্যবহার করে জুম লেভেল সেট করা হয়। যেকোন একটি পদ্ধতিতে কল করলে ZoomState.getZoomRatio() এবং ZoomState.getLinearZoom() সমর্থনকারী মান সেট করে। আপনি যদি স্লাইডারের পাশাপাশি জুম অনুপাতের পাঠ্য প্রদর্শন করতে চান তবে এটি সহায়ক। একটি রূপান্তর করার প্রয়োজন ছাড়াই উভয় আপডেট করতে কেবল ZoomState LiveData পর্যবেক্ষণ করুন৷

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

টর্চ

CameraControl.enableTorch(boolean) টর্চকে সক্ষম বা নিষ্ক্রিয় করে (যা ফ্ল্যাশলাইট নামেও পরিচিত)।

CameraInfo.getTorchState() বর্তমান টর্চ অবস্থা জিজ্ঞাসা করতে ব্যবহার করা যেতে পারে। একটি টর্চ উপলব্ধ কিনা তা নির্ধারণ করতে আপনি CameraInfo.hasFlashUnit() দ্বারা ফেরত দেওয়া মান পরীক্ষা করতে পারেন। যদি তা না হয়, CameraControl.enableTorch(boolean) কল করার ফলে ফিরে আসা ListenableFuture অবিলম্বে একটি ব্যর্থ ফলাফলের সাথে সম্পূর্ণ হয় এবং টর্চ স্টেটকে TorchState.OFF এ সেট করে।

টর্চ সক্রিয় করা হলে, ফ্ল্যাশমোড সেটিং নির্বিশেষে ফটো এবং ভিডিও ক্যাপচারের সময় এটি চালু থাকে। ImageCapture flashMode তখনই কাজ করে যখন টর্চ নিষ্ক্রিয় থাকে।

ফোকাস এবং মিটারিং

CameraControl.startFocusAndMetering() প্রদত্ত FocusMeteringAction এর উপর ভিত্তি করে AF/AE/AWB মিটারিং অঞ্চলগুলি সেট করে অটোফোকাস এবং এক্সপোজার মিটারিং ট্রিগার করে৷ এটি প্রায়শই অনেক ক্যামেরা অ্যাপ্লিকেশনে "ফোকাস করার জন্য আলতো চাপুন" বৈশিষ্ট্যটি বাস্তবায়ন করতে ব্যবহৃত হয়।

মিটারিংপয়েন্ট

শুরু করতে, MeteringPointFactory.createPoint(float x, float y, float size) ব্যবহার করে একটি MeteringPoint তৈরি করুন। একটি MeteringPoint ক্যামেরা Surface একটি একক বিন্দুকে উপস্থাপন করে। এটি একটি স্বাভাবিক আকারে সংরক্ষণ করা হয়েছে যাতে এটিকে সহজেই AF/AE/AWB অঞ্চলগুলি নির্দিষ্ট করার জন্য সেন্সর স্থানাঙ্কে রূপান্তর করা যায়।

MeteringPoint আকার 0 থেকে 1 পর্যন্ত, ডিফল্ট আকার 0.15f এর সাথে। MeteringPointFactory.createPoint(float x, float y, float size) কল করার সময়, CameraX প্রদত্ত size জন্য (x, y) কেন্দ্রিক একটি আয়তক্ষেত্র তৈরি করে।

নিম্নলিখিত কোডটি দেখায় কিভাবে একটি MeteringPoint তৈরি করতে হয়:

কোটলিন

// 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 তৈরি করতে হবে, যেটিতে FLAG_AF , FLAG_AE , FLAG_AWB থেকে ঐচ্ছিক মিটারিং মোড সংমিশ্রণ সহ এক বা একাধিক MeteringPoints রয়েছে৷ নিম্নলিখিত কোড এই ব্যবহার প্রদর্শন করে:

কোটলিন

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 AF/AE/AWB মিটারিং অঞ্চলের জন্য এবং আরেকটি মিটারিংপয়েন্ট শুধুমাত্র AF এবং AE-এর জন্য থাকে।

অভ্যন্তরীণভাবে, CameraX এটিকে Camera2 MeteringRectangles এ রূপান্তর করে এবং সংশ্লিষ্ট CONTROL_AF_REGIONS / CONTROL_AE_REGIONS / CONTROL_AWB_REGIONS প্যারামিটারগুলি ক্যাপচার অনুরোধে সেট করে৷

যেহেতু প্রতিটি ডিভাইস AF/AE/AWB এবং একাধিক অঞ্চল সমর্থন করে না, তাই CameraX সর্বোত্তম প্রচেষ্টার সাথে FocusMeteringAction চালায়। পয়েন্ট যোগ করার ক্রমে CameraX সমর্থিত সর্বাধিক সংখ্যক মিটারিংপয়েন্ট ব্যবহার করে। সর্বাধিক গণনার পরে যোগ করা সমস্ত মিটারিং পয়েন্ট উপেক্ষা করা হয়। উদাহরণস্বরূপ, যদি একটি FocusMeteringAction একটি প্ল্যাটফর্মে 3টি মিটারিংপয়েন্টের সাথে সরবরাহ করা হয় যা শুধুমাত্র 2টি সমর্থন করে, শুধুমাত্র প্রথম 2টি মিটারিংপয়েন্ট ব্যবহার করা হয়। চূড়ান্ত MeteringPoint CameraX দ্বারা উপেক্ষা করা হয়।

এক্সপোজার ক্ষতিপূরণ

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

Exposure = ExposureCompensationIndex * ExposureCompensationStep

সূচক মান হিসাবে এক্সপোজার ক্ষতিপূরণ সেট করার জন্য CameraX Camera.CameraControl.setExposureCompensationIndex() ফাংশন প্রদান করে।

ইতিবাচক সূচকের মানগুলি ছবিটিকে উজ্জ্বল করে, যখন নেতিবাচক মানগুলি ছবিটিকে ম্লান করে। অ্যাপ্লিকেশনগুলি পরবর্তী বিভাগে বর্ণিত CameraInfo.ExposureState.exposureCompensationRange() দ্বারা সমর্থিত পরিসরের জন্য অনুসন্ধান করতে পারে৷ মানটি সমর্থিত হলে, ক্যাপচার অনুরোধে মানটি সফলভাবে সক্ষম হলে প্রত্যাবর্তিত ListenableFuture সম্পূর্ণ হয়; যদি নির্দিষ্ট করা সূচী সমর্থিত সীমার বাইরে থাকে, setExposureCompensationIndex() ফিরে আসা ListenableFuture একটি ব্যর্থ ফলাফলের সাথে অবিলম্বে সম্পূর্ণ করে।

CameraX শুধুমাত্র সর্বশেষ অসামান্য setExposureCompensationIndex() অনুরোধ রাখে এবং পূর্ববর্তী অনুরোধটি কার্যকর হওয়ার আগে ফাংশনটিকে একাধিকবার কল করলে সেটি বাতিল হয়ে যায়।

নিম্নলিখিত স্নিপেট একটি এক্সপোজার ক্ষতিপূরণ সূচক সেট করে এবং যখন এক্সপোজার পরিবর্তনের অনুরোধটি কার্যকর করা হয় তখন একটি কলব্যাক নিবন্ধন করে:

কোটলিন

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 সেটিংস শুরু করে:

কোটলিন

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 নমুনা অ্যাপ
  • বিকাশকারী সম্প্রদায়

    অ্যান্ড্রয়েড ক্যামেরাএক্স আলোচনা গ্রুপ

    ,

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

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

    কোটলিন

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

    জাভা

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

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

    CameraXConfig

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

    CameraXConfig এর সাথে, একটি অ্যাপ্লিকেশন নিম্নলিখিতগুলি করতে পারে:

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

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

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

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

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

    কোটলিন

    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 এমন আচরণ করে যেন সেই ক্যামেরাটি নেই। উদাহরণস্বরূপ, নিম্নলিখিত কোডটি অ্যাপ্লিকেশনটিকে শুধুমাত্র ডিভাইসের ডিফল্ট ব্যাক ক্যামেরা ব্যবহার করতে সীমাবদ্ধ করে:

    কোটলিন

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

    থ্রেড

    অনেক প্ল্যাটফর্ম API যার উপর CameraX তৈরি করা হয়েছে তাদের হার্ডওয়্যার সহ আন্তঃপ্রসেস কমিউনিকেশন (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() দিয়ে এটিকে ওভাররাইড করতে পারেন।

    লগিং

    ক্যামেরাএক্স লগিং অ্যাপ্লিকেশনগুলিকে লগক্যাট বার্তাগুলিকে ফিল্টার করতে দেয়, কারণ এটি আপনার উত্পাদন কোডে ভার্বোস বার্তাগুলি এড়াতে ভাল অনুশীলন হতে পারে৷ ক্যামেরাএক্স চারটি লগিং স্তরকে সমর্থন করে, সবচেয়ে ভার্বস থেকে সবচেয়ে গুরুতর পর্যন্ত:

    • Log.DEBUG (ডিফল্ট)
    • Log.INFO
    • Log.WARN
    • Log.ERROR

    এই লগ স্তরগুলির বিশদ বিবরণের জন্য Android লগ ডকুমেন্টেশন পড়ুন৷ আপনার অ্যাপ্লিকেশনের জন্য উপযুক্ত লগিং স্তর সেট করতে CameraXConfig.Builder.setMinimumLoggingLevel(int) ব্যবহার করুন।

    স্বয়ংক্রিয় নির্বাচন

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

    CameraX এর লক্ষ্য হল সফলভাবে একটি ক্যামেরা সেশন শুরু করা। এর মানে ক্যামেরাএক্স ডিভাইসের ক্ষমতার উপর ভিত্তি করে রেজোলিউশন এবং আকৃতির অনুপাতের সাথে আপস করে। আপস ঘটতে পারে কারণ:

    • ডিভাইসটি অনুরোধ করা রেজোলিউশন সমর্থন করে না।
    • ডিভাইসটির সামঞ্জস্যের সমস্যা রয়েছে, যেমন লিগ্যাসি ডিভাইসগুলির সঠিকভাবে কাজ করার জন্য নির্দিষ্ট রেজোলিউশনের প্রয়োজন।
    • কিছু ডিভাইসে, নির্দিষ্ট ফর্ম্যাটগুলি শুধুমাত্র নির্দিষ্ট আকৃতির অনুপাতগুলিতে উপলব্ধ।
    • ডিভাইসটিতে JPEG বা ভিডিও এনকোডিংয়ের জন্য "নিকটতম mod16" এর জন্য একটি পছন্দ রয়েছে৷ আরও তথ্যের জন্য, SCALER_STREAM_CONFIGURATION_MAP দেখুন।

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

    ঘূর্ণন

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

    আপনার অ্যাপ কনফিগারেশন সেটিংস ব্যবহার করে লক্ষ্য ঘূর্ণন সেট করতে পারে। এটি তারপর ব্যবহার কেস API (যেমন ImageAnalysis.setTargetRotation() ) থেকে পদ্ধতি ব্যবহার করে ঘূর্ণন সেটিংস আপডেট করতে পারে, এমনকি জীবনচক্র চলমান অবস্থায় থাকা অবস্থায়। আপনি এটি ব্যবহার করতে পারেন যখন অ্যাপটি পোর্ট্রেট মোডে লক করা থাকে—এবং তাই ঘূর্ণনে কোনও পুনঃকনফিগারেশন ঘটে না-কিন্তু ফটো বা বিশ্লেষণ ব্যবহারের ক্ষেত্রে ডিভাইসের বর্তমান ঘূর্ণন সম্পর্কে সচেতন হওয়া প্রয়োজন৷ উদাহরণস্বরূপ, ঘূর্ণন সচেতনতার প্রয়োজন হতে পারে যাতে মুখ সনাক্তকরণের জন্য মুখগুলি সঠিকভাবে ভিত্তিক হয়, বা ফটোগুলি ল্যান্ডস্কেপ বা প্রতিকৃতিতে সেট করা হয়।

    ক্যাপচার করা ছবিগুলির ডেটা ঘূর্ণন তথ্য ছাড়াই সংরক্ষণ করা যেতে পারে। Exif ডেটাতে ঘূর্ণন তথ্য রয়েছে যাতে গ্যালারি অ্যাপ্লিকেশনগুলি সংরক্ষণ করার পরে সঠিক অভিযোজনে চিত্রটি দেখাতে পারে।

    সঠিক অভিযোজন সহ পূর্বরূপ তথ্য প্রদর্শন করতে, রূপান্তর তৈরি করতে আপনি Preview.PreviewOutput() থেকে মেটাডেটা আউটপুট ব্যবহার করতে পারেন।

    নিম্নলিখিত কোড নমুনা দেখায় কিভাবে একটি ওরিয়েন্টেশন ইভেন্টে ঘূর্ণন সেট করতে হয়:

    কোটলিন

    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() ব্যবহার করে জানা যায়।
    • ইমেজ অ্যানালাইসিস : মেটাডেটা আউটপুট প্রদান করা হয় যাতে ইমেজ বাফার স্থানাঙ্কগুলি প্রদর্শন স্থানাঙ্কের সাথে সম্পর্কিত হয়।
    • ইমেজ ক্যাপচার : ইমেজ এক্সিফ মেটাডেটা, বাফার, বা বাফার এবং মেটাডেটা উভয়ই ঘূর্ণন সেটিং নোট করার জন্য পরিবর্তিত হয়। পরিবর্তিত মান HAL বাস্তবায়নের উপর নির্ভর করে।

    ক্রপ রেক্ট

    ডিফল্টরূপে, ক্রপ রেক্ট হল সম্পূর্ণ বাফার রেক্ট। আপনি এটিকে ViewPort এবং UseCaseGroup দিয়ে কাস্টমাইজ করতে পারেন। ব্যবহারের কেসগুলিকে গোষ্ঠীবদ্ধ করে এবং ভিউপোর্ট সেট করার মাধ্যমে, CameraX গ্যারান্টি দেয় যে গ্রুপের সমস্ত ব্যবহারের ক্ষেত্রে ক্রপ রেক্ট ক্যামেরা সেন্সরে একই এলাকায় নির্দেশ করে৷

    নিম্নলিখিত কোড স্নিপেট দেখায় কিভাবে এই দুটি ক্লাস ব্যবহার করতে হয়:

    কোটলিন

    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 অবজেক্ট পেতে হয়:

    কোটলিন

    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 তৈরি করতে হয়:

    কোটলিন

    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 অবজেক্ট থেকে উভয় ক্যামেরা অবজেক্ট কিভাবে পেতে হয়।

    কোটলিন

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

    ইমেজ ক্যাপচার এবং ইমেজ বিশ্লেষণ ব্যবহারের ক্ষেত্রে ডিফল্ট অনুপাত হল 4:3।

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

    কোটলিন

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

    জাভা

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

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

    লক্ষ্য ঘূর্ণন দ্বারা সমর্থিত আকারগুলি ঘোরানোর পরে স্থানাঙ্ক ফ্রেমে রেজোলিউশনের Size প্রকাশ করুন। উদাহরণস্বরূপ, প্রাকৃতিক লক্ষ্য ঘূর্ণনে প্রতিকৃতির প্রাকৃতিক অভিযোজন সহ একটি ডিভাইস একটি প্রতিকৃতি চিত্রের জন্য অনুরোধ করে 480x640 নির্দিষ্ট করতে পারে এবং একই ডিভাইস, 90 ডিগ্রি ঘোরানো এবং ল্যান্ডস্কেপ অভিযোজন 640x480 নির্দিষ্ট করতে পারে।

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

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

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

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

    যদি আপনার অ্যাপটি Android 10 বা উচ্চতর সংস্করণে চলছে, তাহলে আপনি একটি নির্দিষ্ট SessionConfiguration যাচাই করতে isSessionConfigurationSupported() ব্যবহার করতে পারেন।

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

    আপনাকে প্রতিটি পৃথক ব্যবহারের ক্ষেত্রে প্রয়োজনীয় ক্যামেরা আউটপুট কনফিগার করতে দেওয়ার পাশাপাশি, CameraX সমস্ত আবদ্ধ ব্যবহারের ক্ষেত্রে সাধারণ ক্যামেরা অপারেশনগুলিকে সমর্থন করার জন্য নিম্নলিখিত ইন্টারফেসগুলিও প্রয়োগ করে:

    • CameraControl আপনাকে সাধারণ ক্যামেরা বৈশিষ্ট্যগুলি কনফিগার করতে দেয়।
    • CameraInfo আপনাকে সেই সাধারণ ক্যামেরা বৈশিষ্ট্যগুলির রাজ্যগুলি জিজ্ঞাসা করতে দেয়৷

    এইগুলি ক্যামেরা কন্ট্রোলের সাথে সমর্থিত ক্যামেরা বৈশিষ্ট্যগুলি:

    • জুম
    • টর্চ
    • ফোকাস এবং মিটারিং (ফোকাস করতে ট্যাপ করুন)
    • এক্সপোজার ক্ষতিপূরণ

    CameraControl এবং CameraInfo এর উদাহরণ পান

    ProcessCameraProvider.bindToLifecycle() দ্বারা প্রত্যাবর্তিত Camera অবজেক্ট ব্যবহার করে CameraControl এবং CameraInfo এর উদাহরণ পুনরুদ্ধার করুন। নিম্নলিখিত কোড একটি উদাহরণ দেখায়:

    কোটলিন

    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 ফেরত দেয়।

    জুম

    ক্যামেরা কন্ট্রোল জুম স্তর পরিবর্তন করার জন্য দুটি পদ্ধতি অফার করে:

    • setZoomRatio() জুম অনুপাত দ্বারা জুম সেট করে।

      অনুপাতটি অবশ্যই CameraInfo.getZoomState().getValue().getMinZoomRatio() এবং CameraInfo.getZoomState().getValue().getMaxZoomRatio() এর সীমার মধ্যে হতে হবে। অন্যথায় ফাংশনটি একটি ব্যর্থ ListenableFuture প্রদান করে।

    • setLinearZoom() 0 থেকে 1.0 পর্যন্ত রৈখিক জুম মান সহ বর্তমান জুম সেট করে।

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

    CameraInfo.getZoomState() বর্তমান জুম অবস্থার একটি লাইভ ডেটা প্রদান করে। ক্যামেরা শুরু হলে মান পরিবর্তন হয় অথবা setZoomRatio() বা setLinearZoom() ব্যবহার করে জুম লেভেল সেট করা হয়। যেকোন একটি পদ্ধতিতে কল করলে ZoomState.getZoomRatio() এবং ZoomState.getLinearZoom() সমর্থনকারী মান সেট করে। আপনি যদি স্লাইডারের পাশাপাশি জুম অনুপাতের পাঠ্য প্রদর্শন করতে চান তবে এটি সহায়ক। একটি রূপান্তর করার প্রয়োজন ছাড়াই উভয় আপডেট করতে কেবল ZoomState LiveData পর্যবেক্ষণ করুন৷

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

    টর্চ

    CameraControl.enableTorch(boolean) টর্চকে সক্ষম বা নিষ্ক্রিয় করে (যা ফ্ল্যাশলাইট নামেও পরিচিত)।

    CameraInfo.getTorchState() বর্তমান টর্চ অবস্থা জিজ্ঞাসা করতে ব্যবহার করা যেতে পারে। একটি টর্চ উপলব্ধ কিনা তা নির্ধারণ করতে আপনি CameraInfo.hasFlashUnit() দ্বারা ফেরত দেওয়া মান পরীক্ষা করতে পারেন। যদি তা না হয়, CameraControl.enableTorch(boolean) কল করার ফলে ফিরে আসা ListenableFuture অবিলম্বে একটি ব্যর্থ ফলাফলের সাথে সম্পূর্ণ হয় এবং টর্চ স্টেটকে TorchState.OFF এ সেট করে।

    টর্চ সক্রিয় করা হলে, ফ্ল্যাশমোড সেটিং নির্বিশেষে ফটো এবং ভিডিও ক্যাপচারের সময় এটি চালু থাকে। ImageCapture flashMode তখনই কাজ করে যখন টর্চ নিষ্ক্রিয় থাকে।

    ফোকাস এবং মিটারিং

    CameraControl.startFocusAndMetering() প্রদত্ত FocusMeteringAction এর উপর ভিত্তি করে AF/AE/AWB মিটারিং অঞ্চলগুলি সেট করে অটোফোকাস এবং এক্সপোজার মিটারিং ট্রিগার করে৷ এটি প্রায়শই অনেক ক্যামেরা অ্যাপ্লিকেশনে "ফোকাস করার জন্য আলতো চাপুন" বৈশিষ্ট্যটি বাস্তবায়ন করতে ব্যবহৃত হয়।

    মিটারিংপয়েন্ট

    শুরু করতে, MeteringPointFactory.createPoint(float x, float y, float size) ব্যবহার করে একটি MeteringPoint তৈরি করুন। একটি MeteringPoint ক্যামেরা Surface একটি একক বিন্দুকে উপস্থাপন করে। এটি একটি স্বাভাবিক আকারে সংরক্ষণ করা হয়েছে যাতে এটিকে সহজেই AF/AE/AWB অঞ্চলগুলি নির্দিষ্ট করার জন্য সেন্সর স্থানাঙ্কে রূপান্তর করা যায়।

    MeteringPoint আকার 0 থেকে 1 পর্যন্ত, ডিফল্ট আকার 0.15f এর সাথে। MeteringPointFactory.createPoint(float x, float y, float size) কল করার সময়, CameraX প্রদত্ত size জন্য (x, y) কেন্দ্রিক একটি আয়তক্ষেত্র তৈরি করে।

    নিম্নলিখিত কোডটি দেখায় কিভাবে একটি MeteringPoint তৈরি করতে হয়:

    কোটলিন

    // 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 তৈরি করতে হবে, যেটিতে FLAG_AF , FLAG_AE , FLAG_AWB থেকে ঐচ্ছিক মিটারিং মোড সংমিশ্রণ সহ এক বা একাধিক MeteringPoints রয়েছে৷ নিম্নলিখিত কোড এই ব্যবহার প্রদর্শন করে:

    কোটলিন

    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 AF/AE/AWB মিটারিং অঞ্চলের জন্য এবং আরেকটি মিটারিংপয়েন্ট শুধুমাত্র AF এবং AE-এর জন্য থাকে।

    অভ্যন্তরীণভাবে, CameraX এটিকে Camera2 MeteringRectangles এ রূপান্তর করে এবং সংশ্লিষ্ট CONTROL_AF_REGIONS / CONTROL_AE_REGIONS / CONTROL_AWB_REGIONS প্যারামিটারগুলি ক্যাপচার অনুরোধে সেট করে৷

    যেহেতু প্রতিটি ডিভাইস AF/AE/AWB এবং একাধিক অঞ্চল সমর্থন করে না, তাই CameraX সর্বোত্তম প্রচেষ্টার সাথে FocusMeteringAction চালায়। পয়েন্ট যোগ করার ক্রমে CameraX সমর্থিত সর্বাধিক সংখ্যক মিটারিংপয়েন্ট ব্যবহার করে। সর্বাধিক গণনার পরে যোগ করা সমস্ত মিটারিং পয়েন্ট উপেক্ষা করা হয়। উদাহরণস্বরূপ, যদি একটি FocusMeteringAction একটি প্ল্যাটফর্মে 3টি মিটারিংপয়েন্টের সাথে সরবরাহ করা হয় যা শুধুমাত্র 2টি সমর্থন করে, শুধুমাত্র প্রথম 2টি মিটারিংপয়েন্ট ব্যবহার করা হয়। চূড়ান্ত MeteringPoint CameraX দ্বারা উপেক্ষা করা হয়।

    এক্সপোজার ক্ষতিপূরণ

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

    Exposure = ExposureCompensationIndex * ExposureCompensationStep

    সূচক মান হিসাবে এক্সপোজার ক্ষতিপূরণ সেট করার জন্য CameraX Camera.CameraControl.setExposureCompensationIndex() ফাংশন প্রদান করে।

    ইতিবাচক সূচকের মানগুলি ছবিটিকে উজ্জ্বল করে, যখন নেতিবাচক মানগুলি ছবিটিকে ম্লান করে। অ্যাপ্লিকেশনগুলি পরবর্তী বিভাগে বর্ণিত CameraInfo.ExposureState.exposureCompensationRange() দ্বারা সমর্থিত পরিসরের জন্য অনুসন্ধান করতে পারে৷ মানটি সমর্থিত হলে, ক্যাপচার অনুরোধে মানটি সফলভাবে সক্ষম হলে প্রত্যাবর্তিত ListenableFuture সম্পূর্ণ হয়; যদি নির্দিষ্ট করা সূচী সমর্থিত সীমার বাইরে থাকে, setExposureCompensationIndex() ফিরে আসা ListenableFuture একটি ব্যর্থ ফলাফলের সাথে অবিলম্বে সম্পূর্ণ করে।

    CameraX শুধুমাত্র সর্বশেষ অসামান্য setExposureCompensationIndex() অনুরোধ রাখে এবং পূর্ববর্তী অনুরোধটি কার্যকর হওয়ার আগে ফাংশনটিকে একাধিকবার কল করলে সেটি বাতিল হয়ে যায়।

    নিম্নলিখিত স্নিপেট একটি এক্সপোজার ক্ষতিপূরণ সূচক সেট করে এবং যখন এক্সপোজার পরিবর্তনের অনুরোধটি কার্যকর করা হয় তখন একটি কলব্যাক নিবন্ধন করে:

    কোটলিন

    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 সেটিংস শুরু করে:

    কোটলিন

    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 নমুনা অ্যাপ
  • বিকাশকারী সম্প্রদায়

    অ্যান্ড্রয়েড ক্যামেরাএক্স আলোচনা গ্রুপ

    ,

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

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

    কোটলিন

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

    জাভা

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

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

    CameraXConfig

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

    CameraXConfig এর সাথে, একটি অ্যাপ্লিকেশন নিম্নলিখিতগুলি করতে পারে:

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

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

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

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

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

    কোটলিন

    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 এমন আচরণ করে যেন সেই ক্যামেরাটি নেই। উদাহরণস্বরূপ, নিম্নলিখিত কোডটি অ্যাপ্লিকেশনটিকে শুধুমাত্র ডিভাইসের ডিফল্ট ব্যাক ক্যামেরা ব্যবহার করতে সীমাবদ্ধ করে:

    কোটলিন

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

    থ্রেড

    অনেক প্ল্যাটফর্ম API যার উপর CameraX তৈরি করা হয়েছে তাদের হার্ডওয়্যার সহ আন্তঃপ্রসেস কমিউনিকেশন (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() দিয়ে এটিকে ওভাররাইড করতে পারেন।

    লগিং

    ক্যামেরাএক্স লগিং অ্যাপ্লিকেশনগুলিকে লগক্যাট বার্তাগুলিকে ফিল্টার করতে দেয়, কারণ এটি আপনার উত্পাদন কোডে ভার্বোস বার্তাগুলি এড়াতে ভাল অনুশীলন হতে পারে৷ ক্যামেরাএক্স চারটি লগিং স্তরকে সমর্থন করে, সবচেয়ে ভার্বস থেকে সবচেয়ে গুরুতর পর্যন্ত:

    • Log.DEBUG (ডিফল্ট)
    • Log.INFO
    • Log.WARN
    • Log.ERROR

    এই লগ স্তরগুলির বিশদ বিবরণের জন্য Android লগ ডকুমেন্টেশন পড়ুন৷ আপনার অ্যাপ্লিকেশনের জন্য উপযুক্ত লগিং স্তর সেট করতে CameraXConfig.Builder.setMinimumLoggingLevel(int) ব্যবহার করুন।

    স্বয়ংক্রিয় নির্বাচন

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

    CameraX এর লক্ষ্য হল সফলভাবে একটি ক্যামেরা সেশন শুরু করা। এর মানে ক্যামেরাএক্স ডিভাইসের ক্ষমতার উপর ভিত্তি করে রেজোলিউশন এবং আকৃতির অনুপাতের সাথে আপস করে। আপস ঘটতে পারে কারণ:

    • ডিভাইসটি অনুরোধ করা রেজোলিউশন সমর্থন করে না।
    • ডিভাইসটির সামঞ্জস্যের সমস্যা রয়েছে, যেমন লিগ্যাসি ডিভাইসগুলির সঠিকভাবে কাজ করার জন্য নির্দিষ্ট রেজোলিউশনের প্রয়োজন।
    • কিছু ডিভাইসে, নির্দিষ্ট ফর্ম্যাটগুলি শুধুমাত্র নির্দিষ্ট আকৃতির অনুপাতগুলিতে উপলব্ধ।
    • ডিভাইসটিতে JPEG বা ভিডিও এনকোডিংয়ের জন্য "নিকটতম mod16" এর জন্য একটি পছন্দ রয়েছে৷ আরও তথ্যের জন্য, SCALER_STREAM_CONFIGURATION_MAP দেখুন।

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

    ঘূর্ণন

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

    আপনার অ্যাপ কনফিগারেশন সেটিংস ব্যবহার করে লক্ষ্য ঘূর্ণন সেট করতে পারে। এটি তারপর ব্যবহার কেস API (যেমন ImageAnalysis.setTargetRotation() ) থেকে পদ্ধতি ব্যবহার করে ঘূর্ণন সেটিংস আপডেট করতে পারে, এমনকি জীবনচক্র চলমান অবস্থায় থাকা অবস্থায়। আপনি এটি ব্যবহার করতে পারেন যখন অ্যাপটি পোর্ট্রেট মোডে লক করা থাকে—এবং তাই ঘূর্ণনে কোনও পুনঃকনফিগারেশন ঘটে না-কিন্তু ফটো বা বিশ্লেষণ ব্যবহারের ক্ষেত্রে ডিভাইসের বর্তমান ঘূর্ণন সম্পর্কে সচেতন হওয়া প্রয়োজন৷ উদাহরণস্বরূপ, ঘূর্ণন সচেতনতার প্রয়োজন হতে পারে যাতে মুখ সনাক্তকরণের জন্য মুখগুলি সঠিকভাবে ভিত্তিক হয়, বা ফটোগুলি ল্যান্ডস্কেপ বা প্রতিকৃতিতে সেট করা হয়।

    ক্যাপচার করা ছবিগুলির ডেটা ঘূর্ণন তথ্য ছাড়াই সংরক্ষণ করা যেতে পারে। Exif ডেটাতে ঘূর্ণন তথ্য রয়েছে যাতে গ্যালারি অ্যাপ্লিকেশনগুলি সংরক্ষণ করার পরে সঠিক অভিযোজনে চিত্রটি দেখাতে পারে।

    সঠিক অভিযোজন সহ পূর্বরূপ তথ্য প্রদর্শন করতে, রূপান্তর তৈরি করতে আপনি Preview.PreviewOutput() থেকে মেটাডেটা আউটপুট ব্যবহার করতে পারেন।

    নিম্নলিখিত কোড নমুনা দেখায় কিভাবে একটি ওরিয়েন্টেশন ইভেন্টে ঘূর্ণন সেট করতে হয়:

    কোটলিন

    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() ব্যবহার করে জানা যায়।
    • ইমেজ অ্যানালাইসিস : মেটাডেটা আউটপুট প্রদান করা হয় যাতে ইমেজ বাফার স্থানাঙ্কগুলি প্রদর্শন স্থানাঙ্কের সাথে সম্পর্কিত হয়।
    • ইমেজ ক্যাপচার : ইমেজ এক্সিফ মেটাডেটা, বাফার, বা বাফার এবং মেটাডেটা উভয়ই ঘূর্ণন সেটিং নোট করার জন্য পরিবর্তিত হয়। পরিবর্তিত মান HAL বাস্তবায়নের উপর নির্ভর করে।

    ক্রপ রেক্ট

    ডিফল্টরূপে, ক্রপ রেক্ট হল সম্পূর্ণ বাফার রেক্ট। আপনি এটিকে ViewPort এবং UseCaseGroup দিয়ে কাস্টমাইজ করতে পারেন। ব্যবহারের কেসগুলিকে গোষ্ঠীবদ্ধ করে এবং ভিউপোর্ট সেট করার মাধ্যমে, CameraX গ্যারান্টি দেয় যে গ্রুপের সমস্ত ব্যবহারের ক্ষেত্রে ক্রপ রেক্ট ক্যামেরা সেন্সরে একই এলাকায় নির্দেশ করে৷

    নিম্নলিখিত কোড স্নিপেট দেখায় কিভাবে এই দুটি ক্লাস ব্যবহার করতে হয়:

    কোটলিন

    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 অবজেক্ট পেতে হয়:

    কোটলিন

    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 তৈরি করতে হয়:

    কোটলিন

    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 অবজেক্ট থেকে উভয় ক্যামেরা অবজেক্ট কিভাবে পেতে হয়।

    কোটলিন

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

    ইমেজ ক্যাপচার এবং ইমেজ বিশ্লেষণ ব্যবহারের ক্ষেত্রে ডিফল্ট অনুপাত হল 4:3।

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

    কোটলিন

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

    জাভা

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

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

    লক্ষ্য ঘূর্ণন দ্বারা সমর্থিত আকারগুলি ঘোরানোর পরে স্থানাঙ্ক ফ্রেমে রেজোলিউশনের Size প্রকাশ করুন। উদাহরণস্বরূপ, প্রাকৃতিক লক্ষ্য ঘূর্ণনে প্রতিকৃতির প্রাকৃতিক অভিযোজন সহ একটি ডিভাইস একটি প্রতিকৃতি চিত্রের জন্য অনুরোধ করে 480x640 নির্দিষ্ট করতে পারে এবং একই ডিভাইস, 90 ডিগ্রি ঘোরানো এবং ল্যান্ডস্কেপ অভিযোজন 640x480 নির্দিষ্ট করতে পারে।

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

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

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

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

    যদি আপনার অ্যাপটি Android 10 বা উচ্চতর সংস্করণে চলছে, তাহলে আপনি একটি নির্দিষ্ট SessionConfiguration যাচাই করতে isSessionConfigurationSupported() ব্যবহার করতে পারেন।

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

    আপনাকে প্রতিটি পৃথক ব্যবহারের ক্ষেত্রে প্রয়োজনীয় ক্যামেরা আউটপুট কনফিগার করতে দেওয়ার পাশাপাশি, CameraX সমস্ত আবদ্ধ ব্যবহারের ক্ষেত্রে সাধারণ ক্যামেরা অপারেশনগুলিকে সমর্থন করার জন্য নিম্নলিখিত ইন্টারফেসগুলিও প্রয়োগ করে:

    • CameraControl আপনাকে সাধারণ ক্যামেরা বৈশিষ্ট্যগুলি কনফিগার করতে দেয়।
    • CameraInfo আপনাকে সেই সাধারণ ক্যামেরা বৈশিষ্ট্যগুলির রাজ্যগুলি জিজ্ঞাসা করতে দেয়৷

    এইগুলি ক্যামেরা কন্ট্রোলের সাথে সমর্থিত ক্যামেরা বৈশিষ্ট্যগুলি:

    • জুম
    • টর্চ
    • ফোকাস এবং মিটারিং (ফোকাস করতে ট্যাপ করুন)
    • এক্সপোজার ক্ষতিপূরণ

    CameraControl এবং CameraInfo এর উদাহরণ পান

    ProcessCameraProvider.bindToLifecycle() দ্বারা প্রত্যাবর্তিত Camera অবজেক্ট ব্যবহার করে CameraControl এবং CameraInfo এর উদাহরণ পুনরুদ্ধার করুন। নিম্নলিখিত কোড একটি উদাহরণ দেখায়:

    কোটলিন

    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 ফেরত দেয়।

    জুম

    ক্যামেরা কন্ট্রোল জুম স্তর পরিবর্তন করার জন্য দুটি পদ্ধতি অফার করে:

    • setZoomRatio() জুম অনুপাত দ্বারা জুম সেট করে।

      অনুপাতটি অবশ্যই CameraInfo.getZoomState().getValue().getMinZoomRatio() এবং CameraInfo.getZoomState().getValue().getMaxZoomRatio() এর সীমার মধ্যে হতে হবে। অন্যথায় ফাংশনটি একটি ব্যর্থ ListenableFuture প্রদান করে।

    • setLinearZoom() 0 থেকে 1.0 পর্যন্ত রৈখিক জুম মান সহ বর্তমান জুম সেট করে।

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

    CameraInfo.getZoomState() বর্তমান জুম অবস্থার একটি লাইভ ডেটা প্রদান করে। ক্যামেরা শুরু হলে মান পরিবর্তন হয় অথবা setZoomRatio() বা setLinearZoom() ব্যবহার করে জুম লেভেল সেট করা হয়। যেকোন একটি পদ্ধতিতে কল করলে ZoomState.getZoomRatio() এবং ZoomState.getLinearZoom() সমর্থনকারী মান সেট করে। আপনি যদি স্লাইডারের পাশাপাশি জুম অনুপাতের পাঠ্য প্রদর্শন করতে চান তবে এটি সহায়ক। একটি রূপান্তর করার প্রয়োজন ছাড়াই উভয় আপডেট করতে কেবল ZoomState LiveData পর্যবেক্ষণ করুন৷

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

    টর্চ

    CameraControl.enableTorch(boolean) টর্চকে সক্ষম বা নিষ্ক্রিয় করে (যা ফ্ল্যাশলাইট নামেও পরিচিত)।

    CameraInfo.getTorchState() বর্তমান টর্চ অবস্থা জিজ্ঞাসা করতে ব্যবহার করা যেতে পারে। একটি টর্চ উপলব্ধ কিনা তা নির্ধারণ করতে আপনি CameraInfo.hasFlashUnit() দ্বারা ফেরত দেওয়া মান পরীক্ষা করতে পারেন। যদি তা না হয়, CameraControl.enableTorch(boolean) কল করার ফলে ফিরে আসা ListenableFuture অবিলম্বে একটি ব্যর্থ ফলাফলের সাথে সম্পূর্ণ হয় এবং টর্চ স্টেটকে TorchState.OFF এ সেট করে।

    টর্চ সক্রিয় করা হলে, ফ্ল্যাশমোড সেটিং নির্বিশেষে ফটো এবং ভিডিও ক্যাপচারের সময় এটি চালু থাকে। ImageCapture flashMode তখনই কাজ করে যখন টর্চ নিষ্ক্রিয় থাকে।

    ফোকাস এবং মিটারিং

    CameraControl.startFocusAndMetering() প্রদত্ত FocusMeteringAction এর উপর ভিত্তি করে AF/AE/AWB মিটারিং অঞ্চলগুলি সেট করে অটোফোকাস এবং এক্সপোজার মিটারিং ট্রিগার করে৷ এটি প্রায়শই অনেক ক্যামেরা অ্যাপ্লিকেশনে "ফোকাস করার জন্য আলতো চাপুন" বৈশিষ্ট্যটি বাস্তবায়ন করতে ব্যবহৃত হয়।

    মিটারিংপয়েন্ট

    শুরু করতে, MeteringPointFactory.createPoint(float x, float y, float size) ব্যবহার করে একটি MeteringPoint তৈরি করুন। একটি MeteringPoint ক্যামেরা Surface একটি একক বিন্দুকে উপস্থাপন করে। এটি একটি স্বাভাবিক আকারে সংরক্ষণ করা হয়েছে যাতে এটিকে সহজেই AF/AE/AWB অঞ্চলগুলি নির্দিষ্ট করার জন্য সেন্সর স্থানাঙ্কে রূপান্তর করা যায়।

    MeteringPoint আকার 0 থেকে 1 পর্যন্ত, ডিফল্ট আকার 0.15f এর সাথে। MeteringPointFactory.createPoint(float x, float y, float size) কল করার সময়, CameraX প্রদত্ত size জন্য (x, y) কেন্দ্রিক একটি আয়তক্ষেত্র তৈরি করে।

    নিম্নলিখিত কোডটি দেখায় কিভাবে একটি MeteringPoint তৈরি করতে হয়:

    কোটলিন

    // 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 তৈরি করতে হবে, যেটিতে FLAG_AF , FLAG_AE , FLAG_AWB থেকে ঐচ্ছিক মিটারিং মোড সংমিশ্রণ সহ এক বা একাধিক MeteringPoints রয়েছে৷ নিম্নলিখিত কোড এই ব্যবহার প্রদর্শন করে:

    কোটলিন

    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 AF/AE/AWB মিটারিং অঞ্চলের জন্য এবং আরেকটি মিটারিংপয়েন্ট শুধুমাত্র AF এবং AE-এর জন্য থাকে।

    অভ্যন্তরীণভাবে, CameraX এটিকে Camera2 MeteringRectangles এ রূপান্তর করে এবং সংশ্লিষ্ট CONTROL_AF_REGIONS / CONTROL_AE_REGIONS / CONTROL_AWB_REGIONS প্যারামিটারগুলি ক্যাপচার অনুরোধে সেট করে৷

    যেহেতু প্রতিটি ডিভাইস AF/AE/AWB এবং একাধিক অঞ্চল সমর্থন করে না, তাই CameraX সর্বোত্তম প্রচেষ্টার সাথে FocusMeteringAction চালায়। পয়েন্ট যোগ করার ক্রমে CameraX সমর্থিত সর্বাধিক সংখ্যক মিটারিংপয়েন্ট ব্যবহার করে। সর্বাধিক গণনার পরে যোগ করা সমস্ত মিটারিং পয়েন্ট উপেক্ষা করা হয়। উদাহরণস্বরূপ, যদি একটি FocusMeteringAction একটি প্ল্যাটফর্মে 3টি মিটারিংপয়েন্টের সাথে সরবরাহ করা হয় যা শুধুমাত্র 2টি সমর্থন করে, শুধুমাত্র প্রথম 2টি মিটারিংপয়েন্ট ব্যবহার করা হয়। চূড়ান্ত MeteringPoint CameraX দ্বারা উপেক্ষা করা হয়।

    এক্সপোজার ক্ষতিপূরণ

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

    Exposure = ExposureCompensationIndex * ExposureCompensationStep

    সূচক মান হিসাবে এক্সপোজার ক্ষতিপূরণ সেট করার জন্য CameraX Camera.CameraControl.setExposureCompensationIndex() ফাংশন প্রদান করে।

    ইতিবাচক সূচকের মানগুলি ছবিটিকে উজ্জ্বল করে, যখন নেতিবাচক মানগুলি ছবিটিকে ম্লান করে। অ্যাপ্লিকেশনগুলি পরবর্তী বিভাগে বর্ণিত CameraInfo.ExposureState.exposureCompensationRange() দ্বারা সমর্থিত পরিসরের জন্য অনুসন্ধান করতে পারে৷ মানটি সমর্থিত হলে, ক্যাপচার অনুরোধে মানটি সফলভাবে সক্ষম হলে প্রত্যাবর্তিত ListenableFuture সম্পূর্ণ হয়; যদি নির্দিষ্ট করা সূচী সমর্থিত সীমার বাইরে থাকে, setExposureCompensationIndex() ফিরে আসা ListenableFuture একটি ব্যর্থ ফলাফলের সাথে অবিলম্বে সম্পূর্ণ করে।

    CameraX শুধুমাত্র সর্বশেষ অসামান্য setExposureCompensationIndex() অনুরোধ রাখে এবং পূর্ববর্তী অনুরোধটি কার্যকর হওয়ার আগে ফাংশনটিকে একাধিকবার কল করলে সেটি বাতিল হয়ে যায়।

    নিম্নলিখিত স্নিপেট একটি এক্সপোজার ক্ষতিপূরণ সূচক সেট করে এবং যখন এক্সপোজার পরিবর্তনের অনুরোধটি কার্যকর করা হয় তখন একটি কলব্যাক নিবন্ধন করে:

    কোটলিন

    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 সেটিংস শুরু করে:

    কোটলিন

    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 নমুনা অ্যাপ
  • বিকাশকারী সম্প্রদায়

    অ্যান্ড্রয়েড ক্যামেরাএক্স আলোচনা গ্রুপ