OSDN Git Service

変換済みのGPXファイルを、EXIF変換先フォルダにも作成する。
[importpicture/importpicture.git] / importPicture / src / osm / jp / gpx / ImportPicture.java
index 15f4c38..d007d53 100644 (file)
@@ -9,16 +9,17 @@ import java.util.Calendar;
 import java.util.Comparator;\r
 import java.util.Date;\r
 import java.util.GregorianCalendar;\r
-import java.util.HashMap;\r
 import java.util.Iterator;\r
 import java.util.Set;\r
 import java.util.TimeZone;\r
+import java.util.TreeMap;\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.TransformerException;\r
 import javax.xml.transform.TransformerFactory;\r
 import javax.xml.transform.dom.DOMSource;\r
 import javax.xml.transform.stream.StreamResult;\r
@@ -36,23 +37,21 @@ import org.apache.commons.imaging.formats.tiff.constants.GpsTagConstants;
 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 extends Thread {\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
-public class ImportPicture {\r
-       public static File gpxDir = new File(".");\r
-       public static File outDir = 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
+     * static initializer によるログ設定の初期化\r
+     */\r
     public static final Logger logger = Logger.getLogger("CommandLogging");\r
     static {\r
         InputStream inStream = null;\r
@@ -72,7 +71,7 @@ public class ImportPicture {
         finally {\r
             try {\r
                 if (inStream != null) {\r
-                       inStream.close();\r
+                    inStream.close();\r
                 }\r
             } catch (IOException e) {\r
                 logger.warning("ログ設定: ログ設定プロパティファイルのストリームクローズ時に例外が発生しました。:"+ e.toString());\r
@@ -94,7 +93,7 @@ public class ImportPicture {
      * argv[0] = 画像ファイルが格納されているディレクトリ\r
      * argv[1] = 時刻補正の基準とする画像ファイル\r
      * argv[2] = 基準画像ファイルの精確な撮影日時 "yyyy-MM-dd'T'HH:mm:ss"\r
-     * argv[3] = [EXIF] EXIF情報の書き換えを行う / [not] EXIF情報の書き換えを行わない\r
+     * argv[3] = [noEXIF] EXIF情報の書き換えを行わない / EXIF情報の書き換えを行う(出力先フォルダ)\r
      * argv[4] = 撮影位置をロギングしたGPXファイル\r
      * \r
      * @throws IOException\r
@@ -104,8 +103,10 @@ public class ImportPicture {
     {\r
         Date jptime;\r
 \r
+        ImportPicture obj = new ImportPicture();\r
+\r
         if (argv.length > 0) {\r
-            gpxDir = new File(argv[0]);\r
+            obj.imgDir = new File(argv[0]);\r
         }\r
 \r
         if (argv.length < 4) {\r
@@ -118,35 +119,68 @@ public class ImportPicture {
         }\r
 \r
         // 基準時刻ファイルの「更新日時」を使って時刻合わせを行う。\r
-        File baseFile = new File(gpxDir, argv[1]);\r
+        File baseFile = new File(obj.imgDir, argv[1]);\r
         jptime = new Date(baseFile.lastModified());\r
+        String timeStr = argv[2];\r
+        try {\r
+            dfjp.setTimeZone(TimeZone.getTimeZone("JST"));\r
+            Date t = dfjp.parse(timeStr);\r
+            obj.delta = t.getTime() - jptime.getTime();\r
+        }\r
+        catch (ParseException e) {\r
+            System.out.println("'"+ timeStr +"' の書式が違います("+ TIME_FORMAT_STRING +")");\r
+        }\r
 \r
         // \r
-        boolean exif = false;\r
-        if (argv[3].toUpperCase().equals("EXIF")) {\r
-            exif = true;\r
+        if (argv[3].toUpperCase().equals("noEXIF")) {\r
+            obj.exif = false;\r
+            obj.outDir = null;\r
+        }\r
+        else {\r
+            obj.exif = true;\r
+            obj.outDir = new File(argv[3]);\r
         }\r
 \r
         // 第6引数が指定されなければ、指定されたディレクトリ内のGPXファイルすべてを対象とする\r
-        ArrayList<File> gpxFiles = new ArrayList<>();\r
-        if (argv.length > 4) {\r
-            gpxFiles.add(new File(gpxDir, argv[4]));\r
+        if (argv.length >= 5) {\r
+            obj.gpxDir = new File(argv[4]);\r
+        }\r
+        else {\r
+            obj.gpxDir = obj.imgDir;\r
+        }\r
+        if (obj.gpxDir.isFile()) {\r
+            obj.gpxFiles.add(new File(obj.gpxDir, argv[4]));            \r
         }\r
         else {\r
-            File[] files = gpxDir.listFiles();\r
+            File[] files = obj.gpxDir.listFiles();\r
             for (File file : files) {\r
                 if (file.isFile()) {\r
                     String filename = file.getName().toUpperCase();\r
                     if (filename.endsWith(".GPX")) {\r
                         if (!filename.endsWith("_.GPX")) {\r
-                            gpxFiles.add(file);\r
+                            obj.gpxFiles.add(file);\r
                         }\r
                     }\r
                 }\r
             }\r
         }\r
-\r
-\r
+        \r
+        obj.start();\r
+        try {\r
+            obj.join();                            \r
+        } catch(InterruptedException end) {}\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 ArrayList<File> gpxFiles = new ArrayList<>();\r
+    \r
+    @Override\r
+    public void run() {\r
+        \r
         /**\r
          *\r
                 <wpt lat="35.25714922" lon="139.15490497">\r
@@ -165,59 +199,57 @@ public class ImportPicture {
         DocumentBuilder        builder;\r
         Node gpx;\r
 \r
-        for (File gpxFile : gpxFiles) {\r
-            String fileName = gpxFile.getName();\r
-            String iStr = fileName.substring(0, fileName.length() - 4);\r
-\r
-            File outputFile = new File(gpxFile.getParent(), iStr +"_.gpx");\r
-            System.out.println(iStr + " => "+ outputFile.getName());\r
-\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
-            HashMap<Long,Element> map = new HashMap<>();\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
-                    trkptMap(trk, map);\r
+        try {\r
+            outDir = new File(outDir, imgDir.getName());\r
+\r
+            for (File gpxFile : this.gpxFiles) {\r
+                String fileName = gpxFile.getName();\r
+                String iStr = fileName.substring(0, fileName.length() - 4);\r
+\r
+                File outputFile = new File(imgDir, iStr +"_.gpx");\r
+                System.out.println(iStr + " => "+ outputFile.getName());\r
+\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
+                TreeMap<Long,Element> map = new TreeMap<>();\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
+                        trkptMap(trk, map);\r
+                    }\r
                 }\r
-            }\r
-\r
-            if (trk != null) {\r
-                dfjp.setTimeZone(TimeZone.getTimeZone("JST"));\r
-                String timeStr = argv[2];\r
-                try {\r
-                    Date t = dfjp.parse(timeStr);\r
-                    long delta = t.getTime() - jptime.getTime();\r
 \r
+                boolean change = false;\r
+                if (trk != null) {\r
                     /*\r
                     * GPXへ割りつける開始時刻と終了時刻を求める\r
                     */\r
@@ -235,30 +267,38 @@ public class ImportPicture {
                     }\r
 \r
                     System.out.println("           時差: "+ (delta / 1000) +"(sec)");\r
-                    System.out.println("    Target GPX: ["+ gpxFile.getName() +"]");\r
+                    System.out.println("    Target GPX: ["+ gpxFile.getAbsolutePath() +"]");\r
                     System.out.println("GPX start time: "+ dfjp.format(new Date(gpxStartTime)) + "\t[GMT " + dfuk.format(new Date(gpxStartTime))+"]");\r
                     System.out.println("  GPX end time: "+ dfjp.format(new Date(gpxEndTime)) + "\t[GMT " + dfuk.format(new Date(gpxEndTime))+"]");\r
+                    System.out.println("          EXIF: "+ (exif ? ("convert to '" + outDir.getAbsolutePath() +"'") : "off"));\r
                     System.out.println();\r
                     System.out.println("------------|--------------------|--------------------|------------|------------|--------|------|");\r
                     System.out.println(" name       | UpdateTime         | GPStime            | Latitude   | Longitude  | ele    |magvar|");\r
                     System.out.println("------------|--------------------|--------------------|------------|------------|--------|------|");\r
-                    proc(gpxDir, delta, gpxStartTime, gpxEndTime, map, exif, gpx);\r
+                    change = proc(imgDir, delta, gpxStartTime, gpxEndTime, map, exif, gpx);\r
                     System.out.println("------------|--------------------|--------------------|------------|------------|--------|------|");\r
                 }\r
-                catch (ParseException e) {\r
-                    System.out.println("'"+ timeStr +"' の書式が違います("+ TIME_FORMAT_STRING +")");\r
+\r
+                // 出力\r
+                if (change) {\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
+                    if (exif) {\r
+                        outputFile = new File(outDir, iStr +"_.gpx");\r
+                        os = new FileOutputStream(outputFile);\r
+                        result = new StreamResult(os);\r
+                        transformer.transform(source, result);\r
+                    }\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 | DOMException | SAXException | IOException | ParseException | ImageReadException | ImageWriteException | IllegalArgumentException | TransformerException e) {\r
         }\r
     }\r
        \r
@@ -269,16 +309,17 @@ public class ImportPicture {
      * @throws ImageReadException \r
      * @throws ImageWriteException \r
      */\r
-    static void proc(File dir, long delta, long gpxStartTime, long gpxEndTime, HashMap<Long,Element> map, boolean exifWrite, Node gpx) throws ParseException, ImageReadException, IOException, ImageWriteException {\r
+    boolean proc(File dir, long delta, long gpxStartTime, long gpxEndTime, TreeMap<Long,Element> map, 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
+        boolean ret = false;\r
         File[] files = dir.listFiles();\r
         Arrays.sort(files, new FileSort());\r
         for (File image : files) {\r
             if (image.isDirectory()) {\r
-                proc(image, delta, gpxStartTime, gpxEndTime, map, exifWrite, gpx);\r
+                ret = proc(image, delta, gpxStartTime, gpxEndTime, map, exifWrite, gpx);\r
             }\r
             else {\r
                 String imageName = image.getName();\r
@@ -288,17 +329,12 @@ public class ImportPicture {
                     if ((uktime.getTime() >= gpxStartTime) && (uktime.getTime() <= gpxEndTime)) {\r
                         Element trkpt = trkpt(map, uktime);\r
                         if (trkpt != null) {\r
-                            System.out.print(String.format("%12s|", image.getName()));\r
-                            System.out.print(String.format("%20s ", dfjp.format(itime)));\r
-                            System.out.print(String.format("%20s|", dfjp.format(uktime)));\r
-\r
                             Element wpt = createWptTag(image, uktime.getTime(), trkpt);\r
                             String latStr = wpt.getAttribute("lat");\r
                             String lonStr = wpt.getAttribute("lon");\r
-                            System.out.print(String.format("%12s %12s|", latStr, lonStr));\r
                             double latitude = Double.parseDouble(latStr);\r
                             double longitude = Double.parseDouble(lonStr);\r
-\r
+                            \r
                             String eleStr = "-";\r
                             String magvarStr = "-";\r
                             NodeList nodes = wpt.getChildNodes();      // 子ノードを取得\r
@@ -315,7 +351,13 @@ public class ImportPicture {
                                     }\r
                                 }\r
                             }\r
+\r
+                            System.out.print(String.format("%12s|", image.getName()));\r
+                            System.out.print(String.format("%20s ", dfjp.format(itime)));\r
+                            System.out.print(String.format("%20s|", dfjp.format(uktime)));\r
+                            System.out.print(String.format("%12s %12s|", latStr, lonStr));\r
                             System.out.println(String.format("%8s|%6s|", eleStr, magvarStr));\r
+                            ret = true;\r
 \r
                             if (exifWrite) {\r
                                 TiffOutputSet outputSet = null;\r
@@ -418,12 +460,9 @@ public class ImportPicture {
                                             RationalNumber.valueOf(latitudeSeconds));\r
                                 }\r
 \r
+                                outDir.mkdir();\r
                                 ExifRewriter rewriter = new ExifRewriter();\r
                                 try {\r
-                                    if (outDir == null) {\r
-                                        outDir = new File(dir, "converted");\r
-                                        outDir.mkdir();\r
-                                    }\r
                                     fos = new FileOutputStream(new File(outDir, imageName));\r
                                     rewriter.updateExifMetadataLossy(image, fos, outputSet);\r
                                 }\r
@@ -441,6 +480,7 @@ public class ImportPicture {
                 }\r
             }\r
         }\r
+        return ret;\r
     }\r
        \r
     static Document document;\r
@@ -461,7 +501,7 @@ public class ImportPicture {
      * @param map\r
      * @throws ParseException\r
      */\r
-    public static void trkptMap(Element trk, HashMap<Long,Element> map) throws ParseException {\r
+    public static void trkptMap(Element trk, TreeMap<Long,Element> map) throws ParseException {\r
         dfuk.setTimeZone(TimeZone.getTimeZone("GMT"));\r
 \r
         NodeList nodes1 = trk.getChildNodes();\r
@@ -509,8 +549,8 @@ public class ImportPicture {
      * @param jptime\r
      * @throws ParseException\r
      */\r
-    public static Element trkpt(HashMap<Long,Element> map, Date jptime) throws ParseException {\r
-        Double R = 20000000 / Math.PI;                  // 地球の半径(m)\r
+    public static Element trkpt(TreeMap<Long,Element> map, Date jptime) throws ParseException {\r
+        Double R = 20000000 / Math.PI;\r
         long sa = 2L * 3600000L;\r
         long jpt = jptime.getTime();\r
         Element ret = null;\r
@@ -571,20 +611,25 @@ public class ImportPicture {
                                         break;\r
                                 }\r
                             }\r
-                            Double dLON = imaLON - maeLON;\r
-                            Double dLAT = imaLAT - maeLAT;\r
-                            Double r = Math.cos(Math.toRadians((imaLAT + maeLAT) * 2)) * R;\r
+                            Double r = Math.cos(Math.toRadians((imaLAT + maeLAT) / 2)) * R;\r
                             Double x = Math.toRadians(imaLON - maeLON) * r;\r
                             Double y = Math.toRadians(imaLAT - maeLAT) * R;\r
-                            double rad = Math.toDegrees(Math.atan(y / x));\r
+                            double rad = Math.toDegrees(Math.atan2(y, x));\r
                             \r
-                            if (y < 0) {\r
-                                rad = rad * -1;\r
-                                if (x > 0) {\r
-                                    rad = rad + 90;\r
+                            if (y >= 0) {\r
+                                if (x >= 0) {\r
+                                    rad = 0 - (rad - 90);\r
+                                }\r
+                                else {\r
+                                    rad = 360 - (rad - 90);\r
+                                }\r
+                            }\r
+                            else {\r
+                                if (x >= 0) {\r
+                                    rad = 90 - rad;\r
                                 }\r
                                 else {\r
-                                    rad = rad - 90;\r
+                                    rad = 90 - rad;\r
                                 }\r
                             }\r
 \r
@@ -596,6 +641,15 @@ public class ImportPicture {
                             }\r
                             magvar.setTextContent(str);\r
                             ret.appendChild(magvar);\r
+                            \r
+                            Element speed = ret.getOwnerDocument().createElement("speed");\r
+                            str = Double.toString(Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)));\r
+                            iDot = str.indexOf('.');\r
+                            if (iDot > 0) {\r
+                                str = str.substring(0, iDot);\r
+                            }\r
+                            speed.setTextContent(str);\r
+                            ret.appendChild(speed);\r
                         }\r
                     }\r
                 }\r
@@ -639,7 +693,7 @@ public class ImportPicture {
      * @param timestamp\r
      * @param trkpt\r
      */\r
-    public static Element createWptTag(File iFile, long timestamp, Element trkpt) {\r
+    public Element createWptTag(File iFile, long timestamp, Element trkpt) {\r
         Element wpt = document.createElement("wpt");\r
 \r
         NamedNodeMap nodeMap = trkpt.getAttributes();\r
@@ -710,7 +764,7 @@ public class ImportPicture {
         wpt.appendChild(name);\r
 \r
         Element link = document.createElement("link");\r
-        link.setAttribute("href", getShortPathName(gpxDir, iFile));\r
+        link.setAttribute("href", getShortPathName(imgDir, iFile));\r
         Element text = document.createElement("text");\r
         text.setTextContent(iFile.getName());\r
         link.appendChild(text);\r