package osm.jp.gpx; import java.io.*; import java.nio.channels.FileChannel; import java.text.DateFormat; import java.text.DecimalFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; import java.util.Comparator; import java.util.Date; import java.util.Map; import java.util.ResourceBundle; import java.util.TimeZone; import java.util.logging.LogManager; import java.util.logging.Logger; import javax.xml.parsers.*; import javax.xml.transform.TransformerException; import org.apache.commons.imaging.ImageReadException; import org.apache.commons.imaging.ImageWriteException; import org.apache.commons.imaging.Imaging; import org.apache.commons.imaging.common.ImageMetadata; import org.apache.commons.imaging.common.RationalNumber; import org.apache.commons.imaging.formats.jpeg.JpegImageMetadata; import org.apache.commons.imaging.formats.jpeg.exif.ExifRewriter; import org.apache.commons.imaging.formats.tiff.TiffImageMetadata; import org.apache.commons.imaging.formats.tiff.constants.ExifTagConstants; import org.apache.commons.imaging.formats.tiff.constants.GpsTagConstants; import org.apache.commons.imaging.formats.tiff.write.TiffOutputDirectory; import org.apache.commons.imaging.formats.tiff.write.TiffOutputSet; import org.w3c.dom.*; import org.xml.sax.SAXException; public class ImportPicture extends Thread { /** * 実行中に発生したExceptionを保持する場所 */ public Exception ex = null; /** * ログ設定プロパティファイルのファイル内容 */ protected static final String LOGGING_PROPERTIES_DATA = "handlers=java.util.logging.ConsoleHandler\n" + ".level=FINEST\n" + "java.util.logging.ConsoleHandler.level=INFO\n" + "java.util.logging.ConsoleHandler.formatter=osm.jp.gpx.YuuLogFormatter"; /** * static initializer によるログ設定の初期化 */ public static final Logger LOGGER = Logger.getLogger("CommandLogging"); static { InputStream inStream = null; try { inStream = new ByteArrayInputStream(LOGGING_PROPERTIES_DATA.getBytes("UTF-8")); try { LogManager.getLogManager().readConfiguration(inStream); // "ログ設定: LogManagerを設定しました。" LOGGER.config("LoggerSettings: LogManager setuped."); } catch (IOException e) { // LogManager設定の際に例外が発生しました. String str = "LoggerSettings: Exception occered:" + e.toString(); LOGGER.warning(str); } } catch (UnsupportedEncodingException e) { String str = "LoggerSettings: Not supported 'UTF-8' encoding: " + e.toString(); LOGGER.severe(str); } finally { try { if (inStream != null) { inStream.close(); } } catch (IOException e) { String str = "LoggerSettings: Exception occored: "+ e.toString(); LOGGER.warning(str); } } } /** メイン * 画像ファイルをGPXファイルに取り込みます。 * * ・画像ファイルの更新日付をその画像の撮影日時とします。(Exi情報は無視します) * ※ 対象とするファイルは'*.jpg'のみ * ・精確な時刻との時差を入力することで、撮影日時を補正します。 * ・画像ファイルの更新日付リストをCSV形式のファイルとして出力する。 * ・・結果は、取り込み元のGPXファイルとは別に、元ファイル名にアンダーバー「_」を付加した.ファイルに出力します。 * * exp) $ java -cp .:AdjustTime.jar:commons-imaging-1.0-SNAPSHOT.jar [AdjustTime.ini] * exp) > java -cp .;AdjustTime.jar;commons-imaging-1.0-SNAPSHOT.jar [AdjustTime.ini] * * @param argv * argv[0] = INIファイルのパス名 * * argv[-] = dummy * argv[0] = 画像ファイルが格納されているディレクトリ --> imgDir * argv[1] = 時刻補正の基準とする画像ファイル --> baseFile * argv[2] = 基準画像ファイルの精確な撮影日時 "yyyy-MM-dd'T'HH:mm:ss" --> timeStr * argv[3] = 出力先フォルダ --> outDir * argv[4] = 撮影位置をロギングしたGPXファイル --> gpxDir * * @throws IOException * @throws ImageReadException */ public static void main(String[] argv) throws Exception { ImportPicture obj = new ImportPicture(); obj.setUp(((argv.length < 1) ? AppParameters.FILE_PATH : argv[0])); } public File gpxDir; public File imgDir; public File outDir; public long delta = 0; public boolean exif = false; public boolean exifBase = false; public ArrayList<File> gpxFiles = new ArrayList<>(); public AppParameters params; public boolean param_GpxSplit = false; public static boolean param_GpxNoFirstNode = false; public boolean param_GpxReuse = false; public boolean param_GpxOutputWpt = true; public boolean param_ImgOutputAll = false; public String param_GpxSourceFolder = "."; public static final String TIME_FORMAT_STRING = "yyyy-MM-dd'T'HH:mm:ss'Z'"; private static final String EXIF_DATE_TIME_FORMAT_STRING = "yyyy:MM:dd HH:mm:ss"; public ResourceBundle i18n = ResourceBundle.getBundle("i18n"); public void setUp(String paramFilePath) throws Exception { System.out.println("Param File = '"+ paramFilePath +"'"); this.params = new AppParameters(paramFilePath); Date imgtime; System.out.println(" - param: "+ AppParameters.IMG_TIME +"="+ this.params.getProperty(AppParameters.IMG_TIME) ); System.out.println(" - param: "+ AppParameters.IMG_BASE_FILE +"="+ this.params.getProperty(AppParameters.IMG_BASE_FILE) ); System.out.println(" - param: "+ AppParameters.GPX_BASETIME +"="+ this.params.getProperty(AppParameters.GPX_BASETIME) ); System.out.println(" - param: "+ AppParameters.IMG_SOURCE_FOLDER +"="+ this.params.getProperty(AppParameters.IMG_SOURCE_FOLDER) ); System.out.println(" - param: "+ AppParameters.IMG_OUTPUT_FOLDER +"="+ this.params.getProperty(AppParameters.IMG_OUTPUT_FOLDER) ); System.out.println(" - param: "+ AppParameters.IMG_OUTPUT +"="+ this.params.getProperty(AppParameters.IMG_OUTPUT)); System.out.println(" - param: "+ AppParameters.IMG_OUTPUT_ALL +"="+ this.param_ImgOutputAll); System.out.println(" - param: "+ AppParameters.IMG_OUTPUT_EXIF +"= "+ String.valueOf(this.exif)); System.out.println(" - param: "+ AppParameters.GPX_SOURCE_FOLDER +"="+ this.param_GpxSourceFolder); System.out.println(" - param: "+ AppParameters.GPX_OUTPUT_WPT +"="+ this.param_GpxOutputWpt); System.out.println(" - param: "+ AppParameters.GPX_OVERWRITE_MAGVAR +"="+ Complementation.param_GpxOverwriteMagvar); System.out.println(" - param: "+ AppParameters.GPX_OUTPUT_SPEED +"="+ Complementation.param_GpxOutputSpeed); System.out.println(" - param: "+ AppParameters.GPX_GPXSPLIT +"="+ this.param_GpxSplit); System.out.println(" - param: "+ AppParameters.GPX_NO_FIRST_NODE +"="+ ImportPicture.param_GpxNoFirstNode); System.out.println(" - param: "+ AppParameters.GPX_REUSE +"="+ this.param_GpxReuse); this.ex = null; // argv[0] --> AppParameters.IMG_SOURCE_FOLDER に置き換え this.imgDir = new File(this.params.getProperty(AppParameters.IMG_SOURCE_FOLDER)); // 基準時刻(ファイル更新日時 | EXIF撮影日時) this.exifBase = (this.params.getProperty(AppParameters.GPX_BASETIME).equals("EXIF_TIME")); // 基準時刻ファイルの「更新日時」を使って時刻合わせを行う。 // argv[1] --> AppParameters.IMG_BASE_FILE に置き換え imgtime = this.adjustTime(new File(this.imgDir, this.params.getProperty(AppParameters.IMG_BASE_FILE))); // 出力ファイル // argv[3] --> AppParameters.IMG_OUTPUT に置き換え this.outDir = new File(this.params.getProperty(AppParameters.IMG_OUTPUT_FOLDER)); // その他のパラメータを読み取る String paramStr = this.params.getProperty(AppParameters.GPX_GPXSPLIT); if ((paramStr != null) && (paramStr.equals(Boolean.toString(true)))) { this.param_GpxSplit = true; } paramStr = this.params.getProperty(AppParameters.GPX_NO_FIRST_NODE); if ((paramStr != null) && (paramStr.equals(Boolean.toString(true)))) { ImportPicture.param_GpxNoFirstNode = true; } paramStr = this.params.getProperty(AppParameters.GPX_REUSE); if ((paramStr != null) && (paramStr.equals(Boolean.toString(true)))) { this.param_GpxReuse = true; } paramStr = this.params.getProperty(AppParameters.IMG_OUTPUT_ALL); if ((paramStr != null) && (paramStr.equals(Boolean.toString(true)))) { this.param_ImgOutputAll = true; } paramStr = this.params.getProperty(AppParameters.GPX_OUTPUT_WPT); if ((paramStr != null) && (paramStr.equals(Boolean.toString(true)))) { this.param_GpxOutputWpt = true; } paramStr = this.params.getProperty(AppParameters.GPX_OVERWRITE_MAGVAR); if ((paramStr != null) && (paramStr.equals(Boolean.toString(true)))) { Complementation.param_GpxOverwriteMagvar = true; } paramStr = this.params.getProperty(AppParameters.GPX_OUTPUT_SPEED); if ((paramStr != null) && (paramStr.equals(Boolean.toString(true)))) { Complementation.param_GpxOutputSpeed = true; } paramStr = this.params.getProperty(AppParameters.GPX_SOURCE_FOLDER); if (paramStr != null) { this.param_GpxSourceFolder = paramStr; this.gpxDir = new File(this.param_GpxSourceFolder); if (!this.gpxDir.exists()) { // GPXファイルまたはディレクトリが存在しません。('%s') System.out.println( String.format(i18n.getString("msg.100"), paramStr) ); return; } } else { this.gpxDir = this.imgDir; } // 指定されたディレクトリ内のGPXファイルすべてを対象とする if (this.gpxDir.isDirectory()) { File[] files = this.gpxDir.listFiles(); if (files == null) { // 対象となるGPXファイルがありませんでした。('%s') System.out.println( String.format(i18n.getString("msg.110"), this.gpxDir.getAbsolutePath()) ); return; } if (this.param_ImgOutputAll && (files.length > 1)) { // "複数のGPXファイルがあるときには、'IMG.OUTPUT_ALL'オプションは指定できません。" System.out.println( i18n.getString("msg.120") ); return; } java.util.Arrays.sort( files, new java.util.Comparator<File>() { @Override public int compare(File file1, File file2){ return file1.getName().compareTo(file2.getName()); } } ); for (File file : files) { if (file.isFile()) { String filename = file.getName().toUpperCase(); if (filename.toUpperCase().endsWith(".GPX")) { if (!filename.toUpperCase().endsWith("_.GPX") || this.param_GpxReuse) { this.gpxFiles.add(file); } } } } } else { this.gpxFiles.add(this.gpxDir); } paramStr = this.params.getProperty(AppParameters.IMG_OUTPUT_EXIF); if ((paramStr != null) && (paramStr.equals(Boolean.toString(true)))) { this.exif = true; } String timeStr = this.params.getProperty(AppParameters.IMG_TIME); try { Date t = toUTCDate(timeStr); this.delta = t.getTime() - imgtime.getTime(); } catch (ParseException e) { // "'%s'の書式が違います(%s)" System.out.println( String.format( i18n.getString("msg.130"), timeStr, TIME_FORMAT_STRING ) ); return; } this.start(); try { this.join(); } catch(InterruptedException end) {} if (this.ex != null) { throw this.ex; } } /** * @code{ <wpt lat="35.25714922" lon="139.15490497"> <ele>62.099998474121094</ele> <time>2012-06-11T00:44:38Z</time> <hdop>0.75</hdop> <name><![CDATA[写真]]></name> <cmt><![CDATA[精度: 3.0m]]></cmt> <link href="2012-06-11_09-44-38.jpg"> <text>2012-06-11_09-44-38.jpg</text> </link> <sat>9</sat> </wpt> * } */ @Override public void run() { try { if (params.getProperty(AppParameters.IMG_OUTPUT).equals(Boolean.toString(true))) { outDir = new File(outDir, imgDir.getName()); } else { outDir = gpxDir; } for (File gpxFile : this.gpxFiles) { procGPXfile(new GpxFile(gpxFile)); } } catch(ParserConfigurationException | DOMException | SAXException | IOException | ParseException | ImageReadException | ImageWriteException | IllegalArgumentException | TransformerException e) { e.printStackTrace(); this.ex = new Exception(e); } } /** * 個別のGPXファイルを処理する * * @throws ParserConfigurationException * @throws IOException * @throws SAXException * @throws ParseException * @throws ImageWriteException * @throws ImageReadException * @throws TransformerException */ void procGPXfile(GpxFile gpxFile) throws ParserConfigurationException, SAXException, IOException, ParseException, ImageReadException, ImageWriteException, TransformerException { System.gc(); System.out.println("time difference: "+ (delta / 1000) +"(sec)"); System.out.println(" Target GPX: ["+ gpxFile.getAbsolutePath() +"]"); System.out.println(" EXIF: "+ (exif ? ("convert to '" + outDir.getAbsolutePath() +"'") : "off")); System.out.println(); // imgDir内の画像ファイルを処理する System.out.println("|--------------------------------|--------------------|--------------------|--------------|--------------|--------|------|------|"); System.out.println("| name | Camera Time | GPStime | Latitude | Longitude | ele |magvar| km/h |"); System.out.println("|--------------------------------|--------------------|--------------------|--------------|--------------|--------|------|------|"); boolean out = proc(imgDir, delta, gpxFile.mapTRKSEG, exif, gpxFile); System.out.println("|--------------------------------|--------------------|--------------------|--------------|--------------|--------|------|------|"); if (out) { // GPX出力 gpxFile.output(outDir); } } /** * 再帰メソッド * @throws ParseException * @throws IOException * @throws ImageReadException * @throws ImageWriteException */ boolean proc(File dir, long delta, ElementMapTRKSEG mapTRKSEG, boolean exifWrite, GpxFile gpxFile) throws ParseException, ImageReadException, IOException, ImageWriteException { boolean ret = false; File[] files = dir.listFiles(new JpegFileFilter()); Arrays.sort(files, new FileSort()); for (File image : files) { System.out.print(String.format("|%-32s|", image.getName())); if (image.isDirectory()) { ret = proc(image, delta, mapTRKSEG, exifWrite, gpxFile); continue; } String imageName = image.getName(); if (!checkFile(imageName)) { System.out.println(String.format("%20s ", "it is not image file.")); continue; } Discripter result = procImageFile(image, delta, mapTRKSEG, exifWrite, gpxFile); ret |= result.ret; switch (result.control) { case Discripter.CONTINUE: continue; case Discripter.BREAK: break; } } return ret; } class Discripter { static final int NEXT = 0; static final int CONTINUE = -1; static final int BREAK = 1; public boolean ret; public int control; public Discripter(boolean ret) { this.ret = ret; this.control = Discripter.NEXT; } } Discripter procImageFile(File imageFile, long delta, ElementMapTRKSEG mapTRKSEG, boolean exifWrite, GpxFile gpxFile) throws ParseException, ImageReadException, IOException, ImageWriteException { Discripter result = new Discripter(false); // itime <-- 画像ファイルの撮影時刻 // ファイルの更新日時/EXIFの撮影日時 Date itime = new Date(imageFile.lastModified()); if (this.exifBase) { ImageMetadata meta = Imaging.getMetadata(imageFile); JpegImageMetadata jpegMetadata = (JpegImageMetadata)meta; if (jpegMetadata == null) { // "'%s'にEXIF情報がありません" System.out.println( String.format( i18n.getString("msg.140"), imageFile.getAbsolutePath() ) ); result.control = Discripter.CONTINUE; return result; } @SuppressWarnings("LocalVariableHidesMemberVariable") TiffImageMetadata exif = jpegMetadata.getExif(); if (exif == null) { // "'%s'にEXIF情報がありません" System.out.println( String.format( i18n.getString("msg.140"), imageFile.getAbsolutePath() ) ); result.control = Discripter.CONTINUE; return result; } String dateTimeOriginal = exif.getFieldValue(ExifTagConstants.EXIF_TAG_DATE_TIME_ORIGINAL)[0]; itime = ImportPicture.toEXIFDate(dateTimeOriginal); } System.out.print(String.format("%20s|", toUTCString(itime))); // uktime <-- 画像撮影時刻に対応するGPX時刻(補正日時) Date correctedtime = new Date(itime.getTime() + delta); System.out.print(String.format("%20s|", toUTCString(correctedtime))); // 時刻uktimeにおける<magver>をtrkptに追加する String eleStr = "-"; String magvarStr = "-"; String speedStr = "-"; TagTrkpt trkptT = null; for (Map.Entry<Date,ElementMapTRKPT> map : mapTRKSEG.entrySet()) { ElementMapTRKPT mapTRKPT = map.getValue(); trkptT = mapTRKPT.getValue(correctedtime); if (trkptT != null) { break; } } if (trkptT == null) { System.out.print(String.format("%-14s|%-14s|", "", "")); System.out.println(String.format("%8s|%6s|%6s|", "", "", "")); if (!this.param_ImgOutputAll) { result.control = Discripter.CONTINUE; return result; } } else { double latitude = trkptT.lat; double longitude = trkptT.lon; if (trkptT.eleStr != null) { eleStr = trkptT.eleStr; } if (trkptT.magvarStr != null) { magvarStr = trkptT.magvarStr; } if (trkptT.speedStr != null) { speedStr = trkptT.speedStr; } System.out.print(String.format("%14.10f|%14.10f|", latitude, longitude)); System.out.println(String.format("%8s|%6s|%6s|", eleStr, magvarStr, speedStr)); } result.ret = true; outDir.mkdir(); if (exifWrite) { exifWrite(imageFile, correctedtime, trkptT); if (Boolean.parseBoolean(params.getProperty(AppParameters.GPX_OUTPUT_WPT))) { if (trkptT != null) { Element temp = gpxFile.createWptTag(imageFile, imgDir, itime.getTime(), trkptT.trkpt); gpxFile.gpx.appendChild(temp); } } } else { if (this.param_ImgOutputAll) { // EXIFの変換を伴わない単純なファイルコピー FileInputStream sStream = new FileInputStream(imageFile); FileInputStream dStream = new FileInputStream(new File(outDir, imageFile.getName())); FileChannel srcChannel = sStream.getChannel(); FileChannel destChannel = dStream.getChannel(); try { srcChannel.transferTo(0, srcChannel.size(), destChannel); } finally { srcChannel.close(); destChannel.close(); sStream.close(); dStream.close(); } } } result.control = Discripter.NEXT; return result; } void exifWrite(File imageFile, Date correctedtime, TagTrkpt trkptT) throws ImageReadException, IOException, ImageWriteException { DecimalFormat yearFormatter = new DecimalFormat("0000"); DecimalFormat monthFormatter = new DecimalFormat("00"); DecimalFormat dayFormatter = new DecimalFormat("00"); TiffOutputSet outputSet = null; ImageMetadata meta = Imaging.getMetadata(imageFile); JpegImageMetadata jpegMetadata = (JpegImageMetadata)meta; if (jpegMetadata != null) { @SuppressWarnings("LocalVariableHidesMemberVariable") TiffImageMetadata exif = jpegMetadata.getExif(); if (exif != null) { outputSet = exif.getOutputSet(); } } if (outputSet == null) { outputSet = new TiffOutputSet(); } //---- EXIF_TAG_DATE_TIME_ORIGINAL / 「撮影日時/オリジナル画像の生成日時」---- TiffOutputDirectory exifDir = outputSet.getOrCreateExifDirectory(); { Calendar cal = Calendar.getInstance(); cal.setTimeZone(TimeZone.getTimeZone("UTC")); cal.setTime(correctedtime); exifDir.removeField(ExifTagConstants.EXIF_TAG_DATE_TIME_ORIGINAL); exifDir.add(ExifTagConstants.EXIF_TAG_DATE_TIME_ORIGINAL, ImportPicture.toEXIFString(cal.getTime())); } //---- EXIF GPS_TIME_STAMP ---- TiffOutputDirectory gpsDir = outputSet.getOrCreateGPSDirectory(); { Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC")); cal.setTimeZone(TimeZone.getTimeZone("GMT+00")); cal.setTime(correctedtime); final String yearStr = yearFormatter.format(cal.get(Calendar.YEAR)); final String monthStr = monthFormatter.format(cal.get(Calendar.MONTH) + 1); final String dayStr = dayFormatter.format(cal.get(Calendar.DAY_OF_MONTH)); final String dateStamp = yearStr +":"+ monthStr +":"+ dayStr; gpsDir.removeField(GpsTagConstants.GPS_TAG_GPS_TIME_STAMP); gpsDir.add( GpsTagConstants.GPS_TAG_GPS_TIME_STAMP, RationalNumber.valueOf(cal.get(Calendar.HOUR_OF_DAY)), RationalNumber.valueOf(cal.get(Calendar.MINUTE)), RationalNumber.valueOf(cal.get(Calendar.SECOND)) ); gpsDir.removeField(GpsTagConstants.GPS_TAG_GPS_DATE_STAMP); gpsDir.add(GpsTagConstants.GPS_TAG_GPS_DATE_STAMP, dateStamp); } if (trkptT != null) { //---- EXIF GPS elevation/ALTITUDE ---- if (trkptT.eleStr != null) { final double altitude = Double.parseDouble(trkptT.eleStr); gpsDir.removeField(GpsTagConstants.GPS_TAG_GPS_ALTITUDE); gpsDir.add(GpsTagConstants.GPS_TAG_GPS_ALTITUDE, RationalNumber.valueOf(altitude)); } //---- EXIF GPS magvar/IMG_DIRECTION ---- if (trkptT.magvarStr != null) { final double magvar = Double.parseDouble(trkptT.magvarStr); gpsDir.removeField(GpsTagConstants.GPS_TAG_GPS_IMG_DIRECTION); gpsDir.add(GpsTagConstants.GPS_TAG_GPS_IMG_DIRECTION, RationalNumber.valueOf(magvar)); } //---- EXIF GPS_ ---- outputSet.setGPSInDegrees(trkptT.lon, trkptT.lat); } ExifRewriter rewriter = new ExifRewriter(); try (FileOutputStream fos = new FileOutputStream(new File(outDir, imageFile.getName()))) { rewriter.updateExifMetadataLossy(imageFile, fos, outputSet); } } // 基準時刻ファイルの「更新日時」を使って時刻合わせを行う。 // argv[1] --> AppParameters.IMG_BASE_FILE に置き換え // File baseFile = new File(this.imgDir, this.params.getProperty(AppParameters.IMG_BASE_FILE)); private Date adjustTime(File baseFile) throws ImageReadException, IOException, ParseException { if (exifBase) { ImageMetadata meta = Imaging.getMetadata(baseFile); JpegImageMetadata jpegMetadata = (JpegImageMetadata)meta; if (jpegMetadata == null) { // "'%s'にEXIF情報がありません" System.out.println( String.format( i18n.getString("msg.140"), baseFile.getAbsolutePath() ) ); return null; } @SuppressWarnings("LocalVariableHidesMemberVariable") TiffImageMetadata exif = jpegMetadata.getExif(); if (exif == null) { // "'%s'にEXIF情報がありません" System.out.println( String.format( i18n.getString("msg.140"), baseFile.getAbsolutePath() ) ); return null; } String dateTimeOriginal = exif.getFieldValue(ExifTagConstants.EXIF_TAG_DATE_TIME_ORIGINAL)[0]; return new Date(ImportPicture.toEXIFDate(dateTimeOriginal).getTime()); } else { return new Date(baseFile.lastModified()); } } /** * 対象は '*.JPG' のみ対象とする * @return * @param name */ public static boolean checkFile(String name) { return ((name != null) && name.toUpperCase().endsWith(".JPG")); } /** * DateをEXIFの文字列に変換する。 * 注意:EXiFの撮影時刻はUTC時間ではない * @param localdate * @return */ public static String toEXIFString(Date localdate) { DateFormat dfUTC = new SimpleDateFormat(EXIF_DATE_TIME_FORMAT_STRING); return dfUTC.format(localdate); } /** * EXIFの文字列をDateに変換する。 * 注意:EXiFの撮影時刻はUTC時間ではない * @param timeStr * @return * @throws ParseException */ public static Date toEXIFDate(String timeStr) throws ParseException { DateFormat dfUTC = new SimpleDateFormat(EXIF_DATE_TIME_FORMAT_STRING); //dfUTC.setTimeZone(TimeZone.getTimeZone("UTC")); return dfUTC.parse(timeStr); } public static String toUTCString(Date localdate) { DateFormat dfUTC = new SimpleDateFormat(TIME_FORMAT_STRING); dfUTC.setTimeZone(TimeZone.getTimeZone("UTC")); return dfUTC.format(localdate); } public static Date toUTCDate(String timeStr) throws ParseException { DateFormat dfUTC = new SimpleDateFormat(TIME_FORMAT_STRING); dfUTC.setTimeZone(TimeZone.getTimeZone("UTC")); return dfUTC.parse(timeStr); } static String getShortPathName(File dir, File iFile) { String dirPath = dir.getAbsolutePath(); String filePath = iFile.getAbsolutePath(); if (filePath.startsWith(dirPath)) { return filePath.substring(dirPath.length()+1); } else { return filePath; } } /** * ファイル名の順序に並び替えるためのソートクラス * * @author hayashi */ static class FileSort implements Comparator<File> { @Override public int compare(File src, File target){ int diff = src.getName().compareTo(target.getName()); return diff; } } /** * JPEGファイルフィルター * @author yuu */ class JpegFileFilter implements FilenameFilter { @Override public boolean accept(File dir, String name) { return name.toUpperCase().matches(".*\\.JPG$"); } } }