web-dev-qa-db-ja.com

Android EXIFデータのサイズ変更と保存(向き、回転など)

Androidアプリがデバイスのカメラを使用して写真を撮影し、サイズを変更する場合(これは、アップロードのサイズを小さくするために非常に一般的です)、このサイズ変更操作stripsExifメタデータ。

特に問題のデバイスが「Orientation」タグに依存して適切に画像を正しく表示している場合、これは問題を引き起こす可能性があります。

さまざまなAndroidデバイスはさまざまな方法でカメラ/画像の回転を処理します-私の信頼できる古いNexus Oneは、キャプチャ後すぐに画像を常に回転させるようです。

ただし、他のデバイス(特に私のテストではSamsung電話)は、画像ファイルのコンテンツをnot回転します-むしろ、Exif 'Orientation'タグを設定します。後で画像が表示されるときはいつでも、関連する画像コードは方向 'タグ'の存在を検出し、画像を適切に回転させる必要があります。しかし、画像に対してビットマップ処理を行って新しいファイルに保存した場合、Exifデータはすべて失われます。

オリエンテーションデータに加えて、メーカー/モデルなどの他の貴重なメタデータも失う可能性があります。

これは数週間私を混乱させました(電話ギャラリーに表示されたとき、画像は直立しているように見えますが、間違った向きで明らかなメタデータなしでサーバーに届きます)。他の人を助けるために、この自己質問をここに追加しています。このブログ投稿はとても役に立ちました。

AndroidはEXIF情報を失うことなく画像のサイズを変更します

48
Mike Repass

他の人が示しているように、Exifデータを元の画像から最終的なサイズ変更された画像にコピーする必要があります。 Sanselan Androidライブラリは通常、これに最適です。Android OSバージョンによっては、ExifInterfaceがExifdataを破損する場合があります。

さらに、ExifInterfaceは、限られた数のExifタグ、つまり「認識している」タグのみを処理します。一方、サンセランはすべてのExiftagとマーカーノートを保持します。

Sanselanを使用して画像データをコピーする方法を示すブログ投稿は次のとおりです。

サンセランを使用したExifメタデータのコピー

ところで、Android私はまた、画像を回転させ、Orientation Exiftagを削除する傾向があります。たとえば、Android 4.03、 Exifmetadataのオリエンテーションタグですが、WebViewはその情報を無視して画像を誤って表示していました。

18
Theo

私が知る限り、メタデータを自動的に永続化するnoメカニズムがあります。

むしろ、特定のプロパティを明示的にチェックし、ExifInterfaceを使用して新しいイメージファイルにそれらをコピーする必要があるようです。

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

のようなもの:

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();
}
43
Mike Repass

怠け者のために、ここに再利用可能な関数があります:

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();
}
30
prom85

Xamarin AndroidバージョンAndroid @ prom85のanswer(C#)および不要なタグのバージョン-画像のサイズ変更のためにコメントアウト(imagewidthなど)が、だれかが一般的なタグのコピーを必要とする場合のために残しておきます。

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

すでに2019年であり、 @ prom85Mike Repass 、および Theo によって提案されたものより良い答えはまだありません。

2016年、Androidチームが導入しました ExifInterface Support Library Androidバージョン間で一貫した動作をさせたい場合に最適なオプションは何ですか? 。タグのサブセットを作成することになりましたExifInterface#EXIF_TAGSソースコード )そして、このサブセットを繰り返し処理して、入力ファイルからメタデータを抽出し、出力に設定します。すべてのタグをコピーする必要がある場合は、コピーしないことをお勧めします!とにかくそれに応じていくつかのタグの値を更新する必要があります(例:TAG_IMAGE_LENGTHおよびTAG_IMAGE_WIDTH)。個人的に、最初にすべてのメテダタデータを保持する必要がある理由を質問し続けました(とにかく使用するデバイスとカメラ間で取得するものが異なります)。GPSの位置と日付/時刻データも保持する必要があることに気付きました。