CameraX 功能的輸出內容有兩塊:緩衝區和轉換資訊。緩衝區是位元組陣列,而轉換資訊則是在向使用者顯示前,處理裁剪跟旋轉的緩衝區。轉換的套用方式取決於緩衝格式。
ImageCapture
針對 ImageCapture
用途,系統會先套用裁剪矩形緩衝區,然後再儲存至磁碟,並將旋轉資料儲存在 Exif 資料中。這個過程不需要在應用程式中採取其他動作。
預覽
使用 Preview
的情況,您可以呼叫 SurfaceRequest.setTransformationInfoListener()
來取得轉換資訊。每次更新轉換時,呼叫端都會收到新的 SurfaceRequest.TransformationInfo
物件。
套用轉換資訊的方式取決於 Surface
的來源,這點至關重要。如果只是要顯示預覽畫面,請使用 PreviewView
。PreviewView
是應用程式自動處理的自訂檢視畫面。如要在進階預覽中編輯預覽串流 (例如使用 OpenGL),請查看 CameraX 核心測試應用程式中的程式碼範例。
轉換座標
使用座標而非緩衝區是另一種常見作法,比方說在預覽畫面中,於偵測到的臉孔周圍繪製方塊。在這種情況下,需要將偵測到的臉部座標,從圖片分析轉換成預覽。
下列這段程式碼會建立矩陣,並將圖片分析座標對應至 PreviewView
座標。如要透過 Matrix
轉換 (x, y) 座標,請參閱 Matrix.mapPoints()
。
Kotlin
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 }
Java
Matrix getMappingMatrix(ImageProxy imageProxy, PreviewView previewView) { Rect cropRect = imageProxy.getCropRect(); int rotationDegrees = imageProxy.getImageInfo().getRotationDegrees(); Matrix matrix = new Matrix(); // A float array of the source vertices (crop rect) in clockwise order. float[] source = { cropRect.left, cropRect.top, cropRect.right, cropRect.top, cropRect.right, cropRect.bottom, cropRect.left, cropRect.bottom }; // A float array of the destination vertices in clockwise order. float[] destination = { 0f, 0f, previewView.getWidth(), 0f, previewView.getWidth(), previewView.getHeight(), 0f, previewView.getHeight() }; // 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. int vertexSize = 2; // The destination needs to be shifted 1 vertex for every 90° rotation. int shiftOffset = rotationDegrees / 90 * vertexSize; float[] tempArray = destination.clone(); for (int toIndex = 0; toIndex < source.length; toIndex++) { int fromIndex = (toIndex + shiftOffset) % source.length; destination[toIndex] = tempArray[fromIndex]; } matrix.setPolyToPoly(source, 0, destination, 0, 4); return matrix; }