Rotación inexplicable de la cámara Android en la captura de algunos dispositivos (no en EXIF)

Lo que estoy haciendo parece que debe ser simple, pero todavía estoy perdido después de haber leído todas las posibles Stackoverflow respuesta que puedo encontrar y Googled cada artículo que pueda encontrar.

Estoy usando una vista previa de SurfaceView y la captura de una imagen de una actividad que se establece para screenOrientation = "paisaje" en mi AndroidManifest.xml.

Seguí el ejemplo del código de la aplicación Cámara y pensé que las cosas funcionaban hasta que probé mi aplicación en unos pocos dispositivos Motorola que ejecutaban 1.5.

Tengo el OrientationEventListener que funciona OK y uso la reflexión para ver si fija la rotación como tal:

final int latchedOrientation = roundOrientation(mLastOrientation + 90); Parameters parameters = preview.camera.getParameters(); JPLog.d("Setting camera rotation = %d", latchedOrientation); try { // if >= 2.0 Method method = Camera.Parameters.class.getMethod("setRotation", int.class); if(method != null) { method.invoke(parameters, latchedOrientation); } } catch(Throwable t) { // if < 2.0 parameters.set("rotation", latchedOrientation); } preview.camera.setParameters(parameters); 

NexusOne (OS 2.2) – Funciona muy bien. LatchedOrientation = 0, OK imagen sin ninguna rotación en el encabezado EXIF.

T-Mobile G1 (OS 1.6) – También funciona muy bien. LatchedOrientation = 0, la imagen OK.

Motorola Backflip (OS 1.5) – Imagen girada. LatchedOrientation = 0, la imagen no tiene rotación EXIF ​​en ella.

Motorola CLIQ (OS 1.5) – Imagen girada. LatchedOrientation = 0, la imagen no tiene rotación EXIF ​​en ella.

¿Qué está pasando con estos dispositivos de Motorola? Pensé que mi problema era que el conductor de la cámara de Motorola no giraba las imágenes, así que encontré las clases de lectura EXL de Sanselan para Android y me preparaba para rotarlas yo mismo. Lo curioso es que hay cabeceras EXIF ​​pero no hay ningún elemento de rotación.

Si configuro la rotación manualmente a 90 grados, las imágenes salen perfectas de los dispositivos Motorola, pero ahora el G1 y el NexusOne tienen imágenes giradas 90 grados (no es lo que yo quiero). Tiene que haber algo que no estoy llegando aquí.

Estoy dudando de que este es un problema de 1,5, o alguien habría publicado información sobre él?

Este es un problema específico del dispositivo que afecta principalmente a los dispositivos de Motorola. Los desarrolladores de google incluyeron una llamada a setDisplayOrientation en API 8 para solucionar el problema. El error principal se archiva aquí .

Para aquellos que no pueden ir a API 8, las dos soluciones comunes son:

Sobreescribir onDraw
Sobreestablece onDraw en un ViewGroup de nivel superior y gire el lienzo en 90 grados para compensar la rotación. Tenga en cuenta que hay una advertencia aquí, ya que sus eventos táctiles también necesitan ser rotados.

Utilizar el modo horizontal
Bloquee la actividad en modo horizontal, pero dibuje los activos como si estuvieran en retrato. Esto significa que usted hace su disposición y gira sus activos de la imagen para parecer que usted está en modo del retrato de modo que la visión parezca normal. Por desgracia, esto hace que sea difícil de usar el menú ya que el menú se abrirá horizontalmente.

También he visto a gente usar un controlador de animación para rotar la vista. El inconveniente aquí que no pude superar es que la vista girada no se estira para llenar la pantalla. Ver la respuesta de Georg para una implementación de ejemplo.

Tuve este problema y utilicé este método para capturar la imagen. (Sin crear una cámara personalizada)

 final Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(image)); startActivityForResult(intent, 0); 

Y hizo el resto en onActivityResult (int requestCode, int resultCode, Intent data) {}

Pero la imagen original (la imagen de la tarjeta SD real) era correcta y el mapa de bits se gira cuando busqué de esta manera. Bitmap bmp = BitmapFactory.decodeStream (..

La solución:

  try { File f = new File(SD_CARD_IMAGE_PATH); ExifInterface exif = new ExifInterface(f.getPath()); int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL); int angle = 0; if (orientation == ExifInterface.ORIENTATION_ROTATE_90) { angle = 90; } else if (orientation == ExifInterface.ORIENTATION_ROTATE_180) { angle = 180; } else if (orientation == ExifInterface.ORIENTATION_ROTATE_270) { angle = 270; } Matrix mat = new Matrix(); mat.postRotate(angle); Bitmap bmp = BitmapFactory.decodeStream(new FileInputStream(f), null, null); Bitmap correctBmp = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), mat, true); } catch (IOException e) { Log.w("TAG", "-- Error in setting image"); } catch(OutOfMemoryError oom) { Log.w("TAG", "-- OOM Error in setting image"); } 

Aquí está el código que usé en ActivityResult () en mi actividad. La intención devuelta fue para escoger una imagen del tipo image / *. ¡Funciona bien para mí!

 Uri imageUri = intent.getData(); String[] orientationColumn = {MediaStore.Images.Media.ORIENTATION}; Cursor cur = managedQuery(imageUri, orientationColumn, null, null, null); int orientation = -1; if (cur != null && cur.moveToFirst()) { orientation = cur.getInt(cur.getColumnIndex(orientationColumn[0])); } Matrix matrix = new Matrix(); matrix.postRotate(orientation); 

Parece que la sugerencia de "modo de paisaje de uso" es lo único que realmente funciona. Parece que está bien que esto esté en el manifiesto, o hecho a través de una llamada a setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) en la actividad onCreate.

  • Android CheckBox - Estado de restauración tras la rotación de la pantalla
  • Rotar imagen sin encogerse en Android
  • Rotación 3D - perspectiva
  • Android: girar un ImageView con el dedo mueve otras vistas alrededor
  • Rotación de ImageView desde el archivo xml de diseño
  • El diseño de la vista no se actualiza en el cambio de orientación en android
  • Android, ¿Cómo puedo girar una flecha (imagen) alrededor de un punto fijo?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.