Implementare un'anteprima

Quando aggiungi un'anteprima alla tua app, utilizza PreviewView, che è un View che può essere ritagliato, ridimensionato e ruotato per una visualizzazione corretta.

L'anteprima dell'immagine viene trasmessa in streaming a una superficie all'interno di PreviewView quando la videocamera si attiva.

Utilizza PreviewView

L'implementazione di un'anteprima per CameraX utilizzando PreviewView prevede i seguenti passaggi, che vengono trattati nelle sezioni successive:

  1. Facoltativamente, configura un CameraXConfig.Provider.
  2. Aggiungi un PreviewView al layout.
  3. Richiedi un ProcessCameraProvider.
  4. Al momento della creazione di View, verifica la presenza di ProcessCameraProvider.
  5. Seleziona una videocamera e associa il ciclo di vita e i casi d'uso.

L'utilizzo di PreviewView presenta alcune limitazioni. Quando utilizzi PreviewView, non puoi eseguire nessuna delle seguenti operazioni:

  • Crea un SurfaceTexture da impostare su TextureView e Preview.SurfaceProvider.
  • Recupera SurfaceTexture da TextureView e impostalo su Preview.SurfaceProvider.
  • Recupera Surface da SurfaceView e impostalo su Preview.SurfaceProvider.

In questi casi, Preview interrompe lo streaming dei frame su PreviewView.

Aggiungi un PreviewView al layout

L'esempio seguente mostra un PreviewView in un layout:

<FrameLayout
    android:id="@+id/container">
        <androidx.camera.view.PreviewView
            android:id="@+id/previewView" />
</FrameLayout>

Richiedi un CameraProvider

Il seguente codice mostra come richiedere un CameraProvider:

// import androidx.camera.lifecycle.ProcessCameraProvider
// import com.google.common.util.concurrent.ListenableFuture

class MainActivity : ComponentActivity() {
    private lateinit var cameraProviderFuture: ListenableFuture<ProcessCameraProvider>
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        cameraProviderFuture = ProcessCameraProvider.getInstance(this)
    }
}

Controlla la disponibilità di CameraProvider

Dopo aver richiesto un CameraProvider, verifica che l'inizializzazione sia andata a buon fine quando viene creata la visualizzazione. Il seguente codice mostra come eseguire questa operazione:

cameraProviderFuture.addListener(
    Runnable {
        val cameraProvider = cameraProviderFuture.get()
        bindPreview(cameraProvider)
    },
    ContextCompat.getMainExecutor(this)
)

Per un esempio della funzione bindPreview utilizzata in questo esempio, consulta il codice fornito nella sezione successiva.

Seleziona una fotocamera e associa il ciclo di vita e i casi d'uso

Dopo aver creato e confermato la CameraProvider, segui questi passaggi:

  1. Crea un Preview.
  2. Specifica l'opzione della videocamera LensFacing che preferisci.
  3. Associa la videocamera selezionata e gli eventuali casi d'uso al ciclo di vita.
  4. Collega Preview a PreviewView.

Il seguente codice mostra un esempio:

fun bindPreview(cameraProvider: ProcessCameraProvider) {
    var preview: Preview = Preview.Builder()
        .build()

    var cameraSelector: CameraSelector = CameraSelector.Builder()
        .requireLensFacing(CameraSelector.LENS_FACING_BACK)
        .build()

    preview.setSurfaceProvider(previewView.getSurfaceProvider())

    var camera = cameraProvider.bindToLifecycle(this as LifecycleOwner, cameraSelector, preview)
}

Tieni presente che bindToLifecycle() restituisce un oggetto Camera. Per ulteriori informazioni sul controllo dell'output della videocamera, ad esempio lo zoom e l'esposizione, consulta Output della videocamera.

Hai completato l'implementazione dell'anteprima della fotocamera. Crea la tua app e verifica che l'anteprima venga visualizzata nell'app e funzioni come previsto.

Controlli aggiuntivi per PreviewView

CameraX PreviewView fornisce alcune API aggiuntive per configurare proprietà come:

Modalità di implementazione

PreviewView può utilizzare una delle seguenti modalità per eseguire il rendering di uno stream di anteprima su View di destinazione:

  • PERFORMANCE è la modalità predefinita. PreviewView utilizza un SurfaceView per visualizzare lo stream video, ma utilizza un TextureView in determinati casi. SurfaceView ha una superficie di disegno dedicata, che ha maggiori probabilità di essere implementata con un overlay hardware dal compositor hardware interno, soprattutto quando non sono presenti altri elementi UI (come i pulsanti) sopra il video di anteprima. Eseguendo il rendering con un overlay hardware, i frame video evitano un percorso GPU, il che può ridurre il consumo energetico e la latenza della piattaforma.

  • COMPATIBLE. In questa modalità, PreviewView utilizza un TextureView che, a differenza di SurfaceView, non ha una superficie di disegno dedicata. Di conseguenza, il video viene visualizzato con la fusione in modo che possa essere mostrato. Durante questo passaggio aggiuntivo, l'applicazione può eseguire un'elaborazione aggiuntiva, ad esempio la scalabilità e la rotazione dei video senza restrizioni.

