Sortie de transformation

La sortie d'un cas d'utilisation de CameraX est double : la mémoire tampon et les informations sur la transformation. Le tampon est un tableau d'octets. Les informations sur la transformation indiquent comment la mémoire tampon doit être recadrée et alternée avant d'être présentée aux utilisateurs finaux. La manière dont la transformation est appliquée dépend du format du tampon.

ImageCapture

Pour le cas d'utilisation ImageCapture, le tampon du rectangle de recadrage est appliqué avant l'enregistrement sur le disque et la rotation est enregistrée dans les données Exif. Aucune autre action n'est requise de la part de l'application.

Aperçu

Pour le cas d'utilisation Preview, vous pouvez obtenir les informations sur la transformation en appelant SurfaceRequest.setTransformationInfoListener(). Chaque fois que la transformation est mise à jour, l'appelant reçoit un nouvel objet SurfaceRequest.TransformationInfo.

La manière d'appliquer les informations de transformation dépend de la source de Surface et est généralement importante. Si l'objectif est simplement d'afficher l'aperçu, utilisez PreviewView. PreviewView est un affichage personnalisé qui gère automatiquement la transformation. Pour les utilisations avancées, lorsque vous devez modifier le flux d'aperçu, par exemple avec OpenGL, consultez l'exemple de code dans l'application principale de test de CameraX.

Transformer des coordonnées

Une autre tâche courante consiste à utiliser les coordonnées au lieu du tampon, par exemple en dessinant un cadre autour du visage détecté dans l'aperçu. Dans ce cas, vous devez transformer en aperçu les coordonnées du visage détecté par l'analyse de l'image.

L'extrait de code suivant crée une matrice qui fait correspondre les coordonnées de l'analyse d'images aux coordonnées PreviewView. Pour transformer les coordonnées (x, y) avec une Matrix, consultez la section 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;
}