Yapılandırma seçenekleri

Her CameraX kullanım alanını, kullanım alanının farklı yönlerini kontrol etmek için yapılandıracaksınız.

Örneğin, görüntü yakalama için bir hedef en boy oranı ve bir flaş modu ayarlayabilirsiniz. Aşağıdaki kodda bir örnek gösterilmektedir:

Kotlin

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

Java

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

Bazı kullanım alanlarında, yapılandırma seçeneklerine ek olarak API'ler, kullanım alanı oluşturulduktan sonra ayarları dinamik olarak değiştirebilir. Bağımsız kullanım alanlarına özel yapılandırma hakkında bilgi için Önizleme uygulama, Görüntüleri analiz etme ve Görüntü yakalama konularına bakın.

CameraXConfig

KameraX'te, kolaylık sağlaması açısından çoğu kullanım senaryosuna uygun dahili yürütücüler ve işleyiciler gibi varsayılan yapılandırmalar bulunur. Ancak uygulamanızın özel gereksinimleri varsa veya bu yapılandırmaları özelleştirmeyi tercih ediyorsa bu amaca yönelik arayüz CameraXConfig'dir.

CameraXConfig ile bir uygulama şunları yapabilir:

Kullanım Modeli

Aşağıdaki prosedürde CameraXConfig özelliğinin nasıl kullanılacağı açıklanmaktadır:

  1. Özelleştirilmiş yapılandırmalarınızla bir CameraXConfig nesnesi oluşturun.
  2. CameraXConfig.Provider arayüzünü Application'inize uygulayın ve CameraXConfig nesnenizi getCameraXConfig() içinde döndürün.
  3. Burada açıklandığı şekilde Application sınıfınızı AndroidManifest.xml dosyanıza ekleyin.

Örneğin, aşağıdaki kod örneği CameraX günlük kaydını yalnızca hata mesajlarıyla kısıtlar:

Kotlin

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

Uygulamanızın, ayarladıktan sonra CameraX yapılandırmasını bilmesi gerekiyorsa CameraXConfig nesnesinin yerel bir kopyasını saklayın.

Kamera sınırlayıcı

ProcessCameraProvider.getInstance() ilk çağrısı sırasında CameraX, cihazda kullanılabilen kameraların özelliklerini sıralar ve sorgular. KameraX'in donanım bileşenleriyle iletişim kurması gerektiğinden, bu işlem her kamera için, özellikle de düşük teknolojili cihazlarda çok önemli olmayan bir zaman alabilir. Uygulamanız cihazda yalnızca belirli kameraları (ör. varsayılan ön kamera) kullanıyorsa CameraX'i diğer kameraları yoksayacak şekilde ayarlayabilirsiniz. Bu, uygulamanızın kullandığı kameraların başlatma gecikmesini azaltabilir.

CameraXConfig.Builder.setAvailableCamerasLimiter() öğesine geçirilen CameraSelector bir kamerayı filtrelerse CameraX adlı kamera mevcut değilmiş gibi davranır. Örneğin, aşağıdaki kod, uygulamayı yalnızca cihazın varsayılan arka kamerasını kullanacak şekilde sınırlandırır:

Kotlin

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

Sohbetler

CameraX'in derlendiği platform API'lerinin çoğu, donanımla işlem arası iletişimin (IPC) engellenmesini gerektirir. Bu da, yanıt vermesi bazen yüzlerce milisaniye sürebilir. Bu nedenle CameraX, bu API'leri yalnızca arka plan iş parçacıklarından çağırır. Böylece ana iş parçacığı engellenmez ve kullanıcı arayüzü esnek kalır. CameraX, bu arka plan ileti dizilerini dahili olarak yöneterek bu davranışın şeffaf görünmesini sağlar. Ancak bazı uygulamalar, iş parçacıkları üzerinde sıkı bir denetim gerektirir. CameraXConfig, bir uygulamanın CameraXConfig.Builder.setCameraExecutor() ve CameraXConfig.Builder.setSchedulerHandler() aracılığıyla kullanılan arka plan ileti dizilerini ayarlamasına olanak tanır.

