OSDN Git Service

fix for javadoc.
[importpicture/importpicture.git] / src / main / java / osm / jp / gpx / ImgFile.java
1 package osm.jp.gpx;
2
3 import java.io.File;
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;
12 import java.util.Map;
13 import java.util.TimeZone;
14
15 import javax.xml.parsers.ParserConfigurationException;
16
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;
30
31 @SuppressWarnings("serial")
32 public class ImgFile extends File {
33         boolean done = false;
34         Date imgtime = null;
35         Date gpstime = null;
36         double latitude = 0.0D;
37         double longitude = 0.0D;
38     String eleStr = "-";
39     String magvarStr = "-";
40     String speedStr = "-";
41
42     public ImgFile(File file) {
43         super(file.getParentFile(), file.getName());
44     }
45     
46     public void setDone(boolean done) {
47         this.done = done;
48     }
49     
50     public boolean isDone() {
51         return this.done;
52     }
53     
54     /**
55      * 対象は '*.JPG' のみ対象とする
56      * @return 
57      */
58     public boolean isImageFile() {
59         String name = this.getName();
60         return ((name != null) && name.toUpperCase().endsWith(".JPG"));
61     }
62     
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();
66         
67         // itime <-- 画像ファイルの撮影時刻
68         //                      ファイルの更新日時/EXIFの撮影日時
69         imgtime = getDate(params);
70         
71         // uktime <-- 画像撮影時刻に対応するGPX時刻(補正日時)
72         gpstime = new Date(imgtime.getTime() + delta);
73
74         // 時刻uktimeにおける<magver>をtrkptに追加する
75         TagTrkpt trkptT = null;
76
77         for (Map.Entry<Date,ElementMapTRKPT> map : gpxFile.getTrksegMap().entrySet()) {
78             ElementMapTRKPT mapTRKPT = map.getValue();
79             trkptT = mapTRKPT.getValue(gpstime);
80             if (trkptT != null) {
81                 break;
82             }
83         }
84
85         if (trkptT == null) {
86             if (!params.isImgOutputAll()) {
87                 return false;
88             }
89         }
90         else {
91             latitude = trkptT.lat;
92             longitude = trkptT.lon;
93             
94             if (trkptT.eleStr != null) {
95                 eleStr = trkptT.eleStr;
96             }
97             
98             if (trkptT.magvarStr != null) {
99                 magvarStr = trkptT.magvarStr;
100             }
101             
102             if (trkptT.speedStr != null) {
103                 speedStr = trkptT.speedStr;
104             }
105         }
106
107         outDir.mkdir();
108         if (exifWrite) {
109             exifWrite(this, gpstime, trkptT, outDir);
110         }
111         else {
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();
118                 try {
119                     srcChannel.transferTo(0, srcChannel.size(), destChannel);
120                 }
121                 finally {
122                     srcChannel.close();
123                     destChannel.close();
124                     sStream.close();
125                     dStream.close();
126                 }
127             }
128         }
129         return true;
130     }
131     
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");
136         
137         TiffOutputSet outputSet = null;
138
139         ImageMetadata meta = Imaging.getMetadata(imageFile);
140         JpegImageMetadata jpegMetadata = (JpegImageMetadata)meta;
141         if (jpegMetadata != null) {
142             TiffImageMetadata exif = jpegMetadata.getExif();
143             if (exif != null) {
144                 outputSet = exif.getOutputSet();
145             }
146         }
147
148         if (outputSet == null) {
149             outputSet = new TiffOutputSet();
150         }
151
152         //---- EXIF_TAG_DATE_TIME_ORIGINAL / 「撮影日時/オリジナル画像の生成日時」----
153         TiffOutputDirectory exifDir = outputSet.getOrCreateExifDirectory();
154         {
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()));
160         }
161
162         //---- EXIF GPS_TIME_STAMP ----
163         TiffOutputDirectory gpsDir = outputSet.getOrCreateGPSDirectory();
164         {
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;
172
173             gpsDir.removeField(GpsTagConstants.GPS_TAG_GPS_TIME_STAMP);
174             gpsDir.add(
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))
179             );
180             gpsDir.removeField(GpsTagConstants.GPS_TAG_GPS_DATE_STAMP);
181             gpsDir.add(GpsTagConstants.GPS_TAG_GPS_DATE_STAMP, dateStamp);
182         }
183
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));
190             }
191
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));
197             }
198
199             //---- EXIF GPS_ ----
200             outputSet.setGPSInDegrees(trkptT.lon, trkptT.lat);
201         }
202
203         ExifRewriter rewriter = new ExifRewriter();
204         try (FileOutputStream fos = new FileOutputStream(new File(outDir, imageFile.getName()))) {
205             rewriter.updateExifMetadataLossy(imageFile, fos, outputSet);
206         }
207     }
208     
209     /**
210      * 基準時刻ファイルの「更新日時」を取得する
211      * @param baseFile = new File(this.imgDir, this.params.getProperty(AppParameters.IMG_BASE_FILE));
212      * @return
213      * @throws ImageReadException
214      * @throws IOException
215      * @throws ParseException
216      */
217     Date getDate(AppParameters params) throws ImageReadException, IOException, ParseException {
218         return getDate(params, this);
219     }
220
221     /**
222      * 基準時刻ファイルの「更新日時」を取得する
223      * @param baseFile = new File(this.imgDir, this.params.getProperty(AppParameters.IMG_BASE_FILE));
224      * @return
225      * @throws ImageReadException
226      * @throws IOException
227      * @throws ParseException
228      */
229     static Date getDate(AppParameters params, File baseFile) throws ImageReadException, IOException, ParseException {
230         if (params.isExifBase()) {
231             // 基準時刻(EXIF撮影日時)
232             ImageMetadata meta = Imaging.getMetadata(baseFile);
233             JpegImageMetadata jpegMetadata = (JpegImageMetadata)meta;
234             if (jpegMetadata == null) {
235                 // "'%s'にEXIF情報がありません"
236                 throw new ImageReadException(
237                     String.format(
238                         ImportPicture.i18n.getString("msg.140"), 
239                         baseFile.getAbsolutePath()
240                     )
241                 );
242             }
243             TiffImageMetadata exif = jpegMetadata.getExif();
244             if (exif == null) {
245                 // "'%s'にEXIF情報がありません"
246                 throw new ImageReadException(
247                     String.format(
248                         ImportPicture.i18n.getString("msg.140"), 
249                         baseFile.getAbsolutePath()
250                     )
251                 );
252             }
253             String dateTimeOriginal = exif.getFieldValue(ExifTagConstants.EXIF_TAG_DATE_TIME_ORIGINAL)[0];
254             return new Date(ImportPicture.toEXIFDate(dateTimeOriginal).getTime());
255         }
256         else {
257             // 基準時刻(ファイル更新日時)
258             return new Date(baseFile.lastModified());
259         }
260     }
261     
262     /**
263      * ImgFileインスタンスの状態をTEXT化
264      * @return  1行
265      */
266     String toText() {
267         String ret = "";
268         if (isDone()) {
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));
274         }
275         else {
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|", "", "", ""));
281         }
282         return ret;
283     }
284     
285     public void printinfo() {
286         System.out.println(toText());
287     }
288     
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("|--------------------------------|--------------------|--------------------|--------------|--------------|--------|------|------|");
293     }
294     
295     public static void printfooter() {
296         System.out.println("|--------------------------------|--------------------|--------------------|--------------|--------------|--------|------|------|");
297         System.out.println();
298     }
299 }