La visualización / vista previa de la cámara en pantalla completa no mantiene la relación de aspecto: la imagen está torcida, estirada para que quepa en la pantalla

He desarrollado una pequeña aplicación para mostrar la vista previa de la cámara en pantalla completa. Estoy usando la API de la cámara para esto.

Este es el diseño de la actividad:

     

Cuando el dispositivo está en vertical, la pantalla se escala verticalmente para que coincida con la altura de la pantalla del dispositivo, por lo que la relación de aspecto no es la misma que la de la cámara original. Estas son 2 imágenes que explican mejor lo que estoy diciendo:

enter image description hereenter image description here

La primera imagen está hecha con un dispositivo de cámara nativo. La segunda imagen está hecha con mi aplicación, con la cámara en pantalla completa: la imagen está sesgada, estirada para que quepa en la pantalla.

Necesito que la vista previa de la cámara sea de pantalla completa, independientemente del tamaño de vista previa proporcionado por getSupportedPreviewSizes() mehod y sin distorsión. ¿Hay alguna manera de lograr esto? ¿Hay alguna forma de mantener la relación de aspecto adecuada cuando la vista previa de la cámara está en pantalla completa? Esperaba que esto se hiciera automáticamente con OS: recortando la imagen para que coincida con la resolución solicitada mientras se mantiene la relación de aspecto, pero esto no sucede.

Intenté hacer SurfaceView más grande que la pantalla (siguiendo esta pregunta: Adaptar una vista previa de la cámara a un SurfaceView más grande que la pantalla ), pero no está bien en mi caso ya que estoy capturando instantáneas (6 cuadros / segundo) y esos no son lo que el usuario ve en la pantalla (el cuadro contiene toda la vista previa de la cámara, aunque no todo esté visible en la pantalla).

Publiqué aquí: https://www.dropbox.com/s/3d52xt8kazynsae/CameraFullScreen.7z?v=0mcn el proyecto completo que hice.

Cualquier idea / solución es más que importante para mí. Muchas gracias.

=============================================== ======================

Actualización debido a la respuesta ss1271:

Analizaré un poco las resoluciones que escribió anteriormente para Samsung Galaxy Ace II .

I. Resolución de pantalla : 480×800 – relación de aspecto 3: 5 = 0,6

II. getSupportedPreviewSizes – Estoy casi seguro de que estos valores provienen de la cámara trasera. A continuación se muestran las relaciones de aspecto para estas resoluciones:

  2560x1920 - 0,75 2560x1536 - 0,60 2048x1536 - 0,75 2048x1232 - 0,60 960x720 - 0,75 640x480 - 0,75 

Por lo tanto, su método devolverá un Size correspondiente a 2560×1536 o a 2048×1232 ; estos tienen la misma relación de aspecto que la resolución de pantalla y el uso de estos valores no distorsionará la imagen. El problema para mí es que no puedo usar resoluciones tan grandes ya que capturo 6 fotogtwigs / segundo y estos deben guardarse a una resolución más baja.

Voy a presentar a continuación algunos resultados de un dispositivo Samsung S2 :

I. Resolución de pantalla : 480 x 800 – relación de aspecto 3: 5 = 0,6

II. Camara trasera
un). getSupportedPreviewSizes :

 800 / 480 - 480/800 = 0,60 800 / 450 - 450/800 = 0,56 720 / 480 - 0,66 640 / 480 - 0,75 352 / 288 - 0,81 320 / 240 - 0,75 176 / 144 - 0,81 

segundo). Resoluciones nativas de la cámara:

 3264 / 2448 - 0,75 - not full screen 3264 / 1968 - 0,60 - FULL SCREEN (since has the same aspect ratio as device screen) 2048 / 1536 - 0,75 - not full screen 2048 / 1232 - 0,60 - FULL SCREEN (same aspect ratio as device screen) 800 / 480 - 0,60 - FULL SCREEN (same aspect ratio as device screen) 640 / 480 - 0, 75 - not full screen 

III. Cámara frontal
un). getSupportedPreviewSizes :

 640 / 480 - 0,75 352 / 288 - 0,81 320 / 240 - 0,75 176 / 144 - 0,81 

