]> gitweb.fperrin.net Git - GpsPrune.git/blobdiff - tim/prune/load/JpegLoader.java
Version 11, August 2010
[GpsPrune.git] / tim / prune / load / JpegLoader.java
index 7939f1b0080310f28076c6dceff6b317e22d2644..feec754f22f7049dc7bcef4b26d71cba534d2ed2 100644 (file)
@@ -17,19 +17,18 @@ import javax.swing.JPanel;
 import javax.swing.JProgressBar;
 
 import tim.prune.App;
-import tim.prune.Config;
 import tim.prune.I18nManager;
+import tim.prune.config.Config;
 import tim.prune.data.Altitude;
 import tim.prune.data.DataPoint;
+import tim.prune.data.Field;
 import tim.prune.data.LatLonRectangle;
 import tim.prune.data.Latitude;
 import tim.prune.data.Longitude;
 import tim.prune.data.Photo;
 import tim.prune.data.Timestamp;
-import tim.prune.drew.jpeg.ExifReader;
-import tim.prune.drew.jpeg.JpegData;
-import tim.prune.drew.jpeg.JpegException;
-import tim.prune.drew.jpeg.Rational;
+import tim.prune.jpeg.ExifGateway;
+import tim.prune.jpeg.JpegData;
 
 /**
  * Class to manage the loading of Jpegs and dealing with the GPS data from them
@@ -92,8 +91,9 @@ public class JpegLoader implements Runnable
                        panel.add(_outsideAreaCheckbox);
                        _fileChooser.setAccessory(panel);
                        // start from directory in config if already set by other operations
-                       File configDir = Config.getWorkingDirectory();
-                       if (configDir != null) {_fileChooser.setCurrentDirectory(configDir);}
+                       String configDir = Config.getConfigString(Config.KEY_PHOTO_DIR);
+                       if (configDir == null) {configDir = Config.getConfigString(Config.KEY_TRACK_DIR);}
+                       if (configDir != null) {_fileChooser.setCurrentDirectory(new File(configDir));}
                }
                // enable/disable track checkbox
                _trackRectangle = inRectangle;
@@ -102,16 +102,23 @@ public class JpegLoader implements Runnable
                if (_fileChooser.showOpenDialog(_parentFrame) == JFileChooser.APPROVE_OPTION)
                {
                        // Bring up dialog before starting
-                       showDialog();
+                       if (_progressDialog == null) {
+                               createProgressDialog();
+                       }
+                       // reset dialog and show it
+                       _progressBar.setValue(0);
+                       _progressBar.setString("");
+                       _progressDialog.setVisible(true);
+                       // start thread for processing
                        new Thread(this).start();
                }
        }
 
 
        /**
-        * Show the main dialog
+        * Create the dialog to show the progress
         */
-       private void showDialog()
+       private void createProgressDialog()
        {
                _progressDialog = new JDialog(_parentFrame, I18nManager.getText("dialog.jpegload.progress.title"));
                _progressDialog.setLocationRelativeTo(_parentFrame);
@@ -134,7 +141,6 @@ public class JpegLoader implements Runnable
                panel.add(cancelButton);
                _progressDialog.getContentPane().add(panel);
                _progressDialog.pack();
-               _progressDialog.setVisible(true);
        }
 
 
@@ -157,6 +163,7 @@ public class JpegLoader implements Runnable
                // Process the files recursively and build lists of photos
                processFileList(files, true, _subdirCheckbox.isSelected());
                _progressDialog.setVisible(false);
+               _progressDialog.dispose(); // Sometimes dialog doesn't disappear without this dispose
                if (_cancelled) {return;}
 
                //System.out.println("Finished - counts are: " + _fileCounts[0] + ", " + _fileCounts[1]
@@ -200,7 +207,7 @@ public class JpegLoader implements Runnable
                if (inFiles != null)
                {
                        // Loop over elements in array
-                       for (int i=0; i<inFiles.length; i++)
+                       for (int i=0; i<inFiles.length && !_cancelled; i++)
                        {
                                File file = inFiles[i];
                                if (file.exists() && file.canRead())
@@ -218,12 +225,7 @@ public class JpegLoader implements Runnable
                                                processFileList(files, false, inDescend);
                                        }
                                }
-                               else
-                               {
-                                       // file doesn't exist or isn't readable - ignore error
-                               }
-                               // check for cancel button pressed
-                               if (_cancelled) break;
+                               // if file doesn't exist or isn't readable - ignore
                        }
                }
        }
@@ -247,19 +249,19 @@ public class JpegLoader implements Runnable
 
                // Create Photo object
                Photo photo = new Photo(inFile);
+               if (inFile.exists() && inFile.canRead()) {
+                       _fileCounts[1]++; // jpeg found
+               }
                // Try to get information out of exif
