web-dev-qa-db-fra.com

Android Image Redimensionnement et conservation des données EXIF ​​(orientation, rotation, etc.)

Si votre application Android utilise l'appareil photo du périphérique pour prendre une photo, puis la redimensionne (il est très courant de réduire la taille du téléchargement), vous ne réaliserez peut-être pas que cette opération de redimensionnement bandes est l'exif métadonnée.

Cela peut poser des problèmes, en particulier si le périphérique en question s’appuie sur la balise 'Orientation' pour afficher correctement l’image verticale.

Différents appareils Android gèrent la rotation de la caméra/des images de différentes manières - mon fidèle Nexus One semble toujours faire pivoter l'image immédiatement après la capture, de sorte que le contenu natif du fichier est toujours «vertical» lorsqu'il est visualisé. Cependant, d'autres appareils (en particulier les téléphones Samsung dans mes tests), ne font pas pivoter le contenu du fichier image; ils définissent plutôt la balise exif 'Orientation'. Chaque fois que l'image est affichée ultérieurement, le code d'image approprié doit détecter la présence de la "balise" d'orientation et faire pivoter l'image de manière appropriée. Mais si vous avez effectué un traitement bitmap sur l'image et l'avez enregistré dans un nouveau fichier, toutes ces données exif sont perdues.

En plus des données d'orientation, vous pourriez également perdre d'autres métadonnées utiles telles que marque/modèle, etc.

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

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

44
Mike Repass

Comme d'autres l'ont indiqué, vous devez copier les données EXIF ​​de l'image d'origine dans l'image redimensionnée finale. La bibliothèque Android de Sanselan est généralement la meilleure solution. Selon la version du système d'exploitation Android, ExifInterface corrompt parfois les données EXIF. En outre, ExifInterface gère également un nombre limité de balises Exif, à savoir uniquement les balises qu’elle "connaît". Sanselan, par contre, conservera toutes les balises EXIF ​​et les notes de marqueur.

Voici un article de blog qui explique comment utiliser Sanselan pour copier des données d'image: http://bricolsoftconsulting.com/copying-exif-metadata-using-sanselan/

BTW, sur Android, j'ai aussi tendance à faire pivoter les images et à supprimer le tag Orientation EXIF. Par exemple, sur un Nexus S avec Android 4.03, la caméra définissait une balise d’orientation dans les métadonnées EXIF, mais la vue Web ignorait ces informations et affichait l’image de manière incorrecte. Malheureusement, la rotation des données d'image réelles et la suppression de la balise d'orientation EXIF ​​constituent le seul moyen d'obtenir que chaque programme affiche les images correctement.

18
Theo

[réponse personnelle]

En fait, il existe un mécanisme no pour conserver automatiquement les métadonnées, voire les instantanés, et les transférer en bloc. 

Au contraire, il semble que vous deviez vérifier explicitement certaines propriétés et les copier vous-même dans le nouveau fichier image à l'aide de l'interface 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();
}
38
Mike Repass

Pour les plus 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
prom85

