轉換輸出內容

CameraX 用途有兩項輸出內容:緩衝區和轉換資訊。緩衝區為位元組陣列,轉換資訊則說明在向使用者顯示前,該如何裁剪及旋轉緩衝區。套用轉換資訊的方式視緩衝區格式而定。

ImageCapture

如果是 ImageCapture 用途,系統會先套用裁剪矩形緩衝區,再儲存至磁碟,並將旋轉資訊儲存在 EXIF 資料中。應用程式不需採取任何額外動作。

Preview

如果是 Preview 用途,可以呼叫 SurfaceRequest.setTransformationInfoListener() 來取得轉換資訊。轉換資訊每次更新時,呼叫端都會收到新的 SurfaceRequest.TransformationInfo 物件。

套用轉換資訊的方式取決於 Surface 的來源,且通常至關重要。如果目標只是要顯示預覽畫面,請使用 PreviewView。PreviewView 是會自動處理轉換資訊的自訂檢視畫面。如果是需要編輯預覽串流 (例如使用 OpenGL) 的進階用途,請參閱 CameraX 核心測試應用程式中的程式碼範例。

轉換座標

另一項常見工作是處理座標而非緩衝區,例如在預覽畫面上偵測到的臉孔周圍繪製方塊。在這類情況下,需要將偵測到的臉孔座標,從圖像分析轉換至預覽畫面。

以下程式碼片段會建立矩陣,將圖像分析座標對應至 PreviewView 座標。如要使用 Matrix 轉換 (x, y) 座標,請參閱 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
}