-               try
+               JpegData jpegData = ExifGateway.getJpegData(inFile);
+               Timestamp timestamp = null;
+               if (jpegData != null)
                {
-                       JpegData jpegData = new ExifReader(inFile).extract();
-                       _fileCounts[1]++; // jpeg found (no exception thrown)
                        if (jpegData.getExifDataPresent())
                                {_fileCounts[2]++;} // exif found
-                       if (jpegData.isValid())
+                       if (jpegData.isGpsValid())
                        {
-                               if (jpegData.getGpsDatestamp() != null && jpegData.getGpsTimestamp() != null)
-                               {
-                                       photo.setTimestamp(createTimestamp(jpegData.getGpsDatestamp(), jpegData.getGpsTimestamp()));
-                               }
+                               timestamp = createTimestamp(jpegData.getGpsDatestamp(), jpegData.getGpsTimestamp());
                                // Make DataPoint and attach to Photo
                                DataPoint point = createDataPoint(jpegData);
                                point.setPhoto(photo);
@@ -269,17 +271,24 @@ public class JpegLoader implements Runnable
                                _fileCounts[3]++;
                        }
                        // Use exif timestamp if gps timestamp not available
-                       if (photo.getTimestamp() == null && jpegData.getOriginalTimestamp() != null)
-                       {
-                               photo.setTimestamp(createTimestamp(jpegData.getOriginalTimestamp()));
+                       if (timestamp == null && jpegData.getOriginalTimestamp() != null) {
+                               timestamp = createTimestamp(jpegData.getOriginalTimestamp());
+                       }
+                       if (timestamp == null && jpegData.getDigitizedTimestamp() != null) {
+                               timestamp = createTimestamp(jpegData.getDigitizedTimestamp());
                        }
                        photo.setExifThumbnail(jpegData.getThumbnailImage());
-               }
-               catch (JpegException jpe) { // don't list errors, just count them
+                       // Also extract orientation tag for setting rotation state of photo
+                       photo.setRotation(jpegData.getRequiredRotation());
                }
                // Use file timestamp if exif timestamp isn't available
-               if (photo.getTimestamp() == null) {
-                       photo.setTimestamp(new Timestamp(inFile.lastModified()));
+               if (timestamp == null) {
+                       timestamp = new Timestamp(inFile.lastModified());
+               }
+               // Apply timestamp to photo and its point (if any)
+               photo.setTimestamp(timestamp);
+               if (photo.getDataPoint() != null) {
+                       photo.getDataPoint().setFieldValue(Field.TIMESTAMP, timestamp.getText(Timestamp.FORMAT_ISO_8601), false);
                }
                // Check the criteria for adding the photo - check whether the photo has coordinates and if so if they're within the rectangle
                if ( (photo.getDataPoint() != null || _noExifCheckbox.isSelected())
@@ -311,7 +320,8 @@ public class JpegLoader implements Runnable
                                {
                                        // Store first directory in config for later
                                        if (i == 0 && inFirstDir) {
-                                               Config.setWorkingDirectory(file.isDirectory()?file:file.getParentFile());
+                                               File workingDir = file.isDirectory()?file:file.getParentFile();
+                                               Config.setConfigString(Config.KEY_PHOTO_DIR, workingDir.getAbsolutePath());
                                        }
                                        // Check whether it's a file or a directory
                                        if (file.isFile())
@@ -344,26 +354,25 @@ public class JpegLoader implements Runnable
                        inData.getLongitudeRef() == 'E' || inData.getLongitudeRef() == 'e');
                Longitude longitude = new Longitude(lonval, Longitude.FORMAT_DEG_MIN_SEC);
                Altitude altitude = null;
-               if (inData.getAltitude() != null)
-               {
-                       altitude = new Altitude(inData.getAltitude().intValue(), Altitude.Format.METRES);
+               if (inData.hasAltitude()) {
+                       altitude = new Altitude(inData.getAltitude(), Altitude.Format.METRES);
                }
                return new DataPoint(latitude, longitude, altitude);
        }
 
 
        /**
-        * Convert an array of 3 Rational numbers into a double coordinate value
-        * @param inRationals array of three Rational objects
+        * Convert an array of 3 doubles (deg-min-sec) into a double coordinate value
+        * @param inValues array of three doubles for deg-min-sec
         * @param isPositive true for positive hemisphere, for positive double value
         * @return double value of coordinate, either positive or negative
         */
-       private static double getCoordinateDoubleValue(Rational[] inRationals, boolean isPositive)
+       private static double getCoordinateDoubleValue(double[] inValues, boolean isPositive)
        {
-               if (inRationals == null || inRationals.length != 3) return 0.0;
-               double value = inRationals[0].doubleValue()        // degrees
-                       + inRationals[1].doubleValue() / 60.0          // minutes
-                       + inRationals[2].doubleValue() / 60.0 / 60.0;  // seconds
+               if (inValues == null || inValues.length != 3) return 0.0;
+               double value = inValues[0]        // degrees
+                       + inValues[1] / 60.0          // minutes
+                       + inValues[2] / 60.0 / 60.0;  // seconds
                // make sure it's the correct sign
                value = Math.abs(value);
                if (!isPositive) value = -value;
@@ -372,17 +381,18 @@ public class JpegLoader implements Runnable
 
 
        /**
-        * Use the given Rational values to create a timestamp
-        * @param inDate rationals describing date
-        * @param inTime rationals describing time
+        * Use the given int values to create a timestamp
+        * @param inDate ints describing date
+        * @param inTime ints describing time
         * @return Timestamp object corresponding to inputs
         */
-       private static Timestamp createTimestamp(Rational[] inDate, Rational[] inTime)
+       private static Timestamp createTimestamp(int[] inDate, int[] inTime)
        {
-               //System.out.println("Making timestamp for date (" + inDate[0].toString() + "," + inDate[1].toString() + "," + inDate[2].toString() + ") and time ("
-               //      + inTime[0].toString() + "," + inTime[1].toString() + "," + inTime[2].toString() + ")");
-               return new Timestamp(inDate[0].intValue(), inDate[1].intValue(), inDate[2].intValue(),
-                       inTime[0].intValue(), inTime[1].intValue(), inTime[2].intValue());
+               if (inDate == null || inTime == null || inDate.length != 3 || inTime.length != 3) {
+                       return null;
+               }
+               return new Timestamp(inDate[0], inDate[1], inDate[2],
+                       inTime[0], inTime[1], inTime[2]);
        }