Kamera Yürütücü

Kamera yürütücü, tüm dahili Kamera platformu API çağrılarının yanı sıra bu API'lerden gelen geri çağırmalar için de kullanılır. CameraX, bu görevleri gerçekleştirmek için dahili bir Executor ayırır ve yönetir. Ancak, uygulamanız iş parçacıkları için daha sıkı kontrol gerektiriyorsa CameraXConfig.Builder.setCameraExecutor() kullanın.

Planlayıcı İşleyici

Planlayıcı işleyici, kamera kullanılamadığında kamerayı açmayı yeniden denemek gibi sabit aralıklarla dahili görevleri planlamak için kullanılır. Bu işleyici, işleri yürütmez ve yalnızca kamera yürütücüye gönderir. Ayrıca, bazen geri çağırmalar için Handler gerektiren eski API platformlarında da kullanılır. Bu durumlarda, geri çağırma işlevleri yine de yalnızca doğrudan kamera yürütücüye gönderilir. CameraX, bu görevleri gerçekleştirmek için dahili bir HandlerThread ayırır ve yönetir, ancak bunu CameraXConfig.Builder.setSchedulerHandler() ile geçersiz kılabilirsiniz.

Günlük kaydı

CameraX günlüğü, üretim kodunuzda ayrıntılı mesajlardan kaçınmak için iyi bir uygulama olabileceğinden, uygulamaların logcat mesajlarını filtrelemesine olanak tanır. CameraX, en ayrıntılıdan en şiddetliye kadar dört günlük kaydı düzeyini destekler:

  • Log.DEBUG (varsayılan)
  • Log.INFO
  • Log.WARN
  • Log.ERROR

Bu günlük düzeylerinin ayrıntılı açıklamaları için Android Günlüğü belgelerine bakın. Uygulamanıza uygun günlük kaydı düzeyini ayarlamak için CameraXConfig.Builder.setMinimumLoggingLevel(int) aracını kullanın.

Otomatik seçim

CameraX, uygulamanızın çalıştığı cihaza özgü işlevleri otomatik olarak sağlar. Örneğin, bir çözünürlük belirtmezseniz veya belirttiğiniz çözünürlük desteklenmiyorsa CameraX kullanılacak en iyi çözünürlüğü otomatik olarak belirler. Tüm bunlar kitaplık tarafından işlenerek cihaza özel kod yazma ihtiyacını ortadan kaldırır.

CameraX'in amacı bir kamera oturumunu başarıyla başlatmaktır. Bu da CameraX'in, cihaz kapasitesine dayalı olarak çözünürlük ve en boy oranlarından ödün verdiği anlamına gelir. Güvenlik ihlali şu nedenlerle gerçekleşebilir:

  • Cihaz, istenen çözünürlüğü desteklemiyor.
  • Cihazda, doğru çalışmak için belirli çözünürlükler gerektiren eski cihazlar gibi uyumluluk sorunları varsa.
  • Bazı cihazlarda belirli biçimler yalnızca belirli en boy oranlarında kullanılabilir.
  • Cihazın JPEG veya video kodlaması için "en yakın mod16" tercihi var. Daha fazla bilgi için SCALER_STREAM_CONFIGURATION_MAP sayfasını inceleyin.

KameraX oturumu oluşturup yönetse de her zaman kodunuzdaki kullanım alanı çıkışında döndürülen resim boyutlarını kontrol edin ve gerekli ayarlamaları yapın.

Döndürme

