OSDN Git Service

refacterring
[importpicture/importpicture.git] / importPicture / src / osm / jp / gpx / ImportPicture.java
index 733d4d2..901ca0c 100644 (file)
 package osm.jp.gpx;\r
+\r
 import java.io.*;\r
+import java.nio.channels.FileChannel;\r
+import java.text.DateFormat;\r
+import java.text.DecimalFormat;\r
 import java.text.ParseException;\r
 import java.text.SimpleDateFormat;\r
+import java.util.ArrayList;\r
+import java.util.Arrays;\r
+import java.util.Calendar;\r
+import java.util.Comparator;\r
 import java.util.Date;\r
-import java.util.HashMap;\r
-import java.util.Iterator;\r
-import java.util.Locale;\r
-import java.util.Set;\r
+import java.util.GregorianCalendar;\r
+import java.util.Map;\r
+import java.util.TimeZone;\r
+import java.util.logging.LogManager;\r
+import java.util.logging.Logger;\r
 \r
 import javax.xml.parsers.*;\r
 import javax.xml.transform.OutputKeys;\r
 import javax.xml.transform.Transformer;\r
-import javax.xml.transform.TransformerConfigurationException;\r
 import javax.xml.transform.TransformerException;\r
 import javax.xml.transform.TransformerFactory;\r
 import javax.xml.transform.dom.DOMSource;\r
 import javax.xml.transform.stream.StreamResult;\r
 \r
+import org.apache.commons.imaging.ImageReadException;\r
+import org.apache.commons.imaging.ImageWriteException;\r
+import org.apache.commons.imaging.Imaging;\r
+import org.apache.commons.imaging.common.ImageMetadata;\r
+import org.apache.commons.imaging.common.RationalNumber;\r
+import org.apache.commons.imaging.formats.jpeg.JpegImageMetadata;\r
+import org.apache.commons.imaging.formats.jpeg.exif.ExifRewriter;\r
+import org.apache.commons.imaging.formats.tiff.TiffImageMetadata;\r
+import org.apache.commons.imaging.formats.tiff.constants.ExifTagConstants;\r
+import org.apache.commons.imaging.formats.tiff.constants.GpsTagConstants;\r
+import org.apache.commons.imaging.formats.tiff.write.TiffOutputDirectory;\r
+import org.apache.commons.imaging.formats.tiff.write.TiffOutputSet;\r
 import org.w3c.dom.*;\r
 import org.xml.sax.SAXException;\r
 \r