segundo). La cámara nativa no está en pantalla completa y no puedo elegir una resolución; la opción está deshabilitada.

Para S2, cámara trasera, me pregunto por qué el método getSupportedPreviewSizes() no devuelve las mismas resoluciones que la cámara nativa o los que se muestran con la cámara nativa son los tamaños de imagen? Me pregunto por qué no tengo opciones como getSupportedPreviewSizes() dadas por el método getSupportedPreviewSizes() ? : enter image description here

En pocas palabras, puede hacer una vista previa de la cámara en pantalla completa; sin embargo, deberá averiguar por su cuenta los tamaños apropiados entre los tamaños de vista previa admitidos, solo si la vista previa personalizada de la cámara es lo que desea.

Para su pregunta, de acuerdo con los desarrolladores de Android – Cámara

Si desea establecer un tamaño específico para la vista previa de su cámara, surfaceChanged() en el método surfaceChanged() como se indica en los comentarios anteriores. Al configurar el tamaño de vista previa, debe usar valores de getSupportedPreviewSizes() . No establezca valores arbitrarios en el método setPreviewSize() .

Parece que no puede pasar manualmente el tamaño que desea que no sean los tamaños proporcionados por getSupportedPreviewSizes() . Con un examen más detallado de los tamaños admitidos por la cámara de su teléfono, verá que la proporción de tamaños admitidos podría no ser exactamente igual a la relación de su pantalla.

Por ejemplo, Samsung Galaxy Ace II tiene una resolución de 480×800, leyendo el Size devuelto por getSupportedPreviewSizes() , su cámara admite:

2560×1920

2560×1536

2048×1536

2048×1232

960×720

640×480

y si desea mostrar la vista previa de la cámara en pantalla completa correctamente (sin estirar), tendrá que calcular, comparar y aplicar la proporción adecuada en estos tamaños de vista previa compatibles.

La implementación de encontrar un tamaño de vista previa adecuado no es tan complicado. Un método común para hacer esto sería algo como esto:

  /** * Calculate the optimal size of camera preview * @param sizes * @param w * @param h * @return */ private Size getOptimalSize(List sizes, int w, int h) { final double ASPECT_TOLERANCE = 0.2; double targetRatio = (double) w / h; if (sizes == null) return null; Size optimalSize = null; double minDiff = Double.MAX_VALUE; int targetHeight = h; // Try to find an size match aspect ratio and size for (Size size : sizes) { // Log.d("CameraActivity", "Checking size " + size.width + "w " + size.height + "h"); double ratio = (double) size.width / size.height; if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue; if (Math.abs(size.height - targetHeight) < minDiff) { optimalSize = size; minDiff = Math.abs(size.height - targetHeight); } } // Cannot find the one match the aspect ratio, ignore the requirement if (optimalSize == null) { minDiff = Double.MAX_VALUE; for (Size size : sizes) { if (Math.abs(size.height - targetHeight) < minDiff) { optimalSize = size; minDiff = Math.abs(size.height - targetHeight); } } } SharedPreferences previewSizePref; if (cameraId == Camera.CameraInfo.CAMERA_FACING_BACK) { previewSizePref = getSharedPreferences("PREVIEW_PREF",MODE_PRIVATE); } else { previewSizePref = getSharedPreferences("FRONT_PREVIEW_PREF",MODE_PRIVATE); } SharedPreferences.Editor prefEditor = previewSizePref.edit(); prefEditor.putInt("width", optimalSize.width); prefEditor.putInt("height", optimalSize.height); prefEditor.commit(); // Log.d("CameraActivity", "Using size: " + optimalSize.width + "w " + optimalSize.height + "h"); return optimalSize; } 

Y también puede hacer lo similar para averiguar los tamaños de cámara adecuados (el tamaño de la imagen de salida).

Nota: Encontré la versión original del código anterior de Internet e hice algunas modificaciones / optimizaciones para mi propio propósito.

Por favor, avíseme si esto funciona para usted.

Me enfrentaba al mismo Issue in Camera2 API, he utilizado el tamaño de vista previa y la relación de aspecto de los dispositivos para resolver el problema. También puede hacer lo mismo con su API de cámara.