Problema de orientación de la cámara en Android

Estoy construyendo una aplicación que utiliza la cámara para tomar fotos. Aquí está mi código fuente para hacer esto:

File file = new File(Environment.getExternalStorageDirectory(), imageFileName); imageFilePath = file.getPath(); Intent intent = new Intent("android.media.action.IMAGE_CAPTURE"); //Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file)); startActivityForResult(intent, ACTIVITY_NATIVE_CAMERA_AQUIRE); 

En el método onActivityResult() , uso BitmapFactory.decodeStream() para recoger la imagen.

Cuando ejecuto mi aplicación en Nexus uno, funciona bien. Pero cuando uso Samsung Galaxy S o HTC Inspire 4G, la dirección de la imagen no es correcta.

  • Capture con el modo vertical, la imagen real (guardar en la tarjeta SD) siempre gira 90 grados.

vista previa de la imagen después del disparoimagen real en la tarjeta SD

Vista previa de la imagen después del disparo ——— Imagen real en la tarjeta SD

  • Capturar con modo horizontal, todo está bien.

Vista previa de la imagen después del disparoImagen real en la tarjeta SD

Vista previa de la imagen después del disparo ——— Imagen real en la tarjeta SD

Hay bastantes temas y problemas similares por aquí. Como no estás escribiendo tu propia cámara, creo que se reduce a esto:

algunos dispositivos rotan la imagen antes de guardarla, mientras que otros simplemente agregan la etiqueta de orientación en los datos exif de la foto.

Recomiendo verificar los datos exif de la foto y buscar particularmente

 ExifInterface exif = new ExifInterface(SourceFileName); //Since API Level 5 String exifOrientation = exif.getAttribute(ExifInterface.TAG_ORIENTATION); 

Dado que la foto se muestra correctamente en su aplicación, no estoy seguro de dónde está el problema, pero esto definitivamente debe establecerlo en el camino correcto.

Acabo de encontrar el mismo problema y lo usé para corregir la orientación:

 public void fixOrientation() { if (mBitmap.getWidth() > mBitmap.getHeight()) { Matrix matrix = new Matrix(); matrix.postRotate(90); mBitmap = Bitmap.createBitmap(mBitmap , 0, 0, mBitmap.getWidth(), mBitmap.getHeight(), matrix, true); } } 

Si el ancho del bitmap es mayor que la altura, la imagen devuelta está en horizontal, por lo que la giro 90 grados.

Espero que ayude a alguien más con este problema.

Hay dos cosas necesarias:

  1. La vista previa de la cámara necesita lo mismo que su rotación. Establezca esto por camera.setDisplayOrientation(result);

  2. Guarde la imagen capturada como la vista previa de su cámara. Hazlo a través de Camera.Parameters .

     int mRotation = getCameraDisplayOrientation(); Camera.Parameters parameters = camera.getParameters(); parameters.setRotation(mRotation); //set rotation to save the picture camera.setDisplayOrientation(result); //set the rotation for preview camera camera.setParameters(parameters); 

Espero que ayude.

  int rotate = 0; try { File imageFile = new File(sourcepath); ExifInterface exif = new ExifInterface( imageFile.getAbsolutePath()); int orientation = exif.getAttributeInt( ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL); switch (orientation) { case ExifInterface.ORIENTATION_ROTATE_270: rotate = 270; break; case ExifInterface.ORIENTATION_ROTATE_180: rotate = 180; break; case ExifInterface.ORIENTATION_ROTATE_90: rotate = 90; break; } } catch (Exception e) { e.printStackTrace(); } Matrix matrix = new Matrix(); matrix.postRotate(rotate); bitmap = Bitmap.createBitmap(bitmap , 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true); 

Otra opción es rotar el bitmap en la pantalla de resultados de esta manera:

 ImageView img=(ImageView)findViewById(R.id.ImageView01); Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.refresh); // Getting width & height of the given image. int w = bmp.getWidth(); int h = bmp.getHeight(); // Setting post rotate to 90 Matrix mtx = new Matrix(); mtx.postRotate(90); // Rotating Bitmap Bitmap rotatedBMP = Bitmap.createBitmap(bmp, 0, 0, w, h, mtx, true); BitmapDrawable bmd = new BitmapDrawable(rotatedBMP); img.setImageDrawable(bmd); 

