Redimensionnement de L'image Android et conservation des données EXIF (Orientation, Rotation, etc) )

si votre application Android utilise la caméra de l'appareil pour prendre une photo et puis redimensionne (c'est très, très courant pour réduire la taille pour le téléchargement), vous pourriez ne pas réaliser que cette opération redimensionner bandes les métadonnées exif.

cela peut causer des problèmes, surtout si l'appareil en question s'appuie sur la balise "Orientation" pour afficher correctement l'image droite.

différents appareils Android gérer caméra / rotation de l'image dans de différentes façons - mon fidèle Vieux Nexus One semble toujours tourner l'image immédiatement après la capture, de sorte que le contenu natif du fichier est toujours "droit" lorsqu'il est vu. Cependant, d'autres appareils (en particulier Les Téléphones Samsung dans mes tests), ne pas tourner le contenu du fichier image - plutôt, ils mettent la balise "Orientation" exif. Chaque fois que l'image est affichée plus tard, le code d'image approprié devrait détecter la présence de la "balise" D'Orientation et faire tourner l'image de manière appropriée. Mais si vous avez fait tout traitement de bitmap sur l'image et enregistrez-le dans un nouveau fichier, les données exif sont perdues.

en plus des données D'Orientation, vous pourriez également perdre d'autres métadonnées précieuses telles que make/model, etc.

cela m'a déconcerté pendant quelques semaines (l'image apparaît droite lorsqu'elle est affichée dans la galerie téléphonique, mais arrive ensuite sur mon serveur avec une mauvaise orientation et aucune métadonnée apparente). J'ajoute cette question pour aider les autres. Ce blog post a été très utile:

http://vikaskanani.wordpress.com/2011/07/17/android-re-size-image-without-loosing-exif-information /

41
demandé sur Mike Repass 2012-11-28 05:52:43

3 réponses

comme d'autres l'ont indiqué, vous devez copier les données EXIF de l'image originale à l'image finale redimensionnée. La bibliothèque Android de Sanselan est typiquement la meilleure pour cela. Selon la version Android OS, L'ExifInterface corrompt parfois les données EXIF. En outre, L'ExifInterface gère également un nombre limité de tags Exif, à savoir uniquement les tags qu'il "connaît". Par contre, Sanselan conservera toutes les étiquettes EXIF et les notes de marquage.

voici un billet de blog cela montre comment utiliser Sanselan pour copier des données d'image: http://bricolsoftconsulting.com/copying-exif-metadata-using-sanselan /

BTW, sur Android j'ai également tendance à tourner les images et supprimer L'Orientation étiquette EXIF. Par exemple, sur un Nexus S avec Android 4.03, la caméra mettait une balise d'orientation dans les métadonnées EXIF, mais le webview ignorait cette information et affichait l'image incorrectement. Malheureusement, la rotation des données d'image réelle et la suppression de la balise d'orientation EXIF est le seul moyen d'obtenir que chaque programme affiche les images correctement.

16
répondu Theo 2013-06-18 17:23:14

[auto réponse]

Afaict, il y a le mécanisme no pour persister les métadonnées automatiquement ou même snapshot ce qui est là et transférer en vrac.

plutôt, il semble que vous devez vérifier explicitement les propriétés spécifiques et les copier vous-même dans le nouveau fichier image en utilisant L'ExifInterface.

http://developer.android.com/reference/android/media/ExifInterface.html

donc quelque chose comme:

ExifInterface oldExif = new ExifInterface(oldImagePath);
String exifOrientation = oldExif.getAttribute(ExifInterface.TAG_ORIENTATION);

if (exifOrientation != null) {
   ExifInterface newExif = new ExifInterface(imagePath);
   newExif.setAttribute(ExifInterface.TAG_ORIENTATION, exifOrientation);
   newExif.saveAttributes();
}
37
répondu Mike Repass 2015-04-25 11:28:56

pour les paresseux, voici une fonction réutilisable:

public static void copyExif(String oldPath, String newPath) throws IOException
{
    ExifInterface oldExif = new ExifInterface(oldPath);

    String[] attributes = new String[]
    {
            ExifInterface.TAG_APERTURE,
            ExifInterface.TAG_DATETIME,
            ExifInterface.TAG_DATETIME_DIGITIZED,
            ExifInterface.TAG_EXPOSURE_TIME,
            ExifInterface.TAG_FLASH,
            ExifInterface.TAG_FOCAL_LENGTH,
            ExifInterface.TAG_GPS_ALTITUDE,
            ExifInterface.TAG_GPS_ALTITUDE_REF,
            ExifInterface.TAG_GPS_DATESTAMP,
            ExifInterface.TAG_GPS_LATITUDE,
            ExifInterface.TAG_GPS_LATITUDE_REF,
            ExifInterface.TAG_GPS_LONGITUDE,
            ExifInterface.TAG_GPS_LONGITUDE_REF,
            ExifInterface.TAG_GPS_PROCESSING_METHOD,
            ExifInterface.TAG_GPS_TIMESTAMP,
            ExifInterface.TAG_IMAGE_LENGTH,
            ExifInterface.TAG_IMAGE_WIDTH,
            ExifInterface.TAG_ISO,
            ExifInterface.TAG_MAKE,
            ExifInterface.TAG_MODEL,
            ExifInterface.TAG_ORIENTATION,
            ExifInterface.TAG_SUBSEC_TIME,
            ExifInterface.TAG_SUBSEC_TIME_DIG,
            ExifInterface.TAG_SUBSEC_TIME_ORIG,
            ExifInterface.TAG_WHITE_BALANCE
    };

    ExifInterface newExif = new ExifInterface(newPath);
    for (int i = 0; i < attributes.length; i++)
    {
        String value = oldExif.getAttribute(attributes[i]);
        if (value != null)
            newExif.setAttribute(attributes[i], value);
    }
    newExif.saveAttributes();
}
23
répondu prom85 2015-11-05 19:38:53