4 import java.nio.channels.FileChannel;
\r
5 import java.text.DateFormat;
\r
6 import java.text.DecimalFormat;
\r
7 import java.text.ParseException;
\r
8 import java.text.SimpleDateFormat;
\r
9 import java.util.ArrayList;
\r
10 import java.util.Arrays;
\r
11 import java.util.Calendar;
\r
12 import java.util.Comparator;
\r
13 import java.util.Date;
\r
14 import java.util.Map;
\r
15 import java.util.ResourceBundle;
\r
16 import java.util.TimeZone;
\r
17 import java.util.logging.LogManager;
\r
18 import java.util.logging.Logger;
\r
20 import javax.xml.parsers.*;
\r
21 import javax.xml.transform.TransformerException;
\r
23 import org.apache.commons.imaging.ImageReadException;
\r
24 import org.apache.commons.imaging.ImageWriteException;
\r
25 import org.apache.commons.imaging.Imaging;
\r
26 import org.apache.commons.imaging.common.ImageMetadata;
\r
27 import org.apache.commons.imaging.common.RationalNumber;
\r
28 import org.apache.commons.imaging.formats.jpeg.JpegImageMetadata;
\r
29 import org.apache.commons.imaging.formats.jpeg.exif.ExifRewriter;
\r
30 import org.apache.commons.imaging.formats.tiff.TiffImageMetadata;
\r
31 import org.apache.commons.imaging.formats.tiff.constants.ExifTagConstants;
\r
32 import org.apache.commons.imaging.formats.tiff.constants.GpsTagConstants;
\r
33 import org.apache.commons.imaging.formats.tiff.write.TiffOutputDirectory;
\r
34 import org.apache.commons.imaging.formats.tiff.write.TiffOutputSet;
\r
35 import org.w3c.dom.*;
\r
36 import org.xml.sax.SAXException;
\r
38 public class ImportPicture extends Thread {
\r
41 * 実行中に発生したExceptionを保持する場所
\r
43 public Exception ex = null;
\r
46 * ログ設定プロパティファイルのファイル内容
\r
48 protected static final String LOGGING_PROPERTIES_DATA
\r
49 = "handlers=java.util.logging.ConsoleHandler\n"
\r
51 + "java.util.logging.ConsoleHandler.level=INFO\n"
\r
52 + "java.util.logging.ConsoleHandler.formatter=osm.jp.gpx.YuuLogFormatter";
\r
55 * static initializer によるログ設定の初期化
\r
57 public static final Logger LOGGER = Logger.getLogger("CommandLogging");
\r
59 InputStream inStream = null;
\r
61 inStream = new ByteArrayInputStream(LOGGING_PROPERTIES_DATA.getBytes("UTF-8"));
\r
63 LogManager.getLogManager().readConfiguration(inStream);
\r
64 // "ログ設定: LogManagerを設定しました。"
\r
65 LOGGER.config("LoggerSettings: LogManager setuped.");
\r
67 catch (IOException e) {
\r
68 // LogManager設定の際に例外が発生しました.
\r
69 String str = "LoggerSettings: Exception occered:" + e.toString();
\r
70 LOGGER.warning(str);
\r
73 catch (UnsupportedEncodingException e) {
\r
74 String str = "LoggerSettings: Not supported 'UTF-8' encoding: " + e.toString();
\r
79 if (inStream != null) {
\r
82 } catch (IOException e) {
\r
83 String str = "LoggerSettings: Exception occored: "+ e.toString();
\r
84 LOGGER.warning(str);
\r
90 * 画像ファイルをGPXファイルに取り込みます。
\r
92 * ・画像ファイルの更新日付をその画像の撮影日時とします。(Exi情報は無視します)
\r
93 * ※ 対象とするファイルは'*.jpg'のみ
\r
94 * ・精確な時刻との時差を入力することで、撮影日時を補正します。
\r
95 * ・画像ファイルの更新日付リストをCSV形式のファイルとして出力する。
\r
96 * ・・結果は、取り込み元のGPXファイルとは別に、元ファイル名にアンダーバー「_」を付加した.ファイルに出力します。
\r
98 * exp) $ java -cp .:AdjustTime.jar:commons-imaging-1.0-SNAPSHOT.jar [AdjustTime.ini]
\r
99 * exp) > java -cp .;AdjustTime.jar;commons-imaging-1.0-SNAPSHOT.jar [AdjustTime.ini]
\r
102 * argv[0] = INIファイルのパス名
\r
105 * argv[0] = 画像ファイルが格納されているディレクトリ --> imgDir
\r
106 * argv[1] = 時刻補正の基準とする画像ファイル --> baseFile
\r
107 * argv[2] = 基準画像ファイルの精確な撮影日時 "yyyy-MM-dd'T'HH:mm:ss" --> timeStr
\r
108 * argv[3] = 出力先フォルダ --> outDir
\r
109 * argv[4] = 撮影位置をロギングしたGPXファイル --> gpxDir
\r
111 * @throws IOException
\r
112 * @throws ImageReadException
\r
114 public static void main(String[] argv) throws Exception
\r
116 ImportPicture obj = new ImportPicture();
\r
117 obj.setUp(((argv.length < 1) ? AppParameters.FILE_PATH : argv[0]));
\r
120 public File gpxDir;
\r
121 public File imgDir;
\r
122 public File outDir;
\r
123 public long delta = 0;
\r
124 public boolean exif = false;
\r
125 public boolean exifBase = false;
\r
126 public ArrayList<File> gpxFiles = new ArrayList<>();
\r
127 public AppParameters params;
\r
128 public boolean param_GpxSplit = false;
\r
129 public static boolean param_GpxNoFirstNode = false;
\r
130 public boolean param_GpxReuse = false;
\r
131 public boolean param_GpxOutputWpt = true;
\r
132 public boolean param_ImgOutputAll = false;
\r
133 public String param_GpxSourceFolder = ".";
\r
135 public static final String TIME_FORMAT_STRING = "yyyy-MM-dd'T'HH:mm:ss'Z'";
\r
136 private static final String EXIF_DATE_TIME_FORMAT_STRING = "yyyy:MM:dd HH:mm:ss";
\r
137 public ResourceBundle i18n = ResourceBundle.getBundle("i18n");
\r
139 public void setUp(String paramFilePath) throws Exception {
\r
140 System.out.println("Param File = '"+ paramFilePath +"'");
\r
141 this.params = new AppParameters(paramFilePath);
\r
145 System.out.println(" - param: "+ AppParameters.IMG_TIME +"="+ this.params.getProperty(AppParameters.IMG_TIME) );
\r
146 System.out.println(" - param: "+ AppParameters.IMG_BASE_FILE +"="+ this.params.getProperty(AppParameters.IMG_BASE_FILE) );
\r
147 System.out.println(" - param: "+ AppParameters.GPX_BASETIME +"="+ this.params.getProperty(AppParameters.GPX_BASETIME) );
\r
148 System.out.println(" - param: "+ AppParameters.IMG_SOURCE_FOLDER +"="+ this.params.getProperty(AppParameters.IMG_SOURCE_FOLDER) );
\r
149 System.out.println(" - param: "+ AppParameters.IMG_OUTPUT_FOLDER +"="+ this.params.getProperty(AppParameters.IMG_OUTPUT_FOLDER) );
\r
150 System.out.println(" - param: "+ AppParameters.IMG_OUTPUT +"="+ this.params.getProperty(AppParameters.IMG_OUTPUT));
\r
151 System.out.println(" - param: "+ AppParameters.IMG_OUTPUT_ALL +"="+ this.param_ImgOutputAll);
\r
152 System.out.println(" - param: "+ AppParameters.IMG_OUTPUT_EXIF +"= "+ String.valueOf(this.exif));
\r
153 System.out.println(" - param: "+ AppParameters.GPX_SOURCE_FOLDER +"="+ this.param_GpxSourceFolder);
\r
154 System.out.println(" - param: "+ AppParameters.GPX_OUTPUT_WPT +"="+ this.param_GpxOutputWpt);
\r
155 System.out.println(" - param: "+ AppParameters.GPX_OVERWRITE_MAGVAR +"="+ Complementation.param_GpxOverwriteMagvar);
\r
156 System.out.println(" - param: "+ AppParameters.GPX_OUTPUT_SPEED +"="+ Complementation.param_GpxOutputSpeed);
\r
157 System.out.println(" - param: "+ AppParameters.GPX_GPXSPLIT +"="+ this.param_GpxSplit);
\r
158 System.out.println(" - param: "+ AppParameters.GPX_NO_FIRST_NODE +"="+ ImportPicture.param_GpxNoFirstNode);
\r
159 System.out.println(" - param: "+ AppParameters.GPX_REUSE +"="+ this.param_GpxReuse);
\r
162 // argv[0] --> AppParameters.IMG_SOURCE_FOLDER に置き換え
\r
163 this.imgDir = new File(this.params.getProperty(AppParameters.IMG_SOURCE_FOLDER));
\r
165 // 基準時刻(ファイル更新日時 | EXIF撮影日時)
\r
166 this.exifBase = (this.params.getProperty(AppParameters.GPX_BASETIME).equals("EXIF_TIME"));
\r
168 // 基準時刻ファイルの「更新日時」を使って時刻合わせを行う。
\r
169 // argv[1] --> AppParameters.IMG_BASE_FILE に置き換え
\r
170 imgtime = this.adjustTime(new File(this.imgDir, this.params.getProperty(AppParameters.IMG_BASE_FILE)));
\r
173 // argv[3] --> AppParameters.IMG_OUTPUT に置き換え
\r
174 this.outDir = new File(this.params.getProperty(AppParameters.IMG_OUTPUT_FOLDER));
\r
177 String paramStr = this.params.getProperty(AppParameters.GPX_GPXSPLIT);
\r
178 if ((paramStr != null) && (paramStr.equals(Boolean.toString(true)))) {
\r
179 this.param_GpxSplit = true;
\r
182 paramStr = this.params.getProperty(AppParameters.GPX_NO_FIRST_NODE);
\r
183 if ((paramStr != null) && (paramStr.equals(Boolean.toString(true)))) {
\r
184 ImportPicture.param_GpxNoFirstNode = true;
\r
187 paramStr = this.params.getProperty(AppParameters.GPX_REUSE);
\r
188 if ((paramStr != null) && (paramStr.equals(Boolean.toString(true)))) {
\r
189 this.param_GpxReuse = true;
\r
192 paramStr = this.params.getProperty(AppParameters.IMG_OUTPUT_ALL);
\r
193 if ((paramStr != null) && (paramStr.equals(Boolean.toString(true)))) {
\r
194 this.param_ImgOutputAll = true;
\r
197 paramStr = this.params.getProperty(AppParameters.GPX_OUTPUT_WPT);
\r
198 if ((paramStr != null) && (paramStr.equals(Boolean.toString(true)))) {
\r
199 this.param_GpxOutputWpt = true;
\r
202 paramStr = this.params.getProperty(AppParameters.GPX_OVERWRITE_MAGVAR);
\r
203 if ((paramStr != null) && (paramStr.equals(Boolean.toString(true)))) {
\r
204 Complementation.param_GpxOverwriteMagvar = true;
\r
207 paramStr = this.params.getProperty(AppParameters.GPX_OUTPUT_SPEED);
\r
208 if ((paramStr != null) && (paramStr.equals(Boolean.toString(true)))) {
\r
209 Complementation.param_GpxOutputSpeed = true;
\r
212 paramStr = this.params.getProperty(AppParameters.GPX_SOURCE_FOLDER);
\r
213 if (paramStr != null) {
\r
214 this.param_GpxSourceFolder = paramStr;
\r
215 this.gpxDir = new File(this.param_GpxSourceFolder);
\r
216 if (!this.gpxDir.exists()) {
\r
217 // GPXファイルまたはディレクトリが存在しません。('%s')
\r
218 System.out.println(
\r
219 String.format(i18n.getString("msg.100"), paramStr)
\r
225 this.gpxDir = this.imgDir;
\r
228 // 指定されたディレクトリ内のGPXファイルすべてを対象とする
\r
229 if (this.gpxDir.isDirectory()) {
\r
230 File[] files = this.gpxDir.listFiles();
\r
231 if (files == null) {
\r
232 // 対象となるGPXファイルがありませんでした。('%s')
\r
233 System.out.println(
\r
234 String.format(i18n.getString("msg.110"), this.gpxDir.getAbsolutePath())
\r
238 if (this.param_ImgOutputAll && (files.length > 1)) {
\r
239 // "複数のGPXファイルがあるときには、'IMG.OUTPUT_ALL'オプションは指定できません。"
\r
240 System.out.println(
\r
241 i18n.getString("msg.120")
\r
246 java.util.Arrays.sort(
\r
247 files, new java.util.Comparator<File>() {
\r
249 public int compare(File file1, File file2){
\r
250 return file1.getName().compareTo(file2.getName());
\r
254 for (File file : files) {
\r
255 if (file.isFile()) {
\r
256 String filename = file.getName().toUpperCase();
\r
257 if (filename.toUpperCase().endsWith(".GPX")) {
\r
258 if (!filename.toUpperCase().endsWith("_.GPX") || this.param_GpxReuse) {
\r
259 this.gpxFiles.add(file);
\r
266 this.gpxFiles.add(this.gpxDir);
\r
269 paramStr = this.params.getProperty(AppParameters.IMG_OUTPUT_EXIF);
\r
270 if ((paramStr != null) && (paramStr.equals(Boolean.toString(true)))) {
\r
274 String timeStr = this.params.getProperty(AppParameters.IMG_TIME);
\r
276 Date t = toUTCDate(timeStr);
\r
277 this.delta = t.getTime() - imgtime.getTime();
\r
279 catch (ParseException e) {
\r
280 // "'%s'の書式が違います(%s)"
\r
281 System.out.println(
\r
283 i18n.getString("msg.130"),
\r
294 } catch(InterruptedException end) {}
\r
295 if (this.ex != null) {
\r
302 <wpt lat="35.25714922" lon="139.15490497">
\r
303 <ele>62.099998474121094</ele>
\r
304 <time>2012-06-11T00:44:38Z</time>
\r
306 <name><![CDATA[写真]]></name>
\r
307 <cmt><![CDATA[精度: 3.0m]]></cmt>
\r
308 <link href="2012-06-11_09-44-38.jpg">
\r
309 <text>2012-06-11_09-44-38.jpg</text>
\r
316 public void run() {
\r
318 if (params.getProperty(AppParameters.IMG_OUTPUT).equals(Boolean.toString(true))) {
\r
319 outDir = new File(outDir, imgDir.getName());
\r
324 for (File gpxFile : this.gpxFiles) {
\r
325 procGPXfile(new GpxFile(gpxFile));
\r
328 catch(ParserConfigurationException | DOMException | SAXException | IOException | ParseException | ImageReadException | ImageWriteException | IllegalArgumentException | TransformerException e) {
\r
329 e.printStackTrace();
\r
330 this.ex = new Exception(e);
\r
337 * @throws ParserConfigurationException
\r
338 * @throws IOException
\r
339 * @throws SAXException
\r
340 * @throws ParseException
\r
341 * @throws ImageWriteException
\r
342 * @throws ImageReadException
\r
343 * @throws TransformerException
\r
345 void procGPXfile(GpxFile gpxFile) throws ParserConfigurationException, SAXException, IOException, ParseException, ImageReadException, ImageWriteException, TransformerException {
\r
348 System.out.println("time difference: "+ (delta / 1000) +"(sec)");
\r
349 System.out.println(" Target GPX: ["+ gpxFile.getAbsolutePath() +"]");
\r
350 System.out.println(" EXIF: "+ (exif ? ("convert to '" + outDir.getAbsolutePath() +"'") : "off"));
\r
351 System.out.println();
\r
353 // imgDir内の画像ファイルを処理する
\r
354 System.out.println("|--------------------------------|--------------------|--------------------|--------------|--------------|--------|------|------|");
\r
355 System.out.println("| name | Camera Time | GPStime | Latitude | Longitude | ele |magvar| km/h |");
\r
356 System.out.println("|--------------------------------|--------------------|--------------------|--------------|--------------|--------|------|------|");
\r
357 boolean out = proc(imgDir, delta, gpxFile.mapTRKSEG, exif, gpxFile);
\r
358 System.out.println("|--------------------------------|--------------------|--------------------|--------------|--------------|--------|------|------|");
\r
361 gpxFile.output(outDir);
\r
367 * @throws ParseException
\r
368 * @throws IOException
\r
369 * @throws ImageReadException
\r
370 * @throws ImageWriteException
\r
372 boolean proc(File dir, long delta, ElementMapTRKSEG mapTRKSEG, boolean exifWrite, GpxFile gpxFile) throws ParseException, ImageReadException, IOException, ImageWriteException {
\r
373 boolean ret = false;
\r
374 File[] files = dir.listFiles(new JpegFileFilter());
\r
375 Arrays.sort(files, new FileSort());
\r
376 for (File image : files) {
\r
377 System.out.print(String.format("|%-32s|", image.getName()));
\r
378 if (image.isDirectory()) {
\r
379 ret = proc(image, delta, mapTRKSEG, exifWrite, gpxFile);
\r
383 String imageName = image.getName();
\r
384 if (!checkFile(imageName)) {
\r
385 System.out.println(String.format("%20s ", "it is not image file."));
\r
389 Discripter result = procImageFile(image, delta, mapTRKSEG, exifWrite, gpxFile);
\r
391 switch (result.control) {
\r
392 case Discripter.CONTINUE:
\r
394 case Discripter.BREAK:
\r
402 static final int NEXT = 0;
\r
403 static final int CONTINUE = -1;
\r
404 static final int BREAK = 1;
\r
406 public boolean ret;
\r
407 public int control;
\r
408 public Discripter(boolean ret) {
\r
410 this.control = Discripter.NEXT;
\r
414 Discripter procImageFile(File imageFile, long delta, ElementMapTRKSEG mapTRKSEG, boolean exifWrite, GpxFile gpxFile) throws ParseException, ImageReadException, IOException, ImageWriteException {
\r
415 Discripter result = new Discripter(false);
\r
417 // itime <-- 画像ファイルの撮影時刻
\r
418 // ファイルの更新日時/EXIFの撮影日時
\r
419 Date itime = new Date(imageFile.lastModified());
\r
420 if (this.exifBase) {
\r
421 ImageMetadata meta = Imaging.getMetadata(imageFile);
\r
422 JpegImageMetadata jpegMetadata = (JpegImageMetadata)meta;
\r
423 if (jpegMetadata == null) {
\r
424 // "'%s'にEXIF情報がありません"
\r
425 System.out.println(
\r
427 i18n.getString("msg.140"),
\r
428 imageFile.getAbsolutePath()
\r
431 result.control = Discripter.CONTINUE;
\r
434 @SuppressWarnings("LocalVariableHidesMemberVariable")
\r
435 TiffImageMetadata exif = jpegMetadata.getExif();
\r
436 if (exif == null) {
\r
437 // "'%s'にEXIF情報がありません"
\r
438 System.out.println(
\r
440 i18n.getString("msg.140"),
\r
441 imageFile.getAbsolutePath()
\r
444 result.control = Discripter.CONTINUE;
\r
447 String dateTimeOriginal = exif.getFieldValue(ExifTagConstants.EXIF_TAG_DATE_TIME_ORIGINAL)[0];
\r
448 itime = ImportPicture.toEXIFDate(dateTimeOriginal);
\r
450 System.out.print(String.format("%20s|", toUTCString(itime)));
\r
452 // uktime <-- 画像撮影時刻に対応するGPX時刻(補正日時)
\r
453 Date correctedtime = new Date(itime.getTime() + delta);
\r
454 System.out.print(String.format("%20s|", toUTCString(correctedtime)));
\r
456 // 時刻uktimeにおける<magver>をtrkptに追加する
\r
457 String eleStr = "-";
\r
458 String magvarStr = "-";
\r
459 String speedStr = "-";
\r
460 TagTrkpt trkptT = null;
\r
462 for (Map.Entry<Date,ElementMapTRKPT> map : mapTRKSEG.entrySet()) {
\r
463 ElementMapTRKPT mapTRKPT = map.getValue();
\r
464 trkptT = mapTRKPT.getValue(correctedtime);
\r
465 if (trkptT != null) {
\r
470 if (trkptT == null) {
\r
471 System.out.print(String.format("%-14s|%-14s|", "", ""));
\r
472 System.out.println(String.format("%8s|%6s|%6s|", "", "", ""));
\r
473 if (!this.param_ImgOutputAll) {
\r
474 result.control = Discripter.CONTINUE;
\r
479 double latitude = trkptT.lat;
\r
480 double longitude = trkptT.lon;
\r
482 if (trkptT.eleStr != null) {
\r
483 eleStr = trkptT.eleStr;
\r
486 if (trkptT.magvarStr != null) {
\r
487 magvarStr = trkptT.magvarStr;
\r
490 if (trkptT.speedStr != null) {
\r
491 speedStr = trkptT.speedStr;
\r
493 System.out.print(String.format("%14.10f|%14.10f|", latitude, longitude));
\r
494 System.out.println(String.format("%8s|%6s|%6s|", eleStr, magvarStr, speedStr));
\r
501 exifWrite(imageFile, correctedtime, trkptT);
\r
503 if (Boolean.parseBoolean(params.getProperty(AppParameters.GPX_OUTPUT_WPT))) {
\r
504 if (trkptT != null) {
\r
505 Element temp = gpxFile.createWptTag(imageFile, imgDir, itime.getTime(), trkptT.trkpt);
\r
506 gpxFile.gpx.appendChild(temp);
\r
511 if (this.param_ImgOutputAll) {
\r
512 // EXIFの変換を伴わない単純なファイルコピー
\r
513 FileInputStream sStream = new FileInputStream(imageFile);
\r
514 FileInputStream dStream = new FileInputStream(new File(outDir, imageFile.getName()));
\r
515 FileChannel srcChannel = sStream.getChannel();
\r
516 FileChannel destChannel = dStream.getChannel();
\r
518 srcChannel.transferTo(0, srcChannel.size(), destChannel);
\r
521 srcChannel.close();
\r
522 destChannel.close();
\r
528 result.control = Discripter.NEXT;
\r
532 void exifWrite(File imageFile, Date correctedtime, TagTrkpt trkptT) throws ImageReadException, IOException, ImageWriteException {
\r
533 DecimalFormat yearFormatter = new DecimalFormat("0000");
\r
534 DecimalFormat monthFormatter = new DecimalFormat("00");
\r
535 DecimalFormat dayFormatter = new DecimalFormat("00");
\r
537 TiffOutputSet outputSet = null;
\r
539 ImageMetadata meta = Imaging.getMetadata(imageFile);
\r
540 JpegImageMetadata jpegMetadata = (JpegImageMetadata)meta;
\r
541 if (jpegMetadata != null) {
\r
542 @SuppressWarnings("LocalVariableHidesMemberVariable")
\r
543 TiffImageMetadata exif = jpegMetadata.getExif();
\r
544 if (exif != null) {
\r
545 outputSet = exif.getOutputSet();
\r
549 if (outputSet == null) {
\r
550 outputSet = new TiffOutputSet();
\r
553 //---- EXIF_TAG_DATE_TIME_ORIGINAL / 「撮影日時/オリジナル画像の生成日時」----
\r
554 TiffOutputDirectory exifDir = outputSet.getOrCreateExifDirectory();
\r
556 Calendar cal = Calendar.getInstance();
\r
557 cal.setTimeZone(TimeZone.getTimeZone("UTC"));
\r
558 cal.setTime(correctedtime);
\r
559 exifDir.removeField(ExifTagConstants.EXIF_TAG_DATE_TIME_ORIGINAL);
\r
560 exifDir.add(ExifTagConstants.EXIF_TAG_DATE_TIME_ORIGINAL, ImportPicture.toEXIFString(cal.getTime()));
\r
563 //---- EXIF GPS_TIME_STAMP ----
\r
564 TiffOutputDirectory gpsDir = outputSet.getOrCreateGPSDirectory();
\r
566 Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
\r
567 cal.setTimeZone(TimeZone.getTimeZone("GMT+00"));
\r
568 cal.setTime(correctedtime);
\r
569 final String yearStr = yearFormatter.format(cal.get(Calendar.YEAR));
\r
570 final String monthStr = monthFormatter.format(cal.get(Calendar.MONTH) + 1);
\r
571 final String dayStr = dayFormatter.format(cal.get(Calendar.DAY_OF_MONTH));
\r
572 final String dateStamp = yearStr +":"+ monthStr +":"+ dayStr;
\r
574 gpsDir.removeField(GpsTagConstants.GPS_TAG_GPS_TIME_STAMP);
\r
576 GpsTagConstants.GPS_TAG_GPS_TIME_STAMP,
\r
577 RationalNumber.valueOf(cal.get(Calendar.HOUR_OF_DAY)),
\r
578 RationalNumber.valueOf(cal.get(Calendar.MINUTE)),
\r
579 RationalNumber.valueOf(cal.get(Calendar.SECOND))
\r
581 gpsDir.removeField(GpsTagConstants.GPS_TAG_GPS_DATE_STAMP);
\r
582 gpsDir.add(GpsTagConstants.GPS_TAG_GPS_DATE_STAMP, dateStamp);
\r
585 if (trkptT != null) {
\r
586 //---- EXIF GPS elevation/ALTITUDE ----
\r
587 if (trkptT.eleStr != null) {
\r
588 final double altitude = Double.parseDouble(trkptT.eleStr);
\r
589 gpsDir.removeField(GpsTagConstants.GPS_TAG_GPS_ALTITUDE);
\r
590 gpsDir.add(GpsTagConstants.GPS_TAG_GPS_ALTITUDE, RationalNumber.valueOf(altitude));
\r
593 //---- EXIF GPS magvar/IMG_DIRECTION ----
\r
594 if (trkptT.magvarStr != null) {
\r
595 final double magvar = Double.parseDouble(trkptT.magvarStr);
\r
596 gpsDir.removeField(GpsTagConstants.GPS_TAG_GPS_IMG_DIRECTION);
\r
597 gpsDir.add(GpsTagConstants.GPS_TAG_GPS_IMG_DIRECTION, RationalNumber.valueOf(magvar));
\r
600 //---- EXIF GPS_ ----
\r
601 outputSet.setGPSInDegrees(trkptT.lon, trkptT.lat);
\r
604 ExifRewriter rewriter = new ExifRewriter();
\r
605 try (FileOutputStream fos = new FileOutputStream(new File(outDir, imageFile.getName()))) {
\r
606 rewriter.updateExifMetadataLossy(imageFile, fos, outputSet);
\r
610 // 基準時刻ファイルの「更新日時」を使って時刻合わせを行う。
\r
611 // argv[1] --> AppParameters.IMG_BASE_FILE に置き換え
\r
612 // File baseFile = new File(this.imgDir, this.params.getProperty(AppParameters.IMG_BASE_FILE));
\r
613 private Date adjustTime(File baseFile) throws ImageReadException, IOException, ParseException {
\r
615 ImageMetadata meta = Imaging.getMetadata(baseFile);
\r
616 JpegImageMetadata jpegMetadata = (JpegImageMetadata)meta;
\r
617 if (jpegMetadata == null) {
\r
618 // "'%s'にEXIF情報がありません"
\r
619 System.out.println(
\r
621 i18n.getString("msg.140"),
\r
622 baseFile.getAbsolutePath()
\r
627 @SuppressWarnings("LocalVariableHidesMemberVariable")
\r
628 TiffImageMetadata exif = jpegMetadata.getExif();
\r
629 if (exif == null) {
\r
630 // "'%s'にEXIF情報がありません"
\r
631 System.out.println(
\r
633 i18n.getString("msg.140"),
\r
634 baseFile.getAbsolutePath()
\r
639 String dateTimeOriginal = exif.getFieldValue(ExifTagConstants.EXIF_TAG_DATE_TIME_ORIGINAL)[0];
\r
640 return new Date(ImportPicture.toEXIFDate(dateTimeOriginal).getTime());
\r
643 return new Date(baseFile.lastModified());
\r
648 * 対象は '*.JPG' のみ対象とする
\r
652 public static boolean checkFile(String name) {
\r
653 return ((name != null) && name.toUpperCase().endsWith(".JPG"));
\r
657 * DateをEXIFの文字列に変換する。
\r
658 * 注意:EXiFの撮影時刻はUTC時間ではない
\r
662 public static String toEXIFString(Date localdate) {
\r
663 DateFormat dfUTC = new SimpleDateFormat(EXIF_DATE_TIME_FORMAT_STRING);
\r
664 return dfUTC.format(localdate);
\r
668 * EXIFの文字列をDateに変換する。
\r
669 * 注意:EXiFの撮影時刻はUTC時間ではない
\r
672 * @throws ParseException
\r
674 public static Date toEXIFDate(String timeStr) throws ParseException {
\r
675 DateFormat dfUTC = new SimpleDateFormat(EXIF_DATE_TIME_FORMAT_STRING);
\r
676 //dfUTC.setTimeZone(TimeZone.getTimeZone("UTC"));
\r
677 return dfUTC.parse(timeStr);
\r
680 public static String toUTCString(Date localdate) {
\r
681 DateFormat dfUTC = new SimpleDateFormat(TIME_FORMAT_STRING);
\r
682 dfUTC.setTimeZone(TimeZone.getTimeZone("UTC"));
\r
683 return dfUTC.format(localdate);
\r
686 public static Date toUTCDate(String timeStr) throws ParseException {
\r
687 DateFormat dfUTC = new SimpleDateFormat(TIME_FORMAT_STRING);
\r
688 dfUTC.setTimeZone(TimeZone.getTimeZone("UTC"));
\r
689 return dfUTC.parse(timeStr);
\r
692 static String getShortPathName(File dir, File iFile) {
\r
693 String dirPath = dir.getAbsolutePath();
\r
694 String filePath = iFile.getAbsolutePath();
\r
695 if (filePath.startsWith(dirPath)) {
\r
696 return filePath.substring(dirPath.length()+1);
\r
704 * ファイル名の順序に並び替えるためのソートクラス
\r
708 static class FileSort implements Comparator<File> {
\r
710 public int compare(File src, File target){
\r
711 int diff = src.getName().compareTo(target.getName());
\r
720 class JpegFileFilter implements FilenameFilter {
\r
722 public boolean accept(File dir, String name) {
\r
723 return name.toUpperCase().matches(".*\\.JPG$");
\r