También tengo este tipo de problema para algún dispositivo:

 private void rotateImage(final String path) { Bitmap scaledBitmap = Bitmap.createScaledBitmap(Conasants.bm1, 1000, 700, true); Bitmap rotatedBitmap = null; try { ExifInterface ei = new ExifInterface(path); int orientation = ei.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL); Matrix matrix = new Matrix(); switch (orientation) { case ExifInterface.ORIENTATION_ROTATE_90: matrix.postRotate(90); rotatedBitmap = Bitmap.createBitmap(scaledBitmap, 0, 0, scaledBitmap.getWidth(), scaledBitmap.getHeight(), matrix, true); break; case ExifInterface.ORIENTATION_ROTATE_180: matrix.postRotate(180); rotatedBitmap = Bitmap.createBitmap(scaledBitmap, 0, 0, scaledBitmap.getWidth(), scaledBitmap.getHeight(), matrix, true); break; case ExifInterface.ORIENTATION_ROTATE_270: matrix.postRotate(270); rotatedBitmap = Bitmap.createBitmap(scaledBitmap, 0, 0, scaledBitmap.getWidth(), scaledBitmap.getHeight(), matrix, true); break; default: rotatedBitmap = Bitmap.createBitmap(scaledBitmap, 0, 0, scaledBitmap.getWidth(), scaledBitmap.getHeight(), matrix, true); break; } } catch (Throwable e) { e.printStackTrace(); } cropImage.setImageBitmap(rotatedBitmap); rotatedBitmap = null; Conasants.bm1 = null; } 

No más verificando los datos exif de la foto. Ve bien con Glide .

Google nos presentó una biblioteca de Image Loader para Android desarrollada por bumptech llamada Glide como una biblioteca recomendada por Google. Se ha utilizado en muchos proyectos de código abierto de Google hasta ahora, incluida la aplicación oficial Google I / O 2014.

Ejemplo: Glide.with (context) .load (uri) .into (imageview);

Para más: https://github.com/bumptech/glide

Pruebe de esta manera: estática Uri image_uri; bitmap estático taken_image = null;

  image_uri=fileUri; // file where image has been saved taken_image=BitmapFactory.decodeFile(image_uri.getPath()); try { ExifInterface exif = new ExifInterface(image_uri.getPath()); int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL); switch(orientation) { case ExifInterface.ORIENTATION_ROTATE_90: taken_image=decodeScaledBitmapFromSdCard(image_uri.getPath(), 200, 200); RotateBitmap(taken_image, 90); break; case ExifInterface.ORIENTATION_ROTATE_180: taken_image=decodeScaledBitmapFromSdCard(image_uri.getPath(), 200, 200); RotateBitmap(taken_image, 180); break; case ExifInterface.ORIENTATION_ROTATE_270: taken_image=decodeScaledBitmapFromSdCard(image_uri.getPath(), 200, 200); RotateBitmap(taken_image, 270); break; case ExifInterface.ORIENTATION_NORMAL: taken_image=decodeScaledBitmapFromSdCard(image_uri.getPath(), 200, 200); RotateBitmap(taken_image, 0); break; } } catch (OutOfMemoryError e) { Toast.makeText(getActivity(),e+"\"memory exception occured\"",Toast.LENGTH_LONG).show(); } public Bitmap RotateBitmap(Bitmap source, float angle) { Matrix matrix = new Matrix(); matrix.postRotate(angle); round_Image = source; round_Image = Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(), matrix, true); return Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(), matrix, true); 

}

 public void setCameraPicOrientation(){ int rotate = 0; try { File imageFile = new File(mCurrentPhotoPath); ExifInterface exif = new ExifInterface( imageFile.getAbsolutePath()); int orientation = exif.getAttributeInt( ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL); switch (orientation) { case ExifInterface.ORIENTATION_ROTATE_270: rotate = 270; break; case ExifInterface.ORIENTATION_ROTATE_180: rotate = 180; break; case ExifInterface.ORIENTATION_ROTATE_90: rotate = 90; break; } } catch (Exception e) { e.printStackTrace(); } Matrix matrix = new Matrix(); matrix.postRotate(rotate); int targetW = 640; int targetH = 640; /* Get the size of the image */ BitmapFactory.Options bmOptions = new BitmapFactory.Options(); bmOptions.inJustDecodeBounds = true; BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions); int photoW = bmOptions.outWidth; int photoH = bmOptions.outHeight; /* Figure out which way needs to be reduced less */ int scaleFactor = 1; if ((targetW > 0) || (targetH > 0)) { scaleFactor = Math.min(photoW/targetW, photoH/targetH); } /* Set bitmap options to scale the image decode target */ bmOptions.inJustDecodeBounds = false; bmOptions.inSampleSize = scaleFactor; bmOptions.inPurgeable = true; /* Decode the JPEG file into a Bitmap */ Bitmap bitmap = BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions); bitmap= Bitmap.createBitmap(bitmap , 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true); /* Associate the Bitmap to the ImageView */ imageView.setImageBitmap(bitmap); } 

