GRV In the groove

手作りソフト実験室

手作りソフト実験室では、基本的なプログラミングで何が出来るかを実験します。

1 指定フォルダ以下のJPGファイルEXIF情報をCSV出力する

開発環境がフリーで用意できるjavaにて実験です。 最初にする実験にしては、初心者向きでないかもしれません。

手元のPCでは2万枚以上の画像ファイルを検索し、内部記録情報をファイルにリスト出力できました。ただし実験ソフトなのでGUI処理は含みません。

指定フォルダ以下のファイル再帰検索

C言語で同じ処理を書くと大変ですが、javaには指定フォルダ(ディレクトリ)のファイルを列挙する便利な機能があります。4行目の dir.listFiles() です。

            
    //指定する親ディレクトリと出力ファイルのハンドラをパラメータとして渡す
    private static void WriteExifList(File dir, PrintWriter pw) {
    	
        File[] fs = dir.listFiles();

        for (File f : fs) {
        	//ディレクトリか判断
            if (f.isDirectory()) {
            	//ディレクトリならば再帰処理(自分自身を呼ぶ
            	WriteExifList(f, pw);
            } else if (f.isFile()) {
                try {
                     if(isJpgFile(f)){
                    	f.getCanonicalPath();
                    	
                        try {
                            //Exif情報抽出 
                            
                            //出力処理
                            //
						//以下、例外処理
                        } catch (JpegProcessingException e) {
                            // handle exception
                        } catch (IOException e) {
                            // handle exception
                        } catch (NullPointerException e) {
                            // handle exception
                        }           
                    	
                    }
                //例外処理
                } catch (IOException ex) {
                    // do nothing
                }
            }
        }

    } 

JPEGファイルよりEXIF情報(撮影時のデータ)を抽出

公開されているEXIF抽出JAVAライブラリmetadata-extractorを利用させていただきました。 releases pageにあるmetadata-extractor-2.9.1.zipをダウンロードして解凍します。

解凍した ①metadata-extractor-2.9.1.jarと②xmpcore-5.1.2.jarをJava開発環境とランタイムライブラリ2か所に保存します。 使用方法についてはここのExample 2を参考にしました。

 
//必要なライブラリをインポート
import com.drew.imaging.ImageMetadataReader;
import com.drew.imaging.ImageProcessingException;
import com.drew.imaging.jpeg.JpegMetadataReader;
import com.drew.imaging.jpeg.JpegProcessingException;
import com.drew.imaging.jpeg.JpegSegmentMetadataReader;
import com.drew.metadata.Metadata;
import com.drew.metadata.exif.ExifReader;
import com.drew.metadata.exif.ExifSubIFDDirectory;
import com.drew.metadata.iptc.IptcReader;

// 画像ファイルのハンドラを f とすると以下のように撮影日時情報を取り出します
        Metadata metadata = JpegMetadataReader.readMetadata(f, readers);
        
        ExifSubIFDDirectory directory = metadata.getFirstDirectoryOfType(ExifSubIFDDirectory.class);

        Date date = directory.getDate(ExifSubIFDDirectory.TAG_DATETIME_DIGITIZED);
                            

ソースコード全体

画像ファイルは拡張子が"jpg"か"JPG"かで判断する簡易方法です。EXIF情報の中から今回は記録日時情報だけ取り出しています。
なお、末尾一行は不要です。

import com.drew.imaging.ImageMetadataReader;
import com.drew.imaging.ImageProcessingException;
import com.drew.imaging.jpeg.JpegMetadataReader;
import com.drew.imaging.jpeg.JpegProcessingException;
import com.drew.imaging.jpeg.JpegSegmentMetadataReader;
import com.drew.metadata.Metadata;
import com.drew.metadata.exif.ExifReader;
import com.drew.metadata.exif.ExifSubIFDDirectory;
import com.drew.metadata.iptc.IptcReader;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

public class RecDir {
	
	// pwd: the current directory 
	static String pwd = new File(".").getAbsoluteFile().getParent();
	static int	n=1;

    public static void main(String[] args) {
        File dir = new File("j:\\マイピクチャ\\2015");
        //File dir = new File("j:\\マイピクチャ");
        //File dir = new File(pwd);
        try {
        	
			//BufferedWriter bw=new BufferedWriter(new FileWriter("jpgList.txt"));
			PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter("jpgList.csv")));

			WriteExifList(dir, pw);
			pw.close();
		} catch (IOException e) {
			// TODO 自動生成された catch ブロック
			e.printStackTrace();
		}       
    }

    private static void WriteExifList(File dir, PrintWriter pw) {
    	
        File[] fs = dir.listFiles();

        for (File f : fs) {
            if (f.isDirectory()) {
            	WriteExifList(f, pw);
            } else if (f.isFile()) {
                try {

                	if(isJpgFile(f)){
                       	String path = f.getCanonicalPath();
                    	
                        try {
                            Iterable readers = Arrays.asList(new ExifReader(), new IptcReader());

                            Metadata metadata = JpegMetadataReader.readMetadata(f, readers);
                            
                            ExifSubIFDDirectory directory = metadata.getFirstDirectoryOfType(ExifSubIFDDirectory.class);

                            Date date = directory.getDate(ExifSubIFDDirectory.TAG_DATETIME_DIGITIZED);
                            
                            System.out.print(n+"  ");
                            System.out.print(date+"    ");
                            System.out.println(f.getCanonicalPath());
                            
                            pw.print(n);
                            pw.print("\t");
                            pw.write(date.toString());
                            pw.write("\t");
                            pw.write(path);
                            pw.write("\n");
                            n++;
                            //print(metadata);

                        } catch (JpegProcessingException e) {
                            // handle exception
                        } catch (IOException e) {
                            // handle exception
                        } catch (NullPointerException e) {
                            // handle exception
                        }           
                    	
                    }
                } catch (IOException ex) {
                    // do nothing
                }
            }
        }

    }
    static boolean isJpgFile(File file) {
    	return file.isFile() && file.canRead() && ((file.getPath().endsWith(".jpg") || (file.getPath().endsWith(".JPG"))));
    }
}

1 2 3 次へ