Les images sockets avec ACTION_IMAGE_CAPTURE retournent toujours 1 pour ExifInterface.TAG_ORIENTATION sur certains périphériques plus récents

J’ai eu le problème de l’orientation lorsque je travaillais avec l’activité ACTION_IMAGE_CAPTURE . J’ai utilisé le TAG_ORIENTATION pour que je fasse pivoter l’image en conséquence. Mais maintenant, nous avons constaté que sur certains appareils plus récents, cela ne fonctionnait pas. En fait, il retourne 1 pour toutes les orientations.

Voici la liste des périphériques sur lesquels nous avons observé ceci;

  • Samsung Infuse 4G (2.3.3)
  • Samsung Galaxy SII X (2.3.5)
  • Sony Xperia Arc (2.3.3)

Chose intéressante, une fois que cette image est la galerie, elle apparaît correctement et si je la sélectionne, la TAG_ORIENTATION est correctement remplie. Ainsi, le OS remplit correctement ces informations, mais pas sur ActivityResult .

Quel est le moyen le plus fiable pour déterminer l’orientation? Quelqu’un sur une autre question a suggéré de comparer la hauteur et la largeur, mais lors de l’obtention de ces informations, celles-ci sont correctement modifiées en fonction de l’orientation (autre mystère).

EDIT: Il semble que cela puisse être connecté à un autre bug où le système d’exploitation duplique l’image prise dans la galerie (il est seulement supposé enregistrer l’image dans l’URL spécifiée par nous), la chose est que cette image dans la galerie celui de l’emplacement spécifié ne le fait pas.

Ceci est le bogue; http://code.google.com/p/android/issues/detail?id=19268

EDIT-2: J’ai déposé un nouveau bogue avec Android. Je suis sûr que c’est un bug lié au système d’exploitation mentionné ci-dessus. http://code.google.com/p/android/issues/detail?id=22822

Ok les gars, il semble que ce bug pour Android ne sera pas corrigé pendant un moment. Bien que j’ai trouvé un moyen d’implémenter ExifInformation de sorte que les deux périphériques (ceux avec une balise Exif correcte et également les tags d’exif impropres fonctionnent ensemble).

Le problème concerne donc certains périphériques (plus récents). Il existe un bogue qui permet d’enregistrer la photo enregistrée dans le dossier de l’application sans balises Exif, alors qu’une image correctement pivotée est enregistrée dans le dossier par défaut (même si elle ne devrait pas l’être). .

