Newer
Older
adjustgpx-gui / src / main / java / osm / jp / gpx / Restamp.java
@haya4 haya4 on 8 Mar 2020 10 KB JDK1.8
  1. package osm.jp.gpx;
  2.  
  3. import java.io.*;
  4. import java.text.DateFormat;
  5. import java.text.SimpleDateFormat;
  6. import java.util.ArrayList;
  7. import java.util.Calendar;
  8. import java.util.Comparator;
  9. import java.util.Date;
  10. import java.util.ResourceBundle;
  11. import java.util.logging.LogManager;
  12. import java.util.logging.Logger;
  13. import org.apache.commons.imaging.ImageReadException;
  14.  
  15. /**
  16. * 動画から一定間隔で切り出したIMAGEファイルの更新日時を書き換える
  17. *
  18. * @author yuu
  19. */
  20. public class Restamp extends Thread {
  21. static public final String TIME_PATTERN = "yyyy-MM-dd HH:mm:ss z";
  22.  
  23. /**
  24. * 実行中に発生したExceptionを保持する場所
  25. */
  26. public Exception ex = null;
  27. /**
  28. * ログ設定プロパティファイルのファイル内容
  29. */
  30. protected static final String LOGGING_PROPERTIES_DATA
  31. = "handlers=java.util.logging.ConsoleHandler\n"
  32. + ".level=FINEST\n"
  33. + "java.util.logging.ConsoleHandler.level=INFO\n"
  34. + "java.util.logging.ConsoleHandler.formatter=osm.jp.gpx.YuuLogFormatter";
  35.  
  36. /**
  37. * static initializer によるログ設定の初期化
  38. */
  39. public static final Logger LOGGER = Logger.getLogger("CommandLogging");
  40. static {
  41. InputStream inStream = null;
  42. try {
  43. inStream = new ByteArrayInputStream(LOGGING_PROPERTIES_DATA.getBytes("UTF-8"));
  44. try {
  45. LogManager.getLogManager().readConfiguration(inStream);
  46. // "ログ設定: LogManagerを設定しました。"
  47. LOGGER.config("LoggerSettings: LogManager setuped.");
  48. }
  49. catch (IOException e) {
  50. // LogManager設定の際に例外が発生しました.
  51. String str = "LoggerSettings: Exception occered:" + e.toString();
  52. LOGGER.warning(str);
  53. }
  54. }
  55. catch (UnsupportedEncodingException e) {
  56. String str = "LoggerSettings: Not supported 'UTF-8' encoding: " + e.toString();
  57. LOGGER.severe(str);
  58. }
  59. finally {
  60. try {
  61. if (inStream != null) {
  62. inStream.close();
  63. }
  64. } catch (IOException e) {
  65. String str = "LoggerSettings: Exception occored: "+ e.toString();
  66. LOGGER.warning(str);
  67. }
  68. }
  69. }
  70.  
  71. /**
  72. * メイン
  73. * 動画から一定間隔で切り出したIMAGEのファイル更新日時を書き換える
  74. *
  75. * ・画像ファイルの更新日付を書き換えます。(Exi情報は無視します)
  76. * ※ 指定されたディレクトリ内のすべての'*.jpg'ファイルを処理の対象とします
  77. * ・画像は連番形式(名前順に並べられること)の名称となっていること
  78. *
  79. * パラメータ
  80. * ・対象のフォルダ(ディレクトリ内のすべての'*.jpg'ファイルを処理の対象とします)
  81. * ・基準となる画像
  82. * ・基準画像の正しい日時
  83. * ・画像ファイルの間隔(秒)
  84. *
  85. * exp) $ java -cp .:AdjustTime.jar:commons-imaging-1.0-SNAPSHOT.jar [AdjustTime.ini]
  86. * exp) > java -cp .;AdjustTime.jar;commons-imaging-1.0-SNAPSHOT.jar [AdjustTime.ini]
  87. *
  88. * 1. 予め、動画から画像を切り出す
  89. *   ソースファイル(mp4ファイル); 「-i 20160427_104154.mp4」
  90. * 出力先: 「-f image2 img/%06d.jpg」 imgフォルダに6桁の連番ファイルを差出力する
  91. *   切り出し開始秒数→ 「-ss 0」 (ファイルの0秒から切り出し開始)
  92. *   切り出し間隔; 「-r 30」 (1秒間隔=30fps間隔)
  93. * ```
  94. * $ cd /home/yuu/Desktop/OSM/20180325_横浜新道
  95. * $ ffmpeg -ss 0 -i 20160427_104154.mp4 -f image2 -r 15 img/%06d.jpg
  96. * ```
  97. *
  98. * 2. ファイルの更新日付を書き換える
  99. * ```
  100. * $ cd /home/yuu/Desktop/workspace/AdjustTime/importPicture/dist
  101. * $ java -cp .:AdjustTime2.jar osm.jp.gpx.Restamp /home/yuu/Desktop/OSM/20180325_横浜新道/img 000033.jpg 2018-03-25_12:20:32 003600.jpg 2018-03-25_13:20:09
  102. * ```
  103. *
  104. * @param argv
  105. * argv[0] = 画像ファイルが格納されているディレクトリ --> imgDir
  106. * argv[1] = 時刻補正の基準とする画像ファイル --> baseFile
  107. * argv[2] = 基準画像ファイルの精確な撮影日時 "yyyy-MM-dd HH:mm:ss z" --> baseTime
  108. * argv[3] = 時刻補正の基準とする画像ファイル --> baseFile
  109. * argv[4] = 基準画像ファイルの精確な撮影日時 "yyyy-MM-dd HH:mm:ss z" --> baseTime
  110. *
  111. * @throws IOException
  112. * @throws ImageReadException
  113. */
  114. public static void main(String[] argv) throws Exception
  115. {
  116. if (argv.length < 5) {
  117. System.out.println("java Restamp <imgDir> <baseFile1> <timeStr1> <baseFile2> <timeStr2>");
  118. return;
  119. }
  120. File imgDir = new File(argv[0]);
  121. if (!imgDir.exists()) {
  122. // "[error] <imgDir>が存在しません。"
  123. System.out.println(i18n.getString("msg.200"));
  124. return;
  125. }
  126. if (!imgDir.isDirectory()) {
  127. // "[error] <imgDir>がフォルダじゃない"
  128. System.out.println(i18n.getString("msg.210"));
  129. return;
  130. }
  131. File baseFile1 = new File(imgDir, argv[1]);
  132. if (!baseFile1.exists()) {
  133. // "[error] <baseFile1>が存在しません。"
  134. System.out.println(i18n.getString("msg.220"));
  135. return;
  136. }
  137. if (!baseFile1.isFile()) {
  138. // "[error] <baseFile1>がファイルじゃない"
  139. System.out.println(i18n.getString("msg.230"));
  140. return;
  141. }
  142. DateFormat df1 = new SimpleDateFormat(TIME_PATTERN);
  143. Date baseTime1 = df1.parse(argv[2]);
  144.  
  145. File baseFile2 = new File(imgDir, argv[3]);
  146. if (!baseFile2.exists()) {
  147. // "[error] <baseFile2>が存在しません。"
  148. System.out.println(i18n.getString("msg.240"));
  149. return;
  150. }
  151. if (!baseFile2.isFile()) {
  152. // "[error] <baseFile2>がファイルじゃない"
  153. System.out.println(i18n.getString("msg.250"));
  154. return;
  155. }
  156. Date baseTime2 = df1.parse(argv[4]);
  157.  
  158. Restamp obj = new Restamp();
  159. obj.setUp(imgDir, baseFile1, baseTime1, baseFile2, baseTime2);
  160. }
  161. public File imgDir;
  162. public Date baseTime1;
  163. public Date baseTime2;
  164. public int bCount1 = 0;
  165. public int bCount2 = 0;
  166. public long span = 0;
  167. public ArrayList<File> jpgFiles = new ArrayList<>();
  168. public static ResourceBundle i18n = ResourceBundle.getBundle("i18n");
  169. public void setUp(File imgDir, File baseFile1, Date baseTime1, File baseFile2, Date baseTime2) throws Exception {
  170. // 指定されたディレクトリ内のGPXファイルすべてを対象とする
  171. File[] files = imgDir.listFiles();
  172. java.util.Arrays.sort(files, new java.util.Comparator<File>() {
  173. @Override
  174. public int compare(File file1, File file2){
  175. return file1.getName().compareTo(file2.getName());
  176. }
  177. });
  178. bCount1 = 0;
  179. bCount2 = 0;
  180. boolean base1 = false;
  181. boolean base2 = false;
  182. for (File file : files) {
  183. if (file.isFile()) {
  184. String filename = file.getName().toUpperCase();
  185. if (filename.toUpperCase().endsWith(".JPG")) {
  186. this.jpgFiles.add(file);
  187. bCount1 += (base1 ? 0 : 1);
  188. bCount2 += (base2 ? 0 : 1);
  189. if (file.getName().equals(baseFile1.getName())) {
  190. base1 = true;
  191. }
  192. if (file.getName().equals(baseFile2.getName())) {
  193. base2 = true;
  194. }
  195. }
  196. }
  197. }
  198.  
  199. try {
  200. DateFormat df2 = new SimpleDateFormat(TIME_PATTERN);
  201. // imgDir内の画像ファイルを処理する
  202. long span = baseTime2.getTime() - baseTime1.getTime();
  203. span = span / (bCount2 - bCount1);
  204. int i = 0;
  205. System.out.println("-------------------------------");
  206. System.out.println("Update last modified date time.");
  207. for (File jpgFile : this.jpgFiles) {
  208. long deltaMsec = (i - (bCount1 -1)) * span;
  209. i++;
  210. Calendar cal = Calendar.getInstance();
  211. cal.setTime(baseTime1);
  212. cal.add(Calendar.MILLISECOND, (int) deltaMsec);
  213. System.out.println(String.format("\t%s --> %s", df2.format(cal.getTime()), jpgFile.getName()));
  214. jpgFile.setLastModified(cal.getTimeInMillis());
  215. }
  216. System.out.println("-------------------------------");
  217. }
  218. catch(Exception e) {
  219. this.ex = new Exception(e);
  220. }
  221. }
  222. /**
  223. * 対象は '*.JPG' のみ対象とする
  224. * @return
  225. * @param name
  226. */
  227. public static boolean checkFile(String name) {
  228. return ((name != null) && name.toUpperCase().endsWith(".JPG"));
  229. }
  230.  
  231. /**
  232. * ファイル名の順序に並び替えるためのソートクラス
  233. *
  234. * @author hayashi
  235. */
  236. static class FileSort implements Comparator<File> {
  237. @Override
  238. public int compare(File src, File target){
  239. int diff = src.getName().compareTo(target.getName());
  240. return diff;
  241. }
  242. }
  243.  
  244. /**
  245. * JPEGファイルフィルター
  246. * @author yuu
  247. */
  248. class JpegFileFilter implements FilenameFilter {
  249. @Override
  250. public boolean accept(File dir, String name) {
  251. return name.toUpperCase().matches(".*\\.JPG$");
  252. }
  253. }
  254. }