Varsayılan olarak kamera dönüşü, kullanım alanı oluşturulurken varsayılan ekranın dönüşüne uyacak şekilde ayarlanır. Bu varsayılan durumda CameraX, uygulamanın önizlemede görmeyi beklediğinizle eşleşmesini sağlamak için çıkışlar üretir. Kullanım alanı nesnelerini yapılandırırken mevcut ekran yönünü veya oluşturulduktan sonra dinamik olarak ileterek, çok ekranlı cihazları desteklemek için rotasyonu özel bir değere ayarlayabilirsiniz.

Uygulamanız, yapılandırma ayarlarını kullanarak hedef rotasyonu ayarlayabilir. Ardından, yaşam döngüsü çalışır durumda olsa bile kullanım alanı API'lerindeki (ImageAnalysis.setTargetRotation() gibi) yöntemleri kullanarak rotasyon ayarlarını güncelleyebilir. Bu özelliği, uygulama dikey moda kilitlendiğinde ve döndürme sırasında yeniden yapılandırma olmadığında kullanabilirsiniz. Ancak, fotoğraf veya analiz kullanım alanının cihazın geçerli dönüşünü bilmesi gerekir. Örneğin, yüz algılamada yüzlerin doğru olması veya fotoğrafların yatay ya da dikey olarak ayarlanması için döndürme farkındalığı gerekebilir.

Çekilen görüntülere ait veriler, döndürme bilgileri olmadan saklanabilir. EXIF verileri, galeri uygulamalarının resmi kaydettikten sonra doğru yönde gösterebilmesi için döndürme bilgileri içerir.

Önizleme verilerini doğru yönde görüntülemek için Preview.PreviewOutput()'teki meta veri çıkışını kullanarak dönüşümler oluşturabilirsiniz.

Aşağıdaki kod örneğinde, bir yön etkinliğinde döndürmenin nasıl ayarlanacağı gösterilmektedir:

Kotlin

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

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

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

Java

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

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

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

           imageCapture.setTargetRotation(rotation);
       }
    };

    orientationEventListener.enable();
}

Ayarlanan rotasyona bağlı olarak her kullanım alanı, resim verilerini doğrudan döndürür veya döndürülmemiş resim verilerinin tüketicilerine rotasyon meta verileri sağlar.

  • Önizleme: Hedef çözünürlüğün rotasyonunun Preview.getTargetRotation() kullanılarak bilinmesi için meta veri çıkışı sağlanır.
  • ImageAnalysis: Resim arabelleği koordinatlarının ekran koordinatlarına göre bilinmesi için meta veri çıkışı sağlanır.
  • ImageCapture: Resim EXIF meta verileri, arabelleği veya hem arabelleği hem de meta verileri, döndürme ayarına dikkat etmek için değiştirilir. Değiştirilen değer, HAL uygulamasına bağlıdır.

Kırpma dikdörtgeni

Varsayılan olarak kırpma dikdörtgeni tam arabellek alanıdır. ViewPort ve UseCaseGroup ile özelleştirebilirsiniz. KameraX, kullanım alanlarını gruplandırarak ve görüntü alanını ayarlayarak gruptaki tüm kullanım alanlarının kırpma alanlarının kamera sensöründe aynı alanı işaret etmesini garanti eder.

Aşağıdaki kod snippet'inde bu iki sınıfın nasıl kullanılacağı gösterilmektedir:

Kotlin

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

Java

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

ViewPort, son kullanıcıların görebildiği arabellek kaynağını tanımlar. Daha sonra CameraX, görüntü alanının özelliklerine ve ekli kullanım alanlarına dayanarak mümkün olan en büyük kırpma alanını hesaplar. Genellikle WYSIWYG etkisi elde etmek için görüntü alanını, önizleme kullanım alanına göre yapılandırabilirsiniz. Görüntü alanını almanın basit bir yolu PreviewView kullanmaktır.

Aşağıdaki kod snippet'lerinde ViewPort nesnesinin nasıl alınacağı gösterilmektedir:

Kotlin

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

Java

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