Voici la version Android de xamarin avec exifdata divisée en versions Android de la réponse de @ prom85 (C #) et des balises inutiles - pour le redimensionnement de l'image - commentées (largeur d'image, etc.) mais laissées au cas où quelqu'un aurait simplement besoin de copier des balises génériques. J'ai combiné toutes les étiquettes pré-guimauve, mais il y a quelques différences.

public static void CopyExif(String oldPath, String newPath) {
    ExifInterface oldExif = new ExifInterface(oldPath);
    String[] attributes;#region Exif Tags based on Android version
    if (Build.VERSION.SdkInt <= BuildVersionCodes.M) {
        attributes = new String[] {

            ExifInterface.TagGpsLongitudeRef,
            ExifInterface.TagGpsLongitude,
            ExifInterface.TagGpsLatitudeRef,
            ExifInterface.TagGpsLatitude,
            ExifInterface.TagSubsecTimeOrig,
            ExifInterface.TagSubsecTimeDigitized,
            ExifInterface.TagSubsecTimeDig,
            //ExifInterface.TagImageLength,
            ExifInterface.TagMake,
            ExifInterface.TagModel,
            ExifInterface.TagDatetime,
            ExifInterface.TagFocalLength,
            ExifInterface.TagGpsDatestamp,
            ExifInterface.TagGpsTimestamp,
            ExifInterface.TagGpsProcessingMethod,
            ExifInterface.TagGpsAltitude,
            ExifInterface.TagGpsAltitudeRef,
            ExifInterface.TagIso,
            ExifInterface.TagExposureTime,
            ExifInterface.TagDatetimeDigitized,
            ExifInterface.TagSubsecTime,

        };
    }
    else if (Build.VERSION.SdkInt <= BuildVersionCodes.N) {
        attributes = new String[] {

            ExifInterface.TagGpsLongitudeRef,
            ExifInterface.TagGpsLongitude,
            ExifInterface.TagGpsLatitudeRef,
            ExifInterface.TagGpsLatitude,
            ExifInterface.TagSubsecTimeOrig,
            ExifInterface.TagSubsecTimeDigitized,
            ExifInterface.TagSubsecTimeDig,
            // ExifInterface.TagImageLength,
            ExifInterface.TagMake,
            ExifInterface.TagModel,
            ExifInterface.TagDatetime,
            ExifInterface.TagFocalLength,
            ExifInterface.TagGpsDatestamp,
            ExifInterface.TagGpsTimestamp,
            ExifInterface.TagGpsProcessingMethod,
            ExifInterface.TagGpsAltitude,
            ExifInterface.TagGpsAltitudeRef,
            ExifInterface.TagIso,
            ExifInterface.TagExposureTime,
            ExifInterface.TagDatetimeDigitized,
            ExifInterface.TagSubsecTime,
            ExifInterface.TagGpsDestBearing,
            ExifInterface.TagGpsDestBearingRef,
            ExifInterface.TagGpsImgDirection,
            ExifInterface.TagGpsDestDistance,
            ExifInterface.TagGpsDestDistanceRef,
            ExifInterface.TagGpsDestLatitude,
            ExifInterface.TagGpsDestLatitudeRef,
            ExifInterface.TagGpsDestLongitude,
            ExifInterface.TagGpsDestLongitudeRef,
            ExifInterface.TagGpsDifferential,
            ExifInterface.TagGpsMeasureMode,
            ExifInterface.TagGpsMapDatum,
            ExifInterface.TagFocalPlaneYResolution,
            ExifInterface.TagGpsTrackRef,
            ExifInterface.TagGpsTrack,
            ExifInterface.TagGpsStatus,
            ExifInterface.TagGpsSpeedRef,
            ExifInterface.TagGpsSpeed,
            ExifInterface.TagFocalPlaneXResolution,
            ExifInterface.TagCompressedBitsPerPixel,
            ExifInterface.TagFocalPlaneResolutionUnit,
            ExifInterface.TagDigitalZoomRatio,
            ExifInterface.TagDeviceSettingDescription,
            ExifInterface.TagDatetimeOriginal,
            ExifInterface.TagApertureValue,
            ExifInterface.TagArtist,
            ExifInterface.TagBitsPerSample,
            ExifInterface.TagBrightnessValue,
            ExifInterface.TagCfaPattern,
            ExifInterface.TagColorSpace,
            ExifInterface.TagFocalLengthIn35mmFilm,
            ExifInterface.TagComponentsConfiguration,
            ExifInterface.TagCompression,
            ExifInterface.TagContrast,
            ExifInterface.TagCopyright,
            ExifInterface.TagCustomRendered,
            ExifInterface.TagFlashpixVersion,
            ExifInterface.TagFlashEnergy,
            ExifInterface.TagFlash,
            ExifInterface.TagFileSource,
            ExifInterface.TagFNumber,
            ExifInterface.TagImageDescription,
            ExifInterface.TagExposureProgram,
            ExifInterface.TagExposureMode,
            ExifInterface.TagExposureIndex,
            ExifInterface.TagExposureBiasValue,
            ExifInterface.TagExifVersion,
            ExifInterface.TagGpsImgDirectionRef,
            ExifInterface.TagGpsSatellites,
            ExifInterface.TagGpsDop,
            ExifInterface.TagSubjectArea,
            ExifInterface.TagSubjectDistance,
            ExifInterface.TagSubjectDistanceRange,
            ExifInterface.TagSpectralSensitivity,
            ExifInterface.TagSaturation,
            ExifInterface.TagYResolution,
            ExifInterface.TagYCbCrSubSampling,
            ExifInterface.TagYCbCrPositioning,
            ExifInterface.TagYCbCrCoefficients,
            ExifInterface.TagXResolution,
            ExifInterface.TagIsoSpeedRatings,
            ExifInterface.TagJpegInterchangeFormat,

            ExifInterface.TagJpegInterchangeFormatLength,

            ExifInterface.TagMakerNote,

            ExifInterface.TagImageUniqueId,

            ExifInterface.TagLightSource,

            ExifInterface.TagMaxApertureValue,

            ExifInterface.TagMeteringMode,

            ExifInterface.TagWhitePoint,

            ExifInterface.TagWhiteBalance,

            ExifInterface.TagUserComment,

            ExifInterface.TagTransferFunction,

            // ExifInterface.TagThumbnailImageWidth,

            //ExifInterface.TagThumbnailImageLength,

            ExifInterface.TagSubsecTimeOriginal,

            ExifInterface.TagSubjectLocation,

            ExifInterface.TagSceneCaptureType,

            ExifInterface.TagSceneType,

            ExifInterface.TagSensingMethod,

            ExifInterface.TagSharpness,

            ExifInterface.TagShutterSpeedValue,

            ExifInterface.TagSoftware,

            ExifInterface.TagSamplesPerPixel,

            ExifInterface.TagSpatialFrequencyResponse,

            ExifInterface.TagStripByteCounts,

            ExifInterface.TagStripOffsets,

            ExifInterface.TagOecf,

            ExifInterface.TagGpsVersionId,

        };
    }
    else

    {
        attributes = new String[] {

            ExifInterface.TagGpsLongitudeRef,
            ExifInterface.TagGpsLongitude,
            ExifInterface.TagGpsLatitudeRef,
            ExifInterface.TagGpsLatitude,
            ExifInterface.TagSubsecTimeOrig,
            ExifInterface.TagSubsecTimeDigitized,
            ExifInterface.TagSubsecTimeDig,
            // ExifInterface.TagImageLength,
            ExifInterface.TagMake,
            ExifInterface.TagModel,
            ExifInterface.TagDatetime,
            ExifInterface.TagFocalLength,
            ExifInterface.TagGpsDatestamp,
            ExifInterface.TagGpsTimestamp,
            ExifInterface.TagGpsProcessingMethod,
            ExifInterface.TagGpsAltitude,
            ExifInterface.TagGpsAltitudeRef,
            ExifInterface.TagIso,
            ExifInterface.TagExposureTime,
            ExifInterface.TagDatetimeDigitized,
            ExifInterface.TagSubsecTime,
            ExifInterface.TagGpsDestBearing,
            ExifInterface.TagGpsDestBearingRef,
            ExifInterface.TagGpsImgDirection,
            ExifInterface.TagGpsDestDistance,
            ExifInterface.TagGpsDestDistanceRef,
            ExifInterface.TagGpsDestLatitude,
            ExifInterface.TagGpsDestLatitudeRef,
            ExifInterface.TagGpsDestLongitude,
            ExifInterface.TagGpsDestLongitudeRef,
            ExifInterface.TagGpsDifferential,
            ExifInterface.TagGpsMeasureMode,
            ExifInterface.TagGpsMapDatum,
            ExifInterface.TagFocalPlaneYResolution,
            ExifInterface.TagGpsTrackRef,
            ExifInterface.TagGpsTrack,
            ExifInterface.TagGpsStatus,

            ExifInterface.TagGpsSpeedRef,

            ExifInterface.TagGpsSpeed,

            ExifInterface.TagFocalPlaneXResolution,

            ExifInterface.TagCompressedBitsPerPixel,

            ExifInterface.TagFocalPlaneResolutionUnit,

            ExifInterface.TagDigitalZoomRatio,

            ExifInterface.TagDeviceSettingDescription,

            ExifInterface.TagDatetimeOriginal,

            ExifInterface.TagApertureValue,

            ExifInterface.TagArtist,

            ExifInterface.TagBitsPerSample,

            ExifInterface.TagBrightnessValue,

            ExifInterface.TagCfaPattern,

            ExifInterface.TagColorSpace,

            ExifInterface.TagFocalLengthIn35mmFilm,

            ExifInterface.TagComponentsConfiguration,

            ExifInterface.TagCompression,

            ExifInterface.TagContrast,

            ExifInterface.TagCopyright,

            ExifInterface.TagCustomRendered,

            ExifInterface.TagFlashpixVersion,

            ExifInterface.TagFlashEnergy,

            ExifInterface.TagFlash,

            ExifInterface.TagFileSource,

            ExifInterface.TagFNumber,

            ExifInterface.TagImageDescription,

            ExifInterface.TagExposureProgram,

            ExifInterface.TagExposureMode,

            ExifInterface.TagExposureIndex,

            ExifInterface.TagExposureBiasValue,

            ExifInterface.TagExifVersion,

            ExifInterface.TagGpsImgDirectionRef,

            ExifInterface.TagGpsSatellites,

            ExifInterface.TagGpsDop,

            ExifInterface.TagSubjectArea,

            ExifInterface.TagSubjectDistance,

            ExifInterface.TagSubjectDistanceRange,

            ExifInterface.TagSpectralSensitivity,

            ExifInterface.TagSaturation,

            ExifInterface.TagYResolution,

            ExifInterface.TagYCbCrSubSampling,

            ExifInterface.TagYCbCrPositioning,

            ExifInterface.TagYCbCrCoefficients,

            ExifInterface.TagXResolution,

            ExifInterface.TagIsoSpeedRatings,

            ExifInterface.TagJpegInterchangeFormat,

            ExifInterface.TagJpegInterchangeFormatLength,

            ExifInterface.TagMakerNote,

            ExifInterface.TagImageUniqueId,

            ExifInterface.TagLightSource,

            ExifInterface.TagMaxApertureValue,

            ExifInterface.TagMeteringMode,

            ExifInterface.TagWhitePoint,

            ExifInterface.TagWhiteBalance,

            ExifInterface.TagUserComment,

            ExifInterface.TagTransferFunction,

            // ExifInterface.TagThumbnailImageWidth,

            //ExifInterface.TagThumbnailImageLength,

            ExifInterface.TagSubsecTimeOriginal,

            ExifInterface.TagSubjectLocation,

            ExifInterface.TagSceneCaptureType,

            ExifInterface.TagSceneType,

            ExifInterface.TagSensingMethod,

            ExifInterface.TagSharpness,

            ExifInterface.TagShutterSpeedValue,

            ExifInterface.TagSoftware,

            ExifInterface.TagSamplesPerPixel,

            ExifInterface.TagSpatialFrequencyResponse,

            ExifInterface.TagStripByteCounts,

            ExifInterface.TagStripOffsets,

            ExifInterface.TagOecf,

            ExifInterface.TagGpsVersionId,
            ExifInterface.TagRw2SensorRightBorder,

            ExifInterface.TagNewSubfileType,

            ExifInterface.TagOrfAspectFrame,

            ExifInterface.TagRw2SensorTopBorder,

            ExifInterface.TagSubfileType,

            ExifInterface.TagDngVersion,

            ExifInterface.TagDefaultCropSize

        };
    }#endregion

    ExifInterface newExif = new ExifInterface(newPath);

    foreach(var attribute in attributes) {
        String value = oldExif.GetAttribute(attribute);
        if (value != null) newExif.SetAttribute(attribute, value);
    }
    newExif.SaveAttributes();

}
0
kkarakk