Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Camera Xライブラリの魅力と最新機能を紐解く

Dai
October 05, 2022

Camera Xライブラリの魅力と最新機能を紐解く

DroidKaigi2022で発表したスライドです

Dai

October 05, 2022
Tweet

More Decks by Dai

Other Decks in Programming

Transcript

  1. ࣗݾ঺հ • ٶຊେ • 5XJUUFS!EBJSPJE • (JUIVC%BJ • גࣜձࣾϚωʔϑΥϫʔυ •

    "OESPJEΤϯδχΞ • ϚωʔϑΥϫʔυϏδωεΧϯύχʔݸਓࣄۀओຊ෦ϓϩμΫτ։ൃ෦ • ΤϯδχΞϦϯάઓུࣨεϚʔτσόΠεΤΩεύʔτάϧʔϓ ݉຿ 2
  2. Χϝϥػೳͷ࣮૷ʹ࢖ΘΕ͖ͯͨ"1*ɾϥΠϒϥϦ 7 Android 4.4Ҏલ Android 5.0Ҏ߱ 2014೥ 2019೥ Camera API

    2 
 ϦϦʔε Camera Xൃද v1.0.0 Stable 
 ϦϦʔε 2021೥ 2022೥6݄ v1.1.0 Stable 
 ϦϦʔε 2022೥8݄ v1.2.0 Beta 
 ϦϦʔε Camera API 1 Intentܦ༝
  3. Χϝϥػೳͷ࣮૷ʹ࢖ΘΕ͖ͯͨ"1*ɾϥΠϒϥϦ 8 Android 4.4Ҏલ Android 5.0Ҏ߱ 2014೥ 2019೥ Camera API

    2 
 ϦϦʔε Camera Xൃද v1.0.0 Stable 
 ϦϦʔε 2021೥ 2022೥6݄ v1.1.0 Stable 
 ϦϦʔε 2022೥8݄ v1.2.0 Beta 
 ϦϦʔε Camera API 1 Intentܦ༝
  4. Χϝϥػೳͷ࣮૷ʹ࢖ΘΕ͖ͯͨ"1*ɾϥΠϒϥϦ 9 Android 4.4Ҏલ Android 5.0Ҏ߱ 2014೥ 2019೥ Camera API

    2 
 ϦϦʔε Camera Xൃද v1.0.0 Stable 
 ϦϦʔε 2021೥ 2022೥6݄ v1.1.0 Stable 
 ϦϦʔε 2022೥8݄ v1.2.0 Beta 
 ϦϦʔε Camera API 1 Intentܦ༝ Deprecated !
  5. Χϝϥػೳͷ࣮૷ʹ࢖ΘΕ͖ͯͨ"1*ɾϥΠϒϥϦ 10 Android 4.4Ҏલ Android 5.0Ҏ߱ 2014೥ 2019೥ Camera API

    2 
 ϦϦʔε Camera Xൃද v1.0.0 Stable 
 ϦϦʔε 2021೥ 2022೥6݄ v1.1.0 Stable 
 ϦϦʔε 2022೥8݄ v1.2.0 Beta 
 ϦϦʔε Camera API 1 Intentܦ༝
  6. Χϝϥػೳͷ࣮૷ʹ࢖ΘΕ͖ͯͨ"1*ɾϥΠϒϥϦ 11 Android 4.4Ҏલ Android 5.0Ҏ߱ 2014೥ 2019೥ Camera API

    2 
 ϦϦʔε Camera Xൃද v1.0.0 Stable 
 ϦϦʔε 2021೥ 2022೥6݄ v1.1.0 Stable 
 ϦϦʔε 2022೥8݄ v1.2.0 Beta 
 ϦϦʔε Camera API 1 Intentܦ༝
  7. private fun startCamera() { val cameraProviderFuture = ProcessCameraProvider.getInstance(context) cameraProviderFuture.addListener({ val

    cameraProvider = cameraProviderFuture.get() … }, ContextCompat.getMainExecutor(context)) } 17 $BNFSB1SPWJEFSΛऔಘ͢Δ
  8. val preview = Preview.Builder() .setTargetAspectRatio(…) / .setTargetResolution(…) .setTargetRotation(…) .build() .also

    { it.setSurfaceProvider( binding.previewView.surfaceProvider ) } 18 1SFWJFX6TF$BTFΛ࢖ͬͯετϦʔϛϯάઃఆΛߦ͏
  9. 20

  10. $BNFSB9ͷ6TF$BTF w 1SFWJFX ΧϝϥϓϨϏϡʔ  w *NBHF$BQUVSF ࣸਅࡱӨ  w

    ࡱӨͯ͠ࢦఆͨ͠৔ॴʹอଘ w *NBHF"OBMZTJT ը૾ղੳ 21 v1.0.0
  11. imageCapture = ImageCapture.Builder().build() try { cameraProvider.unbindAll() cameraProvider.bindToLifecycle( this as LifecycleOwner,

    CameraSelector.DEFAULT_BACK_CAMERA, preview, imageCapture ) } 22 -JGFDZDMFʹ*NBHF$BQUVSF6TF$BTFΛCJOE
  12. private fun takePicture() { val photoFile = File(…) val outputFileOptions

    = ImageCapture.OutputFileOptions.Builder(photoFile) .build() } 23 ࣸਅͷอଘઌͷઃఆ w 'JMF w .FEJB4UPSF w 0VUQVU4USFBN
  13. imageCapture.takePicture( outputFileOptions, ContextCompat.getMainExecutor(context), object : ImageCapture.OnImageSavedCallback { override fun onImageSaved(

    outputFileResults: ImageCapture.OutputFileResults) { outputFileResults.savedUri … } override fun onError(exception: ImageCaptureException) { … } } ) 24 ࣸਅͷࡱӨॲཧ ࢦఆͨ͠อଘઌʹอଘ͢Δ৔߹
  14. imageCapture.takePicture( ContextCompat.getMainExecutor(context), object : ImageCapture.OnImageCapturedCallback() { override fun onCaptureSuccess(image: ImageProxy)

    { … } override fun onError(exception: ImageCaptureException) { … } } ) 25 ࣸਅͷࡱӨॲཧ ը૾όοϑΝΛऔಘ
  15. $BNFSB9Ͱ࣮ݱͰ͖Δิॿػೳ • ζʔϜ 
 DBNFSB$POUSPMTFU-JOFBS;PPN GMPBU TFU;PPN3BUJP GMPBU  •

    τʔν ϑϥογϡ 
 DBNFSB$POUSPMFOBCMF5PSDI CPPMFBO  • λοϓϑΥʔΧε 
 DBNFSB$POUSPMTUBSU'PDVT"OE.FUFSJOH 'PDVT.FUFSJOH"DUJPO  • ࿐ग़ิਖ਼ 
 DBNFSB$POUSPMTFU&YQPTVSF$PNQFOTBUJPO*OEFY JOU 26
  16. $BNFSB9ͷ6TF$BTF w 1SFWJFX ΧϝϥϓϨϏϡʔ  w *NBHF$BQUVSF ࣸਅࡱӨ  w

    *NBHF"OBMZTJT ը૾ղੳ  w Χϝϥͷ͔ΒऔಘͰ͖Δը૾όοϑΝΛ࢖ͬͯɺ 
 ը૾ॲཧ΍ػցֶशͷ࣮ߦ͕Ͱ͖Δ 27 v1.0.0
  17. imageAnalysis = ImageAnalysis.Builder() .build() .also { it.setAnalyzer( Executors.newSingleThreadExecutor(), ImageAnalysis.Analyzer {

    image: ImageProxy -> // ը૾ॲཧͳͲ image.close() } ) } 28 *NBHF"OBMZTJT6TF$BTFͰը૾෼ੳΛߦ͏
  18. ΧϝϥͰऔಘͨ͠ը૾ͷ׆༻ྫ w ը૾ॲཧ w #JUNBQʹม׵ͯ͠Ճ޻ w 0QFO$7 w ػցֶश w

    5FOTPS'MPX-JUF w 'JSFCBTF.BDIJOF-FBSOJOH w .-,JU 29 https://github.com/android/camera-samples/blob/develop/ CameraXTfLite/screenshots/screenshot-1.jpg
  19. WͰશͯͷόʔδϣϯ͕౷Ұ͞Εͨ 32 ϦϦʔε೔ camera-core camera- camera2 camera- lifecycle camera-video camera-view

    camera- extensions 2022/01/26 v1.1.0-beta01 2021/12/15 v1.1.0-alpha12 v1.0.0-alpha32 2021/10/13 v1.1.0-alpha10 v1.0.0-alpha30 2021/05/05 v1.0.0-stable v1.0.0-alpha24
  20. $BNFSB9ͷ6TF$BTF w 1SFWJFX ΧϝϥϓϨϏϡʔ  w *NBHF$BQUVSF ࣸਅࡱӨ  w

    *NBHF"OBMZTJT ը૾ղੳ  w 7JEFP$BQUVSF ಈըࡱӨ 33 v1.1.0
  21. val recorder = Recorder.Builder().build() videoCapture = VideoCapture.withOutput(recorder) try { cameraProvider.unbindAll()

    val camera = cameraProvider.bindToLifecycle( this as LifecycleOwner, CameraSelector.DEFAULT_BACK_CAMERA, preview, videoCapture ) } 34 3FDPSEFSͱ7JEFP$BQUVSFΛ࡞੒ͯ͠-JGFDZDMFʹCJOE
  22. 35 3FDPSEFSͷಈըղ૾౓ͷઃఆ w 4% Q ɺ)% Q ɺ')% Q ɺ6)%

    Q  Recorder.Builder() .setQualitySelector(QualitySelector.from(Quality.UHD)) w ΧϝϥσόΠεʹΑͬͯରԠ͍ͯ͠Δղ૾౓͕ҟͳΔ 2VBMJUZ4FMFDUPSHFU4VQQPSUFE2VBMJUJFT DBNFSBDBNFSB*OGP  w ղ૾౓Λࢦఆ͠ͳ͍৔߹ɺ')%͔ΒॱʹରԠ͍ͯ͠Δղ૾౓Λ୳͠ઃఆ͞ΕΔ
  23. 36 ಈըͷอଘઌͷઃఆ private fun startRecording() { val movieFile = File(…)

    val outputFileOptions = androidx.camera.video.FileOutputOptions .Builder(movieFile) .build() } w 'JMF w .FEJB4UPSF w 1BSDFM'JMF%FTDSJQUPS "OESPJEҎ্
  24. 37 ࿥ըͷ։࢝ recording = videoCapture.output .prepareRecording(context, outputFileOptions) //࿥Ի͢Δ৔߹͸android.permission.RECORD_AUDIO͕ඞཁ .withAudioEnabled() .start(

    ContextCompat.getMainExecutor(context), captureListener ) recording.pause() recording.resume() recording.stop() / recording.close()
  25. 38 ࿥ըঢ়ଶͷϋϯυϦϯά private val captureListener = Consumer<VideoRecordEvent> { event ->

    when (event) { is VideoRecordEvent.Start -> {} is VideoRecordEvent.Pause -> {} is VideoRecordEvent.Resume -> {} is VideoRecordEvent.Finalize -> { event.outputResults.outputUri event.error } } }
  26. 39

  27. 6TF$BTFͷ૊Έ߹Θͤ 40 LEVEL Ͱ͖Δ͜ͱ LEGACY ԼҐޓ׵Ϟʔυ Preview + Image Capture

    + Image Analysisɺ 
 Preview + Video Captureͷซ༻Λαϙʔτ LIMITED Preview + Video Capture + Image Captureͷซ༻Λαϙʔτ FULL Camera 2Ͱɺ 
 ߴ଎࿈ࣸػೳɺϚχϡΞϧηϯαʔίϯτϩʔϧͳͲ͕αϙʔτ͞ΕΔ LEVEL_3 Preview + Video Capture + Image Analysisͷซ༻Λαϙʔτ EXTERNAL USB઀ଓ͞Εͨ֎෦ΧϝϥΛද͢
  28. ΧϝϥσόΠεͷϨϕϧͷௐ΂ํ $BNFSBؔ࿈ͷΧϝϥ৘ใΛऔಘ͢Δ$BNFSB$BNFSB*OGPΛհͯ͠ 
 */'0@4611035&%@)"3%8"3&@-&7&-Λऔಘ͢Δ 41 val camera = provider.bindToLifecycle(this, cameraSelector)

    val level = Camera2CameraInfo.from(camera.cameraInfo) .getCameraCharacteristic( CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL ) val isHardwareLevelLimited = level == CameraMetadata.INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED
  29. -JGFDZDMF$BNFSB$POUSPMMFSͰΑΓ؆୯ʹ࣮૷ 45 val cameraController = LifecycleCameraController(context) binding.previewView.controller = cameraController //

    σϑΥϧτͰ͸ImageCaputreͱImageAnalysisɺ
 // ϐϯνΠϯɾΞ΢τͷζʔϜػೳͱλοϓ&ϑΥʔΧε͕ࣗಈͰ༗ޮʹͳΔ cameraController.bindToLifecycle(this as LifecycleOwner) cameraController .setEnabledUseCases(CameraController.VIDEO_CAPTURE) cameraController.takePicture(…) cameraController.enableTorch(true)
  30. Χϝϥͷঢ়ଶભҠ $BNFSB4UBUF5ZQF 48 Closed OPENING OPEN CLOSING PENDING_OPEN Bind UseCase

    Χϝϥͷىಈ੒ޭ Unbind UseCase Χϝϥऴྃ੒ޭ ΧϝϥىಈͷϦΫΤετ଴ͪ
  31. Wͷ৽ػೳ w $BNFSBNMLJUWJTJPOϥΠϒϥϦ͕௥Ճ w .M,JU"OBMZ[FS͕௥Ճ͞Εɺ.-,JUͱͷ࿈ܞ͕؆୯ʹ౷߹Ͱ͖ΔΑ͏ʹͳͬͨ w ;FSP4IVUUFS-BH"1*͕$BNFSB9Ͱ࢖͑ΔΑ͏ʹͳͬͨ w $"1563&@.0%&@;&30@4)655&3@-"(Λઃఆ͢Δͱɺ 


    γϟολʔϘλϯΛԡ͔ͯ͠ΒࡱӨ͞ΕΔ·Ͱͷϥά͕ܰݮͰ͖Δ w อଘͨ͠ಈըͷ.FUB%BUBʹҐஔ৘ใΛ෇༩Ͱ͖ΔΑ͏ʹͳͬͨ w 0VUQVU0QUJPOTʹTFU-PDBUJPO͕௥Ճ 50 v1.2.0-beta
  32. ΧϝϥσόΠε͕αϙʔτ͍ͯ͠Δղ૾౓ͷऔಘ w ΧϝϥσόΠεͷϋʔυ΢ΣΞϨϕϧ΍ɺࢦఆͨ͠ΞεϖΫτൺɺ 
 ղ૾౓ʹΑͬͯɺ$BNFSB9͕αϙʔτ͢Δ࠷దͳղ૾౓Λࣗಈతʹܾఆ͢Δ w 4USFBN$POGJHVSBUJPO.BQHFU0VUQVU4J[FT ͰσόΠε͕αϙʔτ͢Δ 
 ղ૾౓ͷϦετΛऔಘͰ͖Δ

    53 val camera2Info = Camera2CameraInfo.from(cameraInfo) val config = camera2Info.getCameraCharacteristic( CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP ) val supportResolutionSizes = config?.getOutputSizes(ImageFormat.JPEG)