Exif情報の中の位置情報を削除する方法


Posted on 2021/9/10 at 4:24


デジカメやスマホで撮影した写真には、Exif情報という撮影日時や撮影に使用した設定内容が自動で付与されています。

さらにスマホのカメラアプリで撮影した画像には、GPSの設定によっては撮影した位置情報が付与されます。 「これどこで撮った写真だっけ?」なんて困ることがなくなるため便利ではありますが、 SNSやブログなどにそのまま画像をアップロードすると、個人情報が漏洩してしまう可能性があります。

そういったトラブルに巻き込まれないようExif情報は削除するか、スマホのカメラアプリの位置情報はOFFにしておくことをおすすめいたしますが、 どうしても位置情報を残しておきたい場合は、SNSやブログなどに画像をアップロードする前に位置情報を削除しておきましょう。

今回はWindows標準機能により削除する方法と、プログラミングにより削除する方法を紹介します。

Windows標準機能を使用した方法

画像のプロパティを開いて、「詳細」タブをクリックすると画像内のExif情報画面を開きます。

その下の方に「プロパティや個人情報を削除」という項目があるので、そこをクリックすると削除画面に移動します。

「可能なすべてのプロパティを削除してコピーを作成」を選択すればGPS情報のうち、位置情報は削除してくれます。

「このファイルから次のプロパティを削除」を選択すれば、GPS情報以外のExif情報も削除可能です。

方法としては最も簡単だと思いますが、1ファイルずつ削除しなければならないためファイルが複数ある場合には向いていません。

プログラミング(Java)により削除する方法

Apache Commons Imagingというライブラリを使用してGPSに関する情報を全て削除します。

サンプルコードでは単一ファイルを指定して削除していますが、少しコードを変更すればディレクトリ内の全ての画像のExif情報を削除する事が可能です。

Apache Commons Imagingのダウンロード

Apache Commons Imagingのダウンロードページ の「Binaries」から 「commons-imaging-1.0-alpha2-bin.zip」をダウンロード、 解凍し使用しているIDEのプロジェクトの「ビルド・パス」にcommons-imaging-1.0-alpha2.jarを追加します。 もし、最新版がある場合はそちらをダウンロードしてください。

サンプルコード

jpgディレクトリ内のsrc.jpgファイルを読み込んで、gps情報を削除した後、同じディレクトリ内にdest.jpgとして出力します。

  			
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.List;

import org.apache.commons.imaging.ImageReadException;
import org.apache.commons.imaging.ImageWriteException;
import org.apache.commons.imaging.Imaging;
import org.apache.commons.imaging.common.ImageMetadata;
import org.apache.commons.imaging.formats.jpeg.JpegImageMetadata;
import org.apache.commons.imaging.formats.jpeg.exif.ExifRewriter;
import org.apache.commons.imaging.formats.tiff.TiffField;
import org.apache.commons.imaging.formats.tiff.TiffImageMetadata;
import org.apache.commons.imaging.formats.tiff.constants.ExifTagConstants;
import org.apache.commons.imaging.formats.tiff.write.TiffOutputDirectory;
import org.apache.commons.imaging.formats.tiff.write.TiffOutputField;
import org.apache.commons.imaging.formats.tiff.write.TiffOutputSet;

public class RemoveMetadata {
	
	public static void main(String[] args) {
		try {
			File src = new File("jpg/src.jpg");
			File dest = new File("jpg/dest.jpg");
			System.out.println("*** GPS情報削除前 ***");
			readMetadata(src);
			removeMetadata(src, dest);
			System.out.println("\n*** GPS情報削除後 ***");
			readMetadata(dest);
		} catch (ImageReadException | IOException e) {
			e.printStackTrace();
		} catch (ImageWriteException e) {
			e.printStackTrace();
		}
	}
	
    public static void removeMetadata(File src, File dest) throws ImageReadException, IOException, ImageWriteException {
        final ImageMetadata metadata = Imaging.getMetadata(src);
        if (metadata instanceof JpegImageMetadata) {
        	TiffOutputSet outputSet = null;
            final JpegImageMetadata jpegMetadata = (JpegImageMetadata) metadata;
            final TiffImageMetadata exif = jpegMetadata.getExif();
            if (exif != null) {
                outputSet = exif.getOutputSet();
                if (outputSet == null)
                    outputSet = new TiffOutputSet();
                TiffOutputDirectory gpsDirectory = outputSet.getGPSDirectory();
                List gpsFields = gpsDirectory.getFields();
                for (TiffOutputField gpsField: gpsFields)
                	gpsDirectory.removeField(gpsField.tag);
                outputSet.removeField(ExifTagConstants.EXIF_TAG_GPSINFO);
                FileOutputStream fos = new FileOutputStream(dest);
                OutputStream os = new BufferedOutputStream(fos);
                new ExifRewriter().updateExifMetadataLossless(src, os, outputSet);
                final List fields = exif.getAllFields();
                for (final TiffField field: fields) {
                	System.out.println(getFieldInfo(field));
                }
            }
        }
    }

    private static void readMetadata(File file) throws ImageReadException, IOException {
        final ImageMetadata metadata = Imaging.getMetadata(file);
        if (metadata instanceof JpegImageMetadata) {
            final JpegImageMetadata jpegMetadata = (JpegImageMetadata) metadata;
            final TiffImageMetadata exif = jpegMetadata.getExif();
            final List fields = exif.getAllFields();
            for (final TiffField field: fields) {
            	System.out.println(getFieldInfo(field));
            }
        }
    }

    private static String getFieldInfo(TiffField field) {
        return field.getTag() +
                " " +
                field.getTagInfo().name +
                ": " +
                field.getValueDescription();
    }
    
}
			
  		

実効結果

ExifのGPS情報を削除する前後のExif情報を標準出力しています。GPS関連のExif情報が削除されているのがわかります。

src.jpg内のExif情報の出力内容。位置情報であるGPSLatitude、GPSLongitude、GPSAltitude、それ以外にもGPS関連のExif情報があるのがわかります。

dest.jpg内のExif情報の出力内容。GPS関連のExif情報が全て削除されました。

ちなにみWindows標準機能で削除した場合は、GPS情報のうちGPSLatitude、GPSLongitude、GPSAltitudeのみが削除されるようですね。


関連記事

JavaでEXIF情報を取得するサンプルプログラム

デジカメやiPhoneで撮影した写真には、Exif情報という撮影日時や撮影に使用した設定内容が自動で付与されています。 今回はApache Commons Imagingというライブラリを使用してJPEG画像内のExif情報を読み込んでみます。

関連記事

JavaでEXIFを取得し、画像を正しい向きに回転させる

Apache Commons Imagingというライブラリを使用して 画像の回転に関するEXIFデータを読み取って、正しい向きに修正した状態で保存するサンプルプログラム。