Utilizza PreviewView.setImplementationMode() per selezionare la modalità di implementazione adatta alla tua applicazione. Se la modalità predefinita PERFORMANCE non è adatta alla tua applicazione, il seguente esempio di codice mostra come impostare la modalità COMPATIBLE:

// viewFinder is a PreviewView instance.
viewFinder.implementationMode = PreviewView.ImplementationMode.COMPATIBLE

Tipo di scalabilità

Quando la risoluzione del video di anteprima è diversa dalle dimensioni del target PreviewView, i contenuti video devono essere adattati alla visualizzazione tramite ritaglio o letterbox (mantenendo le proporzioni originali). PreviewView fornisce i seguenti ScaleTypes a questo scopo:

  • FIT_CENTER, FIT_START e FIT_END per il letterbox. L'intero contenuto video viene ridimensionato (verso l'alto o verso il basso) alle dimensioni massime possibili che possono essere visualizzate nel target PreviewView. Tuttavia, anche se l'intero fotogramma del video è visibile, una parte dello schermo potrebbe essere vuota. A seconda del tipo di scala scelto tra questi tre, il frame video si allinea al centro, all'inizio o alla fine della visualizzazione di destinazione.

  • FILL_CENTER, FILL_START, FILL_END per il ritaglio. Se un video non corrisponde alle proporzioni PreviewView, è visibile solo una parte dei contenuti, ma il video riempie l'intero PreviewView.

Il tipo di scala predefinito utilizzato da CameraX è FILL_CENTER. Utilizza PreviewView.setScaleType() per impostare il tipo di scalabilità più appropriato per la tua applicazione. Il seguente esempio di codice imposta il tipo di scalabilità FIT_CENTER:

// viewFinder is a PreviewView instance.
viewFinder.scaleType = PreviewView.ScaleType.FIT_CENTER

La procedura per la visualizzazione di un video è costituita dai seguenti passaggi:

  1. Scala il video:
    • Per i tipi di scalabilità FIT_*, scala il video con min(dst.width/src.width, dst.height/src.height).
    • Per i tipi di scalabilità FILL_*, scala il video con max(dst.width/src.width, dst.height/src.height).
  2. Allinea il video scalato alla destinazione PreviewView:
    • Per FIT_CENTER/FILL_CENTER, allinea al centro il video ridimensionato e la destinazione PreviewView.
    • Per FIT_START/FILL_START, allinea il video scalato e la destinazione PreviewView rispetto all'angolo in alto a sinistra di ciascuno.
    • Per FIT_END/FILL_END, allinea il video scalato e la destinazione PreviewView rispetto all'angolo in basso a destra di ciascuno.

Ad esempio, ecco un video di origine 640 x 480 e una destinazione 1920 x 1080 PreviewView:

Immagine che mostra un video 640 x 480 rispetto a un'anteprima 1920 x 1080

L'immagine seguente mostra il processo di scalabilità di FIT_START/FIT_CENTER/FIT_END:

Immagine che mostra il processo di scalabilità di FIT_START, FIT_CENTER e FIT_END

La procedura è la seguente:

  1. Scala il frame video (mantenendo le proporzioni originali) con min(1920/640, 1080/480) = 2.25 per ottenere un frame video intermedio di 1440 x 1080.
  2. Allinea il frame video 1440 x 1080 con il PreviewView 1920 x 1080.
    • Per FIT_CENTER, allinea il frame video con il centro della finestra PreviewView. Le colonne di 240 pixel iniziali e finali di PreviewView sono vuote.
    • Per FIT_START, allinea il frame video con l'inizio (angolo in alto a sinistra) della finestra PreviewView. Le ultime 480 colonne di pixel di PreviewView sono vuote.
    • Per FIT_END, allinea il frame video alla fine (angolo in basso a destra) della finestra PreviewView. Le prime 480 colonne di pixel di PreviewView sono vuote.

L'immagine seguente mostra il processo di scalabilità di FILL_START/FILL_CENTER/FILL_END:

Immagine che mostra il processo di scalabilità FILL_START, FILL_CENTER e FILL_END

La procedura è la seguente:

  1. Scala il frame video con max(1920/640, 1080/480) = 3 per ottenere un frame video intermedio di 1920 x 1440 (che è più grande delle dimensioni di PreviewView).
  2. Ritaglia il fotogramma video 1920 x 1440 per adattarlo alla finestra 1920 x 1080 di PreviewView.
    • Per FILL_CENTER, ritaglia 1920 x 1080 dal centro del video scalato 1920 x 1440. Le 180 linee superiori e inferiori del video non sono visibili.
    • Per FILL_START, ritaglia 1920 x 1080 dall'inizio del video scalato 1920 x 1440. Le 360 linee inferiori del video non sono visibili.
    • Per FILL_END, ritaglia 1920 x 1080 dalla fine del video scalato 1920 x 1440. Le prime 360 linee del video non sono visibili.

Risorse aggiuntive

Per scoprire di più su CameraX, consulta le seguenti risorse aggiuntive.

Codelab

  • Guida introduttiva a CameraX
  • Esempio di codice

  • App di esempio CameraX