Przekształć dane wyjściowe

Dane wyjściowe przypadku użycia CameraX są dwojakie: bufor i informacje o przekształceniu. Bufor to tablica bajtów, a informacje o przekształceniu określają, jak bufor powinien zostać przycięty i obrócony przed wyświetleniem użytkownikom. Sposób zastosowania przekształcenia zależy od formatu bufora.

ImageCapture

W przypadku ImageCapture bufor prostokąta przycięcia jest stosowany przed zapisaniem na dysku, a obrót jest zapisywany w danych Exif. Nie musisz wykonywać żadnych dodatkowych działań w aplikacji.

Podgląd

W przypadku Preview możesz uzyskać informacje o przekształceniu, wywołując SurfaceRequest.setTransformationInfoListener(). Za każdym razem, gdy przekształcenie jest aktualizowane, obiekt wywołujący otrzymuje nowy obiekt SurfaceRequest.TransformationInfo.

Sposób zastosowania informacji o przekształceniu zależy od źródła Surface i zwykle nie jest prosty. Jeśli celem jest po prostu wyświetlenie podglądu, użyj PreviewView. PreviewView to widok niestandardowy, który automatycznie obsługuje przekształcenia. W przypadku zaawansowanych zastosowań, gdy musisz edytować strumień podglądu, np. za pomocą OpenGL, zapoznaj się z przykładowym kodem w aplikacji testowej CameraX Core.

Współrzędne przekształcenia

Innym częstym zadaniem jest praca ze współrzędnymi zamiast z buforem, np. rysowanie ramki wokół wykrytej twarzy w podglądzie. W takich przypadkach musisz przekształcić współrzędne wykrytej twarzy z analizy obrazu na podgląd.

Poniższy fragment kodu tworzy macierz, która mapuje współrzędne analizy obrazu na współrzędne PreviewView. Aby przekształcić współrzędne (x, y) za pomocą Matrix, zapoznaj się z artykułem Matrix.mapPoints().

fun getCorrectionMatrix(imageProxy: ImageProxy, previewView: PreviewView): Matrix {
    val cropRect = imageProxy.cropRect
    val rotationDegrees = imageProxy.imageInfo.rotationDegrees
    val matrix = Matrix()

    // A float array of the source vertices (crop rect) in clockwise order.
    val source = floatArrayOf(
        cropRect.left.toFloat(),
        cropRect.top.toFloat(),
        cropRect.right.toFloat(),
        cropRect.top.toFloat(),
        cropRect.right.toFloat(),
        cropRect.bottom.toFloat(),
        cropRect.left.toFloat(),
        cropRect.bottom.toFloat()
    )

    // A float array of the destination vertices in clockwise order.
    val destination = floatArrayOf(
        0f,
        0f,
        previewView.width.toFloat(),
        0f,
        previewView.width.toFloat(),
        previewView.height.toFloat(),
        0f,
        previewView.height.toFloat()
    )

    // The destination vertexes need to be shifted based on rotation degrees. The
    // rotation degree represents the clockwise rotation needed to correct the image.

    // Each vertex is represented by 2 float numbers in the vertices array.
    val vertexSize = 2
    // The destination needs to be shifted 1 vertex for every 90° rotation.
    val shiftOffset = rotationDegrees / 90 * vertexSize
    val tempArray = destination.clone()
    for (toIndex in source.indices) {
        val fromIndex = (toIndex + shiftOffset) % source.size
        destination[toIndex] = tempArray[fromIndex]
    }
    matrix.setPolyToPoly(source, 0, destination, 0, 4)
    return matrix
}