-public class ImportPicture {\r
-\r
-       /** メイン\r
-        * 画像ファイルをGPXファイルに取り込みます。\r
-        * \r
-        * ・画像ファイルの更新日付をその画像の撮影日時とします。(Exi情報は無視します)\r
-        *    ※ 対象とするファイルは'*.jpg'のみ\r
-        * ・精確な時刻との時差を入力することで、撮影日時を補正します。\r
-        * ・画像ファイルの更新日付リストをCSV形式のファイルとして出力する。\r
-        * ・・結果は、取り込み元のGPXファイルとは別に、元ファイル名にアンダーバー「_」を付加した.ファイルに出力します。\r
-        *\r
-        * argv[0] = 画像リストの出力ファイル\r
-        * argv[1] = 画像ファイルが格納されているディレクトリ\r
-        * argv[2] = 時刻補正の基準とする画像ファイル\r
-        * argv[3] = 基準画像ファイルの精確な撮影日時 "yyyy-mm-dd'T'HH:MM:ss"\r
-        * argv[4] = 撮影位置をロギングしたGPXファイル\r
-        * \r
-        * @throws IOException\r
-        */\r
-       public static void main(String[] argv) throws IOException\r
-       {\r
-               File csvfile = new File("ImportPicture.csv");\r
-               if (argv.length > 0) {\r
-                       csvfile = new File(argv[0]);\r
-               }\r
-\r
-               File dir = new File(".");\r
-               if (argv.length > 1) {\r
-                       dir = new File(argv[1]);\r
-               }\r
-\r
-               if (argv.length < 4) {\r
-                       System.out.println("> java -jar ListUpdateTime.jar <outputfile> <targetDir> <time base image> <time> <gpx>");\r
-                       System.out.println("> java -jar ListUpdateTime.jar list.csv . IMG_01234.JPG 2012-06-15T12:52:22 鎌倉宮_2012-06-15_12-00-16.gpx");\r
-               }\r
-\r
-               /**\r
-                *\r
-                       <wpt lat="35.25714922" lon="139.15490497">\r
-                               <ele>62.099998474121094</ele>\r
-                               <time>2012-06-11T00:44:38Z</time>\r
-                               <hdop>0.75</hdop>\r
-                               <name><![CDATA[写真]]></name>\r
-                               <cmt><![CDATA[精度: 3.0m]]></cmt>\r
-                               <link href="2012-06-11_09-44-38.jpg">\r
-                                       <text>2012-06-11_09-44-38.jpg</text>\r
-                               </link>\r
-                               <sat>9</sat>\r
-                       </wpt>\r
-                */\r
-               DocumentBuilderFactory factory;\r
-               DocumentBuilder        builder;\r
-\r
-               Node gpx;\r
-               File gpxFile = new File(argv[4]);\r
-\r
-               String fileName = gpxFile.getName();\r
-               String iStr = fileName.substring(0, fileName.length() - 4);\r
-\r
-               File outputFile = new File(iStr +"_.gpx");\r
-               System.out.println(iStr + " => "+ outputFile.getName());\r
-\r
-               try {\r
-                       factory = DocumentBuilderFactory.newInstance();\r
-                       builder = factory.newDocumentBuilder();\r
-                       factory.setIgnoringElementContentWhitespace(true);\r
-                       factory.setIgnoringComments(true);\r
-                       factory.setValidating(true);\r
-\r
-                       // GPX file --> Node root\r
-                       DOMImplementation domImpl = builder.getDOMImplementation();\r
-                       document = domImpl.createDocument("", "gpx", null);\r
-\r
-                       /*\r
-                       <gpx>\r
-                               <trk>\r
-                                       <name><![CDATA[Tracked with OSMTracker for Android?]]></name>\r
-                                       <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
-                                       <trkseg>\r
-                                               <trkpt lat="35.32123832" lon="139.56965631">\r
-                                                       <ele>47.20000076293945</ele>\r
-                                                       <time>2012-06-15T03:00:29Z</time>\r
-                                                       <hdop>0.5</hdop>\r
-                                               </trkpt>\r
-                                       </trkseg>\r
-                               </trk>\r
-                               <wpt lat="35.2564461" lon="139.15437809">\r
-                               </wpt>\r
-                       </gpx>\r
-                       */\r
-                       Element trk = null;\r
-                       gpx    = builder.parse(gpxFile).getFirstChild();\r
-                       NodeList nodes = gpx.getChildNodes();\r
-                       for (int i=0; i < nodes.getLength(); i++) {\r
-                               Node node2 = nodes.item(i);\r
-                               if (node2.getNodeName().equals("trk")) {\r
-                                       trk = (Element) node2;\r
-                               }\r
-                       }\r
-\r
-                       if (trk != null) {\r
-                               HashMap<Long,Element> map = trkptMap(trk);\r
-                               File baseFile = new File(dir, argv[2]);\r
-                               Date jptime = new Date(baseFile.lastModified());\r
-\r
-                               PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(csvfile)));\r
-                               String timeStr = argv[3];\r
-                               try {\r
-                                       Date t = dfjp.parse(timeStr);\r
-                                       long delta = t.getTime() - jptime.getTime();\r
-                                       System.out.println("時差: "+ (delta / 1000) +"(sec)");\r
-                                       pw.println("時差: "+ (delta / 1000) +"(sec)");\r
-                                       ImportPicture.proc(dir, csvfile, delta);\r
-\r
-                                       pw.println("\"name\",\"orignal\",\"gpstime\"");\r
-                                       File[] files = dir.listFiles();\r
-                                       for (File image : files) {\r
-                                               String imageName = image.getName();\r
-                                               if (checkFile(imageName)) {\r
-                                                       Date itime = new Date(image.lastModified());\r
-                                                       Date uktime = new Date(itime.getTime() + delta);\r
-                                                       pw.print("\""+ fileName +"\",");\r
-                                                       pw.print("\""+ dfjp.format(itime) +"\",");\r
-                                                       pw.println("\""+ dfjp.format(uktime) +"\"");\r
-\r
-                                                       Element trkpt = trkpt(map, uktime);\r
-                                                       if (trkpt != null) {\r
-                                                               Element wpt = createWptTag(dir, image, uktime.getTime(), trkpt);\r
-                                                               Element temp = getCopy(gpx.getOwnerDocument(), wpt);\r
-                                                               gpx.appendChild(temp);\r
-                                                       }\r
-                                               }\r
-                                       }\r
-                               }\r
-                               catch (ParseException e) {\r
-                                       System.out.println("'"+ timeStr +"' の書式が違います(yyyy-MM-dd'T'HH:mm:ss)");\r
-                               }\r
-                               finally {\r
-                                       pw.close();\r
-                               }\r
-                       }\r
-\r
-                       // 出力\r
-                       DOMSource source = new DOMSource(gpx);\r
-                       FileOutputStream os = new FileOutputStream(outputFile);\r
-                       StreamResult result = new StreamResult(os);\r
-                       TransformerFactory transFactory = TransformerFactory.newInstance();\r
-                       Transformer transformer = transFactory.newTransformer();\r
-                       transformer.setOutputProperty(OutputKeys.INDENT, "yes");\r
-                       transformer.setOutputProperty(OutputKeys.METHOD, "xml");\r
-                       transformer.transform(source, result);\r
-               }\r
-               catch (ParserConfigurationException e) {\r
-                       e.printStackTrace();\r
-               }\r
-               catch (SAXException e) {\r
-                       e.printStackTrace();\r
-               }\r
-               catch (TransformerConfigurationException e) {\r
-                       e.printStackTrace();\r
-               }\r
-               catch (TransformerException e) {\r
-                       e.printStackTrace();\r
-               } catch (ParseException e) {\r
-                       e.printStackTrace();\r
-               }\r
-               finally {\r
-               }\r
-       }\r
-\r
-       static Document document;\r
-\r
+public class ImportPicture extends Thread {\r
        /**\r
-        * 2012-06-10T05:09:46Z  (日本時間の'2012-06-10T14:09:46')\r
+        * 実行中に発生したExceptionを保持する場所\r
         */\r
-       static SimpleDateFormat dfjp = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");\r
-       static SimpleDateFormat dfuk = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.UK);\r
-\r
-       public static HashMap<Long,Element> trkptMap(Element trk) throws ParseException {\r
-               HashMap<Long,Element> map = new HashMap<Long,Element>();\r
-\r
-               NodeList nodes1 = trk.getChildNodes();\r
-               for (int i1=0; i1 < nodes1.getLength(); i1++) {\r
-                       Node node2 = nodes1.item(i1);\r
-                       if (node2.getNodeName().equals("trkseg")) {\r
-                               Element trkseg = (Element) node2;\r
-                               NodeList nodes2 = trkseg.getChildNodes();\r
-                               for (int i2=0; i2 < nodes2.getLength(); i2++) {\r
-                                       Node node3 = nodes2.item(i2);\r
-                                       if (node3.getNodeName().equals("trkpt")) {\r
-                                               Element trkpt = (Element) node3;\r
-\r
-                                               NodeList nodes3 = trkpt.getChildNodes();\r
-                                               for (int i3=0; i3 < nodes3.getLength(); i3++) {\r
-                                                       Node node4 = nodes3.item(i3);\r
-                                                       if (node4.getNodeName().equals("time")) {\r
-                                                               Element time = (Element) node4;\r
-                                                               NodeList nodes4 = time.getChildNodes();      // 子ノードを取得\r
-                                                               for (int i4=0; i4< nodes4.getLength(); i4++) {\r
-                                                                       Node node5 = nodes4.item(i4);\r
-                                                                       if (node5 != null) {\r
-                                                                               if (node5.getNodeType() == Node.TEXT_NODE) {\r
-                                                                                       String timeStr = node5.getNodeValue();\r
-                                                                                       long t = dfuk.parse(timeStr).getTime() + (9L * 3600000L);\r
-                                                                                       map.put(new Long(t), getCopy(trk.getOwnerDocument(), trkpt));\r
-                                                                               }\r
-                                                                   }\r
-                                                               }\r
-                                                       }\r
-                                               }\r
-                                       }\r
-                               }\r
-                       }\r
-               }\r
-               return map;\r
-       }\r
-\r
-       public static Element trkpt(HashMap<Long,Element> map, Date jptime) throws ParseException {\r
-               long sa = 2L * 3600000L;\r
-               long jpt = jptime.getTime();\r
-               Element ret = null;\r
-\r
-               Set<Long> keySet = map.keySet();  //すべてのキー値を取得\r
-        Iterator<Long> keyIte = keySet.iterator();\r
-        while (keyIte.hasNext()) {    //ループ。反復子iteratorによる キー 取得\r
-            Long time = keyIte.next();\r
-            long t = time.longValue();\r
-                       if (Math.abs(jpt - t) < sa) {\r
-                               sa = Math.abs(jpt - t);\r
-                               ret = map.get(time);\r
-                       }\r
+       public Exception ex = null;\r
+       \r
+    /**\r
+     * ログ設定プロパティファイルのファイル内容\r
+     */\r
+    protected static final String LOGGING_PROPERTIES_DATA\r
+           = "handlers=java.util.logging.ConsoleHandler\n"\r
+           + ".level=FINEST\n"\r
+           + "java.util.logging.ConsoleHandler.level=INFO\n"\r
+           + "java.util.logging.ConsoleHandler.formatter=osm.jp.gpx.YuuLogFormatter";\r
+\r
+    /**\r
+     * static initializer によるログ設定の初期化\r
+     */\r
+    public static final Logger logger = Logger.getLogger("CommandLogging");\r
+    static {\r
+        InputStream inStream = null;\r
+        try {\r
+            inStream = new ByteArrayInputStream(LOGGING_PROPERTIES_DATA.getBytes("UTF-8"));\r
+            try {\r
+                LogManager.getLogManager().readConfiguration(inStream);\r
+                logger.config("ログ設定: LogManagerを設定しました。");\r
+            }\r
+            catch (IOException e) {\r
+                logger.warning("ログ設定: LogManager設定の際に例外が発生しました。:" + e.toString());\r
+            }\r
         }\r
-\r
-        if (sa < (60000L * 10L)) {\r
-               System.out.println(dfuk.format(jpt) +" ("+ sa +")");\r
-               return ret;\r
+        catch (UnsupportedEncodingException e) {\r
+            logger.severe("ログ設定: UTF-8エンコーディングがサポートされていません。:" + e.toString());\r
+        }\r
+        finally {\r
+            try {\r
+                if (inStream != null) {\r
+                    inStream.close();\r
+                }\r
+            } catch (IOException e) {\r
+                logger.warning("ログ設定: ログ設定プロパティファイルのストリームクローズ時に例外が発生しました。:"+ e.toString());\r
+            }\r
+        }\r
+    }\r
+    \r
+\r
+\r
+    /** メイン\r
+     * 画像ファイルをGPXファイルに取り込みます。\r
+     * \r
+     * ・画像ファイルの更新日付をその画像の撮影日時とします。(Exi情報は無視します)\r
+     *    ※ 対象とするファイルは'*.jpg'のみ\r
+     * ・精確な時刻との時差を入力することで、撮影日時を補正します。\r
+     * ・画像ファイルの更新日付リストをCSV形式のファイルとして出力する。\r
+     * ・・結果は、取り込み元のGPXファイルとは別に、元ファイル名にアンダーバー「_」を付加した.ファイルに出力します。\r
+     * \r
+     *  exp) $ java -cp .:AdjustTime.jar:commons-imaging-1.0-SNAPSHOT.jar [AdjustTime.ini]\r
+     *  exp) > java -cp .;AdjustTime.jar;commons-imaging-1.0-SNAPSHOT.jar [AdjustTime.ini]\r
+     *\r
+     * @param argv\r
+     * argv[0] = INIファイルのパス名\r
+     * \r
+     * argv[-] = dummy\r
+     * argv[0] = 画像ファイルが格納されているディレクトリ          --> imgDir\r
+     * argv[1] = 時刻補正の基準とする画像ファイル                              --> baseFile\r
+     * argv[2] = 基準画像ファイルの精確な撮影日時 "yyyy-MM-dd'T'HH:mm:ss"      --> timeStr\r
+     * argv[3] = 出力先フォルダ                                                         --> outDir\r
+     * argv[4] = 撮影位置をロギングしたGPXファイル                              --> gpxDir\r
+     * \r
+     * @throws IOException\r
+     * @throws ImageReadException \r
+     */\r
+    public static void main(String[] argv) throws Exception\r
+    {\r
+        Date imgtime;\r
+\r
+       String paramFilePath = ((argv.length < 1) ? AppParameters.FILE_PATH : argv[0]);\r
+        System.out.println("Param File = '"+ paramFilePath +"'");\r
+        ImportPicture obj = new ImportPicture();\r
+        obj.params = new AppParameters(paramFilePath);\r
+\r
+        System.out.println(" - param: "+ AppParameters.IMG_TIME +"="+ obj.params.getProperty(AppParameters.IMG_TIME) );\r
+        System.out.println(" - param: "+ AppParameters.IMG_BASE_FILE +"="+ obj.params.getProperty(AppParameters.IMG_BASE_FILE) );\r
+        System.out.println(" - param: "+ AppParameters.GPX_BASETIME +"="+ obj.params.getProperty(AppParameters.GPX_BASETIME) );\r
+        System.out.println(" - param: "+ AppParameters.IMG_SOURCE_FOLDER +"="+ obj.params.getProperty(AppParameters.IMG_SOURCE_FOLDER) );\r
+        System.out.println(" - param: "+ AppParameters.IMG_OUTPUT_FOLDER +"="+ obj.params.getProperty(AppParameters.IMG_OUTPUT_FOLDER) );\r
+        System.out.println(" - param: "+ AppParameters.IMG_OUTPUT +"="+ obj.params.getProperty(AppParameters.IMG_OUTPUT));     \r
+        System.out.println(" - param: "+ AppParameters.IMG_OUTPUT_ALL +"="+ obj.param_ImgOutputAll);\r
+        System.out.println(" - param: "+ AppParameters.IMG_OUTPUT_EXIF +"= "+ String.valueOf(obj.exif));\r
+        System.out.println(" - param: "+ AppParameters.GPX_SOURCE_FOLDER +"="+ obj.param_GpxSourceFolder);\r
+        System.out.println(" - param: "+ AppParameters.GPX_OUTPUT_WPT +"="+ obj.param_GpxOutputWpt);\r
+        System.out.println(" - param: "+ AppParameters.GPX_OVERWRITE_MAGVAR +"="+ Complementation.param_GpxOverwriteMagvar);\r
+        System.out.println(" - param: "+ AppParameters.GPX_OUTPUT_SPEED +"="+ Complementation.param_GpxOutputSpeed);\r
+        System.out.println(" - param: "+ AppParameters.GPX_GPXSPLIT +"="+ obj.param_GpxSplit);\r
+        System.out.println(" - param: "+ AppParameters.GPX_NO_FIRST_NODE +"="+ ImportPicture.param_GpxNoFirstNode);        \r
+        System.out.println(" - param: "+ AppParameters.GPX_REUSE +"="+ obj.param_GpxReuse);\r
+\r
+        obj.ex = null;\r
+        // argv[0] --> AppParameters.IMG_SOURCE_FOLDER に置き換え\r
+        obj.imgDir = new File(obj.params.getProperty(AppParameters.IMG_SOURCE_FOLDER));\r
+\r
+        // 基準時刻(ファイル更新日時 | EXIF撮影日時)\r
+       obj.exifBase = (obj.params.getProperty(AppParameters.GPX_BASETIME).equals("EXIF_TIME") ? true : false);\r
+\r
+        // 基準時刻ファイルの「更新日時」を使って時刻合わせを行う。\r
+        // argv[1] --> AppParameters.IMG_BASE_FILE に置き換え\r
+        File baseFile = new File(obj.imgDir, obj.params.getProperty(AppParameters.IMG_BASE_FILE));\r
+        if (obj.exifBase) {\r
+            ImageMetadata meta = Imaging.getMetadata(baseFile);\r
+            JpegImageMetadata jpegMetadata = (JpegImageMetadata)meta;\r
+            if (jpegMetadata == null) {\r
+                System.out.println("'"+ baseFile.getAbsolutePath() +"' にEXIF情報がありません");\r
+                return;\r
+            }\r
+            TiffImageMetadata exif = jpegMetadata.getExif();\r
+            if (exif == null) {\r
+                System.out.println("'"+ baseFile.getAbsolutePath() +"' にEXIF情報がありません");\r
+                return;\r
+            }\r
+               String dateTimeOriginal = exif.getFieldValue(ExifTagConstants.EXIF_TAG_DATE_TIME_ORIGINAL)[0];\r
+               long lastModifyTime = ImportPicture.toEXIFDate(dateTimeOriginal).getTime();\r
+               imgtime = new Date(lastModifyTime);\r
+        }\r
+        else {\r
+            imgtime = new Date(baseFile.lastModified());\r
         }\r
-        return null;\r
-       }\r
-\r
-       /**\r
-        *\r
-        *      <wpt lat="35.25714922" lon="139.15490497">\r
-        *              <ele>62.099998474121094</ele>\r
-        *              <time>2012-06-11T00:44:38Z</time>\r
-        *              <name><![CDATA[写真]]></name>\r
-        *              <link href="2012-06-11_09-44-38.jpg">\r
-        *                      <text>2012-06-11_09-44-38.jpg</text>\r
-        *              </link>\r
-        *      </wpt>\r
-        *\r
-        * @param dir\r
-        * @param csvfile\r
-        * @param delta\r
-        * @throws IOException\r
-        */\r
-       public static void proc (File dir, File csvfile, long delta) throws IOException {\r
-               int counter = 0;\r
-               PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(csvfile)));\r
-               pw.println("\"name\",\"orignal\",\"gpstime\"");\r
-\r
-               try {\r
-                       File[] files = dir.listFiles();\r
-                       for (File iFile : files) {\r
-                               String fileName = iFile.getName();\r
-                               if (checkFile(fileName)) {\r
-                                       counter++;\r
-                                       Date jptime = new Date(iFile.lastModified());\r
-                                       Date uktime = new Date(jptime.getTime() + delta);\r
-                                       pw.print("\""+ fileName +"\",");\r
-                                       pw.print("\""+ dfjp.format(jptime) +"\",");\r
-                                       pw.println("\""+ dfjp.format(uktime) +"\"");\r
-                               }\r
-                       }\r
-               }\r
-               finally {\r
-                       pw.close();\r
-                       System.out.println("Image file count = "+ counter);\r
-               }\r
-               System.out.println("SUCESS 'ListUpdateTime' => '"+ csvfile.getAbsolutePath() +"' !");\r
-       }\r
 \r
-       /**\r
-        * 対象は '*.JPG' のみ対象とする\r
-        */\r
-       public static boolean checkFile(String name) {\r
-               if (name != null && name.toUpperCase().endsWith(".JPG")) {\r
-                       return true;\r
-               }\r
-               return false;\r
-       }\r
+        // 出力ファイル\r
+        // argv[3] --> AppParameters.IMG_OUTPUT に置き換え\r
+        obj.outDir = new File(obj.params.getProperty(AppParameters.IMG_OUTPUT_FOLDER));\r
+\r
+        // その他のパラメータを読み取る\r
+       String paramStr = obj.params.getProperty(AppParameters.GPX_GPXSPLIT);\r
+       if ((paramStr != null) && (paramStr.equals(Boolean.toString(true)))) {\r
+               obj.param_GpxSplit = true;\r
+       }\r
+        \r
+       paramStr = obj.params.getProperty(AppParameters.GPX_NO_FIRST_NODE);\r
+       if ((paramStr != null) && (paramStr.equals(Boolean.toString(true)))) {\r
+               ImportPicture.param_GpxNoFirstNode = true;\r
+       }\r
+       \r
+       paramStr = obj.params.getProperty(AppParameters.GPX_REUSE);\r
+       if ((paramStr != null) && (paramStr.equals(Boolean.toString(true)))) {\r
+               obj.param_GpxReuse = true;\r
+       }\r
+        \r
+       paramStr = obj.params.getProperty(AppParameters.IMG_OUTPUT_ALL);\r
+       if ((paramStr != null) && (paramStr.equals(Boolean.toString(true)))) {\r
+               obj.param_ImgOutputAll = true;\r
+       }\r
+\r
+       paramStr = obj.params.getProperty(AppParameters.GPX_OUTPUT_WPT);\r
+       if ((paramStr != null) && (paramStr.equals(Boolean.toString(true)))) {\r
+               obj.param_GpxOutputWpt = true;\r
+       }\r
+       \r
+       paramStr = obj.params.getProperty(AppParameters.GPX_OVERWRITE_MAGVAR);\r
+       if ((paramStr != null) && (paramStr.equals(Boolean.toString(true)))) {\r
+               Complementation.param_GpxOverwriteMagvar = true;\r
+       }\r
+\r
+       paramStr = obj.params.getProperty(AppParameters.GPX_OUTPUT_SPEED);\r
+       if ((paramStr != null) && (paramStr.equals(Boolean.toString(true)))) {\r
+               Complementation.param_GpxOutputSpeed = true;\r
+       }\r
+\r
+       paramStr = obj.params.getProperty(AppParameters.GPX_SOURCE_FOLDER);\r
+       if (paramStr != null) {\r
+               obj.param_GpxSourceFolder = new String(paramStr);\r
+            obj.gpxDir = new File(obj.param_GpxSourceFolder);\r
+            if (!obj.gpxDir.exists()) {\r
+               // GPXファイルまたはディレクトリが存在しません。\r
+               System.out.println("GPXファイルまたはディレクトリが存在しません。('"+ paramStr +"')");\r
+               return;\r
+            }\r
+       }\r
+        else {\r
+            obj.gpxDir = obj.imgDir;\r
+        }\r
 \r
-       /**\r
-        *      <wpt lat="35.25714922" lon="139.15490497">\r
-        *              <ele>62.099998474121094</ele>\r
-        *              <time>2012-06-11T00:44:38Z</time>\r
-        *              <name><![CDATA[写真]]></name>\r
-        *              <link href="2012-06-11_09-44-38.jpg">\r
-        *                      <text>2012-06-11_09-44-38.jpg</text>\r
-        *              </link>\r
-        *      </wpt>\r
-        *\r
-        *      <trkpt lat="35.32123832" lon="139.56965631">\r
-        *              <ele>47.20000076293945</ele>\r
-        *              <time>2012-06-15T03:00:29Z</time>\r
-        *      </trkpt>\r
-        *\r
-        * @param dir\r
-        * @param csvfile\r
-        * @param delta\r
-        * @throws IOException\r
-        */\r
-       public static Element createWptTag(File dir, File iFile, long timestamp, Element trkpt) {\r
-               Element wpt = document.createElement("wpt");\r
-\r
-               NamedNodeMap nodeMap = trkpt.getAttributes();\r
-               if (null != nodeMap) {\r
-                       for (int j=0; j < nodeMap.getLength(); j++ ) {\r
-                               if (nodeMap.item(j).getNodeName().equals("lat")) {\r
-                                       String lat = nodeMap.item(j).getNodeValue();\r
-                                       wpt.setAttribute("lat", lat);\r
-                               }\r
-                               else if (nodeMap.item(j).getNodeName().equals("lon")) {\r
-                                       String lon = nodeMap.item(j).getNodeValue();\r
-                                       wpt.setAttribute("lon", lon);\r
-                               }\r
-                       }\r
-               }\r
-\r
-               NodeList nodes1 = trkpt.getChildNodes();\r
-               for (int i1=0; i1 < nodes1.getLength(); i1++) {\r
-                       Node node1 = nodes1.item(i1);\r
-                       if (node1.getNodeName().equals("ele")) {\r
-                               NodeList nodes2 = node1.getChildNodes();\r
-                               for (int i2=0; i2 < nodes2.getLength(); i2++) {\r
-                                       Node node2 = nodes2.item(i2);\r
-                                       if (node2 != null) {\r
-                                               if (node2.getNodeType() == Node.TEXT_NODE) {\r
-                                                       String eleStr = node2.getNodeValue();\r
-                                                       Element eleE = document.createElement("ele");\r
-                                                       eleE.setTextContent(eleStr);\r
-                                                       wpt.appendChild(eleE);\r
-                                               }\r
-                                   }\r
-                               }\r
-                       }\r
-                       else if (node1.getNodeName().equals("time")) {\r
-                               NodeList nodes2 = node1.getChildNodes();\r
-                               for (int i2=0; i2 < nodes2.getLength(); i2++) {\r
-                                       Node node2 = nodes2.item(i2);\r
-                                       if (node2 != null) {\r
-                                               if (node2.getNodeType() == Node.TEXT_NODE) {\r
-                                                       String timeStr = node2.getNodeValue();\r
-                                                       Element timeE = document.createElement("time");\r
-                                                       timeE.setTextContent(timeStr);\r
-                                                       wpt.appendChild(timeE);\r
-                                               }\r
-                                   }\r
-                               }\r
-                       }\r
-               }\r
+       // 指定されたディレクトリ内のGPXファイルすべてを対象とする\r
+        if (obj.gpxDir.isDirectory()) {\r
+            File[] files = obj.gpxDir.listFiles();\r
+            if (files == null) {\r
+               // 対象となるGPXファイルがありませんでした。\r
+               System.out.println("対象となるGPXファイルがありませんでした。('"+ obj.gpxDir.getAbsolutePath() +"')");\r
+               return;\r
+            }\r
+            if (obj.param_ImgOutputAll && (files.length > 1)) {\r
+               System.out.println("複数のGPXファイルがあるときには、'IMG.OUTPUT_ALL'オプションは指定できません。");\r
+               return;\r
+            }\r
+            \r
+            java.util.Arrays.sort(files, new java.util.Comparator<File>() {\r
+                       public int compare(File file1, File file2){\r
+                           return file1.getName().compareTo(file2.getName());\r
+                       }\r
+           });\r
+            for (File file : files) {\r
+                if (file.isFile()) {\r
+                    String filename = file.getName().toUpperCase();\r
+                    if (filename.toUpperCase().endsWith(".GPX")) {\r
+                        if (!filename.toUpperCase().endsWith("_.GPX") || obj.param_GpxReuse) {\r
+                            obj.gpxFiles.add(file);\r
+                        }\r
+                    }\r
+                }\r
+            }\r
+        }\r
+        else {\r
+            obj.gpxFiles.add(obj.gpxDir);\r
+        }\r
 \r
-               Element name = document.createElement("name");\r
-               name.appendChild(document.createCDATASection("写真"));\r
-               wpt.appendChild(name);\r
+       paramStr = obj.params.getProperty(AppParameters.IMG_OUTPUT_EXIF);\r
+       if ((paramStr != null) && (paramStr.equals(Boolean.toString(true)))) {\r
+               obj.exif = true;\r
+       }\r
+       \r
+        String timeStr = obj.params.getProperty(AppParameters.IMG_TIME);\r
+        try {\r
+            Date t = toUTCDate(timeStr);\r
+            obj.delta = t.getTime() - imgtime.getTime();\r
+        }\r
+        catch (ParseException e) {\r
+            System.out.println("'"+ timeStr +"' の書式が違います("+ TIME_FORMAT_STRING +")");\r
+            return;\r
+        }\r
 \r
-               Element link = document.createElement("link");\r
-               link.setAttribute("href", dir.getName() + "/"+ iFile.getName());\r
-               Element text = document.createElement("text");\r
-               text.setTextContent(iFile.getName());\r
-               link.appendChild(text);\r
-               wpt.appendChild(link);\r
+        obj.start();\r
+        try {\r
+            obj.join();\r
+        } catch(InterruptedException end) {}\r
+        if (obj.ex != null) {\r
+               throw obj.ex;\r
+        }\r
+    }\r
+    \r
+    public File gpxDir;\r
+    public File imgDir;\r
+    public File outDir;\r
+    public long delta = 0;\r
+    public boolean exif = false;\r
+    public boolean exifBase = false;\r
+    public ArrayList<File> gpxFiles = new ArrayList<>();\r
+    public AppParameters params;\r
+       public boolean param_GpxSplit = false;\r
+       public static boolean param_GpxNoFirstNode = false;\r
+       public boolean param_GpxReuse = false;\r
+       public boolean param_GpxOutputWpt = true;\r
+       public boolean param_ImgOutputAll = false;\r
+       public String param_GpxSourceFolder = ".";\r
+    Document document;\r
+       \r
+    public static final String TIME_FORMAT_STRING = "yyyy-MM-dd'T'HH:mm:ss'Z'";\r
+    private static final String EXIF_DATE_TIME_FORMAT_STRING = "yyyy:MM:dd HH:mm:ss";\r
+\r
+    @Override\r
+    public void run() {\r
+        /**\r
+         *\r
+                <wpt lat="35.25714922" lon="139.15490497">\r
+                        <ele>62.099998474121094</ele>\r
+                        <time>2012-06-11T00:44:38Z</time>\r
+                        <hdop>0.75</hdop>\r
+                        <name><![CDATA[写真]]></name>\r
+                        <cmt><![CDATA[精度: 3.0m]]></cmt>\r
+                        <link href="2012-06-11_09-44-38.jpg">\r
+                                <text>2012-06-11_09-44-38.jpg</text>\r
+                        </link>\r
+                        <sat>9</sat>\r
+                </wpt>\r
+         */\r
+        try {\r
+               if (params.getProperty(AppParameters.IMG_OUTPUT).equals(Boolean.toString(true))) {\r
+                outDir = new File(outDir, imgDir.getName());\r
+               }\r
+               else {\r
+                outDir = gpxDir;\r
+               }\r
+\r
+            for (File gpxFile : this.gpxFiles) {\r
+               procGPXfile(gpxFile);\r
+            }\r
+        }\r
+        catch(ParserConfigurationException | DOMException | SAXException | IOException | ParseException | ImageReadException | ImageWriteException | IllegalArgumentException | TransformerException e) {\r
+               e.printStackTrace();\r
+               this.ex = new Exception(e);\r
+        }\r
+    }\r
+    \r
+    /**\r
+     * 個別のGPXファイルを処理する\r
+     * \r
+     * @throws ParserConfigurationException \r
+     * @throws IOException \r
+     * @throws SAXException \r
+     * @throws ParseException \r
+     * @throws ImageWriteException \r
+     * @throws ImageReadException \r
+     * @throws TransformerException \r
+     */\r
+    void procGPXfile(File gpxFile) throws ParserConfigurationException, SAXException, IOException, ParseException, ImageReadException, ImageWriteException, TransformerException {\r
+        DocumentBuilderFactory factory = null;\r
+        DocumentBuilder        builder = null;\r
+        ElementMapTRKSEG mapTRKSEG = null;\r
+        Node gpx = null;\r
+        \r
+        System.gc();\r
+\r
+        String fileName = gpxFile.getName();\r
+        String iStr = fileName.substring(0, fileName.length() - 4);\r
+\r
+        File outputFile = new File(outDir, iStr +"_.gpx");\r
+        System.out.println(gpxFile.getAbsolutePath() + " => "+ outputFile.getAbsolutePath());\r
+        System.out.println("           時差: "+ (delta / 1000) +"(sec)");\r
+        System.out.println("    Target GPX: ["+ gpxFile.getAbsolutePath() +"]");\r
+        System.out.println("          EXIF: "+ (exif ? ("convert to '" + outDir.getAbsolutePath() +"'") : "off"));\r
+        System.out.println();\r
+\r
+        factory = DocumentBuilderFactory.newInstance();\r
+        builder = factory.newDocumentBuilder();\r
+        factory.setIgnoringElementContentWhitespace(true);\r
+        factory.setIgnoringComments(true);\r
+        factory.setValidating(true);\r
+\r
+        // GPXファイルをパースする\r
+        mapTRKSEG = new ElementMapTRKSEG();\r
+        document = mapTRKSEG.parse(gpxFile);\r
+        \r
+        // パースされた mapTRKSEG の中身を出力する\r
+        mapTRKSEG.printinfo();\r
+        \r
+        // GPX file --> Node root\r
+        gpx = builder.parse(gpxFile).getFirstChild();\r
+\r
+        // imgDir内の画像ファイルを処理する\r
+               System.out.println("|--------------------------------|--------------------|--------------------|--------------|--------------|--------|------|------|");\r
+               System.out.println("| name                           | Camera Time        | GPStime            |   Latitude   |   Longitude  | ele    |magvar| km/h |");\r
+               System.out.println("|--------------------------------|--------------------|--------------------|--------------|--------------|--------|------|------|");\r
+               proc(imgDir, delta, mapTRKSEG, exif, gpx);\r
+               System.out.println("|--------------------------------|--------------------|--------------------|--------------|--------------|--------|------|------|");\r
+\r
+        // 出力\r
+        outputFile.getParentFile().mkdirs();\r
+        DOMSource source = new DOMSource(gpx);\r
+        FileOutputStream os = new FileOutputStream(outputFile);\r
+        StreamResult result = new StreamResult(os);\r
+        TransformerFactory transFactory = TransformerFactory.newInstance();\r
+        Transformer transformer = transFactory.newTransformer();\r
+        transformer.setOutputProperty(OutputKeys.INDENT, "yes");\r
+        transformer.setOutputProperty(OutputKeys.METHOD, "xml");\r
+        transformer.transform(source, result);         \r
+\r
+        os = new FileOutputStream(outputFile);\r
+        result = new StreamResult(os);\r
+        transformer.transform(source, result);\r
+    }\r
+    \r
+       \r
+    /**\r
+     * 再帰メソッド\r
+     * @throws ParseException \r
+     * @throws IOException \r
+     * @throws ImageReadException \r
+     * @throws ImageWriteException \r
+     */\r
+    boolean proc(File dir, long delta, ElementMapTRKSEG mapTRKSEG, boolean exifWrite, Node gpx) throws ParseException, ImageReadException, IOException, ImageWriteException {\r
+        boolean ret = false;\r
+        File[] files = dir.listFiles(new JpegFileFilter());\r
+        Arrays.sort(files, new FileSort());\r
+        for (File image : files) {\r
+            System.out.print(String.format("|%-32s|", image.getName()));\r
+            if (image.isDirectory()) {\r
+                ret = proc(image, delta, mapTRKSEG, exifWrite, gpx);\r
+                continue;\r
+            }\r
+            \r
+            String imageName = image.getName();\r
+            if (!checkFile(imageName)) {\r
+                System.out.println(String.format("%20s ", "it is not image file."));\r
+               continue;\r
+            }\r
+            \r
+            Discripter result = procImageFile(image, delta, mapTRKSEG, exifWrite, gpx);\r
+            ret |= result.ret;\r
+            switch (result.control) {\r
+            case Discripter.CONTINUE:\r
+               continue;\r
+            case Discripter.BREAK:\r
+               break;\r
+            }\r
+        }\r
+        return ret;\r
+    }\r
+    \r
+    class Discripter {\r
+       static final int NEXT = 0;\r
+       static final int CONTINUE = -1;\r
+       static final int BREAK = 1;\r
+       \r
+       public boolean ret;\r
+       public int control;\r
+       public Discripter(boolean ret) {\r
+               this.ret = ret;\r
+               this.control = Discripter.NEXT;\r
+       }\r
+    }\r
+    \r
+    Discripter procImageFile(File image, long delta, ElementMapTRKSEG mapTRKSEG, boolean exifWrite, Node gpx) throws ParseException, ImageReadException, IOException, ImageWriteException {\r
+        DecimalFormat yearFormatter = new DecimalFormat("0000");\r
+        DecimalFormat monthFormatter = new DecimalFormat("00");\r
+        DecimalFormat dayFormatter = new DecimalFormat("00");\r
+        \r
+        Discripter result = new Discripter(false);\r
+        \r
+        // itime <-- 画像ファイルの撮影時刻\r
+        //                     ファイルの更新日時/EXIFの撮影日時\r
+        Date itime = new Date(image.lastModified());\r
+        if (this.exifBase) {\r
+            ImageMetadata meta = Imaging.getMetadata(image);\r
+            JpegImageMetadata jpegMetadata = (JpegImageMetadata)meta;\r
+            if (jpegMetadata == null) {\r
+                System.out.println("'"+ image.getAbsolutePath() +"' にEXIF情報がありません");\r
+                result.control = Discripter.CONTINUE;\r
+                return result;\r
+            }\r
+            TiffImageMetadata exif = jpegMetadata.getExif();\r
+            if (exif == null) {\r
+                System.out.println("'"+ image.getAbsolutePath() +"' にEXIF情報がありません");\r
+                result.control = Discripter.CONTINUE;\r
+                return result;\r
+            }\r
+               String dateTimeOriginal = exif.getFieldValue(ExifTagConstants.EXIF_TAG_DATE_TIME_ORIGINAL)[0];\r
+               itime = ImportPicture.toEXIFDate(dateTimeOriginal);\r
+        }\r
+        System.out.print(String.format("%20s|", toUTCString(itime)));\r
+\r
+        // uktime <-- 画像撮影時刻に対応するGPX時刻(補正日時)\r
+        Date correctedtime = new Date(itime.getTime() + delta);\r
+        System.out.print(String.format("%20s|", toUTCString(correctedtime)));\r
+\r
+               // 時刻uktimeにおける<magver>をtrkptに追加する\r
+        String eleStr = "-";\r
+        String magvarStr = "-";\r
+        String speedStr = "-";\r
+        double latitude = 90.5D;\r
+        double longitude = 180.5D;\r
+        //Element trkptE = null;\r
+        TagTrkpt trkptT = null;\r
+\r
+        for (Map.Entry<Date,ElementMapTRKPT> map : mapTRKSEG.entrySet()) {\r
+               ElementMapTRKPT mapTRKPT = map.getValue();\r
+               trkptT = mapTRKPT.getValue(correctedtime);\r
+            if (trkptT != null) {\r
+                break;\r
+            }\r
+        }\r
 \r
-               return wpt;\r
-       }\r
+        if (trkptT == null) {\r
+            System.out.print(String.format("%-14s|%-14s|", "", ""));\r
+            System.out.println(String.format("%8s|%6s|%6s|", "", "", ""));\r
+            if (!this.param_ImgOutputAll) {\r
+                result.control = Discripter.CONTINUE;\r
+                return result;\r
+            }\r
+        }\r
+        else {\r
+            latitude = trkptT.lat;\r
+            longitude = trkptT.lon;\r
+            \r
+            if (trkptT.eleStr != null) {\r
+               eleStr = new String(trkptT.eleStr);\r
+            }\r
+            \r
+            if (trkptT.magvarStr != null) {\r
+               magvarStr = new String(trkptT.magvarStr);\r
+            }\r
+            \r
+            if (trkptT.speedStr != null) {\r
+               speedStr = new String(trkptT.speedStr);\r
+            }\r
+            //System.out.print(String.format("%-14s|%-14s|", (new Double(latitude)).toString(), (new Double(longitude)).toString()));\r
+            System.out.print(String.format("%14.10f|%14.10f|", latitude, longitude));\r
+            System.out.println(String.format("%8s|%6s|%6s|", eleStr, magvarStr, speedStr));\r
+        }\r
 \r
-       public static Element getCopy(Document doc, Node node) {\r
-               Element root = doc.createElement(node.getNodeName());\r
+        result.ret = true;\r
+        FileOutputStream fos = null;\r
+        outDir.mkdir();\r
+\r
+        if (exifWrite) {\r
+            TiffOutputSet outputSet = null;\r
+\r
+            ImageMetadata meta = Imaging.getMetadata(image);\r
+            JpegImageMetadata jpegMetadata = (JpegImageMetadata)meta;\r
+            if (jpegMetadata != null) {\r
+                TiffImageMetadata exif = jpegMetadata.getExif();\r
+                if (exif != null) {\r
+                    outputSet = exif.getOutputSet();\r
+                }\r
+            }\r
+\r
+            if (outputSet == null) {\r
+                System.out.println("added : new tiff output set");\r
+                outputSet = new TiffOutputSet();\r
+            }\r
+\r
+            //---- EXIF_TAG_DATE_TIME_ORIGINAL / 「撮影日時/オリジナル画像の生成日時」----\r
+            TiffOutputDirectory exifDir = outputSet.getOrCreateExifDirectory();\r
+            {\r
+                Calendar cal = GregorianCalendar.getInstance();\r
+                cal.setTimeZone(TimeZone.getTimeZone("UTC"));\r
+                cal.setTime(correctedtime);\r
+                exifDir.removeField(ExifTagConstants.EXIF_TAG_DATE_TIME_ORIGINAL);\r
+                exifDir.add(ExifTagConstants.EXIF_TAG_DATE_TIME_ORIGINAL, ImportPicture.toEXIFString(cal.getTime()));\r
+            }\r
+\r
+            //---- EXIF GPS_TIME_STAMP ----\r
+            TiffOutputDirectory gpsDir = outputSet.getOrCreateGPSDirectory();\r
+            {\r
+                Calendar cal = GregorianCalendar.getInstance(TimeZone.getTimeZone("UTC"));\r
+                cal.setTimeZone(TimeZone.getTimeZone("GMT+00"));\r
+                cal.setTime(correctedtime);\r
+                final String yearStr = yearFormatter.format(cal.get(Calendar.YEAR));\r
+                final String monthStr = monthFormatter.format(cal.get(Calendar.MONTH) + 1);\r
+                final String dayStr = dayFormatter.format(cal.get(Calendar.DAY_OF_MONTH));\r
+                final String dateStamp = yearStr +":"+ monthStr +":"+ dayStr;\r
+\r
+                gpsDir.removeField(GpsTagConstants.GPS_TAG_GPS_TIME_STAMP);\r
+                gpsDir.add(GpsTagConstants.GPS_TAG_GPS_TIME_STAMP,\r
+                        RationalNumber.valueOf(cal.get(Calendar.HOUR_OF_DAY)),\r
+                        RationalNumber.valueOf(cal.get(Calendar.MINUTE)),\r
+                        RationalNumber.valueOf(cal.get(Calendar.SECOND)));\r
+                gpsDir.removeField(GpsTagConstants.GPS_TAG_GPS_DATE_STAMP);\r
+                gpsDir.add(GpsTagConstants.GPS_TAG_GPS_DATE_STAMP, dateStamp);\r
+            }\r
+\r
+            if (trkptT != null) {\r
+                //---- EXIF GPS elevation/ALTITUDE ----\r
+                if (eleStr.equals("-") == false) {\r
+                    final double altitude = Double.parseDouble(eleStr);\r
+                    gpsDir.removeField(GpsTagConstants.GPS_TAG_GPS_ALTITUDE);\r
+                    gpsDir.add(GpsTagConstants.GPS_TAG_GPS_ALTITUDE, RationalNumber.valueOf(altitude));\r
+                }\r
+\r
+                //---- EXIF GPS magvar/IMG_DIRECTION ----\r
+                if (magvarStr.equals("-") == false) {\r
+                    final double magvar = Double.parseDouble(magvarStr);\r
+                    gpsDir.removeField(GpsTagConstants.GPS_TAG_GPS_IMG_DIRECTION);\r
+                    gpsDir.add(GpsTagConstants.GPS_TAG_GPS_IMG_DIRECTION, RationalNumber.valueOf(magvar));\r
+                }\r
+\r
+                //---- EXIF GPS_ ----\r
+                longitude = Math.abs(longitude);\r
+                latitude = Math.abs(latitude);\r
+                outputSet.setGPSInDegrees(longitude, latitude);\r
+            }\r
+\r
+            ExifRewriter rewriter = new ExifRewriter();\r
+            try {\r
+                fos = new FileOutputStream(new File(outDir, image.getName()));\r
+                rewriter.updateExifMetadataLossy(image, fos, outputSet);\r
+            }\r
+            finally {\r
+                if (fos != null) {\r
+                    fos.close();\r
+                }\r
+            }\r
+\r
+            if (Boolean.parseBoolean(params.getProperty(AppParameters.GPX_OUTPUT_WPT))) {\r
+               if (trkptT != null) {\r
+                       Element temp = createWptTag(image, itime.getTime(), trkptT.trkpt);\r
+                    gpx.appendChild(temp);\r
+               }\r
+            }\r
+        }\r
+        else {\r
+               if (this.param_ImgOutputAll) {\r
+               // EXIFの変換を伴わない単純なファイルコピー\r
+                       FileInputStream sStream = new FileInputStream(image);\r
+                       FileInputStream dStream = new FileInputStream(new File(outDir, image.getName()));\r
+                FileChannel srcChannel = sStream.getChannel();\r
+                FileChannel destChannel = dStream.getChannel();\r
+                try {\r
+                    srcChannel.transferTo(0, srcChannel.size(), destChannel);\r
+                }\r
+                finally {\r
+                    srcChannel.close();\r
+                    destChannel.close();\r
+                    sStream.close();\r
+                    dStream.close();\r
+                }\r
+               }\r
+        }\r
+        result.control = Discripter.NEXT;\r
+        return result;\r
+    }\r
+       \r
+    /**\r
+     * 対象は '*.JPG' のみ対象とする\r
+     * @return \r
+     * @param name\r
+     */\r
+    public static boolean checkFile(String name) {\r
+        return ((name != null) && name.toUpperCase().endsWith(".JPG"));\r
+    }\r
+\r
+    /**\r
+     * <wpt lat="35.25714922" lon="139.15490497">\r
+     *         <ele>62.099998474121094</ele>\r
+     *         <time>2012-06-11T00:44:38Z</time>\r
+     *         <name><![CDATA[写真]]></name>\r
+     *         <link href="2012-06-11_09-44-38.jpg">\r
+     *                 <text>2012-06-11_09-44-38.jpg</text>\r
+     *         </link>\r
+     * </wpt>\r
+     *\r
+     * <trkpt lat="35.32123832" lon="139.56965631">\r
+     *         <ele>47.20000076293945</ele>\r
+     *         <time>2012-06-15T03:00:29Z</time>\r
+     * </trkpt>\r
+     *\r
+     * @return\r
+     * @param iFile\r
+     * @param timestamp\r
+     * @param trkpt\r
+     */\r
+    public Element createWptTag(File iFile, long timestamp, Element trkpt) {\r
+        Element wpt = document.createElement("wpt");\r
+\r
+        NamedNodeMap nodeMap = trkpt.getAttributes();\r
+        if (null != nodeMap) {\r
+            for (int j=0; j < nodeMap.getLength(); j++ ) {\r
+                switch (nodeMap.item(j).getNodeName()) {\r
+                case "lat":\r
+                    String lat = nodeMap.item(j).getNodeValue();\r
+                    wpt.setAttribute("lat", lat);\r
+                    break;\r
+                case "lon":\r
+                    String lon = nodeMap.item(j).getNodeValue();\r
+                    wpt.setAttribute("lon", lon);\r
+                    break;\r
+                }\r
+            }\r
+        }\r
 \r
-               NamedNodeMap nodeMap = node.getAttributes();\r
-               if (null != nodeMap) {\r
-                       for (int j=0; j < nodeMap.getLength(); j++ ) {\r
-                               root.setAttribute(nodeMap.item(j).getNodeName(), nodeMap.item(j).getNodeValue());\r
-                       }\r
-               }\r
+        NodeList nodes1 = trkpt.getChildNodes();\r
+        for (int i1=0; i1 < nodes1.getLength(); i1++) {\r
+            Node node1 = nodes1.item(i1);\r
+            NodeList nodes2 = node1.getChildNodes();\r
+            switch (node1.getNodeName()) {\r
+            case "ele":\r
+                for (int i2=0; i2 < nodes2.getLength(); i2++) {\r
+                    Node node2 = nodes2.item(i2);\r
+                    if (node2 != null) {\r
+                        if (node2.getNodeType() == Node.TEXT_NODE) {\r
+                            String eleStr = node2.getNodeValue();\r
+                            Element eleE = document.createElement("ele");\r
+                            eleE.setTextContent(eleStr);\r
+                            wpt.appendChild(eleE);\r
+                        }\r
+                    }\r
+                }\r
+                break;\r
+            case "time":\r
+                for (int i2=0; i2 < nodes2.getLength(); i2++) {\r
+                    Node node2 = nodes2.item(i2);\r
+                    if (node2 != null) {\r
+                        if (node2.getNodeType() == Node.TEXT_NODE) {\r
+                            String timeStr = node2.getNodeValue();\r
+                            Element timeE = document.createElement("time");\r
+                            timeE.setTextContent(timeStr);\r
+                            wpt.appendChild(timeE);\r
+                        }\r
+                    }\r
+                }\r
+                break;\r
+            case "magvar":\r
+                for (int i2=0; i2 < nodes2.getLength(); i2++) {\r
+                    Node node2 = nodes2.item(i2);\r
+                    if (node2 != null) {\r
+                        if (node2.getNodeType() == Node.TEXT_NODE) {\r
+                            String magvarStr = node2.getNodeValue();\r
+                            Element magvarE = document.createElement("magvar");\r
+                            magvarE.setTextContent(magvarStr);\r
+                            wpt.appendChild(magvarE);\r
+                        }\r
+                    }\r
+                }\r
+                break;\r
+            case "speed":\r
+                for (int i2=0; i2 < nodes2.getLength(); i2++) {\r
+                    Node node2 = nodes2.item(i2);\r
+                    if (node2 != null) {\r
+                        if (node2.getNodeType() == Node.TEXT_NODE) {\r
+                            String speedStr = node2.getNodeValue();\r
+                            Element speedE = document.createElement("speed");\r
+                            speedE.setTextContent(speedStr);\r
+                            wpt.appendChild(speedE);\r
+                        }\r
+                    }\r
+                }\r
+                break;\r
+            }\r
+        }\r
 \r
-               NodeList nodes = node.getChildNodes();\r
-               for (int i=0; i < nodes.getLength(); i++) {\r
-                       Node node2 = nodes.item(i);\r
-                       if (node2.getNodeType() == Node.ELEMENT_NODE) {\r
-                               root.appendChild(getCopy(doc, node2));\r
-                       }\r
-                       else if (node2.getNodeType() == Node.TEXT_NODE) {\r
-                               String str = node2.getNodeValue();\r
-                               Text textContents = doc.createTextNode(str);\r
-                               root.appendChild(textContents);\r
-                       }\r
-                       else if (node2.getNodeType() == Node.CDATA_SECTION_NODE) {\r
-                               String str = node2.getNodeValue();\r
-                               CDATASection cdataSection = doc.createCDATASection(str);\r
-                               root.appendChild(cdataSection);\r
+        Element name = document.createElement("name");\r
+        name.appendChild(document.createCDATASection("写真"));\r
+        wpt.appendChild(name);\r
+\r
+        Element link = document.createElement("link");\r
+        link.setAttribute("href", ImportPicture.getShortPathName(imgDir, iFile));\r
+        Element text = document.createElement("text");\r
+        text.setTextContent(iFile.getName());\r
+        link.appendChild(text);\r
+        wpt.appendChild(link);\r
+\r
+        return wpt;\r
+    }\r
+    \r
+    /**\r
+     * DateをEXIFの文字列に変換する。\r
+     * 注意:EXiFの撮影時刻はUTC時間ではない\r
+     * @param localdate\r
+     * @return\r
+     */\r
+    public static String toEXIFString(Date localdate) {\r
+       DateFormat dfUTC = new SimpleDateFormat(EXIF_DATE_TIME_FORMAT_STRING);\r
+       return dfUTC.format(localdate);\r
+    }\r
+    \r
+    /**\r
+     * EXIFの文字列をDateに変換する。\r
+     * 注意:EXiFの撮影時刻はUTC時間ではない\r
+     * @param timeStr\r
+     * @return\r
+     * @throws ParseException\r
+     */\r
+    public static Date toEXIFDate(String timeStr) throws ParseException {\r
+       DateFormat dfUTC = new SimpleDateFormat(EXIF_DATE_TIME_FORMAT_STRING);\r
+       //dfUTC.setTimeZone(TimeZone.getTimeZone("UTC"));\r
+       return dfUTC.parse(timeStr);\r
+    }\r
+       \r
+    public static String toUTCString(Date localdate) {\r
+       DateFormat dfUTC = new SimpleDateFormat(TIME_FORMAT_STRING);\r
+       dfUTC.setTimeZone(TimeZone.getTimeZone("UTC"));\r
+       return dfUTC.format(localdate);\r
+    }\r
+       \r
+    public static Date toUTCDate(String timeStr) throws ParseException {\r
+       DateFormat dfUTC = new SimpleDateFormat(TIME_FORMAT_STRING);\r
+       dfUTC.setTimeZone(TimeZone.getTimeZone("UTC"));\r
+       return dfUTC.parse(timeStr);\r
+    }\r
+       \r
+    static String getShortPathName(File dir, File iFile) {\r
+        String dirPath = dir.getAbsolutePath();\r
+        String filePath = iFile.getAbsolutePath();\r
+        if (filePath.startsWith(dirPath)) {\r
+            return filePath.substring(dirPath.length()+1);\r
+        }\r
+        else {\r
+            return filePath;\r
+        }\r
+    }\r
+    \r
+    /**\r
+     * ファイル名の順序に並び替えるためのソートクラス\r
+     * \r
+     * @author hayashi\r
+     */\r
+    static class FileSort implements Comparator<File> {\r
+        @Override\r
+        public int compare(File src, File target){\r
+            int diff = src.getName().compareTo(target.getName());\r
+            return diff;\r
+        }\r
+    }\r
+\r
+    /**\r
+     * JPEGファイルフィルター\r
+     * @author yuu\r
+     */\r
+       class JpegFileFilter implements FilenameFilter {\r
+       public boolean accept(File dir, String name) {\r
+                       if (name.toUpperCase().matches(".*\\.JPG$")) {\r
+                               return true;\r
                        }\r
-               }\r
-               return root;\r
+                       return false;\r
+       }\r
        }\r
 }
\ No newline at end of file