OSDN Git Service

test green: GerminGPX のログ形式に対応
[importpicture/importpicture.git] / importPicture / src / osm / jp / gpx / ImportPicture.java
1 package osm.jp.gpx;\r
2 import java.io.*;\r
3 import java.nio.channels.FileChannel;\r
4 import java.text.DecimalFormat;\r
5 import java.text.ParseException;\r
6 import java.text.SimpleDateFormat;\r
7 import java.util.ArrayList;\r
8 import java.util.Arrays;\r
9 import java.util.Calendar;\r
10 import java.util.Comparator;\r
11 import java.util.Date;\r
12 import java.util.GregorianCalendar;\r
13 import java.util.Iterator;\r
14 import java.util.Set;\r
15 import java.util.TimeZone;\r
16 import java.util.TreeMap;\r
17 import java.util.logging.LogManager;\r
18 import java.util.logging.Logger;\r
19 \r
20 import javax.xml.parsers.*;\r
21 import javax.xml.transform.OutputKeys;\r
22 import javax.xml.transform.Transformer;\r
23 import javax.xml.transform.TransformerException;\r
24 import javax.xml.transform.TransformerFactory;\r
25 import javax.xml.transform.dom.DOMSource;\r
26 import javax.xml.transform.stream.StreamResult;\r
27 \r
28 import org.apache.commons.imaging.ImageReadException;\r
29 import org.apache.commons.imaging.ImageWriteException;\r
30 import org.apache.commons.imaging.Imaging;\r
31 import org.apache.commons.imaging.common.ImageMetadata;\r
32 import org.apache.commons.imaging.common.RationalNumber;\r
33 import org.apache.commons.imaging.formats.jpeg.JpegImageMetadata;\r
34 import org.apache.commons.imaging.formats.jpeg.exif.ExifRewriter;\r
35 import org.apache.commons.imaging.formats.tiff.TiffImageMetadata;\r
36 import org.apache.commons.imaging.formats.tiff.constants.ExifTagConstants;\r
37 import org.apache.commons.imaging.formats.tiff.constants.GpsTagConstants;\r
38 import org.apache.commons.imaging.formats.tiff.write.TiffOutputDirectory;\r
39 import org.apache.commons.imaging.formats.tiff.write.TiffOutputSet;\r
40 import org.w3c.dom.*;\r
41 import org.xml.sax.SAXException;\r
42 \r
43 public class ImportPicture extends Thread {\r
44         /**\r
45          * 実行中に発生したExceptionを保持する場所\r
46          */\r
47         public Exception ex = null;\r
48         \r
49     /**\r
50      * ログ設定プロパティファイルのファイル内容\r
51      */\r
52     protected static final String LOGGING_PROPERTIES_DATA\r
53            = "handlers=java.util.logging.ConsoleHandler\n"\r
54            + ".level=FINEST\n"\r
55            + "java.util.logging.ConsoleHandler.level=INFO\n"\r
56            + "java.util.logging.ConsoleHandler.formatter=osm.jp.gpx.YuuLogFormatter";\r
57 \r
58     /**\r
59      * static initializer によるログ設定の初期化\r
60      */\r
61     public static final Logger logger = Logger.getLogger("CommandLogging");\r
62     static {\r
63         InputStream inStream = null;\r
64         try {\r
65             inStream = new ByteArrayInputStream(LOGGING_PROPERTIES_DATA.getBytes("UTF-8"));\r
66             try {\r
67                 LogManager.getLogManager().readConfiguration(inStream);\r
68                 logger.config("ログ設定: LogManagerを設定しました。");\r
69             }\r
70             catch (IOException e) {\r
71                 logger.warning("ログ設定: LogManager設定の際に例外が発生しました。:" + e.toString());\r
72             }\r
73         }\r
74         catch (UnsupportedEncodingException e) {\r
75             logger.severe("ログ設定: UTF-8エンコーディングがサポートされていません。:" + e.toString());\r
76         }\r
77         finally {\r
78             try {\r
79                 if (inStream != null) {\r
80                     inStream.close();\r
81                 }\r
82             } catch (IOException e) {\r
83                 logger.warning("ログ設定: ログ設定プロパティファイルのストリームクローズ時に例外が発生しました。:"+ e.toString());\r
84             }\r
85         }\r
86     }\r
87     \r
88 \r
89 \r
90     /** メイン\r
91      * 画像ファイルをGPXファイルに取り込みます。\r
92      * \r
93      * ・画像ファイルの更新日付をその画像の撮影日時とします。(Exi情報は無視します)\r
94      *    ※ 対象とするファイルは'*.jpg'のみ\r
95      * ・精確な時刻との時差を入力することで、撮影日時を補正します。\r
96      * ・画像ファイルの更新日付リストをCSV形式のファイルとして出力する。\r
97      * ・・結果は、取り込み元のGPXファイルとは別に、元ファイル名にアンダーバー「_」を付加した.ファイルに出力します。\r
98      *\r
99      * @param argv\r
100      * argv[-] = dummy\r
101      * argv[0] = 画像ファイルが格納されているディレクトリ           --> imgDir\r
102      * argv[1] = 時刻補正の基準とする画像ファイル                               --> baseFile\r
103      * argv[2] = 基準画像ファイルの精確な撮影日時 "yyyy-MM-dd'T'HH:mm:ss"       --> timeStr\r
104      * argv[3] = 出力先フォルダ                                                          --> outDir\r
105      * argv[4] = 撮影位置をロギングしたGPXファイル                               --> gpxDir\r
106      * \r
107      * @throws IOException\r
108      * @throws ImageReadException \r
109      */\r
110     public static void main(String[] argv) throws Exception\r
111     {\r
112         Date jptime;\r
113 \r
114         ImportPicture obj = new ImportPicture();\r
115         obj.ex = null;\r
116 \r
117         if (argv.length > 0) {\r
118             obj.imgDir = new File(argv[0]);\r
119         }\r
120 \r
121         if (argv.length < 4) {\r
122             System.out.println("!!! Illigal command call. !!!");\r
123             System.out.println("> java -cp .:AdjustTime.jar:commons-imaging-1.0-SNAPSHOT.jar <targetDir> <time base image> <time> {EXIF/not} (gpx)");\r
124             System.out.println("> java -cp .:AdjustTime.jar:commons-imaging-1.0-SNAPSHOT.jar. IMG_01234.JPG 2012-06-15T12:52:22 EXIF");\r
125             System.out.println("> java -cp .:AdjustTime.jar . IMG_01234.JPG 2012-06-15T12:52:22 not");\r
126             System.out.println();\r
127             return;\r
128         }\r
129 \r
130         obj.params = new AppParameters();\r
131 \r
132         // 基準時刻(ファイル更新日時 | EXIF撮影日時)\r
133         obj.exifBase = (obj.params.getProperty(AppParameters.GPX_BASETIME).equals("EXIF_TIME") ? true : false);\r
134 \r
135         // 基準時刻ファイルの「更新日時」を使って時刻合わせを行う。\r
136         File baseFile = new File(obj.imgDir, argv[1]);\r
137         if (obj.exifBase) {\r
138             ImageMetadata meta = Imaging.getMetadata(baseFile);\r
139             JpegImageMetadata jpegMetadata = (JpegImageMetadata)meta;\r
140             if (jpegMetadata == null) {\r
141                 System.out.println("'"+ baseFile.getAbsolutePath() +"' にEXIF情報がありません");\r
142                 return;\r
143             }\r
144             TiffImageMetadata exif = jpegMetadata.getExif();\r
145             if (exif == null) {\r
146                 System.out.println("'"+ baseFile.getAbsolutePath() +"' にEXIF情報がありません");\r
147                 return;\r
148             }\r
149                 String dateTimeOriginal = exif.getFieldValue(ExifTagConstants.EXIF_TAG_DATE_TIME_ORIGINAL)[0];\r
150                 long lastModifyTime = (new SimpleDateFormat("yyyy:MM:dd HH:mm:ss")).parse(dateTimeOriginal).getTime();\r
151                 jptime = new Date(lastModifyTime);\r
152         }\r
153         else {\r
154             jptime = new Date(baseFile.lastModified());\r
155         }\r
156 \r
157         String timeStr = argv[2];\r
158         try {\r
159             dfjp.setTimeZone(TimeZone.getTimeZone("JST"));\r
160             Date t = dfjp.parse(timeStr);\r
161             obj.delta = t.getTime() - jptime.getTime();\r
162         }\r
163         catch (ParseException e) {\r
164             System.out.println("'"+ timeStr +"' の書式が違います("+ TIME_FORMAT_STRING +")");\r
165             return;\r
166         }\r
167 \r
168         // 出力ファイル\r
169         obj.outDir = new File(argv[3]);\r
170 \r
171         // その他のパラメータを読み取る\r
172         String paramStr = obj.params.getProperty(AppParameters.GPX_GPXSPLIT);\r
173         if ((paramStr != null) && (paramStr.equals(Boolean.toString(true)))) {\r
174                 obj.param_GpxSplit = true;\r
175         }\r
176         \r
177         paramStr = obj.params.getProperty(AppParameters.GPX_NO_FIRST_NODE);\r
178         if ((paramStr != null) && (paramStr.equals(Boolean.toString(true)))) {\r
179                 obj.param_GpxNoFirstNode = true;\r
180         }\r
181         \r
182         paramStr = obj.params.getProperty(AppParameters.GPX_REUSE);\r
183         if ((paramStr != null) && (paramStr.equals(Boolean.toString(true)))) {\r
184                 obj.param_GpxReuse = true;\r
185         }\r
186         \r
187         paramStr = obj.params.getProperty(AppParameters.IMG_OUTPUT_ALL);\r
188         if ((paramStr != null) && (paramStr.equals(Boolean.toString(true)))) {\r
189                 obj.param_ImgOutputAll = true;\r
190         }\r
191 \r
192         paramStr = obj.params.getProperty(AppParameters.GPX_OUTPUT_WPT);\r
193         if ((paramStr != null) && (paramStr.equals(Boolean.toString(true)))) {\r
194                 obj.param_GpxOutputWpt = true;\r
195         }\r
196         \r
197         paramStr = obj.params.getProperty(AppParameters.GPX_OVERWRITE_MAGVAR);\r
198         if ((paramStr != null) && (paramStr.equals(Boolean.toString(true)))) {\r
199                 Complementation.param_GpxOverwriteMagvar = true;\r
200         }\r
201 \r
202         paramStr = obj.params.getProperty(AppParameters.GPX_OUTPUT_SPEED);\r
203         if ((paramStr != null) && (paramStr.equals(Boolean.toString(true)))) {\r
204                 Complementation.param_GpxOutputSpeed = true;\r
205         }\r
206 \r
207         paramStr = obj.params.getProperty(AppParameters.GPX_SOURCE_FOLDER);\r
208         if (paramStr != null) {\r
209                 obj.param_GpxSourceFolder = new String(paramStr);\r
210             obj.gpxDir = new File(obj.param_GpxSourceFolder);\r
211             if (!obj.gpxDir.exists()) {\r
212                 // GPXファイルまたはディレクトリが存在しません。\r
213                 System.out.println("GPXファイルまたはディレクトリが存在しません。('"+ paramStr +"')");\r
214                 return;\r
215             }\r
216         }\r
217         else {\r
218             obj.gpxDir = obj.imgDir;\r
219         }\r
220 \r
221         // 指定されたディレクトリ内のGPXファイルすべてを対象とする\r
222         if (obj.gpxDir.isDirectory()) {\r
223             File[] files = obj.gpxDir.listFiles();\r
224             if (files == null) {\r
225                 // 対象となるGPXファイルがありませんでした。\r
226                 System.out.println("対象となるGPXファイルがありませんでした。('"+ obj.gpxDir.getAbsolutePath() +"')");\r
227                 return;\r
228             }\r
229             if (obj.param_ImgOutputAll && (files.length > 1)) {\r
230                 System.out.println("複数のGPXファイルがあるときには、'IMG.OUTPUT_ALL'オプションは指定できません。");\r
231                 return;\r
232             }\r
233             \r
234             java.util.Arrays.sort(files, new java.util.Comparator<File>() {\r
235                         public int compare(File file1, File file2){\r
236                             return file1.getName().compareTo(file2.getName());\r
237                         }\r
238             });\r
239             for (File file : files) {\r
240                 if (file.isFile()) {\r
241                     String filename = file.getName().toUpperCase();\r
242                     if (filename.toUpperCase().endsWith(".GPX")) {\r
243                         if (!filename.toUpperCase().endsWith("_.GPX") || obj.param_GpxReuse) {\r
244                             obj.gpxFiles.add(file);\r
245                         }\r
246                     }\r
247                 }\r
248             }\r
249         }\r
250         else {\r
251             obj.gpxFiles.add(obj.gpxDir);\r
252         }\r
253 \r
254         paramStr = obj.params.getProperty(AppParameters.IMG_OUTPUT_EXIF);\r
255         if ((paramStr != null) && (paramStr.equals(Boolean.toString(true)))) {\r
256                 obj.exif = true;\r
257         }\r
258         \r
259         System.out.println(" - param: imgDir = '"+ obj.imgDir.getAbsolutePath() +"'");\r
260         System.out.println(" - param: outDir = '"+ (obj.outDir == null ? "" : obj.outDir.getAbsolutePath()) +"'");\r
261         System.out.println(" - param: gpxDir = '"+ (obj.gpxDir == null ? "" : obj.gpxDir.getAbsolutePath()) +"'");\r
262         System.out.println(" - param: number of gpxFiles = '"+ obj.gpxFiles.size() +"'");\r
263         System.out.println(" - param: "+ AppParameters.GPX_GPXSPLIT +"="+ obj.param_GpxSplit);\r
264         System.out.println(" - param: "+ AppParameters.GPX_NO_FIRST_NODE +"="+ obj.param_GpxNoFirstNode);        \r
265         System.out.println(" - param: "+ AppParameters.GPX_REUSE +"="+ obj.param_GpxReuse);\r
266         System.out.println(" - param: "+ AppParameters.IMG_BASE_FILE +"="+ obj.params.getProperty(AppParameters.IMG_BASE_FILE) );\r
267         System.out.println(" - param: "+ AppParameters.GPX_BASETIME +"="+ obj.params.getProperty(AppParameters.GPX_BASETIME) );\r
268         System.out.println(" - param: "+ AppParameters.IMG_OUTPUT +"="+ obj.params.getProperty(AppParameters.IMG_OUTPUT));     \r
269         System.out.println(" - param: "+ AppParameters.IMG_OUTPUT_ALL +"="+ obj.param_ImgOutputAll);\r
270         System.out.println(" - param: "+ AppParameters.IMG_OUTPUT_EXIF +"= "+ String.valueOf(obj.exif));\r
271         System.out.println(" - param: "+ AppParameters.GPX_SOURCE_FOLDER +"="+ obj.param_GpxSourceFolder);\r
272         System.out.println(" - param: "+ AppParameters.GPX_OUTPUT_WPT +"="+ obj.param_GpxOutputWpt);\r
273         System.out.println(" - param: "+ AppParameters.GPX_OVERWRITE_MAGVAR +"="+ Complementation.param_GpxOverwriteMagvar);\r
274         System.out.println(" - param: "+ AppParameters.GPX_OUTPUT_SPEED +"="+ Complementation.param_GpxOutputSpeed);\r
275         obj.start();\r
276         try {\r
277             obj.join();\r
278         } catch(InterruptedException end) {}\r
279         if (obj.ex != null) {\r
280                 throw obj.ex;\r
281         }\r
282     }\r
283     \r
284     public File gpxDir;\r
285     public File imgDir;\r
286     public File outDir;\r
287     public long delta = 0;\r
288     public boolean exif = false;\r
289     public boolean exifBase = false;\r
290     public ArrayList<File> gpxFiles = new ArrayList<>();\r
291     public AppParameters params;\r
292         public boolean param_GpxSplit = false;\r
293         public boolean param_GpxNoFirstNode = false;\r
294         public boolean param_GpxReuse = false;\r
295         //public boolean Complementation.param_GpxOutputSpeed = false;\r
296         //public boolean Complementation.param_GpxOverwriteMagvar = false;\r
297         public boolean param_GpxOutputWpt = true;\r
298         public boolean param_ImgOutputAll = false;\r
299         public String param_GpxSourceFolder = ".";\r
300         public static final long DIFF_MAE_TIME = 3000L; // before 3 secound\r
301         \r
302     @Override\r
303     public void run() {\r
304         /**\r
305          *\r
306                 <wpt lat="35.25714922" lon="139.15490497">\r
307                         <ele>62.099998474121094</ele>\r
308                         <time>2012-06-11T00:44:38Z</time>\r
309                         <hdop>0.75</hdop>\r
310                         <name><![CDATA[写真]]></name>\r
311                         <cmt><![CDATA[精度: 3.0m]]></cmt>\r
312                         <link href="2012-06-11_09-44-38.jpg">\r
313                                 <text>2012-06-11_09-44-38.jpg</text>\r
314                         </link>\r
315                         <sat>9</sat>\r
316                 </wpt>\r
317          */\r
318         try {\r
319                 if (params.getProperty(AppParameters.IMG_OUTPUT).equals(Boolean.toString(true))) {\r
320                 outDir = new File(outDir, imgDir.getName());\r
321                 }\r
322                 else {\r
323                 outDir = gpxDir;\r
324                 }\r
325 \r
326             for (File gpxFile : this.gpxFiles) {\r
327                 procGPXfile(gpxFile);\r
328             }\r
329         }\r
330         catch(ParserConfigurationException | DOMException | SAXException | IOException | ParseException | ImageReadException | ImageWriteException | IllegalArgumentException | TransformerException e) {\r
331                 e.printStackTrace();\r
332                 this.ex = new Exception(e);\r
333         }\r
334     }\r
335     \r
336     /**\r
337      * 個別のGPXファイルを処理する\r
338      * \r
339      * @throws ParserConfigurationException \r
340      * @throws IOException \r
341      * @throws SAXException \r
342      * @throws ParseException \r
343      * @throws ImageWriteException \r
344      * @throws ImageReadException \r
345      * @throws TransformerException \r
346      */\r
347     void procGPXfile(File gpxFile) throws ParserConfigurationException, SAXException, IOException, ParseException, ImageReadException, ImageWriteException, TransformerException {\r
348         DocumentBuilderFactory factory;\r
349         DocumentBuilder        builder;\r
350         Node gpx;\r
351 \r
352         String fileName = gpxFile.getName();\r
353         String iStr = fileName.substring(0, fileName.length() - 4);\r
354 \r
355         File outputFile = new File(outDir, iStr +"_.gpx");\r
356         System.out.println(gpxFile.getAbsolutePath() + " => "+ outputFile.getAbsolutePath());\r
357         System.out.println("           時差: "+ (delta / 1000) +"(sec)");\r
358         System.out.println("    Target GPX: ["+ gpxFile.getAbsolutePath() +"]");\r
359         System.out.println("          EXIF: "+ (exif ? ("convert to '" + outDir.getAbsolutePath() +"'") : "off"));\r
360         System.out.println();\r
361 \r
362         factory = DocumentBuilderFactory.newInstance();\r
363         builder = factory.newDocumentBuilder();\r
364         factory.setIgnoringElementContentWhitespace(true);\r
365         factory.setIgnoringComments(true);\r
366         factory.setValidating(true);\r
367 \r
368         // GPX file --> Node root\r
369         DOMImplementation domImpl = builder.getDOMImplementation();\r
370         document = domImpl.createDocument("", "gpx", null);\r
371 \r
372         /*\r
373          * <gpx>\r
374          *   <trk>\r
375          *     <name><![CDATA[Tracked with OSMTracker for Android?]]></name>\r
376          *     <cmt><![CDATA[警告: HDOP values aren't the HDOP as returned by the GPS device. They're approximated from the location accuracy in meters.]]></cmt>\r
377          *     <trkseg>\r
378          *       <trkpt lat="35.32123832" lon="139.56965631">\r
379          *         <ele>47.20000076293945</ele>\r
380          *         <time>2012-06-15T03:00:29Z</time>\r
381          *         <hdop>0.5</hdop>\r
382          *       </trkpt>\r
383          *     </trkseg>\r
384          *   </trk>\r
385          *   <wpt lat="35.2564461" lon="139.15437809"></wpt>\r
386          * </gpx>\r
387          */\r
388         TreeMap<Long,Element> map = new TreeMap<Long, Element>();\r
389         TreeMap<Long,Element> mapTRKSEG = new TreeMap<>();\r
390         Element trk = null;\r
391         //Element maeTRKPT = null;\r
392         gpx    = builder.parse(gpxFile).getFirstChild();\r
393         document = gpx.getOwnerDocument();\r
394         NodeList nodes = gpx.getChildNodes();\r
395         for (int i=0; i < nodes.getLength(); i++) {\r
396             Node node2 = nodes.item(i);\r
397             if (node2.getNodeName().equals("trk")) {\r
398                 trk = (Element) node2;\r
399                 \r
400                 NodeList nodes1 = trk.getChildNodes();\r
401                 int trksegCounter = 0;\r
402                 for (int i1=0; i1 < nodes1.getLength(); i1++) {\r
403                     Node nodeTRKSEG = nodes1.item(i1);\r
404                     if (nodeTRKSEG.getNodeName().equals("trkseg")) {\r
405                         trksegCounter++;\r
406                         Element newTRKSEG = document.createElement("trkseg");\r
407                         Element trkseg = (Element) nodeTRKSEG;\r
408                         NodeList nodes2 = trkseg.getChildNodes();\r
409                         for (int i2=0; i2 < nodes2.getLength(); i2++) {\r
410                             Node nodeTRKPT = nodes2.item(i2);\r
411                             if (nodeTRKPT.getNodeName().equals("trkpt")) {\r
412                                 if (param_GpxNoFirstNode && (i2 == 0)) {\r
413                                         continue;\r
414                                 }\r
415                                 newTRKSEG.appendChild(getCopy(document, nodeTRKPT));\r
416                             }\r
417                         }\r
418                         mapTRKSEG.put(new Long(trksegCounter), getCopy(document, newTRKSEG));\r
419 \r
420                         // <trk>から<trkseg>を削除する。\r
421                         trk.removeChild(nodeTRKSEG);\r
422                     }\r
423                 }\r
424                 \r
425                 // <trkseg>毎に実行する\r
426                 Iterator<Long> keyIte = mapTRKSEG.keySet().iterator();\r
427                 while (keyIte.hasNext()) {    //ループ。反復子iteratorによる キー 取得\r
428 \r
429                         // <trk>に、新たな<trkseg>を追加する。\r
430                         Element newTRKSEG = mapTRKSEG.get(keyIte.next());\r
431                     trk.appendChild(newTRKSEG);\r
432                     \r
433                     // mapに、<trkpt>を割り付ける\r
434                     trkptMap(newTRKSEG, map);\r
435                 }\r
436             }\r
437         }\r
438         \r
439         /*\r
440          * GPXへ割りつける開始時刻と終了時刻を求める\r
441          */\r
442                 long gpxStartTime = (new Date()).getTime();             // 対象とする開始時刻(現在時刻)\r
443                 long gpxEndTime = 0L;                                                   // 対象とする終了時刻\r
444                 Set<Long> keySet = map.keySet();  //すべてのキー値を取得\r
445                 for (Long timeLong : keySet) {\r
446                         long gpxTime = timeLong;\r
447                         if (gpxStartTime > gpxTime) {\r
448                              gpxStartTime = gpxTime;\r
449                         }\r
450                         if (gpxEndTime < gpxTime) {\r
451                              gpxEndTime = gpxTime;\r
452                         }\r
453                 }\r
454                 \r
455                 /*\r
456                  * SPEEDをGPXに設定する\r
457                  * 条件: SPEEDを書き出すフラグがONの時\r
458                  * 条件: オリジナルのSPEEDがある場合「上書きする/変更しない」(GPX_OUTPUT_SPEED)\r
459                  */\r
460                 /*\r
461         TreeMap<Long,Element> map2 = new TreeMap<Long, Element>();\r
462                 if (Boolean.parseBoolean(params.getProperty(AppParameters.GPX_OUTPUT_SPEED))) {\r
463                         for (Long timeL : keySet) {\r
464                     Element trkptE = trkpt(map, new Date(timeL));\r
465                     if (trkptE != null) {\r
466                         map2.put(timeL, trkptE);\r
467                     }\r
468                     else {\r
469                         map2.put(timeL, map.get(timeL));\r
470                     }\r
471                         }\r
472                 }\r
473                 else {\r
474                         map2 = (TreeMap<Long, Element>) map.clone();\r
475                 }\r
476                 */\r
477                  \r
478                 System.out.println("GPX start time: "+ dfjp.format(new Date(gpxStartTime)) + "\t[GMT " + dfuk.format(new Date(gpxStartTime))+"]");\r
479                 System.out.println("  GPX end time: "+ dfjp.format(new Date(gpxEndTime)) + "\t[GMT " + dfuk.format(new Date(gpxEndTime))+"]");\r
480                 System.out.println("------------------------|--------------------|--------------------|--------------|--------------|--------|------|------|");\r
481                 System.out.println(" name                   | UpdateTime         | GPStime            |   Latitude   |   Longitude  | ele    |magvar| km/h |");\r
482                 System.out.println("------------------------|--------------------|--------------------|--------------|--------------|--------|------|------|");\r
483                 proc(imgDir, delta, gpxStartTime, gpxEndTime, map, exif, gpx);\r
484                 System.out.println("------------------------|--------------------|--------------------|--------------|--------------|--------|------|------|");\r
485 \r
486         // 出力\r
487         outputFile.getParentFile().mkdirs();\r
488         DOMSource source = new DOMSource(gpx);\r
489         FileOutputStream os = new FileOutputStream(outputFile);\r
490         StreamResult result = new StreamResult(os);\r
491         TransformerFactory transFactory = TransformerFactory.newInstance();\r
492         Transformer transformer = transFactory.newTransformer();\r
493         transformer.setOutputProperty(OutputKeys.INDENT, "yes");\r
494         transformer.setOutputProperty(OutputKeys.METHOD, "xml");\r
495         transformer.transform(source, result);         \r
496 \r
497         os = new FileOutputStream(outputFile);\r
498         result = new StreamResult(os);\r
499         transformer.transform(source, result);\r
500     }\r
501     \r
502         \r
503     /**\r
504      * 再帰メソッド\r
505      * @throws ParseException \r
506      * @throws IOException \r
507      * @throws ImageReadException \r
508      * @throws ImageWriteException \r
509      */\r
510     boolean proc(File dir, long delta, long gpxStartTime, long gpxEndTime, TreeMap<Long,Element> map, boolean exifWrite, Node gpx) throws ParseException, ImageReadException, IOException, ImageWriteException {\r
511         DecimalFormat yearFormatter = new DecimalFormat("0000");\r
512         DecimalFormat monthFormatter = new DecimalFormat("00");\r
513         DecimalFormat dayFormatter = new DecimalFormat("00");\r
514 \r
515         boolean ret = false;\r
516         File[] files = dir.listFiles(new JpegFileFilter());\r
517         Arrays.sort(files, new FileSort());\r
518         for (File image : files) {\r
519             System.out.print(String.format("%-24s|", image.getName()));\r
520             if (image.isDirectory()) {\r
521                 ret = proc(image, delta, gpxStartTime, gpxEndTime, map, exifWrite, gpx);\r
522                 continue;\r
523             }\r
524             \r
525             String imageName = image.getName();\r
526             if (!checkFile(imageName)) {\r
527                 System.out.println(String.format("%20s ", "it is not image file."));\r
528                 continue;\r
529             }\r
530             \r
531             Date itime = new Date(image.lastModified());\r
532             if (this.exifBase) {\r
533                 ImageMetadata meta = Imaging.getMetadata(image);\r
534                 JpegImageMetadata jpegMetadata = (JpegImageMetadata)meta;\r
535                 if (jpegMetadata == null) {\r
536                     System.out.println("'"+ image.getAbsolutePath() +"' にEXIF情報がありません");\r
537                     continue;\r
538                 }\r
539                 TiffImageMetadata exif = jpegMetadata.getExif();\r
540                 if (exif == null) {\r
541                     System.out.println("'"+ image.getAbsolutePath() +"' にEXIF情報がありません");\r
542                     continue;\r
543                 }\r
544                 String dateTimeOriginal = exif.getFieldValue(ExifTagConstants.EXIF_TAG_DATE_TIME_ORIGINAL)[0];\r
545                 long lastModifyTime = (new SimpleDateFormat("yyyy:MM:dd HH:mm:ss")).parse(dateTimeOriginal).getTime();\r
546                 itime = new Date(lastModifyTime);\r
547             }\r
548 \r
549             // uktime <-- 画像撮影時刻に対応するGPX時刻\r
550             Date uktime = new Date(itime.getTime() + delta);\r
551             System.out.print(String.format("%20s ", dfjp.format(itime)));\r
552             System.out.print(String.format("%20s|", dfjp.format(uktime)));\r
553             if ((uktime.getTime() < gpxStartTime) || (uktime.getTime() > gpxEndTime)) {\r
554                 System.out.println(String.format("%20s ", "out of time."));\r
555                 if (!this.param_ImgOutputAll) {\r
556                         continue;\r
557                 }\r
558             }\r
559 \r
560                 // 時刻uktimeにおける<magver>をtrkptに追加する\r
561             Element trkptE = trkpt(map, uktime);\r
562             String eleStr = "-";\r
563             String magvarStr = "-";\r
564             String speedStr = "-";\r
565             double latitude = 90.5D;\r
566             double longitude = 180.5D;\r
567             TagTrkpt trkptT = null;\r
568             if (trkptE == null) {\r
569                 System.out.println(String.format("%20s ", "Out of GPX logging time."));\r
570                 if (!this.param_ImgOutputAll) {\r
571                         continue;\r
572                 }\r
573             }\r
574             else {\r
575                 trkptT = new TagTrkpt(trkptE);\r
576 \r
577                 //Element wpt = createWptTag(image, uktime.getTime(), trkptE);\r
578                 //String latStr = trkptT.lat.toString();\r
579                 //String lonStr = trkptT.lon.toString();\r
580                 latitude = trkptT.lat;\r
581                 longitude = trkptT.lon;\r
582                 \r
583                 if (trkptT.eleStr != null) {\r
584                         eleStr = new String(trkptT.eleStr);\r
585                 }\r
586                 \r
587                 if (trkptT.magvarStr != null) {\r
588                         magvarStr = new String(trkptT.magvarStr);\r
589                 }\r
590                 \r
591                 if (trkptT.speedStr != null) {\r
592                         speedStr = new String(trkptT.speedStr);\r
593                 }\r
594                 System.out.print(String.format("%-14s %-14s|", (new Double(latitude)).toString(), (new Double(longitude)).toString()));\r
595                 System.out.println(String.format("%8s|%6s|%6s|", eleStr, magvarStr, speedStr));\r
596             }\r
597 \r
598             ret = true;\r
599             FileOutputStream fos = null;\r
600             outDir.mkdir();\r
601 \r
602             if (exifWrite) {\r
603                 TiffOutputSet outputSet = null;\r
604 \r
605                 ImageMetadata meta = Imaging.getMetadata(image);\r
606                 JpegImageMetadata jpegMetadata = (JpegImageMetadata)meta;\r
607                 if (jpegMetadata != null) {\r
608                     TiffImageMetadata exif = jpegMetadata.getExif();\r
609                     if (exif != null) {\r
610                         outputSet = exif.getOutputSet();\r
611                     }\r
612                 }\r
613 \r
614                 if (outputSet == null) {\r
615                     System.out.println("added : new tiff output set");\r
616                     outputSet = new TiffOutputSet();\r
617                 }\r
618 \r
619                 //---- EXIF_TAG_DATE_TIME_ORIGINAL / 「撮影日時/オリジナル画像の生成日時」----\r
620                 TiffOutputDirectory exifDir = outputSet.getOrCreateExifDirectory();\r
621                 {\r
622                     Calendar cal = GregorianCalendar.getInstance();\r
623                     cal.setTime(uktime);\r
624                     exifDir.removeField(ExifTagConstants.EXIF_TAG_DATE_TIME_ORIGINAL);\r
625                     exifDir.add(ExifTagConstants.EXIF_TAG_DATE_TIME_ORIGINAL, new SimpleDateFormat("yyyy:MM:dd HH:mm:ss").format(cal.getTime()));\r
626                 }\r
627 \r
628                 //---- EXIF GPS_TIME_STAMP ----\r
629                 TiffOutputDirectory gpsDir = outputSet.getOrCreateGPSDirectory();\r
630                 {\r
631                     Calendar cal = GregorianCalendar.getInstance(TimeZone.getTimeZone("UTC"));\r
632                     cal.setTime(uktime);\r
633                     final String yearStr = yearFormatter.format(cal.get(Calendar.YEAR));\r
634                     final String monthStr = monthFormatter.format(cal.get(Calendar.MONTH) + 1);\r
635                     final String dayStr = dayFormatter.format(cal.get(Calendar.DAY_OF_MONTH));\r
636                     final String dateStamp = yearStr +":"+ monthStr +":"+ dayStr;\r
637 \r
638                     gpsDir.removeField(GpsTagConstants.GPS_TAG_GPS_TIME_STAMP);\r
639                     gpsDir.add(GpsTagConstants.GPS_TAG_GPS_TIME_STAMP,\r
640                             RationalNumber.valueOf(cal.get(Calendar.HOUR_OF_DAY)),\r
641                             RationalNumber.valueOf(cal.get(Calendar.MINUTE)),\r
642                             RationalNumber.valueOf(cal.get(Calendar.SECOND)));\r
643                     gpsDir.removeField(GpsTagConstants.GPS_TAG_GPS_DATE_STAMP);\r
644                     gpsDir.add(GpsTagConstants.GPS_TAG_GPS_DATE_STAMP, dateStamp);\r
645                 }\r
646 \r
647                 if (trkptE != null) {\r
648                         //---- EXIF GPS elevation/ALTITUDE ----\r
649                         if (eleStr.equals("-") == false) {\r
650                             final double altitude = Double.parseDouble(eleStr);\r
651                             gpsDir.removeField(GpsTagConstants.GPS_TAG_GPS_ALTITUDE);\r
652                             gpsDir.add(GpsTagConstants.GPS_TAG_GPS_ALTITUDE, RationalNumber.valueOf(altitude));\r
653                         }\r
654         \r
655                         //---- EXIF GPS magvar/IMG_DIRECTION ----\r
656                         if (magvarStr.equals("-") == false) {\r
657                             final double magvar = Double.parseDouble(magvarStr);\r
658                             gpsDir.removeField(GpsTagConstants.GPS_TAG_GPS_IMG_DIRECTION);\r
659                             gpsDir.add(GpsTagConstants.GPS_TAG_GPS_IMG_DIRECTION, RationalNumber.valueOf(magvar));\r
660                         }\r
661         \r
662                         //---- EXIF GPS_ ----\r
663                     final String longitudeRef = (longitude < 0 ? "W" : "E");\r
664                     longitude = Math.abs(longitude);\r
665                     final String latitudeRef = (latitude < 0 ? "S" : "N");\r
666                     latitude = Math.abs(latitude);\r
667 \r
668                     gpsDir.removeField(GpsTagConstants.GPS_TAG_GPS_LONGITUDE_REF);\r
669                     gpsDir.add(GpsTagConstants.GPS_TAG_GPS_LONGITUDE_REF, longitudeRef);\r
670                     gpsDir.removeField(GpsTagConstants.GPS_TAG_GPS_LATITUDE_REF);\r
671                     gpsDir.add(GpsTagConstants.GPS_TAG_GPS_LATITUDE_REF, latitudeRef);\r
672                     {\r
673                         double value = longitude;\r
674                         final double longitudeDegrees = (long) value;\r
675                         value %= 1;\r
676                         value *= 60.0;\r
677                         final double longitudeMinutes = (long) value;\r
678                         value %= 1;\r
679                         value *= 60.0;\r
680                         final double longitudeSeconds = value;\r
681                         gpsDir.removeField(GpsTagConstants.GPS_TAG_GPS_LONGITUDE);\r
682                         gpsDir.add(GpsTagConstants.GPS_TAG_GPS_LONGITUDE,\r
683                                 RationalNumber.valueOf(longitudeDegrees),\r
684                                 RationalNumber.valueOf(longitudeMinutes),\r
685                                 RationalNumber.valueOf(longitudeSeconds));\r
686                     }\r
687                     {\r
688                         double value = latitude;\r
689                         final double latitudeDegrees = (long) value;\r
690                         value %= 1;\r
691                         value *= 60.0;\r
692                         final double latitudeMinutes = (long) value;\r
693                         value %= 1;\r
694                         value *= 60.0;\r
695                         final double latitudeSeconds = value;\r
696                         gpsDir.removeField(GpsTagConstants.GPS_TAG_GPS_LATITUDE);\r
697                         gpsDir.add(GpsTagConstants.GPS_TAG_GPS_LATITUDE,\r
698                                 RationalNumber.valueOf(latitudeDegrees),\r
699                                 RationalNumber.valueOf(latitudeMinutes),\r
700                                 RationalNumber.valueOf(latitudeSeconds));\r
701                     }\r
702                 }\r
703 \r
704                 ExifRewriter rewriter = new ExifRewriter();\r
705                 try {\r
706                     fos = new FileOutputStream(new File(outDir, imageName));\r
707                     rewriter.updateExifMetadataLossy(image, fos, outputSet);\r
708                 }\r
709                 finally {\r
710                     if (fos != null) {\r
711                         fos.close();\r
712                     }\r
713                 }\r
714 \r
715                 if (Boolean.parseBoolean(params.getProperty(AppParameters.GPX_OUTPUT_WPT))) {\r
716                         if (trkptT != null) {\r
717                         Element temp = createWptTag(image, itime.getTime(), trkptT.trkpt);\r
718                         gpx.appendChild(temp);\r
719                         }\r
720                 }\r
721             }\r
722             else {\r
723                 if (this.param_ImgOutputAll) {\r
724                         // EXIFの変換を伴わない単純なファイルコピー\r
725                         FileInputStream sStream = new FileInputStream(image);\r
726                         FileInputStream dStream = new FileInputStream(new File(outDir, imageName));\r
727                     FileChannel srcChannel = sStream.getChannel();\r
728                     FileChannel destChannel = dStream.getChannel();\r
729                     try {\r
730                         srcChannel.transferTo(0, srcChannel.size(), destChannel);\r
731                     }\r
732                     finally {\r
733                         srcChannel.close();\r
734                         destChannel.close();\r
735                         sStream.close();\r
736                         dStream.close();\r
737                     }\r
738                 }\r
739             }\r
740         }\r
741         return ret;\r
742     }\r
743         \r
744     static Document document;\r
745 \r
746 \r
747     /**\r
748      * 2012-06-10T05:09:46Z  (日本時間の'2012-06-10T14:09:46')\r
749      */\r
750     public static final String TIME_FORMAT_STRING = "yyyy-MM-dd'T'HH:mm:ss";\r
751     public static SimpleDateFormat dfjp = new SimpleDateFormat(TIME_FORMAT_STRING);\r
752     public static SimpleDateFormat dfuk = new SimpleDateFormat(TIME_FORMAT_STRING +"'Z'");\r
753 \r
754     /**\r
755      * XMLエレメント<trkpt>をTIMEでキー付したHashMapを生成する<br>\r
756      * \r
757      * <trkseg>\r
758      *  <trkpt lat="34.976635" lon="138.466228">\r
759      *          <ele>267.291</ele>\r
760      *          <magvar>359</magvar>\r
761      *          <speed></speed>\r
762      *          <time>2016-07-02T08:25:18Z</time>\r
763      *  </trkpt>\r
764      * </trkseg>\r
765      * \r
766      * @param trk\r
767      * @param map\r
768      * @throws ParseException\r
769      */\r
770     public void trkptMap(Element trkseg, TreeMap<Long,Element> map) throws ParseException {\r
771         dfuk.setTimeZone(TimeZone.getTimeZone("GMT"));\r
772 \r
773         NodeList nodes2 = trkseg.getChildNodes();\r
774         for (int i2=0; i2 < nodes2.getLength(); i2++) {\r
775             Node node3 = nodes2.item(i2);\r
776             if (node3.getNodeName().equals("trkpt")) {\r
777                 Element trkpt = (Element) node3;\r
778 \r
779                 NodeList nodes3 = trkpt.getChildNodes();\r
780                 for (int i3=0; i3 < nodes3.getLength(); i3++) {\r
781                     Node node4 = nodes3.item(i3);\r
782                     if (node4.getNodeName().equals("time")) {\r
783                         Element time = (Element) node4;\r
784                         NodeList nodes4 = time.getChildNodes();      // 子ノードを取得\r
785                         for (int i4=0; i4< nodes4.getLength(); i4++) {\r
786                             Node node5 = nodes4.item(i4);\r
787                             if (node5 != null) {\r
788                                 if (node5.getNodeType() == Node.TEXT_NODE) {\r
789                                     String timeStr = node5.getNodeValue();\r
790                                     long t = dfuk.parse(timeStr).getTime();\r
791                                     map.put(t, getCopy(trkseg.getOwnerDocument(), trkpt));\r
792                                 }\r
793                             }\r
794                         }\r
795                     }\r
796                 }\r
797             }\r
798         }\r
799     }\r
800 \r
801     \r
802     /**\r
803      *  <trkpt lat="35.32123832" lon="139.56965631">\r
804      *          <ele>47.20000076293945</ele>\r
805      *          <time>2012-06-15T03:00:29Z</time>\r
806      *  </trkpt>\r
807      *DIFF_MAE_TIME\r
808      * @return\r
809      * @param map\r
810      * @param jptime    画像ファイルの撮影日時 ミリ秒(日本時間)\r
811      * @throws ParseException\r
812      */\r
813     public Element trkpt(TreeMap<Long,Element> map, Date jptime) throws ParseException {\r
814         // 指定した時刻のエレメント(imaTrkpt)を取得する\r
815         Element imaE = getTrkpt(map, jptime);\r
816         if (imaE != null) {\r
817                 Element maeE = getMaeTrkpt(map, new TagTrkpt(imaE));\r
818             if (maeE != null) {\r
819                 Complementation comp = new Complementation(imaE, maeE);\r
820 \r
821                 // <MAGVAR>がなければ、\r
822                 // 直前の位置と、現在地から進行方向を求める\r
823                 // 経度(longitude)と経度から進行方向を求める\r
824                 if (Complementation.param_GpxOverwriteMagvar) {\r
825                         comp.complementationMagvar();\r
826                 }\r
827 \r
828                 // 緯度・経度と時間差から速度(km/h)を求める\r
829                 if (Complementation.param_GpxOutputSpeed) {\r
830                         comp.complementationSpeed();\r
831                 }\r
832                 imaE = (Element)(comp.imaTag.trkpt.cloneNode(true));\r
833             }\r
834         }\r
835         return imaE;\r
836     }\r
837 \r
838     /**\r
839      * [map]から指定した時刻の<trkpt>エレメントを取り出す。\r
840      * GPX時刻との差が10分以上は無効\r
841      * \r
842      * @param map\r
843      * @param jptime\r
844      * @return\r
845      * @throws ParseException\r
846      */\r
847     public Element getTrkpt(TreeMap<Long,Element> map, Date jptime) throws ParseException {\r
848         long sa = 2L * 3600000L;\r
849         long jpt = jptime.getTime();\r
850         \r
851         Element ret = null;\r
852 \r
853         Set<Long> keySet = map.keySet();  //すべてのキー値を取得\r
854         Iterator<Long> keyIte = keySet.iterator();\r
855         while (keyIte.hasNext()) {    //ループ。反復子iteratorによる キー 取得\r
856             Long time = keyIte.next();\r
857             long t = time;\r
858 \r
859             if (Math.abs(jpt - t) < sa) {\r
860                 sa = Math.abs(jpt - t);\r
861                 ret = map.get(time);\r
862             }\r
863         }\r
864 \r
865         if (sa < (60000L * 10L)) {\r
866                 // GPX時刻との差が10分以内なら有効\r
867             return ret;\r
868         }\r
869         return null;\r
870     }\r
871 \r
872     public Element getMaeTrkpt(TreeMap<Long,Element> map, TagTrkpt imaTrkpt) throws ParseException {\r
873         Element ret = null;\r
874         long diffTime = 2L * 3600000L;          // 2時間\r
875         long jpt = imaTrkpt.time.getTime() - DIFF_MAE_TIME;\r
876 \r
877         Set<Long> keySet = map.keySet();  //すべてのキー値を取得\r
878         Iterator<Long> keyIte = keySet.iterator();\r
879         while (keyIte.hasNext()) {    //ループ。反復子iteratorによる キー 取得\r
880             Long time = keyIte.next();\r
881             long t = time;\r
882 \r
883             if (Math.abs(jpt - t) < diffTime) {\r
884                 diffTime = Math.abs(jpt - t);\r
885                 ret = map.get(time);\r
886             }\r
887         }\r
888 \r
889         if (diffTime < (60000L * 10L)) {\r
890                 // GPX時刻との差が10分以内なら有効\r
891                 if (diffTime < (imaTrkpt.time.getTime() - 1000)) {\r
892                         // 元の時刻との差が1秒以上あること\r
893                 return ret;\r
894                 }\r
895         }\r
896         return null;\r
897     }\r
898     \r
899     /**\r
900      * 対象は '*.JPG' のみ対象とする\r
901      * @return \r
902      * @param name\r
903      */\r
904     public static boolean checkFile(String name) {\r
905         return ((name != null) && name.toUpperCase().endsWith(".JPG"));\r
906     }\r
907 \r
908     /**\r
909      *  <wpt lat="35.25714922" lon="139.15490497">\r
910      *          <ele>62.099998474121094</ele>\r
911      *          <time>2012-06-11T00:44:38Z</time>\r
912      *          <name><![CDATA[写真]]></name>\r
913      *          <link href="2012-06-11_09-44-38.jpg">\r
914      *                  <text>2012-06-11_09-44-38.jpg</text>\r
915      *          </link>\r
916      *  </wpt>\r
917      *\r
918      *  <trkpt lat="35.32123832" lon="139.56965631">\r
919      *          <ele>47.20000076293945</ele>\r
920      *          <time>2012-06-15T03:00:29Z</time>\r
921      *  </trkpt>\r
922      *\r
923      * @return\r
924      * @param iFile\r
925      * @param timestamp\r
926      * @param trkpt\r
927      */\r
928     public Element createWptTag(File iFile, long timestamp, Element trkpt) {\r
929         Element wpt = document.createElement("wpt");\r
930 \r
931         NamedNodeMap nodeMap = trkpt.getAttributes();\r
932         if (null != nodeMap) {\r
933             for (int j=0; j < nodeMap.getLength(); j++ ) {\r
934                 switch (nodeMap.item(j).getNodeName()) {\r
935                 case "lat":\r
936                     String lat = nodeMap.item(j).getNodeValue();\r
937                     wpt.setAttribute("lat", lat);\r
938                     break;\r
939                 case "lon":\r
940                     String lon = nodeMap.item(j).getNodeValue();\r
941                     wpt.setAttribute("lon", lon);\r
942                     break;\r
943                 }\r
944             }\r
945         }\r
946 \r
947         NodeList nodes1 = trkpt.getChildNodes();\r
948         for (int i1=0; i1 < nodes1.getLength(); i1++) {\r
949             Node node1 = nodes1.item(i1);\r
950             NodeList nodes2 = node1.getChildNodes();\r
951             switch (node1.getNodeName()) {\r
952             case "ele":\r
953                 for (int i2=0; i2 < nodes2.getLength(); i2++) {\r
954                     Node node2 = nodes2.item(i2);\r
955                     if (node2 != null) {\r
956                         if (node2.getNodeType() == Node.TEXT_NODE) {\r
957                             String eleStr = node2.getNodeValue();\r
958                             Element eleE = document.createElement("ele");\r
959                             eleE.setTextContent(eleStr);\r
960                             wpt.appendChild(eleE);\r
961                         }\r
962                     }\r
963                 }\r
964                 break;\r
965             case "time":\r
966                 for (int i2=0; i2 < nodes2.getLength(); i2++) {\r
967                     Node node2 = nodes2.item(i2);\r
968                     if (node2 != null) {\r
969                         if (node2.getNodeType() == Node.TEXT_NODE) {\r
970                             String timeStr = node2.getNodeValue();\r
971                             Element timeE = document.createElement("time");\r
972                             timeE.setTextContent(timeStr);\r
973                             wpt.appendChild(timeE);\r
974                         }\r
975                     }\r
976                 }\r
977                 break;\r
978             case "magvar":\r
979                 for (int i2=0; i2 < nodes2.getLength(); i2++) {\r
980                     Node node2 = nodes2.item(i2);\r
981                     if (node2 != null) {\r
982                         if (node2.getNodeType() == Node.TEXT_NODE) {\r
983                             String magvarStr = node2.getNodeValue();\r
984                             Element magvarE = document.createElement("magvar");\r
985                             magvarE.setTextContent(magvarStr);\r
986                             wpt.appendChild(magvarE);\r
987                         }\r
988                     }\r
989                 }\r
990                 break;\r
991             case "speed":\r
992                 for (int i2=0; i2 < nodes2.getLength(); i2++) {\r
993                     Node node2 = nodes2.item(i2);\r
994                     if (node2 != null) {\r
995                         if (node2.getNodeType() == Node.TEXT_NODE) {\r
996                             String speedStr = node2.getNodeValue();\r
997                             Element speedE = document.createElement("speed");\r
998                             speedE.setTextContent(speedStr);\r
999                             wpt.appendChild(speedE);\r
1000                         }\r
1001                     }\r
1002                 }\r
1003                 break;\r
1004             }\r
1005         }\r
1006 \r
1007         Element name = document.createElement("name");\r
1008         name.appendChild(document.createCDATASection("写真"));\r
1009         wpt.appendChild(name);\r
1010 \r
1011         Element link = document.createElement("link");\r
1012         link.setAttribute("href", getShortPathName(imgDir, iFile));\r
1013         Element text = document.createElement("text");\r
1014         text.setTextContent(iFile.getName());\r
1015         link.appendChild(text);\r
1016         wpt.appendChild(link);\r
1017 \r
1018         return wpt;\r
1019     }\r
1020         \r
1021     static String getShortPathName(File dir, File iFile) {\r
1022         String dirPath = dir.getAbsolutePath();\r
1023         String filePath = iFile.getAbsolutePath();\r
1024         if (filePath.startsWith(dirPath)) {\r
1025             return filePath.substring(dirPath.length()+1);\r
1026         }\r
1027         else {\r
1028             return filePath;\r
1029         }\r
1030     }\r
1031 \r
1032     public static Element getCopy(Document doc, Node node) {\r
1033         Element root = doc.createElement(node.getNodeName());\r
1034 \r
1035         NamedNodeMap nodeMap = node.getAttributes();\r
1036         if (null != nodeMap) {\r
1037             for (int j=0; j < nodeMap.getLength(); j++ ) {\r
1038                 root.setAttribute(nodeMap.item(j).getNodeName(), nodeMap.item(j).getNodeValue());\r
1039             }\r
1040         }\r
1041 \r
1042         NodeList nodes = node.getChildNodes();\r
1043         for (int i=0; i < nodes.getLength(); i++) {\r
1044             Node node2 = nodes.item(i);\r
1045             if (node2.getNodeType() == Node.ELEMENT_NODE) {\r
1046                 root.appendChild(getCopy(doc, node2));\r
1047             }\r
1048             else if (node2.getNodeType() == Node.TEXT_NODE) {\r
1049                 String str = node2.getNodeValue();\r
1050                 Text textContents = doc.createTextNode(str);\r
1051                 root.appendChild(textContents);\r
1052             }\r
1053             else if (node2.getNodeType() == Node.CDATA_SECTION_NODE) {\r
1054                 String str = node2.getNodeValue();\r
1055                 CDATASection cdataSection = doc.createCDATASection(str);\r
1056                 root.appendChild(cdataSection);\r
1057             }\r
1058         }\r
1059         return root;\r
1060     }\r
1061         \r
1062     /**\r
1063      * ファイル名の順序に並び替えるためのソートクラス\r
1064      * \r
1065      * @author hayashi\r
1066      */\r
1067     static class FileSort implements Comparator<File>{\r
1068         @Override\r
1069         public int compare(File src, File target){\r
1070             int diff = src.getName().compareTo(target.getName());\r
1071             return diff;\r
1072         }\r
1073     }\r
1074 \r
1075     /**\r
1076      * JPEGファイルフィルター\r
1077      * @author yuu\r
1078      */\r
1079         class JpegFileFilter implements FilenameFilter{\r
1080         public boolean accept(File dir, String name) {\r
1081                         if (name.toUpperCase().matches(".*\\.JPG$")) {\r
1082                                 return true;\r
1083                         }\r
1084                         return false;\r
1085         }\r
1086         }\r
1087 }