Đầu ra của trường hợp sử dụng CameraX có 2 phần: vùng đệm và thông tin chuyển đổi. Vùng đệm là một mảng byte và thông tin chuyển đổi là cách mà vùng đệm được cắt và xoay trước khi hiện ra cho người dùng cuối. Cách áp dụng chuyển đổi phụ thuộc vào định dạng của vùng đệm.
ImageCapture
Đối với trường hợp sử dụng ImageCapture
, vùng đệm kích cỡ khuôn hình chữ nhật cắt ảnh được áp dụng trước khi lưu vào ổ đĩa và chế độ xoay được lưu trong dữ liệu Exif. Ứng dụng không cần làm gì thêm.
Xem trước
Đối với trường hợp sử dụng Preview
, bạn có thể lấy thông tin chuyển đổi bằng cách
gọi
SurfaceRequest.setTransformationInfoListener()
.
Mỗi lần chuyển đổi được cập nhật, lệnh gọi sẽ nhận được một đối tượng
SurfaceRequest.TransformationInfo
mới.
Cách áp dụng thông tin chuyển đổi phụ thuộc vào nguồn của
Surface
và thường không đơn giản. Nếu mục tiêu chỉ là hiển thị
bản xem trước, hãy sử dụng PreviewView
. PreviewView
là chế độ xem tuỳ chỉnh tự động
xử lý việc chuyển đổi. Đối với các trường hợp sử dụng nâng cao, khi bạn cần chỉnh sửa luồng xem trước, chẳng hạn như với OpenGL, hãy xem mã mẫu trong Ứng dụng kiểm thử cốt lõi CameraX.
Chuyển đổi toạ độ
Một nhiệm vụ phổ biến khác là làm việc với các toạ độ thay vì vùng đệm, chẳng hạn như vẽ một hộp xung quanh khuôn mặt được phát hiện trong bản xem trước. Trong trường hợp như vậy, bạn cần chuyển đổi toạ độ của khuôn mặt đã phát hiện từ dữ liệu phân tích hình ảnh thành bản xem trước.
Đoạn mã sau đây sẽ tạo một ma trận liên kết từ các toạ độ
phân tích hình ảnh đến các toạ độ PreviewView
. Để chuyển đổi toạ độ (x, y) bằng một
Matrix
, hãy xem
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; }