2010-10-04 10 views
27

Lo que estoy haciendo parece que debería ser simple, pero aún estoy perdido después de haber leído todas las respuestas posibles de Stackoverflow que puedo encontrar y de buscar en Google cada artículo que puedo encontrar.Rotación inexplicable de la cámara Android en la captura de algunos dispositivos (no en EXIF)

Estoy usando una vista previa de SurfaceView y capturando una imagen de una actividad que está configurada para screenOrientation = "landscape" en mi AndroidManifest.xml.

Seguí el código de la aplicación de la cámara de muestra y pensé que todo estaba funcionando hasta que probé mi aplicación en algunos dispositivos Motorola con 1.5.

que tienen la OrientationEventListener funcionando bien y me utilizar la reflexión para ver si se ajusta 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, imagen OK sin rotación en el encabezado EXIF.

T-Mobile G1 (OS 1.6) - También funciona de maravilla. latchedOrientation = 0, imagen OK.

Motorola Backflip (OS 1.5) - Imagen girada. latchedOrientation = 0, la imagen no tiene rotación EXIF.

Motorola CLIQ (OS 1.5) - Imagen girada. latchedOrientation = 0, la imagen no tiene rotación EXIF.

¿Qué está pasando con estos dispositivos Motorola? Pensé que mi problema era que el controlador de la cámara Motorola no estaba rotando las imágenes, así que encontré las clases de lectura Sanselan EXIF ​​para Android y me estaba preparando para rotarlas. Lo curioso es que hay encabezados EXIF ​​pero 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 que se giran 90 grados (no es lo que deseo). Tiene que haber algo que no estoy recibiendo aquí.

Estoy dudando de que este sea un problema de 1.5, ¿o alguien hubiera publicado información al respecto?

+0

respuesta aquí http://stackoverflow.com/questions/14066038/why-image-captured-using-camera-intent-gets -rotated-on-some-devices-in-android –

Respuesta

9

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

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

Override onDraw
Override onDraw en un nivel superior ViewGroup y gire el lienzo 90 grados para compensar la rotación. Tenga en cuenta que hay una advertencia aquí ya que sus eventos táctiles también deberán rotarse.

Modo de uso del paisaje
Bloquear la actividad a modo de paisaje, sino dibujar activos como si estuvieran en el retrato. Esto significa que debe hacer su diseño y rotar los activos de su imagen para que parezca que está en modo vertical para que la vista se vea normal. Desafortunadamente, esto dificulta el uso del menú, ya que el menú se abrirá horizontalmente.

También he visto personas 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 el answer by Georg para una implementación de muestra.

+0

Lamentablemente no hay una buena manera de hacerlo y parece que hay un error en los controladores de la cámara Moto. –

0

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

4

Aquí está el código que utilicé en ActivityResult() en mi actividad. El intento devuelto fue para elegir una imagen del tipo imagen/*. ¡Me funciona bien!

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); 
+0

Necesito capturar la imagen dentro de mi aplicación y configurar los parámetros como en el fragmento que publiqué en la pregunta. Sin embargo, sería más fácil si desactivé la intención de que otra aplicación tome la fotografía por mí. –

+0

Todavía puede usar esto en el URI donde su aplicación almacena imágenes tomadas con la Cámara. Esto es solo código para rotar una imagen a la orientación correcta con un URI. No importa de dónde sea. – dbaugh

44

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

e hizo el resto en onActivityResult (int requestCode, int resultCode, los datos de intención) {}

Pero el (la imagen real de la tarjeta SD) imagen original era correcta y de mapa de bits fue rotado cuando fui a buscar de esta manera. mapa de bits 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"); 
    } 
+6

Gran solución, acabo de mejorarlo un poco, como en el caso de 'angle = 0' no hay necesidad de decodificarlo y crear un segundo mapa de bits con una rotación de 0. Esto debería, en caso de funcionar en un dispositivo no afectado , reduzca el consumo de memoria en un 50% para este proceso. – WarrenFaith

+0

Como un encanto :) –

+5

no funcionaba para mí :( –

Cuestiones relacionadas