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 }