Maintenant, ce que je fais, c’est enregistrer l’heure à laquelle je lance l’application appareil photo depuis mon application. Sur le résultat de l’activité, je demande au fournisseur de média si des images ont été enregistrées après ce délai que j’ai enregistré. Cela signifie que, le plus probable, le système d’exploitation a enregistré l’image correctement tournée dans le dossier par défaut et a bien sûr placé une entrée dans le magasin de supports et nous pouvons utiliser les informations de rotation de cette ligne. Maintenant, pour nous assurer que nous regardons la bonne image, je compare la taille de ce fichier à celle à laquelle j’ai access (enregistrée dans mon propre dossier d’application);

  int rotation =-1; long fileSize = new File(filePath).length(); Cursor mediaCursor = content.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, new Ssortingng[] {MediaStore.Images.ImageColumns.ORIENTATION, MediaStore.MediaColumns.SIZE }, MediaStore.MediaColumns.DATE_ADDED + ">=?", new Ssortingng[]{Ssortingng.valueOf(captureTime/1000 - 1)}, MediaStore.MediaColumns.DATE_ADDED + " desc"); if (mediaCursor != null && captureTime != 0 && mediaCursor.getCount() !=0 ) { while(mediaCursor.moveToNext()){ long size = mediaCursor.getLong(1); //Extra check to make sure that we are getting the orientation from the proper file if(size == fileSize){ rotation = mediaCursor.getInt(0); break; } } } 

Maintenant, si la rotation à ce stade est toujours -1, cela signifie que c’est l’un des téléphones avec des informations de rotation correctes. À ce stade, nous pouvons utiliser l’orientation exif régulière sur le fichier renvoyé à notre onActivityResult

  else if(rotation == -1){ rotation = getExifOrientationAtsortingbute(filePath); } 

Vous pouvez facilement trouver comment trouver des orientations d’exif comme la réponse à cette question Problème d’orientation de l’ appareil photo dans Android

Notez également qu’ExifInterface est uniquement pris en charge après le niveau Api 5. Donc, si vous voulez prendre en charge les téléphones avant 2.0, vous pouvez utiliser cette bibliothèque pratique trouvée par java pour Drew Noakes; http://www.drewnoakes.com/code/exif/

Bonne chance avec votre image en rotation!

EDIT: Parce qu’il a été demandé, l’intention que j’ai utilisé et comment j’ai commencé était comme ça

 Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); //mediaFile is where the image will be saved intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(mediaFile)); startActivityForResult(intent, 1); 

vous pouvez aussi aller dans cette direction:

 Masortingx masortingx = new Masortingx(); // rotate the Bitmap (there a problem with exif so we'll query the mediaStore for orientation Cursor cursor = getApplicationContext().getContentResolver().query(selectedImage, new Ssortingng[] { MediaStore.Images.ImageColumns.ORIENTATION }, null, null, null); if (cursor.getCount() == 1) { cursor.moveToFirst(); int orientation = cursor.getInt(0); masortingx.preRotate(orientation); } 

En effet un bug problématique! Je ne suis pas sûr que j’aime la solution de contournement suggérée, alors en voici une autre 🙂

La clé est d’utiliser EXTRA_OUTPUT et de l’interroger lorsque l’image a été capturée! Évidemment, cela ne fonctionne que si vous vous autorisez à spécifier le nom du fichier.

 protected void takePictureSequence() { try { ContentValues values = new ContentValues(); values.put(MediaStore.Images.Media.TITLE, UUID.randomUUID().toSsortingng() + ".jpg"); newPhotoUri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); Intent intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE); intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, newPhotoUri); startActivityForResult(intent, ActivityResults.TAKE_NEW_PICTURE_RESULT); } catch (Exception e) { Toast.makeText(this, R.ssortingng.could_not_initalize_camera, Toast.LENGTH_LONG).show(); } } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == ActivityResults.TAKE_NEW_PICTURE_RESULT) { if (resultCode == RESULT_OK) { try { Ssortingng[] projection = { MediaStore.Images.Media.DATA }; CursorLoader loader = new CursorLoader(this, newPhotoUri, projection, null, null, null); Cursor cursor = loader.loadInBackground(); int column_index_data = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); cursor.moveToFirst(); // Rotation is stored in an EXIF tag, and this tag seems to return 0 for URIs. // Hence, we resortingeve it using an absolute path instead! int rotation = 0; Ssortingng realPath = cursor.getSsortingng(column_index_data); if (realPath != null) { rotation = ImageHelper.getRotationForImage(realPath); } // Now we can load the bitmap from the Uri, using the correct rotation. } } catch (Exception e) { e.printStackTrace(); } } } public int getRotationForImage(Ssortingng path) { int rotation = 0; try { ExifInterface exif = new ExifInterface(path); rotation = (int)exifOrientationToDegrees(exif.getAtsortingbuteInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL)); } catch (IOException e) { e.printStackTrace(); } return rotation; } 

Ce que j’ai appris récemment, c’est que si vous redimensionnez l’image, elle perd généralement ses informations EXIF. Vous voulez donc donner au nouveau fichier les anciennes informations EXIF.

La source.

Ma solution pour cela. Testé sur LG G2 mobile. J’ai remarqué que lorsque j’utilise l’appareil photo et que je prends une nouvelle photo, tout fonctionne bien. ExifInterface renvoie l’orientation correcte. Donc, ce doit être quelque chose dans le chemin car mon chemin était nul dans cette ligne de code:

 exif = new ExifInterface(path); 

mais quand j’ai utilisé le chemin absolu, mon application se bloque. Mais la solution réside dans cette méthode ci-dessous, car elle dépend de votre version de SDK. Une autre note à mentionner, j’ai utilisé le chemin absolu uniquement pour sélectionner la photo de la galerie, car si je l’ai utilisé pour la caméra, mon application est tombée en panne. Im nouveau dans la programmation et juste perdu 2 jours pour résoudre ce problème. J’espère que ça va aider quelqu’un.

  public Ssortingng getRealPathFromURI(Uri uri) { if(Build.VERSION.SDK_INT >= 19){ Ssortingng id = uri.getLastPathSegment().split(":")[1]; final Ssortingng[] imageColumns = {MediaStore.Images.Media.DATA }; final Ssortingng imageOrderBy = null; Uri tempUri = getUri(); Cursor imageCursor = getContentResolver().query(tempUri, imageColumns, MediaStore.Images.Media._ID + "="+id, null, imageOrderBy); if (imageCursor.moveToFirst()) { return imageCursor.getSsortingng(imageCursor.getColumnIndex(MediaStore.Images.Media.DATA)); }else{ return null; } }else{ Ssortingng[] projection = { MediaStore.MediaColumns.DATA }; Cursor cursor = getContentResolver().query(uri, projection, null, null, null); if (cursor != null) { int column_index = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA); cursor.moveToFirst(); return cursor.getSsortingng(column_index); } else return null; } } 

Donc, je reçois mon ExifInterface dans la méthode onActivityResult

 @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == GALLERY_IMAGE_REQUEST && resultCode == RESULT_OK && data != null) { try { exif = new ExifInterface(getRealPathFromURI(data.getData())); } catch (IOException e) { e.printStackTrace(); } showImage(data.getData()); } else if (requestCode == CAMERA_IMAGE_REQUEST && resultCode == RESULT_OK) { try { exif = new ExifInterface(Uri.fromFile(getCameraFile()).getPath()); } catch (IOException e) { e.printStackTrace(); } showImage(Uri.fromFile(getCameraFile())); } } 

et ma méthode d’image de spectacle ressemble à ceci

 public void showImage(Uri uri) { if (uri != null) { try { Bitmap bitmap = scaleBitmapDown(MediaStore.Images.Media.getBitmap(getContentResolver(), uri), IMAGE_SIZE); int orientation = exif.getAtsortingbuteInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL); bitmap = rotateBitmap(bitmap, orientation); if (whatPlayer.equals("Player1")) { mImagePlayer1.setImageBitmap(bitmap); bitmapPlayer1 = bitmap; //*save picture in static variable so other activity can use this } if (whatPlayer.equals("Player2")) { mImagePlayer2.setImageBitmap(bitmap); bitmapPlayer2 = bitmap; } } catch (IOException e) { Log.d(TAG, "Image picking failed because " + e.getMessage()); Toast.makeText(this, R.ssortingng.image_picker_error, Toast.LENGTH_LONG).show(); } } else { Log.d(TAG, "Image picker gave us a null image."); Toast.makeText(this, R.ssortingng.image_picker_error, Toast.LENGTH_LONG).show(); } }