4 import java.io.FileInputStream;
5 import java.io.FileOutputStream;
6 import java.io.IOException;
7 import java.nio.channels.FileChannel;
8 import java.text.DecimalFormat;
9 import java.text.ParseException;
10 import java.util.Calendar;
11 import java.util.Date;
13 import java.util.TimeZone;
15 import javax.xml.parsers.ParserConfigurationException;
17 import org.apache.commons.imaging.ImageReadException;
18 import org.apache.commons.imaging.ImageWriteException;
19 import org.apache.commons.imaging.Imaging;
20 import org.apache.commons.imaging.common.ImageMetadata;
21 import org.apache.commons.imaging.common.RationalNumber;
22 import org.apache.commons.imaging.formats.jpeg.JpegImageMetadata;
23 import org.apache.commons.imaging.formats.jpeg.exif.ExifRewriter;
24 import org.apache.commons.imaging.formats.tiff.TiffImageMetadata;
25 import org.apache.commons.imaging.formats.tiff.constants.ExifTagConstants;
26 import org.apache.commons.imaging.formats.tiff.constants.GpsTagConstants;
27 import org.apache.commons.imaging.formats.tiff.write.TiffOutputDirectory;
28 import org.apache.commons.imaging.formats.tiff.write.TiffOutputSet;
29 import org.xml.sax.SAXException;
31 @SuppressWarnings("serial")
32 public class ImgFile extends File {
36 double latitude = 0.0D;
37 double longitude = 0.0D;
39 String magvarStr = "-";
40 String speedStr = "-";
42 public ImgFile(File file) {
43 super(file.getParentFile(), file.getName());
46 public void setDone(boolean done) {
50 public boolean isDone() {
58 public boolean isImageFile() {
59 String name = this.getName();
60 return ((name != null) && name.toUpperCase().endsWith(".JPG"));
63 public boolean procImageFile(AppParameters params, long delta, GpxFile gpxFile, File outDir) throws ParseException, ImageReadException, IOException, ImageWriteException, ParserConfigurationException, SAXException {
64 //ElementMapTRKSEG mapTRKSEG = gpxFile.parse();
65 boolean exifWrite = params.isImgOutputExif();
67 // itime <-- 画像ファイルの撮影時刻
68 // ファイルの更新日時/EXIFの撮影日時
69 imgtime = getDate(params);
71 // uktime <-- 画像撮影時刻に対応するGPX時刻(補正日時)
72 gpstime = new Date(imgtime.getTime() + delta);
74 // 時刻uktimeにおける<magver>をtrkptに追加する
75 TagTrkpt trkptT = null;
77 for (Map.Entry<Date,ElementMapTRKPT> map : gpxFile.getTrksegMap().entrySet()) {
78 ElementMapTRKPT mapTRKPT = map.getValue();
79 trkptT = mapTRKPT.getValue(gpstime);
86 if (!params.isImgOutputAll()) {
91 latitude = trkptT.lat;
92 longitude = trkptT.lon;
94 if (trkptT.eleStr != null) {
95 eleStr = trkptT.eleStr;
98 if (trkptT.magvarStr != null) {
99 magvarStr = trkptT.magvarStr;
102 if (trkptT.speedStr != null) {
103 speedStr = trkptT.speedStr;
109 exifWrite(this, gpstime, trkptT, outDir);
112 if (params.isImgOutputAll()) {
113 // EXIFの変換を伴わない単純なファイルコピー
114 FileInputStream sStream = new FileInputStream(this);
115 FileInputStream dStream = new FileInputStream(new File(outDir, this.getName()));
116 FileChannel srcChannel = sStream.getChannel();
117 FileChannel destChannel = dStream.getChannel();
119 srcChannel.transferTo(0, srcChannel.size(), destChannel);
132 void exifWrite(File imageFile, Date correctedtime, TagTrkpt trkptT, File outDir) throws ImageReadException, IOException, ImageWriteException {
133 DecimalFormat yearFormatter = new DecimalFormat("0000");
134 DecimalFormat monthFormatter = new DecimalFormat("00");
135 DecimalFormat dayFormatter = new DecimalFormat("00");
137 TiffOutputSet outputSet = null;
139 ImageMetadata meta = Imaging.getMetadata(imageFile);
140 JpegImageMetadata jpegMetadata = (JpegImageMetadata)meta;
141 if (jpegMetadata != null) {
142 TiffImageMetadata exif = jpegMetadata.getExif();
144 outputSet = exif.getOutputSet();
148 if (outputSet == null) {
149 outputSet = new TiffOutputSet();
152 //---- EXIF_TAG_DATE_TIME_ORIGINAL / 「撮影日時/オリジナル画像の生成日時」----
153 TiffOutputDirectory exifDir = outputSet.getOrCreateExifDirectory();
155 Calendar cal = Calendar.getInstance();
156 cal.setTimeZone(TimeZone.getTimeZone("UTC"));
157 cal.setTime(correctedtime);
158 exifDir.removeField(ExifTagConstants.EXIF_TAG_DATE_TIME_ORIGINAL);
159 exifDir.add(ExifTagConstants.EXIF_TAG_DATE_TIME_ORIGINAL, ImportPicture.toEXIFString(cal.getTime()));
162 //---- EXIF GPS_TIME_STAMP ----
163 TiffOutputDirectory gpsDir = outputSet.getOrCreateGPSDirectory();
165 Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
166 cal.setTimeZone(TimeZone.getTimeZone("GMT+00"));
167 cal.setTime(correctedtime);
168 final String yearStr = yearFormatter.format(cal.get(Calendar.YEAR));
169 final String monthStr = monthFormatter.format(cal.get(Calendar.MONTH) + 1);
170 final String dayStr = dayFormatter.format(cal.get(Calendar.DAY_OF_MONTH));
171 final String dateStamp = yearStr +":"+ monthStr +":"+ dayStr;
173 gpsDir.removeField(GpsTagConstants.GPS_TAG_GPS_TIME_STAMP);
175 GpsTagConstants.GPS_TAG_GPS_TIME_STAMP,
176 RationalNumber.valueOf(cal.get(Calendar.HOUR_OF_DAY)),
177 RationalNumber.valueOf(cal.get(Calendar.MINUTE)),
178 RationalNumber.valueOf(cal.get(Calendar.SECOND))
180 gpsDir.removeField(GpsTagConstants.GPS_TAG_GPS_DATE_STAMP);
181 gpsDir.add(GpsTagConstants.GPS_TAG_GPS_DATE_STAMP, dateStamp);
184 if (trkptT != null) {
185 //---- EXIF GPS elevation/ALTITUDE ----
186 if (trkptT.eleStr != null) {
187 final double altitude = Double.parseDouble(trkptT.eleStr);
188 gpsDir.removeField(GpsTagConstants.GPS_TAG_GPS_ALTITUDE);
189 gpsDir.add(GpsTagConstants.GPS_TAG_GPS_ALTITUDE, RationalNumber.valueOf(altitude));
192 //---- EXIF GPS magvar/IMG_DIRECTION ----
193 if (trkptT.magvarStr != null) {
194 final double magvar = Double.parseDouble(trkptT.magvarStr);
195 gpsDir.removeField(GpsTagConstants.GPS_TAG_GPS_IMG_DIRECTION);
196 gpsDir.add(GpsTagConstants.GPS_TAG_GPS_IMG_DIRECTION, RationalNumber.valueOf(magvar));
199 //---- EXIF GPS_ ----
200 outputSet.setGPSInDegrees(trkptT.lon, trkptT.lat);
203 ExifRewriter rewriter = new ExifRewriter();
204 try (FileOutputStream fos = new FileOutputStream(new File(outDir, imageFile.getName()))) {
205 rewriter.updateExifMetadataLossy(imageFile, fos, outputSet);
210 * 基準時刻ファイルの「更新日時」を取得する
211 * @param baseFile = new File(this.imgDir, this.params.getProperty(AppParameters.IMG_BASE_FILE));
213 * @throws ImageReadException
214 * @throws IOException
215 * @throws ParseException
217 Date getDate(AppParameters params) throws ImageReadException, IOException, ParseException {
218 return getDate(params, this);
222 * 基準時刻ファイルの「更新日時」を取得する
223 * @param baseFile = new File(this.imgDir, this.params.getProperty(AppParameters.IMG_BASE_FILE));
225 * @throws ImageReadException
226 * @throws IOException
227 * @throws ParseException
229 static Date getDate(AppParameters params, File baseFile) throws ImageReadException, IOException, ParseException {
230 if (params.isExifBase()) {
232 ImageMetadata meta = Imaging.getMetadata(baseFile);
233 JpegImageMetadata jpegMetadata = (JpegImageMetadata)meta;
234 if (jpegMetadata == null) {
235 // "'%s'にEXIF情報がありません"
236 throw new ImageReadException(
238 ImportPicture.i18n.getString("msg.140"),
239 baseFile.getAbsolutePath()
243 TiffImageMetadata exif = jpegMetadata.getExif();
245 // "'%s'にEXIF情報がありません"
246 throw new ImageReadException(
248 ImportPicture.i18n.getString("msg.140"),
249 baseFile.getAbsolutePath()
253 String dateTimeOriginal = exif.getFieldValue(ExifTagConstants.EXIF_TAG_DATE_TIME_ORIGINAL)[0];
254 return new Date(ImportPicture.toEXIFDate(dateTimeOriginal).getTime());
258 return new Date(baseFile.lastModified());
263 * ImgFileインスタンスの状態をTEXT化
269 ret += (String.format("|%-32s|", this.getName()));
270 ret += (String.format("%20s|", (imgtime==null ? "" : ImportPicture.toUTCString(imgtime))));
271 ret += (String.format("%20s|", (gpstime==null ? "" : ImportPicture.toUTCString(gpstime))));
272 ret += (String.format("%14.10f|%14.10f|", latitude, longitude));
273 ret += (String.format("%8s|%6s|%6s|", eleStr, magvarStr, speedStr));
276 ret += (String.format("|%-32s|", this.getName()));
277 ret += (String.format("%20s|", (imgtime==null ? "" : ImportPicture.toUTCString(imgtime))));
278 ret += (String.format("%20s|", (gpstime==null ? "" : ImportPicture.toUTCString(gpstime))));
279 ret += (String.format("%-14s|%-14s|", "", ""));
280 ret += (String.format("%8s|%6s|%6s|", "", "", ""));
285 public void printinfo() {
286 System.out.println(toText());
289 public static void printheader() {
290 System.out.println("|--------------------------------|--------------------|--------------------|--------------|--------------|--------|------|------|");
291 System.out.println("| name | Camera Time | GPStime | Latitude | Longitude | ele |magvar| km/h |");
292 System.out.println("|--------------------------------|--------------------|--------------------|--------------|--------------|--------|------|------|");
295 public static void printfooter() {
296 System.out.println("|--------------------------------|--------------------|--------------------|--------------|--------------|--------|------|------|");
297 System.out.println();