web-dev-qa-db-fra.com

Caméra Android Intention Enregistrement du paysage de l'image une fois prise

J'ai jeté un coup d'œil autour de moi, mais il ne semble pas y avoir de solution/solution au problème très irritant.

Je prends une photo en orientation portrait et lorsque je clique sur Enregistrer/Jeter, les boutons sont également dans la bonne orientation. Le problème est que lorsque je récupère ensuite l'image plus tard, elle est en orientation paysage (l'image a été tournée de 90 degrés dans le sens inverse des aiguilles d'une montre).

Je ne veux pas forcer l'utilisateur à utiliser l'appareil photo dans une certaine orientation.

Existe-t-il un moyen de détecter si la photo a été prise en mode portrait, puis de décoder le bitmap et de le retourner dans le bon sens?

37
StuStirling

La photo est toujours prise dans le sens où l'appareil photo est intégré à l'appareil. Pour faire pivoter votre image correctement, vous devez lire les informations d'orientation stockées dans l'image (métadonnées EXIF). Il est stocké comment l'orientation de l'appareil, lorsque l'image a été prise.

Voici un code qui lit les données EXIF ​​et fait pivoter l'image en conséquence: file est le nom du fichier image.

BitmapFactory.Options bounds = new BitmapFactory.Options();
bounds.inJustDecodeBounds = true;
BitmapFactory.decodeFile(file, bounds);

BitmapFactory.Options opts = new BitmapFactory.Options();
Bitmap bm = BitmapFactory.decodeFile(file, opts);
ExifInterface exif = new ExifInterface(file);
String orientString = exif.getAttribute(ExifInterface.TAG_ORIENTATION);
int orientation = orientString != null ? Integer.parseInt(orientString) :  ExifInterface.ORIENTATION_NORMAL;

int rotationAngle = 0;
if (orientation == ExifInterface.ORIENTATION_ROTATE_90) rotationAngle = 90;
if (orientation == ExifInterface.ORIENTATION_ROTATE_180) rotationAngle = 180;
if (orientation == ExifInterface.ORIENTATION_ROTATE_270) rotationAngle = 270;

Matrix matrix = new Matrix();
matrix.setRotate(rotationAngle, (float) bm.getWidth() / 2, (float) bm.getHeight() / 2);
Bitmap rotatedBitmap = Bitmap.createBitmap(bm, 0, 0, bounds.outWidth, bounds.outHeight, matrix, true);

UPDATE 2017-01-16

Avec la sortie de la bibliothèque de support 25.1.0, une bibliothèque de support ExifInterface a été introduite, ce qui devrait peut-être faciliter l'accès aux attributs Exif. Voir le Blog du développeur Android pour un article à ce sujet.

85
Ridcully

La réponse sélectionnée utilise la méthode la plus couramment utilisée pour répondre à cette question et à des questions similaires. Cependant, cela ne fonctionnait pas pour moi avec les appareils photo avant et arrière de Samsung. Pour ceux qui recherchent une autre solution compatible avec les appareils photo avant et arrière de Samsung et d'autres grands fabricants, cette réponse de nvhausid est géniale:

https://stackoverflow.com/a/18915443/6080472

Pour ceux qui ne veulent pas cliquer, la magie appropriée consiste à utiliser CameraInfo plutôt que de compter sur EXIF ​​ou un curseur sur les fichiers multimédias.

Bitmap realImage = BitmapFactory.decodeByteArray(data, 0, data.length);
Android.hardware.Camera.CameraInfo info = new Android.hardware.Camera.CameraInfo();
Android.hardware.Camera.getCameraInfo(mCurrentCameraId, info);
Bitmap bitmap = rotate(realImage, info.orientation);

Code complet dans le lien.

1
D. Scott