Chuyển đổi đầu ra

Đầu ra của trường hợp sử dụng CameraX có hai 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 thị 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;
}