--- /dev/null
+package osm.jp.gpx;\r
+import java.io.*;\r
+import java.text.ParseException;\r
+import java.text.SimpleDateFormat;\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
+\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.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
+ /**\r
+ * 2012-06-10T05:09:46Z (日本時間の'2012-06-10T14:09:46')\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
+ }\r
+\r
+ if (sa < (60000L * 10L)) {\r
+ System.out.println(dfuk.format(jpt) +" ("+ sa +")");\r
+ return ret;\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
+ /**\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
+\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", dir.getName() + "/"+ iFile.getName());\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
+ public static Element getCopy(Document doc, Node node) {\r
+ Element root = doc.createElement(node.getNodeName());\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
+\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
+ }\r
+ }\r
+ return root;\r
+ }\r
+}
\ No newline at end of file