Espero que esto ayude !! Gracias

  public static int mOrientation = 1; OrientationEventListener myOrientationEventListener; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.takephoto); setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); myOrientationEventListener = new OrientationEventListener(getApplicationContext()) { @Override public void onOrientationChanged(int o) { // TODO Auto-generated method stub if(!isTablet(getApplicationContext())) { if(o<=285 && o>=80) mOrientation = 2; else mOrientation = 1; } else { if(o<=285 && o>=80) mOrientation = 1; else mOrientation = 2; } } }; myOrientationEventListener.enable(); } public static boolean isTablet(Context context) { return (context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_LARGE; } } 

Espero que esto ayude. ¡Gracias!

Solo encontramos el mismo problema aquí, el siguiente fragmento de código me funciona:

 private static final String[] CONTENT_ORIENTATION = new String[] { MediaStore.Images.ImageColumns.ORIENTATION }; static int getExifOrientation(ContentResolver contentResolver, Uri uri) { Cursor cursor = null; try { cursor = contentResolver.query(uri, CONTENT_ORIENTATION, null, null, null); if (cursor == null || !cursor.moveToFirst()) { return 0; } return cursor.getInt(0); } catch (RuntimeException ignored) { // If the orientation column doesn't exist, assume no rotation. return 0; } finally { if (cursor != null) { cursor.close(); } } } 

Espero que esto ayude 🙂

Intenta esto en callback de SurfaceChanged:

 Camera.Parameters parameters=mCamera.getParameters(); if(this.getResources().getConfiguration().orientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT){ parameters.setRotation(90); }else{ parameters.setRotation(0); } mCamera.setParameters(parameters); 

dos soluciones de una línea usando Picasso y la biblioteca de planeo

Después de pasar mucho tiempo con una gran cantidad de soluciones para el problema de rotación de imágenes, finalmente encontré dos soluciones simples. No necesitamos hacer ningún trabajo adicional. Picasso y Glide son una biblioteca muy poderosa para el manejo de imágenes en su aplicación. Leerá los datos EXIF ​​de la imagen y auto-rota las imágenes.

Usando la biblioteca glide https://github.com/bumptech/glide

 Glide.with(this).load("http url or sdcard url").into(imgageView); 

Usando la biblioteca de Picasso https://github.com/square/picasso

 Picasso.with(context).load("http url or sdcard url").into(imageView); 

El código es funcionalmente para paisaje y retrato @frontCameraID = variable lo obtuvo el método clásico para mostrar la cámara deseada

 @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { if(holder.getSurface() == null) { return; } try{ camera.stopPreview(); } catch (Exception e){ } try{ int orientation = getDisplayOrientation(frontCameraID); Camera.Parameters parameters = camera.getParameters(); parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height); if (parameters.getSupportedFocusModes().contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) { parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE); } parameters.setRotation(rotationPicture); camera.setParameters(parameters); camera.setDisplayOrientation(orientation); camera.startPreview(); } catch (Exception e) { Log.i("ERROR", "Camera error changed: " + e.getMessage()); } } 

Método para obtener orientación y rotación para guardar la imagen y orientación de la pantalla @result = orientación en la vista de vista previa de la cámara @rotationPicture = rotación necesaria para guardar la imagen correctamente

 private int getDisplayOrientation(int cameraId) { android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo(); android.hardware.Camera.getCameraInfo(cameraId, info); int rotation = ((Activity) context).getWindowManager().getDefaultDisplay().getRotation(); int degrees = 0; switch (rotation) { case Surface.ROTATION_0: degrees = 0; break; case Surface.ROTATION_90: degrees = 90; break; case Surface.ROTATION_180: degrees = 180; break; case Surface.ROTATION_270: degrees = 270; break; } int result; if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { result = (info.orientation + degrees) % 360; result = (360 - result) % 360; rotationPicture = (360 - result) % 360; } else { result = (info.orientation - degrees + 360) % 360; rotationPicture = result; } return result; } 

Alguien pregunta sobre el código, por favor dígame.