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

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

    ক্যামেরা নির্বাচন

    ক্যামেরাক্স স্বয়ংক্রিয়ভাবে আপনার অ্যাপ্লিকেশনটির প্রয়োজনীয়তা এবং ব্যবহারের ক্ষেত্রে সেরা ক্যামেরা ডিভাইস নির্বাচন করে। আপনি যদি আপনার জন্য নির্বাচিতের চেয়ে আলাদা ডিভাইস ব্যবহার করতে চান তবে কয়েকটি বিকল্প রয়েছে:

    • CameraSelector.DEFAULT_FRONT_CAMERA সহ ডিফল্ট ফ্রন্ট ফেসিং ক্যামেরাটির জন্য অনুরোধ করুন।
    • CameraSelector.DEFAULT_BACK_CAMERA সহ ডিফল্ট রিয়ার ফেসিং ক্যামেরাটির জন্য অনুরোধ করুন।
    • ক্যামেরাচারাক্টেরিস্টিকস দ্বারা CameraSelector.Builder.addCameraFilter() এর সাথে তাদের CameraCharacteristics দ্বারা উপলব্ধ ডিভাইসের তালিকা ফিল্টার করুন।

    নিম্নলিখিত কোড নমুনাটি কীভাবে ডিভাইস নির্বাচনকে প্রভাবিত করতে 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)

    একযোগে একাধিক ক্যামেরা নির্বাচন করুন

    ক্যামেরাক্স 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);

    ক্যামেরা রেজুলেশন

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

    স্বয়ংক্রিয় রেজোলিউশন

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

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

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

    উদাহরণস্বরূপ, একটি অ্যাপ্লিকেশন নিম্নলিখিতগুলির যে কোনওটি করতে পারে:

    • ব্যবহারের ক্ষেত্রে 4: 3 বা 16: 9 এর একটি লক্ষ্য রেজোলিউশন নির্দিষ্ট করুন
    • একটি কাস্টম রেজোলিউশন নির্দিষ্ট করুন, যা ক্যামেরাক্স নিকটতম ম্যাচটি সন্ধান করার চেষ্টা করে
    • ImageCapture জন্য একটি ক্রপিং দিক অনুপাত নির্দিষ্ট করুন

    ক্যামেরাক্স অভ্যন্তরীণ ক্যামেরা 2 পৃষ্ঠের রেজোলিউশনগুলি স্বয়ংক্রিয়ভাবে চয়ন করে। নিম্নলিখিত টেবিলটি রেজোলিউশনগুলি দেখায়:

    কেস ব্যবহার করুন অভ্যন্তরীণ পৃষ্ঠ রেজোলিউশন আউটপুট ডেটা রেজোলিউশন
    পূর্বরূপ দিক অনুপাত: রেজোলিউশন যা সেটিংয়ের সাথে লক্ষ্যটিকে সর্বোত্তমভাবে ফিট করে। অভ্যন্তরীণ পৃষ্ঠ রেজোলিউশন। মেটাডেটা একটি ভিউ ক্রপ, স্কেল এবং লক্ষ্য দিক অনুপাতের জন্য ঘোরানোর জন্য সরবরাহ করা হয়।
    ডিফল্ট রেজোলিউশন: সর্বোচ্চ পূর্বরূপ রেজোলিউশন, বা সর্বোচ্চ ডিভাইস-পছন্দসই রেজোলিউশন যা পূর্বরূপের দিক অনুপাতের সাথে মেলে।
    সর্বোচ্চ রেজোলিউশন: পূর্বরূপ আকার, যা ডিভাইসের স্ক্রিন রেজোলিউশনের সেরা আকারের ম্যাচ বা 1080p (1920x1080), যেটি ছোট তা বোঝায়।
    চিত্র বিশ্লেষণ দিক অনুপাত: রেজোলিউশন যা সেটিংয়ের সাথে লক্ষ্যটিকে সর্বোত্তমভাবে ফিট করে। অভ্যন্তরীণ পৃষ্ঠ রেজোলিউশন।
    ডিফল্ট রেজোলিউশন: ডিফল্ট লক্ষ্য রেজোলিউশন সেটিংটি 640x480। লক্ষ্য রেজোলিউশন এবং সংশ্লিষ্ট দিক অনুপাত উভয়ই সামঞ্জস্য করা একটি সেরা-সমর্থিত রেজোলিউশনে ফলাফল।
    সর্বাধিক রেজোলিউশন: ক্যামেরার ডিভাইসের YUV_420_888 ফর্ম্যাটের সর্বাধিক আউটপুট রেজোলিউশন যা StreamConfigurationMap.getOutputSizes() থেকে পুনরুদ্ধার করা হয়। লক্ষ্য রেজোলিউশনটি ডিফল্টরূপে 640x480 হিসাবে সেট করা হয়েছে, সুতরাং আপনি যদি 640x480 এর চেয়ে বড় রেজোলিউশন চান তবে আপনাকে অবশ্যই সমর্থিত রেজোলিউশনগুলি থেকে নিকটতমটি পেতে setTargetResolution() এবং setTargetAspectRatio() ব্যবহার করতে হবে।
    ইমেজ ক্যাপচার দিক অনুপাত: দিক অনুপাত যা সেটিংসকে সর্বোত্তমভাবে ফিট করে। অভ্যন্তরীণ পৃষ্ঠ রেজোলিউশন।
    ডিফল্ট রেজোলিউশন: সর্বোচ্চ রেজোলিউশন উপলব্ধ, বা সর্বোচ্চ ডিভাইস-পছন্দসই রেজোলিউশন যা ইমেজক্যাপচারের দিক অনুপাতের সাথে মেলে।
    সর্বাধিক রেজোলিউশন: একটি জেপিগ ফর্ম্যাটে ক্যামেরা ডিভাইসের সর্বাধিক আউটপুট রেজোলিউশন। এটি পুনরুদ্ধার করতে 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 একই দিক অনুপাত সহ রেজোলিউশনগুলিকে বিভিন্ন দিক অনুপাতের রেজোলিউশনের চেয়ে বেশি অগ্রাধিকার দেওয়া হয়।

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

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

    যদি আপনার অ্যাপ্লিকেশনটি অ্যান্ড্রয়েড 10 বা তার বেশি সময়ে চলমান থাকে তবে আপনি একটি নির্দিষ্ট SessionConfiguration যাচাই করতে isSessionConfigurationSupported() ব্যবহার করতে পারেন।

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

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

    • 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 অবধি লিনিয়ার জুম মান সহ বর্তমান জুম সেট করে।

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

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

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

    টর্চ

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

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

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

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

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

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

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

    MeteringPoint আকার 0 থেকে 1 অবধি 0.15F এর ডিফল্ট আকার সহ। MeteringPointFactory.createPoint(float x, float y, float size) কল করার সময়, ক্যামেরাক্স প্রদত্ত 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 তৈরি করতে হবে, যা FLAG_AF , FLAG_AE , FLAG_AWB থেকে al চ্ছিক মিটারিং মোড সংমিশ্রণগুলির সাথে এক বা একাধিক 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() এএফ/এই/এডাব্লুবি মিটারিং অঞ্চলগুলির জন্য একটি MeteringPoint এবং কেবল এএফ এবং এইএর জন্য অন্য মিটারিংপয়েন্টের সমন্বয়ে একটি FocusMeteringAction নেয়।

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

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

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

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

    Exposure = ExposureCompensationIndex * ExposureCompensationStep

    ক্যামেরাক্স Camera.CameraControl.setExposureCompensationIndex()

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

    ক্যামেরাক্স কেবলমাত্র সর্বশেষতম আউটস্ট্যান্ডিং 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
    }

    অতিরিক্ত সম্পদ

    ক্যামেরাক্স সম্পর্কে আরও জানতে, নিম্নলিখিত অতিরিক্ত সংস্থানগুলির সাথে পরামর্শ করুন।

    কোডল্যাব

  • ক্যামেরাক্স দিয়ে শুরু করা
  • কোড নমুনা

  • ক্যামেরাক্স নমুনা অ্যাপ্লিকেশন
  • বিকাশকারী সম্প্রদায়

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

    ,

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

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

    কোটলিন

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

    জাভা

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

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

    CameraXConfig

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

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

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

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

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

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

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

    কোটলিন

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

    আপনার অ্যাপ্লিকেশনটি সেট করার পরে ক্যামেরাক্স কনফিগারেশনটি জানতে চাইলে CameraXConfig অবজেক্টের একটি স্থানীয় অনুলিপি রাখুন।

    ক্যামেরা সীমাবদ্ধ

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

    যদি CameraSelector CameraXConfig.Builder.setAvailableCamerasLimiter() একটি ক্যামেরা ফিল্টার করে দেয়, ক্যামেরাক্স এমন আচরণ করে যেন সেই ক্যামেরাটির অস্তিত্ব নেই। উদাহরণস্বরূপ, নিম্নলিখিত কোডটি কেবল ডিভাইসের ডিফল্ট ব্যাক ক্যামেরাটি ব্যবহার করতে অ্যাপ্লিকেশনটিকে সীমাবদ্ধ করে:

    কোটলিন

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

    থ্রেড

    ক্যামেরাক্স যে প্ল্যাটফর্মের এপিআইগুলি নির্মিত হয়েছে তার অনেকগুলি হার্ডওয়্যার সহ ইন্টারপ্রোসেস যোগাযোগ (আইপিসি) ব্লকিং করা প্রয়োজন যা কখনও কখনও প্রতিক্রিয়া জানাতে কয়েকশ মিলিসেকেন্ড নিতে পারে। এই কারণে, ক্যামেরাক্স কেবল ব্যাকগ্রাউন্ড থ্রেডগুলি থেকে এই এপিআইগুলিকে কল করে, যাতে মূল থ্রেডটি অবরুদ্ধ না হয় এবং ইউআই তরল থাকে। ক্যামেরাক্স অভ্যন্তরীণভাবে এই ব্যাকগ্রাউন্ড থ্রেডগুলি পরিচালনা করে যাতে এই আচরণটি স্বচ্ছ প্রদর্শিত হয়। তবে কিছু অ্যাপ্লিকেশনগুলির থ্রেডগুলির কঠোর নিয়ন্ত্রণ প্রয়োজন। CameraXConfig একটি অ্যাপ্লিকেশনটিকে CameraXConfig.Builder.setCameraExecutor() এবং CameraXConfig.Builder.setSchedulerHandler() এর মাধ্যমে ব্যবহৃত ব্যাকগ্রাউন্ড থ্রেডগুলি সেট করতে দেয়।

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

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

    সময়সূচী হ্যান্ডলার

    শিডিয়ুলার হ্যান্ডলারটি স্থির বিরতিতে অভ্যন্তরীণ কার্যগুলি নির্ধারণ করতে ব্যবহৃত হয়, যেমন ক্যামেরাটি যখন উপলভ্য হয় না তখন পুনরায় চেষ্টা করা। এই হ্যান্ডলারটি চাকরি কার্যকর করে না এবং কেবল এগুলি ক্যামেরা এক্সিকিউটারে প্রেরণ করে। এটি কখনও কখনও লিগ্যাসি এপিআই প্ল্যাটফর্মগুলিতেও ব্যবহৃত হয় যা কলব্যাকের জন্য Handler প্রয়োজন। এই ক্ষেত্রে, কলব্যাকগুলি এখনও কেবল ক্যামেরা এক্সিকিউটারের কাছে সরাসরি প্রেরণ করা হয়। ক্যামেরাক্স এই কাজগুলি সম্পাদনের জন্য একটি অভ্যন্তরীণ HandlerThread বরাদ্দ করে এবং পরিচালনা করে তবে আপনি এটি CameraXConfig.Builder.setSchedulerHandler() দিয়ে ওভাররাইড করতে পারেন।

    লগিং

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

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

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

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

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

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

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

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

    ঘূর্ণন

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

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

    ক্যাপচার করা চিত্রগুলির জন্য ডেটা ঘূর্ণন তথ্য ছাড়াই সংরক্ষণ করা যেতে পারে। এক্সআইএফ ডেটাতে ঘূর্ণন সম্পর্কিত তথ্য রয়েছে যাতে গ্যালারী অ্যাপ্লিকেশনগুলি সংরক্ষণের পরে সঠিক ওরিয়েন্টেশনে চিত্রটি প্রদর্শন করতে পারে।

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

    ক্রপ রেক্ট

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

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

    কোটলিন

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

    ক্যামেরা নির্বাচন

    ক্যামেরাক্স স্বয়ংক্রিয়ভাবে আপনার অ্যাপ্লিকেশনটির প্রয়োজনীয়তা এবং ব্যবহারের ক্ষেত্রে সেরা ক্যামেরা ডিভাইস নির্বাচন করে। আপনি যদি আপনার জন্য নির্বাচিতের চেয়ে আলাদা ডিভাইস ব্যবহার করতে চান তবে কয়েকটি বিকল্প রয়েছে:

    • CameraSelector.DEFAULT_FRONT_CAMERA সহ ডিফল্ট ফ্রন্ট ফেসিং ক্যামেরাটির জন্য অনুরোধ করুন।
    • CameraSelector.DEFAULT_BACK_CAMERA সহ ডিফল্ট রিয়ার ফেসিং ক্যামেরাটির জন্য অনুরোধ করুন।
    • ক্যামেরাচারাক্টেরিস্টিকস দ্বারা CameraSelector.Builder.addCameraFilter() এর সাথে তাদের CameraCharacteristics দ্বারা উপলব্ধ ডিভাইসের তালিকা ফিল্টার করুন।

    নিম্নলিখিত কোড নমুনাটি কীভাবে ডিভাইস নির্বাচনকে প্রভাবিত করতে 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)

    একযোগে একাধিক ক্যামেরা নির্বাচন করুন

    ক্যামেরাক্স 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);

    ক্যামেরা রেজুলেশন

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

    স্বয়ংক্রিয় রেজোলিউশন

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

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

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

    উদাহরণস্বরূপ, একটি অ্যাপ্লিকেশন নিম্নলিখিতগুলির যে কোনওটি করতে পারে:

    • ব্যবহারের ক্ষেত্রে 4: 3 বা 16: 9 এর একটি লক্ষ্য রেজোলিউশন নির্দিষ্ট করুন
    • একটি কাস্টম রেজোলিউশন নির্দিষ্ট করুন, যা ক্যামেরাক্স নিকটতম ম্যাচটি সন্ধান করার চেষ্টা করে
    • ImageCapture জন্য একটি ক্রপিং দিক অনুপাত নির্দিষ্ট করুন

    ক্যামেরাক্স অভ্যন্তরীণ ক্যামেরা 2 পৃষ্ঠের রেজোলিউশনগুলি স্বয়ংক্রিয়ভাবে চয়ন করে। নিম্নলিখিত টেবিলটি রেজোলিউশনগুলি দেখায়:

    কেস ব্যবহার করুন অভ্যন্তরীণ পৃষ্ঠ রেজোলিউশন আউটপুট ডেটা রেজোলিউশন
    পূর্বরূপ দিক অনুপাত: রেজোলিউশন যা সেটিংয়ের সাথে লক্ষ্যটিকে সর্বোত্তমভাবে ফিট করে। অভ্যন্তরীণ পৃষ্ঠ রেজোলিউশন। মেটাডেটা একটি ভিউ ক্রপ, স্কেল এবং লক্ষ্য দিক অনুপাতের জন্য ঘোরানোর জন্য সরবরাহ করা হয়।
    ডিফল্ট রেজোলিউশন: সর্বোচ্চ পূর্বরূপ রেজোলিউশন, বা সর্বোচ্চ ডিভাইস-পছন্দসই রেজোলিউশন যা পূর্বরূপের দিক অনুপাতের সাথে মেলে।
    সর্বোচ্চ রেজোলিউশন: পূর্বরূপ আকার, যা ডিভাইসের স্ক্রিন রেজোলিউশনের সেরা আকারের ম্যাচ বা 1080p (1920x1080), যেটি ছোট তা বোঝায়।
    চিত্র বিশ্লেষণ দিক অনুপাত: রেজোলিউশন যা সেটিংয়ের সাথে লক্ষ্যটিকে সর্বোত্তমভাবে ফিট করে। অভ্যন্তরীণ পৃষ্ঠ রেজোলিউশন।
    ডিফল্ট রেজোলিউশন: ডিফল্ট লক্ষ্য রেজোলিউশন সেটিংটি 640x480। লক্ষ্য রেজোলিউশন এবং সংশ্লিষ্ট দিক অনুপাত উভয়ই সামঞ্জস্য করা একটি সেরা-সমর্থিত রেজোলিউশনে ফলাফল।
    সর্বাধিক রেজোলিউশন: ক্যামেরার ডিভাইসের YUV_420_888 ফর্ম্যাটের সর্বাধিক আউটপুট রেজোলিউশন যা StreamConfigurationMap.getOutputSizes() থেকে পুনরুদ্ধার করা হয়। লক্ষ্য রেজোলিউশনটি ডিফল্টরূপে 640x480 হিসাবে সেট করা হয়েছে, সুতরাং আপনি যদি 640x480 এর চেয়ে বড় রেজোলিউশন চান তবে আপনাকে অবশ্যই সমর্থিত রেজোলিউশনগুলি থেকে নিকটতমটি পেতে setTargetResolution() এবং setTargetAspectRatio() ব্যবহার করতে হবে।
    ইমেজ ক্যাপচার দিক অনুপাত: দিক অনুপাত যা সেটিংসকে সর্বোত্তমভাবে ফিট করে। অভ্যন্তরীণ পৃষ্ঠ রেজোলিউশন।
    ডিফল্ট রেজোলিউশন: সর্বোচ্চ রেজোলিউশন উপলব্ধ, বা সর্বোচ্চ ডিভাইস-পছন্দসই রেজোলিউশন যা ইমেজক্যাপচারের দিক অনুপাতের সাথে মেলে।
    সর্বাধিক রেজোলিউশন: একটি জেপিগ ফর্ম্যাটে ক্যামেরা ডিভাইসের সর্বাধিক আউটপুট রেজোলিউশন। এটি পুনরুদ্ধার করতে 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 একই দিক অনুপাত সহ রেজোলিউশনগুলিকে বিভিন্ন দিক অনুপাতের রেজোলিউশনের চেয়ে বেশি অগ্রাধিকার দেওয়া হয়।

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

    যদি আপনার অ্যাপ্লিকেশনটির একটি সঠিক রেজোলিউশন প্রয়োজন হয় তবে প্রতিটি হার্ডওয়্যার স্তর দ্বারা সর্বাধিক রেজোলিউশনগুলি কী সমর্থন করে তা নির্ধারণ করতে createCaptureSession() এর মধ্যে টেবিলটি দেখুন। To check for the specific resolutions supported by the current device, see StreamConfigurationMap.getOutputSizes(int) .

    If your app is running on Android 10 or higher, you can use isSessionConfigurationSupported() to verify a specific SessionConfiguration .

    Control camera output

    In addition to letting you configure the camera output as-needed for each individual use case, CameraX also implements the following interfaces to support camera operations common to all bound use cases:

    • CameraControl lets you configure common camera features.
    • CameraInfo lets you query the states of those common camera features.

    These are the supported camera features with CameraControl:

    • জুম
    • টর্চ
    • Focus and Metering (tap-to-focus)
    • এক্সপোজার ক্ষতিপূরণ

    Get instances of CameraControl and CameraInfo

    Retrieve instances of CameraControl and CameraInfo using the Camera object returned by ProcessCameraProvider.bindToLifecycle() . নিম্নলিখিত কোড একটি উদাহরণ দেখায়:

    কোটলিন

    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()

    For example, you can submit zoom and other CameraControl operations after calling bindToLifecycle() . After you stop or destroy the activity used to bind the camera instance, CameraControl can no longer execute operations and returns a failed ListenableFuture .

    জুম

    CameraControl offers two methods for changing the zoom level:

    • setZoomRatio() sets the zoom by the zoom ratio.

      The ratio must be within the range of CameraInfo.getZoomState().getValue().getMinZoomRatio() and CameraInfo.getZoomState().getValue().getMaxZoomRatio() . Otherwise the function returns a failed ListenableFuture .

    • setLinearZoom() sets the current zoom with a linear zoom value ranging from 0 to 1.0.

      The advantage of linear zoom is that it makes the field of view (FOV) scale with changes in zoom. This makes it ideal for use with a Slider view.

    CameraInfo.getZoomState() returns a LiveData of the current zoom state. The value changes when the camera is initialized or if the zoom level is set using setZoomRatio() or setLinearZoom() . Calling either method sets the values backing ZoomState.getZoomRatio() and ZoomState.getLinearZoom() . This is helpful if you want to display zoom ratio text alongside a slider. Simply observe the ZoomState LiveData to update both without needing to do a conversion.

    The ListenableFuture returned by both APIs offers the option for applications to be notified when a repeating request with the specified zoom value is completed. In addition, if you set a new zoom value while the previous operation is still executing, the previous zoom operation's ListenableFuture fails immediately.

    টর্চ

    CameraControl.enableTorch(boolean) enables or disables the torch (also known as the flashlight).

    CameraInfo.getTorchState() can be used to query the current torch state. You can check the value returned by CameraInfo.hasFlashUnit() to determine whether a torch is available. If not, calling CameraControl.enableTorch(boolean) causes the returned ListenableFuture to complete immediately with a failed result and sets the torch state to TorchState.OFF .

    When the torch is enabled, it remains on during photo and video capture regardless of the flashMode setting. The flashMode in ImageCapture works only when the torch is disabled.

    Focus and Metering

    CameraControl.startFocusAndMetering() triggers autofocus and exposure metering by setting AF/AE/AWB metering regions based on the given FocusMeteringAction. This is often used to implement the “tap to focus” feature in many camera applications.

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

    To begin, create a MeteringPoint using MeteringPointFactory.createPoint(float x, float y, float size) . A MeteringPoint represents a single point on the camera Surface . It's stored in a normalized form so that it can be easily converted to sensor coordinates for specifying AF/AE/AWB regions.

    The size of the MeteringPoint ranges from 0 to 1, with a default size of 0.15f. When calling MeteringPointFactory.createPoint(float x, float y, float size) , CameraX creates a rectangle region centered at (x, y) for the provided size .

    The following code demonstrates how to create a 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 and FocusMeteringAction

    To invoke startFocusAndMetering() , applications must build a FocusMeteringAction , which consists of one or more MeteringPoints with optional metering mode combinations from FLAG_AF , FLAG_AE , FLAG_AWB . The follow code demonstrates this usage:

    কোটলিন

    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)

    As shown in the preceding code, startFocusAndMetering() takes a FocusMeteringAction consisting of one MeteringPoint for AF/AE/AWB metering regions and another MeteringPoint for AF and AE only.

    Internally, CameraX converts it into Camera2 MeteringRectangles and sets the corresponding CONTROL_AF_REGIONS / CONTROL_AE_REGIONS / CONTROL_AWB_REGIONS parameters to the capture request.

    Since not every device supports AF/AE/AWB and multiple regions, CameraX executes the FocusMeteringAction with best effort. CameraX uses the maximum number of MeteringPoints supported, in the order that points were added. All MeteringPoints added after the maximum count are ignored. For example, if a FocusMeteringAction is supplied with 3 MeteringPoints on a platform supporting just 2, only the first 2 MeteringPoints are used. The final MeteringPoint is ignored by CameraX.

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

    Exposure compensation is useful when applications need to fine-tune exposure values (EV) beyond the auto exposure (AE) output result. Exposure compensation values are combined in the following way to determine the necessary exposure for current image conditions:

    Exposure = ExposureCompensationIndex * ExposureCompensationStep

    CameraX provides the Camera.CameraControl.setExposureCompensationIndex() function for setting the exposure compensation as an index value.

    Positive index values make the image brighter, while negative values dim the image. Applications can query the supported range by CameraInfo.ExposureState.exposureCompensationRange() described in the next section. If the value is supported, the returned ListenableFuture completes when the value is successfully enabled in the capture request; if the specified index is out of the supported range, setExposureCompensationIndex() causes the returned ListenableFuture to complete immediately with a failed result.

    CameraX keeps only the latest outstanding setExposureCompensationIndex() request, and calling the function multiple times before the previous request gets executed results in its cancellation.

    The following snippet sets an exposure compensation index and registers a callback for when the exposure change request has been executed:

    কোটলিন

    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() retrieves the current ExposureState including:

      • The supportability of exposure compensation control.
      • The current exposure compensation index.
      • The exposure compensation index range.
      • The exposure compensation step used in exposure compensation value calculation.

    For example, the following code initializes the settings for an exposure SeekBar with current ExposureState values:

    কোটলিন

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

    অতিরিক্ত সম্পদ

    To learn more about CameraX, consult the following additional resources.

    কোডল্যাব

  • Getting Started with CameraX
  • কোড নমুনা

  • CameraX sample apps
  • বিকাশকারী সম্প্রদায়

    Android CameraX Discussion Group

    ,

    You configure each CameraX use case to control different aspects of the use case's operations.

    For example, with the image capture use case, you can set a target aspect ratio and a flash mode. The following code shows one example:

    কোটলিন

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

    জাভা

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

    In addition to configuration options, some use cases expose APIs to dynamically alter settings after the use case has been created. For information about configuration that is specific to the individual use cases, see Implement a preview , Analyze images , and Image capture .

    CameraXConfig

    For simplicity, CameraX has default configurations such as internal executors and handlers that are suitable for most usage scenarios. However, if your application has special requirements or prefers to customize those configurations, CameraXConfig is the interface for that purpose.

    With CameraXConfig , an application can do the following:

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

    The following procedure describes how to use CameraXConfig :

    1. Create a CameraXConfig object with your customized configurations.
    2. Implement the CameraXConfig.Provider interface in your Application , and return your CameraXConfig object in getCameraXConfig() .
    3. Add your Application class to your AndroidManifest.xml file, as described here .

    For example, the following code sample restricts CameraX logging to error messages only:

    কোটলিন

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

    Keep a local copy of the CameraXConfig object if your application needs to know the CameraX configuration after setting it.

    Camera Limiter

    During the first invocation of ProcessCameraProvider.getInstance() , CameraX enumerates and queries characteristics of the cameras available on the device. Because CameraX needs to communicate with hardware components, this process can take a non-trivial amount of time for each camera, particularly on low-end devices. If your application only uses specific cameras on the device, such as the default front camera, you can set CameraX to ignore other cameras, which can reduce startup latency for the cameras your application uses.

    If the CameraSelector passed to CameraXConfig.Builder.setAvailableCamerasLimiter() filters out a camera, CameraX behaves as if that camera doesn't exist. For example, the following code limits the application to only use the device's default back camera:

    কোটলিন

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

    থ্রেড

    Many of the platform APIs on which CameraX is built require blocking interprocess communication (IPC) with hardware that can sometimes take hundreds of milliseconds to respond. For this reason, CameraX only calls these APIs from background threads, so that the main thread isn't blocked and the UI remains fluid. CameraX internally manages these background threads so that this behavior appears transparent. However, some applications require strict control of threads. CameraXConfig lets an application set the background threads that are used through CameraXConfig.Builder.setCameraExecutor() and CameraXConfig.Builder.setSchedulerHandler() .

    Camera Executor

    The camera executor is used for all internal Camera platform API calls, as well as for callbacks from these APIs. CameraX allocates and manages an internal Executor to perform these tasks. However, if your application requires stricter control of threads, use CameraXConfig.Builder.setCameraExecutor() .

    Scheduler Handler

    The scheduler handler is used to schedule internal tasks at fixed intervals, such as retrying opening the camera when it isn't available. This handler does not execute jobs, and only dispatches them to the camera executor. It is also sometimes used on the legacy API platforms that require a Handler for callbacks. In these cases, the callbacks are still only dispatched directly to the camera executor. CameraX allocates and manages an internal HandlerThread to perform these tasks, but you can overridde it with CameraXConfig.Builder.setSchedulerHandler() .

    লগিং

    CameraX logging lets applications filter logcat messages, as it can be good practice to avoid verbose messages in your production code. CameraX supports four logging levels, from the most verbose to the most severe:

    • Log.DEBUG (default)
    • Log.INFO
    • Log.WARN
    • Log.ERROR

    Refer to the Android Log documentation for detailed descriptions of these log levels. Use CameraXConfig.Builder.setMinimumLoggingLevel(int) to set the appropriate logging level for your application.

    Automatic selection

    CameraX automatically provides functionality that is specific to the device that your app is running on. For example, CameraX automatically determines the best resolution to use if you don't specify a resolution, or if the resolution you specify is unsupported. All of this is handled by the library, eliminating the need for you to write device-specific code.

    CameraX's goal is to successfully initialize a camera session. This means CameraX compromises on resolution and aspect ratios based on device capability. The compromise can happen because:

    • The device doesn't support the requested resolution.
    • The device has compatibility issues, such as legacy devices that require certain resolutions to operate correctly.
    • On some devices, certain formats are only available at certain aspect ratios.
    • The device has a preference for a "nearest mod16" for JPEG or video encoding. For more information, see SCALER_STREAM_CONFIGURATION_MAP .

    Although CameraX creates and manages the session, always check the returned image sizes on the use case output in your code and adjust accordingly.

    ঘূর্ণন

    By default, the camera rotation is set to match the default display's rotation during the creation of the use case. In this default case, CameraX produces outputs to let the app match what you expect to see in the preview. You can change the rotation to a custom value to support multi-display devices by passing in the current display orientation when configuring use case objects or dynamically after they have been created.

    Your app can set the target rotation using configuration settings. It can then update rotation settings by using the methods from the use case APIs (such as ImageAnalysis.setTargetRotation() ), even while the lifecycle is in a running state. You might use this when the app is locked to portrait mode—and so no reconfiguration occurs on rotation—but the photo or analysis use case needs to be aware of the current rotation of the device. For example, rotation awareness might be needed so faces are oriented correctly for face detection, or photos are set to landscape or portrait.

    Data for captured images might be stored without rotation information. Exif data contains rotation information so that gallery applications can show the image in the correct orientation after saving.

    To display preview data with the correct orientation, you can use the metadata output from Preview.PreviewOutput() to create transforms.

    The following code sample shows how to set the rotation on an orientation event:

    কোটলিন

    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();
    }

    Based on the set rotation, each use case either rotates the image data directly or provides rotation metadata to the consumers of the non-rotated image data.

    • Preview : Metadata output is provided so that the rotation of the target resolution is known using Preview.getTargetRotation() .
    • ImageAnalysis : Metadata output is provided so that image buffer coordinates are known relative to display coordinates.
    • ImageCapture : The image Exif metadata, buffer, or both the buffer and metadata are altered to note the rotation setting. The value altered depends upon the HAL implementation.

    Crop rect

    By default, the crop rect is the full buffer rect. You can customize it with ViewPort and UseCaseGroup . By grouping use cases and setting the viewport, CameraX guarantees that the crop rects of all the use cases in the group point to the same area in the camera sensor.

    The following code snippet shows how to use these two classes:

    কোটলিন

    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 defines the buffer rect visible to end users. Then CameraX calculates the largest possible crop rect based on the properties of the viewport and the attached use cases. Usually, to achieve a WYSIWYG effect, you can configure the viewport based on the preview use case. A simple way to get the viewport is to use PreviewView .

    The following code snippets shows how to get the ViewPort object:

    কোটলিন

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

    জাভা

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

    In the preceding example, what the app gets from ImageAnalysis and ImageCapture matches what the end user sees in PreviewView , assuming the PreviewView 's scale type is set to the default, FILL_CENTER . After applying the crop rect and rotation to the output buffer, the image from all use cases is the same, though possibly with different resolutions. For more information about how to apply the transformation info, see transform output .

    ক্যামেরা নির্বাচন

    CameraX automatically selects the best camera device for your application's requirements and use cases. If you wish to use a different device than the one selected for you, there are a few options:

    The following code sample illustrates how to create a CameraSelector to influence device selection:

    কোটলিন

    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)

    Select multiple cameras concurrently

    Starting with CameraX 1.3, you can also select multiple cameras concurrently. For example, you can bind to a front and back camera to take photos or record videos from both perspectives simultaneously.

    When using the Concurrent Camera feature, the device can operate two cameras with different-facing lenses at the same time, or operate two back cameras at the same time. The following code block shows how to set two cameras when calling bindToLifecycle , and how to get both Camera objects from the returned ConcurrentCamera object.

    কোটলিন

    // 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);

    ক্যামেরা রেজুলেশন

    You can choose to let CameraX set the image resolution based on a combination of the device capabilities, device's supported hardware level , use case, and provided aspect ratio. Alternatively, you can set a specific target resolution or a specific aspect ratio in use cases that support that configuration.

    Automatic resolution

    CameraX can automatically determine the best resolution settings based on the use cases specified in cameraProcessProvider.bindToLifecycle() . Whenever possible, specify all the use cases needed to run concurrently in a single session in a single bindToLifecycle() call. CameraX determines resolutions based on the set of use cases bound by considering the device's supported hardware level and by accounting for device-specific variance (where a device exceeds or doesn't meet the stream configurations available ). The intent is to let the application run on a wide variety of devices while minimizing device-specific code paths.

    The default aspect ratio for image capture and image analysis use cases is 4:3.

    Use cases have a configurable aspect ratio to let the application specify the desired aspect ratio based on UI design. CameraX output is produced to match the aspect ratios requested as closely as the device supports. If there is no exact-match resolution supported, the one that fulfills the most conditions is selected. Thus, the application dictates how the camera appears in the app, and CameraX determines the best camera resolution settings to satisfy that on different devices.

    For example, an app can do any of the following:

    • Specify a target resolution of 4:3 or 16:9 for a use case
    • Specify a custom resolution, which CameraX attempts to find the closest match to
    • Specify a cropping aspect ratio for ImageCapture

    CameraX chooses the internal Camera2 surface resolutions automatically. The following table shows the resolutions:

    কেস ব্যবহার করুন Internal surface resolution Output data resolution
    পূর্বরূপ Aspect Ratio: The resolution that best fits the target to the setting. Internal surface resolution. Metadata is provided to let a View crop, scale, and rotate for the target aspect ratio.
    Default resolution: Highest preview resolution, or highest device-preferred resolution that matches the Preview's aspect ratio.
    Max resolution: Preview size, which refers to the best size match to the device's screen resolution, or to 1080p (1920x1080), whichever is smaller.
    চিত্র বিশ্লেষণ Aspect ratio: The resolution that best fits the target to the setting. Internal surface resolution.
    Default resolution: The default target resolution setting is 640x480. Adjusting both target resolution and corresponding aspect ratio results in a best-supported resolution.
    Max resolution: The camera device's maximum output resolution of YUV_420_888 format which is retrieved from StreamConfigurationMap.getOutputSizes() . The target resolution is set as 640x480 by default, so if you want a resolution larger than 640x480, you must use setTargetResolution() and setTargetAspectRatio() to get the closest one from the supported resolutions.
    ইমেজ ক্যাপচার Aspect ratio: Aspect ratio that best fits the setting. Internal surface resolution.
    Default resolution: Highest resolution available, or highest device-preferred resolution that matches the ImageCapture's aspect ratio.
    Max resolution: The camera device's maximum output resolution in a JPEG format. Use StreamConfigurationMap.getOutputSizes() to retrieve this.

    Specify a resolution

    You can set specific resolutions when building use cases using the setTargetResolution(Size resolution) method, as shown in the following code sample:

    কোটলিন

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

    জাভা

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

    You can't set both target aspect ratio and target resolution on the same use case. Doing so throws an IllegalArgumentException when building the configuration object.

    Express the resolution Size in the coordinate frame after rotating the supported sizes by the target rotation. For example, a device with portrait natural orientation in natural target rotation requesting a portrait image can specify 480x640, and the same device, rotated 90 degrees and targeting landscape orientation can specify 640x480.

    The target resolution attempts to establish a minimum bound for the image resolution. The actual image resolution is the closest available resolution in size that isn't smaller than the target resolution, as determined by the Camera implementation.

    However, if no resolution exists that is equal to or larger than the target resolution, the nearest available resolution smaller than the target resolution is chosen. Resolutions with the same aspect ratio of the provided Size are given higher priority than resolutions of different aspect ratios.

    CameraX applies the best suitable resolution based on the requests. If the primary need is to satisfy aspect ratio, specify only setTargetAspectRatio , and CameraX determines a specific resolution suitable based on the device. If the primary need of the app is to specify a resolution in order to make image processing more efficient (for example a small or mid-sized image based on device processing capability), use setTargetResolution(Size resolution) .

    If your app requires an exact resolution, see the table within createCaptureSession() to determine what maximum resolutions are supported by each hardware level. To check for the specific resolutions supported by the current device, see StreamConfigurationMap.getOutputSizes(int) .

    If your app is running on Android 10 or higher, you can use isSessionConfigurationSupported() to verify a specific SessionConfiguration .

    Control camera output

    In addition to letting you configure the camera output as-needed for each individual use case, CameraX also implements the following interfaces to support camera operations common to all bound use cases:

    • CameraControl lets you configure common camera features.
    • CameraInfo lets you query the states of those common camera features.

    These are the supported camera features with CameraControl:

    • জুম
    • টর্চ
    • Focus and Metering (tap-to-focus)
    • এক্সপোজার ক্ষতিপূরণ

    Get instances of CameraControl and CameraInfo

    Retrieve instances of CameraControl and CameraInfo using the Camera object returned by ProcessCameraProvider.bindToLifecycle() . নিম্নলিখিত কোড একটি উদাহরণ দেখায়:

    কোটলিন

    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()

    For example, you can submit zoom and other CameraControl operations after calling bindToLifecycle() . After you stop or destroy the activity used to bind the camera instance, CameraControl can no longer execute operations and returns a failed ListenableFuture .

    জুম

    CameraControl offers two methods for changing the zoom level:

    • setZoomRatio() sets the zoom by the zoom ratio.

      The ratio must be within the range of CameraInfo.getZoomState().getValue().getMinZoomRatio() and CameraInfo.getZoomState().getValue().getMaxZoomRatio() . Otherwise the function returns a failed ListenableFuture .

    • setLinearZoom() sets the current zoom with a linear zoom value ranging from 0 to 1.0.

      The advantage of linear zoom is that it makes the field of view (FOV) scale with changes in zoom. This makes it ideal for use with a Slider view.

    CameraInfo.getZoomState() returns a LiveData of the current zoom state. The value changes when the camera is initialized or if the zoom level is set using setZoomRatio() or setLinearZoom() . Calling either method sets the values backing ZoomState.getZoomRatio() and ZoomState.getLinearZoom() . This is helpful if you want to display zoom ratio text alongside a slider. Simply observe the ZoomState LiveData to update both without needing to do a conversion.

    The ListenableFuture returned by both APIs offers the option for applications to be notified when a repeating request with the specified zoom value is completed. In addition, if you set a new zoom value while the previous operation is still executing, the previous zoom operation's ListenableFuture fails immediately.

    টর্চ

    CameraControl.enableTorch(boolean) enables or disables the torch (also known as the flashlight).

    CameraInfo.getTorchState() can be used to query the current torch state. You can check the value returned by CameraInfo.hasFlashUnit() to determine whether a torch is available. If not, calling CameraControl.enableTorch(boolean) causes the returned ListenableFuture to complete immediately with a failed result and sets the torch state to TorchState.OFF .

    When the torch is enabled, it remains on during photo and video capture regardless of the flashMode setting. The flashMode in ImageCapture works only when the torch is disabled.

    Focus and Metering

    CameraControl.startFocusAndMetering() triggers autofocus and exposure metering by setting AF/AE/AWB metering regions based on the given FocusMeteringAction. This is often used to implement the “tap to focus” feature in many camera applications.

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

    To begin, create a MeteringPoint using MeteringPointFactory.createPoint(float x, float y, float size) . A MeteringPoint represents a single point on the camera Surface . It's stored in a normalized form so that it can be easily converted to sensor coordinates for specifying AF/AE/AWB regions.

    The size of the MeteringPoint ranges from 0 to 1, with a default size of 0.15f. When calling MeteringPointFactory.createPoint(float x, float y, float size) , CameraX creates a rectangle region centered at (x, y) for the provided size .

    The following code demonstrates how to create a 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 and FocusMeteringAction

    To invoke startFocusAndMetering() , applications must build a FocusMeteringAction , which consists of one or more MeteringPoints with optional metering mode combinations from FLAG_AF , FLAG_AE , FLAG_AWB . The follow code demonstrates this usage:

    কোটলিন

    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)

    As shown in the preceding code, startFocusAndMetering() takes a FocusMeteringAction consisting of one MeteringPoint for AF/AE/AWB metering regions and another MeteringPoint for AF and AE only.

    Internally, CameraX converts it into Camera2 MeteringRectangles and sets the corresponding CONTROL_AF_REGIONS / CONTROL_AE_REGIONS / CONTROL_AWB_REGIONS parameters to the capture request.

    Since not every device supports AF/AE/AWB and multiple regions, CameraX executes the FocusMeteringAction with best effort. CameraX uses the maximum number of MeteringPoints supported, in the order that points were added. All MeteringPoints added after the maximum count are ignored. For example, if a FocusMeteringAction is supplied with 3 MeteringPoints on a platform supporting just 2, only the first 2 MeteringPoints are used. The final MeteringPoint is ignored by CameraX.

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

    Exposure compensation is useful when applications need to fine-tune exposure values (EV) beyond the auto exposure (AE) output result. Exposure compensation values are combined in the following way to determine the necessary exposure for current image conditions:

    Exposure = ExposureCompensationIndex * ExposureCompensationStep

    CameraX provides the Camera.CameraControl.setExposureCompensationIndex() function for setting the exposure compensation as an index value.

    Positive index values make the image brighter, while negative values dim the image. Applications can query the supported range by CameraInfo.ExposureState.exposureCompensationRange() described in the next section. If the value is supported, the returned ListenableFuture completes when the value is successfully enabled in the capture request; if the specified index is out of the supported range, setExposureCompensationIndex() causes the returned ListenableFuture to complete immediately with a failed result.

    CameraX keeps only the latest outstanding setExposureCompensationIndex() request, and calling the function multiple times before the previous request gets executed results in its cancellation.

    The following snippet sets an exposure compensation index and registers a callback for when the exposure change request has been executed:

    কোটলিন

    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() retrieves the current ExposureState including:

      • The supportability of exposure compensation control.
      • The current exposure compensation index.
      • The exposure compensation index range.
      • The exposure compensation step used in exposure compensation value calculation.

    For example, the following code initializes the settings for an exposure SeekBar with current ExposureState values:

    কোটলিন

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

    অতিরিক্ত সম্পদ

    To learn more about CameraX, consult the following additional resources.

    কোডল্যাব

  • Getting Started with CameraX
  • কোড নমুনা

  • CameraX sample apps
  • বিকাশকারী সম্প্রদায়

    Android CameraX Discussion Group