Yukarıdaki örnekte, uygulamanın ImageAnalysis ve ImageCapture değerlerinden elde ettiği değer, son kullanıcının PreviewView ürününde gördüğü değerle eşleşir (PreviewView öğesinin ölçek türünün varsayılan değer (FILL_CENTER) olarak ayarlandığı varsayılır. Kırpma alanı ve döndürme işlemi çıkış arabelleğine uygulandıktan sonra, tüm kullanım durumlarındaki görüntü aynıdır ancak muhtemelen farklı çözünürlüklere sahiptir. Dönüştürme bilgilerinin nasıl uygulanacağı hakkında daha fazla bilgi için çıkışı dönüştürme bölümüne bakın.

Kamera seçimi

CameraX, uygulamanızın gereksinimleri ve kullanım alanlarına en uygun kamera cihazını otomatik olarak seçer. Sizin için seçilenden farklı bir cihaz kullanmak istiyorsanız birkaç seçeneğiniz vardır:

Aşağıdaki kod örneğinde, cihaz seçimini etkilemek için nasıl CameraSelector oluşturulacağı gösterilmektedir:

Kotlin

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

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

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

Aynı anda birden fazla kamera seçme

CameraX 1.3 sürümünden itibaren, aynı anda birden fazla kamera da seçebilirsiniz. Örneğin, aynı anda her iki açıdan fotoğraf çekmek veya video kaydetmek için ön ve arka kameraya bağlanabilirsiniz.

Eşzamanlı Kamera özelliği kullanılırken cihaz, aynı anda farklı lenslere sahip iki kamerayı veya aynı anda arka iki kamerayı kullanabilir. Aşağıdaki kod bloğunda, bindToLifecycle çağrılırken iki kameranın nasıl ayarlanacağı ve döndürülen ConcurrentCamera nesnesinden her iki Kamera nesnesinin nasıl alınacağı gösterilmektedir.

Kotlin

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

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

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

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

Java

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

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

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

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

Kamera çözünürlüğü

KameraX'in görüntü çözünürlüğünü cihaz özellikleri, cihazın desteklenen donanım düzeyi, kullanım alanı ve sağlanan en boy oranı kombinasyonuna göre ayarlamasına izin verebilirsiniz. Alternatif olarak, kullanım alanlarında bu yapılandırmayı destekleyen belirli bir hedef çözünürlük veya belirli bir en boy oranı ayarlayabilirsiniz.

Otomatik çözünürlük

CameraX, cameraProcessProvider.bindToLifecycle() özelliğinde belirtilen kullanım alanlarına göre en iyi çözünürlük ayarlarını otomatik olarak belirleyebilir. Mümkün olduğunda, tek bir bindToLifecycle() çağrısında tek bir oturumda eşzamanlı olarak çalışmak için gereken tüm kullanım alanlarını belirtin. CameraX, çözünürlükleri, cihazın desteklenen donanım düzeyini göz önünde bulundurarak ve cihaza özgü varyansı (bir cihazın mevcut akış yapılandırmalarını aştığı veya karşılamadığı durumlarda) hesaba katarak bağlı olan kullanım alanları grubuna göre belirler. Amaç, uygulamanın çok çeşitli cihazlarda çalışmasını sağlarken cihaza özel kod yollarını en aza indirmektir.

Görüntü yakalama ve görüntü analizi kullanım alanları için varsayılan en boy oranı 4:3'tür.

Kullanım alanları, uygulamanın kullanıcı arayüzü tasarımına göre istenen en boy oranını belirtmesi için yapılandırılabilir bir en boy oranına sahiptir. CameraX çıkışı, istenen en boy oranları cihazın desteklediği en boy oranıyla eşleşecek şekilde üretilir. Tam eşleşme çözünürlüğü desteklenmiyorsa en fazla koşulu karşılayan çözünürlük seçilir. Bu nedenle, kameranın uygulamada nasıl görüneceğini uygulama belirler. CameraX ise farklı cihazlarda bunu karşılayacak en iyi kamera çözünürlüğü ayarlarını belirler.

Örneğin, bir uygulama aşağıdakilerden herhangi birini yapabilir:

  • Kullanım alanı için 4:3 veya 16:9 hedef çözünürlüğü belirtin
  • CameraX'in en yakın eşleşmeyi bulmaya çalışacağı özel bir çözünürlük belirtin
  • ImageCapture için kırpma en boy oranı belirtin

CameraX, dahili Camera2 yüzey çözünürlüklerini otomatik olarak seçer. Aşağıdaki tabloda çözünürlükler gösterilmektedir:

Kullanım alanı Dahili yüzey çözünürlüğü Çıkış verilerinin çözünürlüğü
Önizle En Boy Oranı: Hedefe en uygun çözünürlük. Dahili yüzey çözünürlüğü. Meta veriler, Görünüm'ün hedef en boy oranına göre kırpma, ölçeklendirme ve döndürme işlemleri yapabilmesi için sağlanır.
Varsayılan çözünürlük: Önizlemenin en boy oranıyla eşleşen en yüksek önizleme çözünürlüğü veya cihaz tarafından tercih edilen en yüksek çözünürlük.
Maksimum çözünürlük: Cihazın ekran çözünürlüğüyle en iyi eşleşen boyutu veya 1080p (1920x1080) için (hangisi daha küçükse) önizleme boyutu.
Görüntü analizi En boy oranı: Hedefle ayara en iyi uyan çözünürlük. Dahili yüzey çözünürlüğü.
Varsayılan çözünürlük: Varsayılan hedef çözünürlük ayarı 640x480'dir. Hem hedef çözünürlüğü hem de karşılık gelen en boy oranını ayarladığınızda en iyi desteklenen çözünürlük elde edilir.
Maksimum çözünürlük: Kamera cihazının StreamConfigurationMap.getOutputSizes() adresinden alınan YUV_420_888 biçiminde maksimum çıkış çözünürlüğüdür. Hedef çözünürlük varsayılan olarak 640x480 olarak ayarlanır. Bu nedenle, 640x480'den daha yüksek bir çözünürlük istiyorsanız desteklenen çözünürlüklerden en yakın olanı elde etmek için setTargetResolution() ve setTargetAspectRatio() kullanmanız gerekir.
Görüntü yakalama En boy oranı: Ayara en uygun en boy oranı. Dahili yüzey çözünürlüğü.
Varsayılan çözünürlük: Mevcut en yüksek çözünürlük veya ImageCapture'ın en boy oranıyla eşleşen, cihaz tarafından tercih edilen en yüksek çözünürlük.
Maksimum çözünürlük: Kamera cihazının JPEG biçimindeki maksimum çıkış çözünürlüğü. Bunu almak için StreamConfigurationMap.getOutputSizes() öğesini kullanın.

Çözünürlük belirtin

Kullanım alanları oluştururken aşağıdaki kod örneğinde gösterildiği gibi setTargetResolution(Size resolution) yöntemini kullanarak belirli çözünürlükler ayarlayabilirsiniz:

Kotlin

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

Java

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

Aynı kullanım alanında hem hedef en boy oranını hem de hedef çözünürlüğü ayarlayamazsınız. Bu işlem, yapılandırma nesnesini oluştururken bir IllegalArgumentException hatası verir.

Desteklenen boyutları hedef rotasyona göre döndürdükten sonra koordinat çerçevesinde Size çözünürlüğünü ifade edin. Örneğin, doğal hedef rotasyonunda dikey resim isteyen bir cihaz dikey resim isteyen bir cihazın 480x640 değerini belirtebilirken, aynı cihaz 90 derece döndürülmüş ve yatay hedefleme yönü 640x480 olarak belirtilebilir.

Hedef çözünürlük, görüntü çözünürlüğü için minimum sınır belirlemeye çalışır. Gerçek resim çözünürlüğü, Kamera uygulaması tarafından belirlendiği şekilde, hedef çözünürlükden küçük olmayan, kullanılabilir en yakın çözünürlükdür.

Ancak hedef çözünürlüğe eşit veya bundan daha büyük bir çözünürlük yoksa hedef çözünürlükten daha küçük olan en yakın çözünürlük seçilir. Sağlanan Size ile aynı en boy oranına sahip çözünürlüklere, farklı en boy oranlarındaki çözünürlüklerden daha yüksek öncelik verilir.

CameraX, isteklere göre en uygun çözünürlüğü uygular. Asıl ihtiyaç, en boy oranını karşılamaksa yalnızca setTargetAspectRatio değerini belirtin. KameraX, cihaza göre uygun belirli bir çözünürlük belirler. Uygulamanın birincil ihtiyacı, görüntü işlemeyi daha verimli hale getirmek için çözünürlük belirtmekse (örneğin, cihaz işleme özelliğine göre küçük veya orta boyutlu bir resim) setTargetResolution(Size resolution) kullanın.

Uygulamanız için tam bir çözünürlük gerekiyorsa her donanım düzeyinde hangi maksimum çözünürlüklerin desteklendiğini belirlemek için createCaptureSession() içindeki tabloya bakın. Mevcut cihazın desteklediği belirli çözünürlükleri kontrol etmek için StreamConfigurationMap.getOutputSizes(int) bölümüne bakın.

Uygulamanız Android 10 veya sonraki bir sürümde çalışıyorsa belirli bir SessionConfiguration sürümünü doğrulamak için isSessionConfigurationSupported() aracını kullanabilirsiniz.

Kamera çıkışını kontrol edin

CameraX, kamera çıkışını her bir kullanım alanı için gereken şekilde yapılandırmanıza olanak tanımanın yanı sıra tüm bağlı kullanım alanlarında ortak kamera işlemlerini desteklemek için aşağıdaki arayüzleri de uygular:

  • CameraControl, yaygın olarak kullanılan kamera özelliklerini yapılandırmanıza olanak tanır.
  • CameraInfo, bu yaygın kamera özelliklerinin durumlarını sorgulamanıza olanak tanır.

CameraControl'de desteklenen kamera özellikleri şunlardır:

  • Yakınlaştırma
  • Flaş
  • Odak ve Ölçme (dokunarak odaklama)
  • Pozlama Telafisi

CameraControl ve CameraInfo örneklerini alma

ProcessCameraProvider.bindToLifecycle() tarafından döndürülen Camera nesnesini kullanarak CameraControl ve CameraInfo örneklerini alın. Aşağıdaki kodda bir örnek gösterilmektedir:

Kotlin

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

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

Java

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

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

Örneğin, bindToLifecycle() çağırdıktan sonra yakınlaştırma ve diğer CameraControl işlemlerini gönderebilirsiniz. Kamera örneğini bağlamak için kullanılan etkinliği durdurmanızdan veya kaldırmanızdan sonra, CameraControl artık işlemleri yürütemez ve başarısız bir ListenableFuture döndürür.

Yakınlaştırma

CameraControl, yakınlaştırma seviyesini değiştirmek için iki yöntem sunar:

  • setZoomRatio(), yakınlaştırmayı yakınlaştırma oranına göre ayarlar.

    Oran, CameraInfo.getZoomState().getValue().getMinZoomRatio() ve CameraInfo.getZoomState().getValue().getMaxZoomRatio() aralığında olmalıdır. Aksi takdirde, işlev başarısız bir ListenableFuture döndürür.

  • setLinearZoom(), geçerli yakınlaştırmayı 0 ile 1,0 arasında değişen bir doğrusal yakınlaştırma değeriyle ayarlar.

    Doğrusal yakınlaştırmanın avantajı, zumda yapılan değişikliklerle görüş alanı (FOV) ölçeğini artırmasıdır. Bu nedenle, Slider görünümüyle kullanım için idealdir.

CameraInfo.getZoomState(), geçerli yakınlaştırma durumunun LiveData değerini döndürür. Değer, kamera başlatıldığında veya yakınlaştırma seviyesi setZoomRatio() ya da setLinearZoom() kullanılarak ayarlandığında değişir. İki yöntemden birinin çağrılması, ZoomState.getZoomRatio() ve ZoomState.getLinearZoom() değerlerini yedeklemeyi ayarlar. Bu, yakınlaştırma oranı metnini kaydırma çubuğuyla birlikte görüntülemek istediğinizde yararlı olur. Dönüşüm yapmanıza gerek kalmadan her ikisini de güncellemek için ZoomState LiveData ifadesini gözlemlemeniz yeterlidir.

Her iki API'nin döndürdüğü ListenableFuture, belirtilen yakınlaştırma değeriyle yinelenen bir istek tamamlandığında uygulamaların bilgilendirilmesi için seçenek sunar. Ayrıca, önceki işlem devam ederken yeni bir yakınlaştırma değeri ayarlarsanız önceki yakınlaştırma işleminin ListenableFuture değeri de anında başarısız olur.

Flaş

CameraControl.enableTorch(boolean), feneri (el feneri olarak da bilinir) etkinleştirir veya devre dışı bırakır.

Mevcut flaş durumunu sorgulamak için CameraInfo.getTorchState() kullanılabilir. Flaşın mevcut olup olmadığını belirlemek için CameraInfo.hasFlashUnit() tarafından döndürülen değeri kontrol edebilirsiniz. Aksi takdirde, CameraControl.enableTorch(boolean) çağrısı, döndürülen ListenableFuture parametresinin başarısız bir sonuçla hemen tamamlanmasına ve flaş durumunu TorchState.OFF olarak ayarlamasına neden olur.

Flaş etkinleştirildiğinde, flashMode ayarından bağımsız olarak fotoğraf ve video çekimi sırasında açık kalır. ImageCapture öğesindeki flashMode yalnızca flaş devre dışıyken çalışır.

Odak ve Ölçme

CameraControl.startFocusAndMetering(), belirtilen FocusMeteringAction'a göre AF/AE/AWB ölçüm bölgelerini ayarlayarak otomatik odaklamayı ve pozlama sayacını tetikler. Bu genellikle birçok kamera uygulamasında "odaklamak için dokun" özelliğini uygulamak için kullanılır.

Ölçüm Noktası

Başlamak için MeteringPointFactory.createPoint(float x, float y, float size) kullanarak bir MeteringPoint oluşturun. MeteringPoint, Surface kameradaki tek bir noktayı temsil eder. AF/AE/AWB bölgelerini belirtmek üzere kolayca sensör koordinatlarına dönüştürülebilmesi için normalleştirilmiş bir biçimde saklanır.

MeteringPoint öğesinin boyutu, varsayılan boyutu 0,15f olacak şekilde 0 ile 1 arasında değişir. MeteringPointFactory.createPoint(float x, float y, float size) çağrılırken CameraX, sağlanan size için (x, y) merkezinde ortalanmış bir dikdörtgen bölge oluşturur.

Aşağıdaki kodda MeteringPoint özelliğinin nasıl oluşturulacağı gösterilmektedir:

Kotlin

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

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

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

startFocusAndMetering ve FocusMeteringAction

startFocusAndMetering()'yi çağırmak için uygulamaların bir FocusMeteringAction derlemesi gerekir. Bu FocusMeteringAction, bir veya daha fazla MeteringPoints ile FLAG_AF, FLAG_AE ve FLAG_AWB şeklindeki isteğe bağlı sayaç modu kombinasyonlarından oluşur. Aşağıdaki kod bu kullanımı gösterir:

Kotlin

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

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

Önceki kodda gösterildiği gibi startFocusAndMetering(), AF/AE/AWB ölçüm bölgeleri için bir MeteringPoint, yalnızca AF ve AE için başka bir MeteringPoint'ten oluşan FocusMeteringAction alır.

KameraX dahili olarak bunu Camera2'ye MeteringRectangles dönüştürür ve ilgili CONTROL_AF_REGIONS / CONTROL_AE_REGIONS / CONTROL_AWB_REGIONS parametrelerini yakalama isteğine ayarlar.

Her cihaz AF/AE/AWB ve birden çok bölgeyi desteklemediğinden, CameraX FocusMeteringAction işlemini en iyi şekilde gerçekleştirir. CameraX, noktaların eklendiği sırayla desteklenen maksimum MeteringPoint sayısını kullanır. Maksimum sayıdan sonra eklenen tüm MeteringPoint'ler yoksayılır. Örneğin, yalnızca 2 metriği destekleyen bir platformda 3 MeteringPoints ile FocusMeteringAction sağlanırsa yalnızca ilk 2 MeteringPoint kullanılır. Son MeteringPoint, CameraX tarafından yok sayılır.

Pozlama Telafisi

Uygulamaların otomatik pozlama (AE) çıkış sonucunun ötesinde pozlama değerlerinde (EV) ince ayar yapması gerektiğinde pozlama dengelemesi faydalıdır. Pozlama dengelemesi değerleri, mevcut resim koşulları için gerekli pozlamanın belirlenmesi amacıyla aşağıdaki şekilde birleştirilir:

Exposure = ExposureCompensationIndex * ExposureCompensationStep

CameraX, pozlama telafisini dizin değeri olarak ayarlamak için Camera.CameraControl.setExposureCompensationIndex() işlevini sağlar.

Pozitif dizin değerleri resmi daha parlak hale getirirken negatif değerler resmi kararır. Uygulamalar, desteklenen aralığı bir sonraki bölümde açıklanan şekilde CameraInfo.ExposureState.exposureCompensationRange() ile sorgulayabilir. Değer destekleniyorsa yakalama isteğinde değer başarıyla etkinleştirildiğinde döndürülen ListenableFuture tamamlanır. Belirtilen dizin desteklenen aralığın dışındaysa setExposureCompensationIndex() işlevi, döndürülen ListenableFuture işlevinin başarısız bir sonuçla hemen tamamlanmasına neden olur.

CameraX, yalnızca bekleyen en son setExposureCompensationIndex() isteğini tutar ve önceki istek yürütülmeden önce işlevin birden fazla kez çağrılması sonucunda iptal olur.

Aşağıdaki snippet, bir karşılaşma tazminatı dizini ayarlar ve karşılaşma değişikliği isteği yürütüldüğünde bir geri çağırma kaydeder:

Kotlin

camera.cameraControl.setExposureCompensationIndex(exposureCompensationIndex)
   .addListener({
      // Get the current exposure compensation index, it might be
      // different from the asked value in case this request was
      // canceled by a newer setting request.
      val currentExposureIndex = camera.cameraInfo.exposureState.exposureCompensationIndex
      …
   }, mainExecutor)
  • Camera.CameraInfo.getExposureState(), aşağıdakiler dahil mevcut ExposureState özelliğini alır:

    • Pozlama dengeleme kontrolünün desteklenebilirliği.
    • Geçerli pozlama dengeleme dizini.
    • Pozlama telafisi dizini aralığı.
    • Pozlama telafisi değeri hesaplamasında kullanılan pozlama dengeleme adımı.

Örneğin, aşağıdaki kod, geçerli ExposureState değerlerine sahip bir karşılaşma SeekBar ayarlarını başlatır:

Kotlin

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

Ek kaynaklar

CameraX hakkında daha fazla bilgi edinmek için aşağıdaki ek kaynaklara bakın.

Kod Laboratuvarı

  • CameraX'i Kullanmaya Başlama
  • Kod örneği

  • CameraX örnek uygulamaları
  • Geliştirici topluluğu

    Android CameraX Tartışma Grubu