42 votes

Les Images prises avec ACTION_IMAGE_CAPTURE retourne toujours 1 pour ExifInterface.TAG_ORIENTATION sur certains appareils récents

J'ai eu la question de l'orientation lorsque vous travaillez avec des ACTION_IMAGE_CAPTURE de l'activité. J'ai utilisé l' TAG_ORIENTATION , de sorte que je voudrais faire pivoter l'image en conséquence. Mais maintenant, nous avons constaté que sur certains appareils récents, cela ne fonctionne pas. En fait, il renvoie 1 pour toutes les orientations.

Voici la liste des appareils nous avons observé cela sur;

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

Chose intéressante, c'est qu'une fois cette image de la galerie, elle s'affiche correctement et si je le sélectionner, l' TAG_ORIENTATION est rempli correctement. Donc, en quelque sorte l' OS remplit correctement cette information, mais pas sur l' ActivityResult.

Quel est le moyen le plus fiable de la figure de l'orientation? Quelqu'un sur une autre question a suggéré la comparaison de la hauteur et la largeur, mais lors de l'obtention de ceux-ci, ils sont bien basé sur la commutation sur l'orientation (un mystère)

EDIT: Il semble que cela pourrait être connecté à un autre bug où le système d'exploitation de dupliquer l'image prise dans la galerie (c'est supposé enregistrer l'image dans l'URL spécifiée par nous), le truc, c'est cette image dans la galerie a l' ORIENTATION d'informations tandis que l'un dans l'emplacement spécifié ne pas.

C'est le bug; http://code.google.com/p/android/issues/detail?id=19268

EDIT 2: j'ai déposé un nouveau bug avec Android. Je suis assez sûr que c'est un OS bug lié ladite bug. http://code.google.com/p/android/issues/detail?id=22822

56voto

Tolga E Points 1995

Ok les gars, il semble que ce bug pour android ne sera pas corrigé depuis un moment. Même si j'ai trouvé un moyen de mettre en œuvre les ExifInformation afin que les deux appareils (avec la bonne balise Exif, et aussi une mauvaise tags exif travailler ensemble)..

Donc, la question est sur certaines (les plus récents) des appareils, il y a un bug qui fait que la photo prise enregistré dans votre dossier app sans balises exif tout un bon sens de l'image est enregistré dans l'android dossier par défaut (même si elle ne devrait pas l'être)..

Maintenant ce que je fais est, j'enregistre le temps quand je suis démarrage de l'application appareil photo à partir de mon application. Ensuite, sur l'activité résultat, j'ai une requête au Fournisseur de Médias pour voir si des photos ont été enregistrées après cette date / heure, j'ai sauvé. Cela signifie que, très probablement OS enregistré le correctement rotation de l'image dans le dossier par défaut et bien sûr, mettre une entrée dans la boutique multimédia et nous pouvons utiliser les informations de rotation à partir de cette ligne. Maintenant, assurez-vous que nous sommes à la recherche à la droite de l'image, je compare la taille de ce fichier à celui que j'ai accès à l' (enregistré dans mon dossier app);

    int rotation =-1;
    long fileSize = new File(filePath).length();

    Cursor mediaCursor = content.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, new String[] {MediaStore.Images.ImageColumns.ORIENTATION, MediaStore.MediaColumns.SIZE }, MediaStore.MediaColumns.DATE_ADDED + ">=?", new String[]{String.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 encore -1, cela signifie que c'est l'un des téléphones avec une rotation de l'information. À ce stade, nous pouvons l'utilisation de l'orientation exif sur le fichier qui est retourné à notre onActivityResult

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

Vous pouvez facilement trouver comment trouver exif orientations comme la réponse à cette question de l'orientation de l'Appareil problème dans android

Notez également que ExifInterface est uniquement pris en charge après l'Api de niveau 5.. Donc si vous voulez soutenir les téléphones avant 2.0, vous pouvez utiliser cette pratique de la bibliothèque que j'ai trouvé pour java courtoisie de Drew Noakes; http://www.drewnoakes.com/code/exif/

Bonne chance avec votre image de tourner!

EDIT: Parce que c'était demandé, l'intention que j'ai utilisé et que j'ai commencé comme cela a été

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

7voto

oferiko Points 143

vous pouvez aller de cette façon:

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

7voto

l33t Points 2845

En effet, un problème de bug! Je ne suis pas sûr que j'aime la solution de contournement proposée, donc voici un autre :)

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

protected void takePictureSequence() {      
    try {
        ContentValues values = new ContentValues();  
        values.put(MediaStore.Images.Media.TITLE, UUID.randomUUID().toString() + ".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.string.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 {
                String[] 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 retrieve it using an absolute path instead!
                int rotation = 0;
                String realPath = cursor.getString(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(String path) {
    int rotation = 0;

    try {
        ExifInterface exif = new ExifInterface(path);
        rotation = (int)exifOrientationToDegrees(exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL));
    } catch (IOException e) {
        e.printStackTrace();
    }

    return rotation;
}

2voto

user3677912 Points 18

Ce que j'ai appris récemment, c'est que si vous redimensionnez l'image, il perd ses informations EXIF. Alors que vous souhaitez donner au fichier nouveau le vieux les informations EXIF.

Source.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X