تبدیل خروجی

خروجی یک مورد استفاده CameraX دو بخش دارد: بافر و اطلاعات تبدیل. بافر یک آرایه بایتی است و اطلاعات تبدیل، نحوه برش و چرخش بافر قبل از نمایش به کاربران نهایی است. نحوه اعمال تبدیل به فرمت بافر بستگی دارد.

ضبط تصویر

برای مورد استفاده ImageCapture ، قبل از ذخیره روی دیسک، بافر crop rect اعمال می‌شود و چرخش در داده‌های Exif ذخیره می‌شود. هیچ اقدام اضافی از سوی برنامه لازم نیست.

پیش‌نمایش

برای حالت Preview ، می‌توانید اطلاعات تبدیل را با فراخوانی SurfaceRequest.setTransformationInfoListener() دریافت کنید. هر بار که تبدیل به‌روزرسانی می‌شود، فراخوانی‌کننده یک شیء SurfaceRequest.TransformationInfo جدید دریافت می‌کند.

نحوه اعمال اطلاعات تبدیل به منبع Surface بستگی دارد و معمولاً چیز ساده‌ای نیست. اگر هدف نمایش ساده پیش‌نمایش است، از PreviewView استفاده کنید. PreviewView یک نمای سفارشی است که به طور خودکار تبدیل را مدیریت می‌کند. برای کاربردهای پیشرفته، وقتی نیاز به ویرایش جریان پیش‌نمایش دارید، مانند OpenGL، به نمونه کد در برنامه تست اصلی CameraX نگاهی بیندازید.

تبدیل مختصات

یکی دیگر از کارهای رایج، کار با مختصات به جای بافر است، مانند کشیدن یک کادر دور چهره شناسایی شده در پیش‌نمایش. در مواردی مانند این، باید مختصات چهره شناسایی شده را از تحلیل تصویر به پیش‌نمایش تبدیل کنید.

قطعه کد زیر ماتریسی ایجاد می‌کند که مختصات تحلیل تصویر را به مختصات PreviewView نگاشت می‌کند. برای تبدیل مختصات (x، y) با یک Matrix ، به 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
}

جاوا

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;
}