Her bir CameraX kullanım alanını, kullanım alanı işlemlerinin farklı yönlerini kontrol edecek şekilde yapılandırırsınız.
Örneğin, Resim Yakalama kullanım alanında hedef en boy oranı ve 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();
Yapılandırma seçeneklerine ek olarak bazı kullanım alanları, kullanım alanı oluşturulduktan sonra ayarları dinamik olarak değiştirmek için API'leri kullanıma sunar. Kullanım alanlarına özel yapılandırma hakkında bilgi edinmek için Önizleme uygulama, Resimleri analiz etme ve Resim yakalama başlıklı makaleleri inceleyin.
CameraXConfig
CameraX, kullanım kolaylığı için çoğu kullanım senaryosuna uygun dahili yürütücüler ve işleyiciler gibi varsayılan yapılandırmalara sahiptir. Ancak uygulamanızın özel gereksinimleri varsa veya bu yapılandırmaları özelleştirmek istiyorsanız CameraXConfig arayüzünü kullanabilirsiniz.
CameraXConfig ile bir uygulama şunları yapabilir:
setAvailableCameraLimiter()ile başlatma gecikmesini optimize edin.setCameraExecutor()ile uygulamanın yürütücüsünü CameraX'e sağlayın.- Varsayılan programlayıcı işleyiciyi
setSchedulerHandler()ile değiştirin. - Günlük kaydı düzeyini
setMinimumLoggingLevel()ile değiştirin.
Kullanım Modeli
Aşağıdaki prosedürde CameraXConfig aracının nasıl kullanılacağı açıklanmaktadır:
- Özelleştirilmiş yapılandırmalarınızla bir
CameraXConfignesnesi oluşturun. ApplicationiçindeCameraXConfig.Providerarayüzünü uygulayın vegetCameraXConfig()içindeCameraXConfignesnenizi döndürün.- Burada açıklandığı şekilde
ApplicationsınıfınızıAndroidManifest.xmldosyanıza ekleyin.
Örneğin, aşağıdaki kod örneği CameraX günlük kaydını yalnızca hata mesajlarıyla sınırlandırır:
Kotlin
class CameraApplication : Application(), CameraXConfig.Provider { override fun getCameraXConfig(): CameraXConfig { return CameraXConfig.Builder.fromConfig(Camera2Config.defaultConfig()) .setMinimumLoggingLevel(Log.ERROR).build() } }
Uygulamanızın, ayarlandı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 kez çağrıldığında CameraX, cihazdaki kameraları listeler ve özelliklerini sorgular. CameraX'in donanım bileşenleriyle iletişim kurması gerektiğinden bu işlem, özellikle düşük kaliteli cihazlarda her kamera için önemli miktarda zaman alabilir. Uygulamanız cihazda yalnızca varsayılan ön kamera gibi belirli kameraları kullanıyorsa CameraX'i diğer kameraları yoksayacak şekilde ayarlayabilirsiniz. Bu sayede, uygulamanızın kullandığı kameraların başlatma gecikmesi azaltılabilir.
CameraXConfig.Builder.setAvailableCamerasLimiter() yöntemine iletilen CameraSelector bir kamerayı filtrelerse CameraX, o kamera yokmuş 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() } }
İleti Dizileri
CameraX'in üzerine inşa edildiği platform API'lerinin çoğu, yanıt vermesi bazen yüzlerce milisaniye sürebilen donanımlarla işlemler arası iletişimin (IPC) engellenmesini gerektirir. 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ü akıcı kalır. CameraX, bu arka plan iş parçacıklarını dahili olarak yönetir. Böylece bu davranış şeffaf görünür. Ancak bazı uygulamalar, iş parçacıklarının sıkı bir şekilde kontrol edilmesini gerektirir. CameraXConfig, bir uygulamanın CameraXConfig.Builder.setCameraExecutor() ve CameraXConfig.Builder.setSchedulerHandler() aracılığıyla kullanılan arka plan iş parçacıklarını ayarlamasına olanak tanır.
Camera Executor
Kamera yürütücüsü, tüm dahili Kamera platformu API çağrıları ve bu API'lerden gelen geri çağırmalar için kullanılır. CameraX, bu görevleri gerçekleştirmek için dahili bir Executor tahsis eder ve yönetir.
Ancak uygulamanız ileti dizileri üzerinde daha sıkı kontrol gerektiriyorsa CameraXConfig.Builder.setCameraExecutor() kullanın.
Zamanlayıcı İşleyici
Zamanlayıcı işleyici, dahili görevleri sabit aralıklarla planlamak için kullanılır.
Örneğin, kamera kullanılamadığında kamerayı açmayı yeniden denemek için kullanılır. Bu işleyici, işleri yürütmez ve yalnızca kamera yürütücüsüne gönderir. Ayrıca bazen geri çağırmalar için Handler gerektiren eski API platformlarında da kullanılır. Bu durumlarda geri çağırmalar yalnızca doğrudan kamera yürütücüsüne 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ük kaydı, uygulamaların logcat mesajlarını filtrelemesine olanak tanır. Bu, üretim kodunuzda ayrıntılı mesajlardan kaçınmak için iyi bir yöntem olabilir. CameraX, en ayrıntılıdan en ciddi düzeye kadar dört günlük kaydı düzeyini destekler:
Log.DEBUG(varsayılan)Log.INFOLog.WARNLog.ERROR
Bu günlük düzeylerinin ayrıntılı açıklamaları için Android Günlüğü belgelerini inceleyin. Uygulamanız için uygun günlük kaydı düzeyini ayarlamak üzere CameraXConfig.Builder.setMinimumLoggingLevel(int) kullanın.
Otomatik seçim
CameraX, uygulamanızın çalıştığı cihaza özel işlevleri otomatik olarak sağlar. Örneğin, CameraX bir çözünürlük belirtmezseniz veya belirttiğiniz çözünürlük desteklenmiyorsa kullanılacak en iyi çözünürlüğü otomatik olarak belirler. Tüm bunlar kitaplık tarafından gerçekleştirilir. Böylece cihaza özel kod yazmanıza gerek kalmaz.
CameraX'in amacı, kamera oturumunu başarıyla başlatmaktır. Yani CameraX, cihazın özelliklerine göre çözünürlük ve en boy oranlarından ödün verir. Güvenlik ihlali aşağıdaki nedenlerle gerçekleşebilir:
- Cihaz, istenen çözünürlüğü desteklemiyor.
- Cihazda uyumluluk sorunları varsa (ör. doğru şekilde çalışması için belirli çözünürlükler gerektiren eski cihazlar)
- Bazı cihazlarda, belirli biçimler yalnızca belirli en boy oranlarında kullanılabilir.
- Cihaz, JPEG veya video kodlama için "en yakın mod16" tercihine sahiptir. Daha fazla bilgi için
SCALER_STREAM_CONFIGURATION_MAPkonusuna bakın.
Oturumu CameraX oluşturup yönetse de kodunuzdaki kullanım alanı çıkışında döndürülen resim boyutlarını her zaman kontrol edin ve buna göre ayarlayın.
Döndürme
Kullanım alanı oluşturulurken kamera dönüşü, varsayılan ekranın dönüşüyle eşleşecek şekilde ayarlanır. Bu varsayılan durumda CameraX, uygulamanın önizlemede görmeyi beklediğinizle eşleşmesini sağlayacak çıkışlar üretir. Kullanım alanı nesnelerini yapılandırırken veya oluşturulduktan sonra dinamik olarak mevcut ekran yönünü ileterek çoklu ekran cihazlarını desteklemek için dönüşü özel bir değerle değiştirebilirsiniz.
Uygulamanız, yapılandırma ayarlarını kullanarak hedef dönüşü ayarlayabilir. Ardından, yaşam döngüsü çalışır durumdayken bile kullanım alanı API'lerindeki yöntemleri (ör. ImageAnalysis.setTargetRotation()) kullanarak rotasyon ayarlarını güncelleyebilir. Uygulama portre moduna kilitliyken ve bu nedenle döndürme sırasında yeniden yapılandırma gerçekleşmediğinde, ancak fotoğraf veya analiz kullanım alanının cihazın mevcut dönüşünden haberdar olması gerektiğinde bunu kullanabilirsiniz. Örneğin, yüz algılama için yüzlerin doğru şekilde yönlendirilmesi veya fotoğrafların yatay ya da dikey olarak ayarlanması için dönüş farkındalığı gerekebilir.
Çekilen resimlerin verileri, döndürme bilgileri olmadan depolanabilir. Exif verileri, galeri uygulamalarının resmi kaydettikten sonra doğru yönde gösterebilmesi için döndürme bilgilerini içerir.
Önizleme verilerini doğru yönlendirmeyle görüntülemek için Preview.PreviewOutput() tarafından sağlanan meta veri çıkışını kullanarak dönüşümler oluşturabilirsiniz.
Aşağıdaki kod örneğinde, bir yönlendirme etkinliğinde dönüşün 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 dönüşünün
Preview.getTargetRotation()kullanılarak bilinmesi için meta veri çıkışı sağlanır. - ImageAnalysis: Görüntü arabelleği koordinatlarının ekran koordinatlarına göre bilinmesi için meta veri çıkışı sağlanır.
- ImageCapture: Resim Exif meta verileri, arabellek veya hem arabellek hem de meta veriler, döndürme ayarını belirtmek 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 dikdörtgenidir. ViewPort ve UseCaseGroup ile özelleştirebilirsiniz. CameraX, kullanım alanlarını gruplandırıp görüntü alanını ayarlayarak gruptaki tüm kullanım alanlarının kırpma dikdörtgenlerinin kamera sensöründe aynı alanı işaret etmesini sağlar.
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ılara gösterilen tampon dikdörtgeni tanımlar. Ardından CameraX, görüntü alanının ve ekli kullanım alanlarının özelliklerine göre mümkün olan en büyük kırpma dikdörtgenini hesaplar. Genellikle WYSIWYG efekti 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 öğelerinden aldığı değerler, son kullanıcının PreviewView öğesinde gördüğü değerlerle eşleşir. Bu örnekte, PreviewView öğesinin ölçek türünün varsayılan değer olan FILL_CENTER olarak ayarlandığı varsayılmıştır. Kırpma dikdörtgeni ve döndürme, çıkış arabelleğine uygulandıktan sonra tüm kullanım alanlarındaki görüntü aynı olur ancak çözünürlükleri farklı olabilir. Dönüşüm bilgilerinin nasıl uygulanacağı hakkında daha fazla bilgi için dönüşüm çıkışı bölümüne bakın.
Kamera seçimi
CameraX, uygulamanızın gereksinimleri ve kullanım alanları için en iyi kamera cihazını otomatik olarak seçer. Sizin için seçilen cihazdan farklı bir cihaz kullanmak istiyorsanız birkaç seçeneğiniz vardır:
CameraSelector.DEFAULT_FRONT_CAMERAile varsayılan ön kamerayı isteyin.CameraSelector.DEFAULT_BACK_CAMERAile varsayılan arka kamerayı isteyin.- Kullanılabilir cihazların listesini
CameraSelector.Builder.addCameraFilter()ileCameraCharacteristicsölçütüne göre filtreleyin.
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'ten itibaren aynı anda birden fazla kamera da seçebilirsiniz. Örneğin, aynı anda her iki perspektiften fotoğraf çekmek veya video kaydetmek için ön ve arka kameraya bağlanabilirsiniz.
Eşzamanlı Kamera özelliği kullanılırken cihaz, farklı yönlere bakan lenslere sahip iki kamerayı veya iki arka kamerayı aynı anda çalıştırabilir. 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üğü
CameraX'in görüntü çözünürlüğünü cihaz özelliklerinin, cihazın desteklediği donanım seviyesinin, kullanım alanının ve sağlanan en boy oranının bir kombinasyonuna göre ayarlamasını seçebilirsiniz. Alternatif olarak, bu yapılandırmayı destekleyen kullanım alanlarında belirli bir hedef çözünürlük veya belirli bir en-boy oranı ayarlayabilirsiniz.
Otomatik çözünürlük
CameraX, cameraProcessProvider.bindToLifecycle() iç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 oturumda eşzamanlı olarak çalıştırılması gereken tüm kullanım alanlarını tek bir bindToLifecycle() çağrısında belirtin. CameraX, çözünürlükleri cihazın desteklenen donanım seviyesini dikkate alarak ve cihaza özgü farklılıkları (cihazın mevcut akış yapılandırmalarını aştığı veya karşılamadığı durumlar) hesaba katarak bağlı kullanım alanları grubuna göre belirler.
Amaç, cihaza özgü kod yollarını en aza indirirken uygulamanın çok çeşitli cihazlarda çalışmasını sağlamaktır.
Resim 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ı belirtebilmesi için yapılandırılabilir bir en boy oranına sahiptir. CameraX çıkışı, istenen en boy oranlarıyla cihazın desteklediği ölçüde eşleşecek şekilde üretilir. Tam eşleşen bir çözünürlük desteklenmiyorsa en fazla koşulu karşılayan çözünürlük seçilir. Bu nedenle, uygulamanın kameranın uygulamada nasıl görüneceğini belirlemesi gerekir. CameraX, farklı cihazlarda bu gereksinimi karşılayacak en iyi kamera çözünürlüğü ayarlarını belirler.
Örneğin, bir uygulama aşağıdakilerden herhangi birini yapabilir:
- Bir kullanım alanı için 4:3 veya 16:9 hedef çözünürlük belirtme
- CameraX'in en yakın eşleşmeyi bulmaya çalıştığı özel bir çözünürlük belirtin.
ImageCaptureiç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ış verisi çözünürlüğü |
|---|---|---|
| Önizle | En Boy Oranı: Hedefi ayara en iyi şekilde uyduran çözünürlük. | Dahili yüzey çözünürlüğü. Meta veriler, bir görünümün hedef en boy oranı için kırpılması, ölçeklendirilmesi ve döndürülmesi amacıyla sağlanır. |
| Varsayılan çözünürlük: En yüksek önizleme çözünürlüğü veya önizlemenin en-boy oranıyla eşleşen, 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 boyut veya 1080p (1920x1080) (hangisi daha küçükse) olan önizleme boyutu. | ||
| Görüntü analizi | En boy oranı: Hedefi ayara en iyi şekilde uyduran çö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 ilgili en boy oranını ayarlamak, en iyi desteklenen çözünürlüğü sağlar. | ||
Maksimum çözünürlük: Kamera cihazının, StreamConfigurationMap.getOutputSizes() adresinden alınan YUV_420_888 biçimindeki maksimum çıkış çözünürlüğü.
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ükler arasından en yakın olanı elde etmek için setTargetResolution() ve setTargetAspectRatio() kullanmanız gerekir.
|
||
| Resim 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()
kullanın.
|
Çözünürlük belirtme
Aşağıdaki kod örneğinde gösterildiği gibi, setTargetResolution(Size resolution) yöntemini kullanarak kullanım alanları oluştururken 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. Bunu yaptığınızda, yapılandırma nesnesi oluşturulurken IllegalArgumentException hatası verilir.
Desteklenen boyutları hedef dönüşe göre döndürdükten sonra çözünürlüğü Size koordinat çerçevesinde ifade edin. Örneğin, doğal hedef rotasyonunda doğal dikey yönlendirmeye sahip bir cihaz, dikey resim isterken 480x640 değerini belirtebilir. Aynı cihaz, 90 derece döndürülüp yatay yönlendirmeyi hedeflediğinde 640x480 değerini belirtebilir.
Hedef çözünürlük, resim çözünürlüğü için minimum bir sınır belirlemeye çalışır. Gerçek görüntü çözünürlüğü, kamera uygulaması tarafından belirlenen hedef çözünürlükten küçük olmayan, boyuta göre mevcut en yakın çözünürlüktür.
Ancak hedef çözünürlüğe eşit veya ondan 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ına sahip çözünürlüklerden daha yüksek öncelik verilir.
CameraX, isteklere göre en uygun çözünürlüğü uygular. Öncelikli ihtiyaç en boy oranını karşılamaksa yalnızca setTargetAspectRatio değerini belirtin. CameraX, cihaza göre uygun bir çözünürlük belirler.
Uygulamanın birincil ihtiyacı, görüntü işlemeyi daha verimli hale getirmek için bir çözünürlük belirtmekse (ör. cihazın işleme kapasitesine göre küçük veya orta boyutlu bir resim) setTargetResolution(Size resolution) kullanın.
Uygulamanız tam bir çözünürlük gerektiriyorsa her donanım seviyesinin desteklediği maksimum çözünürlükleri belirlemek için createCaptureSession() bölümündeki 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 doğrulamak için isSessionConfigurationSupported() kullanabilirsiniz.
Kamera çıkışını kontrol etme
CameraX, kamera çıkışını her bir kullanım alanı için gerektiği gibi yapılandırmanıza olanak tanımanın yanı sıra, tüm bağlı kullanım alanlarında ortak olan kamera işlemlerini desteklemek için aşağıdaki arayüzleri de uygular:
CameraControl, yaygın kamera özelliklerini yapılandırmanıza olanak tanır.CameraInfo, bu yaygın kamera özelliklerinin durumlarını sorgulamanıza olanak tanır.
CameraControl ile desteklenen kamera özellikleri şunlardır:
- Zoom
- Desteklenen cihazlarda el feneri gücü dahil olmak üzere el feneri
- Desteklenen cihazlarda düşük ışık güçlendirmesi
- Odaklama ve ölçüm (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() yöntemini ç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 durdurduktan veya yok ettikten sonra CameraControl artık işlemleri yürütemez ve başarısız bir ListenableFuture döndürür.
Zoom
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()ileCameraInfo.getZoomState().getValue().getMaxZoomRatio()arasında olmalıdır. Aksi takdirde işlev, başarısız birListenableFuturedöndürür.setLinearZoom(), mevcut yakınlaştırmayı 0 ile 1,0 arasında değişen doğrusal bir yakınlaştırma değeriyle ayarlar.Doğrusal yakınlaştırmanın avantajı, görüş alanının (FOV) yakınlaştırmadaki değişikliklerle ölçeklenmesini sağlamasıdır. Bu nedenle,
Slidergörünümüyle kullanım için idealdir.
CameraInfo.getZoomState()
mevcut yakınlaştırma durumunun LiveData'sını döndürür. Kamera başlatıldığında veya yakınlaştırma seviyesi setZoomRatio() ya da setLinearZoom() kullanılarak ayarlandığında değer değişir. Bu yöntemlerden birini çağırmak, ZoomState.getZoomRatio() ve ZoomState.getLinearZoom() değerlerini ayarlar.
Bu özellik, yakınlaştırma oranı metnini bir kaydırma çubuğunun yanında göstermek istiyorsanız kullanışlıdır.
Dönüştürme yapmanıza gerek kalmadan her ikisini de güncellemek için ZoomState LiveData değerini gözlemlemeniz yeterlidir.
Her iki API tarafından döndürülen ListenableFuture, belirtilen yakınlaştırma değerine sahip yinelenen bir istek tamamlandığında uygulamaların bildirim almasını sağlar. Ayrıca, önceki işlem hâlâ yürütülürken yeni bir yakınlaştırma değeri ayarlarsanız önceki yakınlaştırma işleminin ListenableFuture değeri hemen başarısız olur.
Torch
CameraControl.enableTorch(boolean),
el fenerini etkinleştirir veya devre dışı bırakır.
CameraInfo.getTorchState()
mevcut fener durumunu sorgulamak için kullanılabilir. Bir fenerin 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 işleminin başarısız sonuçla hemen tamamlanmasına neden olur ve fener durumunu TorchState.OFF olarak ayarlar.
Fener etkinleştirildiğinde, flaş modu ayarından bağımsız olarak fotoğraf ve video çekimi sırasında açık kalır. ImageCapture.setFlashMode() ile ayarlanan flaş modu yalnızca fener devre dışı bırakıldığında çalışır.
Odak ve ölçüm
CameraControl.startFocusAndMetering(), verilen FocusMeteringAction değerine göre ölçüm bölgeleri ayarlayarak otomatik odaklama (AF), otomatik pozlama (AE) ve otomatik beyaz dengesi (AWB) ölçümünü tetikler. Kamera uygulamalarında dokunarak odaklama özelliğini uygulamak için bu yöntemi kullanabilirsiniz.
MeteringPoint
Başlamak için MeteringPointFactory.createPoint(float x, float y, float
size) kullanarak bir MeteringPoint oluşturun.
MeteringPoint, kameradaki tek bir noktayı temsil eder
Surface. AF/AE/AWB bölgelerini belirtmek için sensör koordinatlarına dönüştürülebilecek şekilde normalleştirilmiş bir biçimde depolanır.
MeteringPoint boyutu 0 ile 1 arasında değişir ve varsayılan boyutu 0, 15f'dir. MeteringPointFactory.createPoint(float x, float y, float
size) çağrıldığında CameraX, sağlanan size için (x, y) merkezli bir dikdörtgen bölge oluşturur.
Aşağıdaki kodda MeteringPoint oluşturma işlemi gösterilmektedir:
// Use PreviewView.getMeteringPointFactory if PreviewView is used for preview.
previewView.setOnTouchListener { view, motionEvent ->
if (motionEvent.action == MotionEvent.ACTION_UP) {
val meteringPoint = previewView.meteringPointFactory
.createPoint(motionEvent.x, motionEvent.y)
// Build and start a FocusMeteringAction with meteringPoint.
view.performClick()
}
true
}
// Use DisplayOrientedMeteringPointFactory if SurfaceView / TextureView is used
// for preview. 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 displayFactory = DisplayOrientedMeteringPointFactory(
surfaceView.display,
camera.cameraInfo,
surfaceView.width.toFloat(),
surfaceView.height.toFloat()
)
// Use SurfaceOrientedMeteringPointFactory if the point is specified in
// ImageAnalysis ImageProxy.
val surfaceFactory = SurfaceOrientedMeteringPointFactory(
imageWidth.toFloat(),
imageHeight.toFloat(),
imageAnalysis
)
startFocusAndMetering ve FocusMeteringAction
startFocusAndMetering()'ı çağırmak için uygulamaların, FLAG_AF, FLAG_AE ve FLAG_AWB'den isteğe bağlı ölçüm modu kombinasyonları içeren bir veya daha fazla MeteringPoint nesnesinden oluşan bir FocusMeteringAction oluşturması gerekir. Aşağıdaki kodda bu kullanım gösterilmektedir:
// meteringPointFactory is any MeteringPointFactory from the previous example.
val meteringPoint1 = meteringPointFactory.createPoint(x1, y1)
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 or 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))
Yukarıdaki kodda gösterildiği gibi,
startFocusAndMetering()
AF/AE/AWB ölçüm bölgeleri için bir MeteringPoint ve yalnızca AF ve AE için başka bir MeteringPoint içeren bir FocusMeteringAction alır.
Her cihaz AF/AE/AWB ve birden fazla bölgeyi desteklemediğinden CameraX, FocusMeteringAction işlemini en iyi şekilde yürütür. CameraX, desteklenen maksimum MeteringPoint nesne sayısını, noktaların eklendiği sırayla kullanır. Maksimum sayıdan sonra eklenen tüm noktalar yok sayılır. Örneğin, bir
FocusMeteringAction, yalnızca iki nesnesini destekleyen bir
platformda üç MeteringPoint nesnesiyle sağlanırsa yalnızca ilk iki nokta kullanılır. Son MeteringPoint, CameraX tarafından yok sayılır.
Pozlama telafisi
Pozlama telafisi, uygulamaların pozlama değerlerini (EV) otomatik pozlama (AE) çıkış sonucunun ötesinde hassas bir şekilde ayarlaması gerektiğinde kullanışlıdır. Pozlama telafisi değerleri, mevcut görüntü koşulları için gerekli pozlamayı belirlemek üzere aşağıdaki şekilde birleştirilir:
Exposure = ExposureCompensationIndex * ExposureCompensationStep
CameraX, pozlama telafisini dizin değeri olarak ayarlamak için CameraControl.setExposureCompensationIndex() işlevini sağlar.
Pozitif dizin değerleri görüntüyü daha parlak hale getirirken negatif değerler görüntüyü karartır. Uygulamalar, desteklenen aralığı ExposureState.getExposureCompensationRange() ile sorgulayabilir.
Değer destekleniyorsa döndürülen ListenableFuture, değer yakalama isteğinde başarıyla etkinleştirildiğinde tamamlanır. Belirtilen dizin desteklenen aralığın dışındaysa setExposureCompensationIndex(), döndürülen ListenableFuture'nin başarısız sonuçla hemen tamamlanmasına neden olur.
CameraX yalnızca en son bekleyen setExposureCompensationIndex() isteğini saklar. CameraX önceki isteği uygulamadan önce işlevi tekrar çağırırsanız CameraX önceki isteği iptal eder.
Aşağıdaki snippet, bir pozlama telafisi dizini ayarlar ve pozlama değişikliği isteği yürütüldüğünde bir geri çağırma kaydeder:
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
// Handle the updated exposure compensation index.
}, mainExecutor)
CameraInfo.getExposureState()mevcutExposureStatebilgilerini alır. Bu bilgiler şunlardır:- Pozlama telafisi kontrolünün desteklenebilirliği.
- Mevcut pozlama telafisi dizini.
- Pozlama telafisi dizini aralığı.
- Pozlama telafisi değeri hesaplamasında kullanılan pozlama telafisi adımı.
Örneğin, aşağıdaki kod, geçerli ExposureState değerleriyle bir pozlama SeekBar için ayarları başlatır. SeekBar ilerleme değeri 0'dan başladığı için kod, pozlama telafisi aralığının alt sınırına göre bu değeri dengeler:
val exposureState = camera.cameraInfo.exposureState
val range = exposureState.exposureCompensationRange
binding.seekBar.apply {
isEnabled = exposureState.isExposureCompensationSupported
max = range.upper - range.lower
progress = exposureState.exposureCompensationIndex - range.lower
setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
if (fromUser) {
camera.cameraControl.setExposureCompensationIndex(progress + range.lower)
}
}
override fun onStartTrackingTouch(seekBar: SeekBar) {}
override fun onStopTrackingTouch(seekBar: SeekBar) {}
})
}
Ek kaynaklar
CameraX hakkında daha fazla bilgi edinmek için aşağıdaki ek kaynaklara göz atın.
Codelab
Kod örneği
Geliştirici topluluğu
Android CameraX Tartışma Grubu