- package osm.jp.gpx;
-
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.nio.channels.FileChannel;
- import java.text.DecimalFormat;
- import java.text.ParseException;
- import java.util.Calendar;
- import java.util.Date;
- import java.util.Map;
- import java.util.TimeZone;
-
- import javax.xml.parsers.ParserConfigurationException;
-
- 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.xml.sax.SAXException;
-
- @SuppressWarnings("serial")
- public class ImgFile extends File {
- boolean done = false;
- Date imgtime = null;
- Date gpstime = null;
- double latitude = 0.0D;
- double longitude = 0.0D;
- String eleStr = "-";
- String magvarStr = "-";
- String speedStr = "-";
-
- public ImgFile(File file) {
- super(file.getParentFile(), file.getName());
- }
-
- public void setDone(boolean done) {
- this.done = done;
- }
-
- public boolean isDone() {
- return this.done;
- }
-
- /**
- * 対象は '*.JPG' のみ対象とする
- * @return
- * @param name
- */
- public boolean isImageFile() {
- String name = this.getName();
- return ((name != null) && name.toUpperCase().endsWith(".JPG"));
- }
-
- public boolean procImageFile(AppParameters params, long delta, GpxFile gpxFile, File outDir) throws ParseException, ImageReadException, IOException, ImageWriteException, ParserConfigurationException, SAXException {
- //ElementMapTRKSEG mapTRKSEG = gpxFile.parse();
- boolean exifWrite = params.isImgOutputExif();
-
- // itime <-- 画像ファイルの撮影時刻
- // ファイルの更新日時/EXIFの撮影日時
- imgtime = getDate(params);
-
- // uktime <-- 画像撮影時刻に対応するGPX時刻(補正日時)
- gpstime = new Date(imgtime.getTime() + delta);
-
- // 時刻uktimeにおける<magver>をtrkptに追加する
- TagTrkpt trkptT = null;
-
- for (Map.Entry<Date,ElementMapTRKPT> map : gpxFile.getTrksegMap().entrySet()) {
- ElementMapTRKPT mapTRKPT = map.getValue();
- trkptT = mapTRKPT.getValue(gpstime);
- if (trkptT != null) {
- break;
- }
- }
-
- if (trkptT == null) {
- if (!params.isImgOutputAll()) {
- return false;
- }
- }
- else {
- latitude = trkptT.lat;
- longitude = trkptT.lon;
-
- if (trkptT.eleStr != null) {
- eleStr = trkptT.eleStr;
- }
-
- if (trkptT.magvarStr != null) {
- magvarStr = trkptT.magvarStr;
- }
-
- if (trkptT.speedStr != null) {
- speedStr = trkptT.speedStr;
- }
- }
-
- outDir.mkdir();
- if (exifWrite) {
- exifWrite(this, gpstime, trkptT, outDir);
- }
- else {
- if (params.isImgOutputAll()) {
- // EXIFの変換を伴わない単純なファイルコピー
- FileInputStream sStream = new FileInputStream(this);
- FileInputStream dStream = new FileInputStream(new File(outDir, this.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();
- }
- }
- }
- return true;
- }
-
- void exifWrite(File imageFile, Date correctedtime, TagTrkpt trkptT, File outDir) 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) {
- 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);
- }
- }
-
- /**
- * 基準時刻ファイルの「更新日時」を取得する
- * @param baseFile = new File(this.imgDir, this.params.getProperty(AppParameters.IMG_BASE_FILE));
- * @return
- * @throws ImageReadException
- * @throws IOException
- * @throws ParseException
- */
- Date getDate(AppParameters params) throws ImageReadException, IOException, ParseException {
- return getDate(params, this);
- }
-
- /**
- * 基準時刻ファイルの「更新日時」を取得する
- * @param baseFile = new File(this.imgDir, this.params.getProperty(AppParameters.IMG_BASE_FILE));
- * @return
- * @throws ImageReadException
- * @throws IOException
- * @throws ParseException
- */
- static Date getDate(AppParameters params, File baseFile) throws ImageReadException, IOException, ParseException {
- if (params.isExifBase()) {
- // 基準時刻(EXIF撮影日時)
- ImageMetadata meta = Imaging.getMetadata(baseFile);
- JpegImageMetadata jpegMetadata = (JpegImageMetadata)meta;
- if (jpegMetadata == null) {
- // "'%s'にEXIF情報がありません"
- throw new ImageReadException(
- String.format(
- ImportPicture.i18n.getString("msg.140"),
- baseFile.getAbsolutePath()
- )
- );
- }
- TiffImageMetadata exif = jpegMetadata.getExif();
- if (exif == null) {
- // "'%s'にEXIF情報がありません"
- throw new ImageReadException(
- String.format(
- ImportPicture.i18n.getString("msg.140"),
- baseFile.getAbsolutePath()
- )
- );
- }
- String dateTimeOriginal = exif.getFieldValue(ExifTagConstants.EXIF_TAG_DATE_TIME_ORIGINAL)[0];
- return new Date(ImportPicture.toEXIFDate(dateTimeOriginal).getTime());
- }
- else {
- // 基準時刻(ファイル更新日時)
- return new Date(baseFile.lastModified());
- }
- }
-
- /**
- * ImgFileインスタンスの状態をTEXT化
- * @return 1行
- */
- String toText() {
- String ret = "";
- if (isDone()) {
- ret += (String.format("|%-32s|", this.getName()));
- ret += (String.format("%20s|", (imgtime==null ? "" : ImportPicture.toUTCString(imgtime))));
- ret += (String.format("%20s|", (gpstime==null ? "" : ImportPicture.toUTCString(gpstime))));
- ret += (String.format("%14.10f|%14.10f|", latitude, longitude));
- ret += (String.format("%8s|%6s|%6s|", eleStr, magvarStr, speedStr));
- }
- else {
- ret += (String.format("|%-32s|", this.getName()));
- ret += (String.format("%20s|", (imgtime==null ? "" : ImportPicture.toUTCString(imgtime))));
- ret += (String.format("%20s|", (gpstime==null ? "" : ImportPicture.toUTCString(gpstime))));
- ret += (String.format("%-14s|%-14s|", "", ""));
- ret += (String.format("%8s|%6s|%6s|", "", "", ""));
- }
- return ret;
- }
-
- public void printinfo() {
- System.out.println(toText());
- }
-
- public static void printheader() {
- System.out.println("|--------------------------------|--------------------|--------------------|--------------|--------------|--------|------|------|");
- System.out.println("| name | Camera Time | GPStime | Latitude | Longitude | ele |magvar| km/h |");
- System.out.println("|--------------------------------|--------------------|--------------------|--------------|--------------|--------|------|------|");
- }
-
- public static void printfooter() {
- System.out.println("|--------------------------------|--------------------|--------------------|--------------|--------------|--------|------|------|");
- System.out.println();
- }
- }