Package net.sourceforge.gpstools.exif

Source Code of net.sourceforge.gpstools.exif.SanselanExifReader

package net.sourceforge.gpstools.exif;

/* gpsdings
* Copyright (C) 2006-2009 Moritz Ringler
* $Id: MediaUtilExifReader.java 382 2009-01-12 17:59:56Z ringler $
*
*  This program is free software: you can redistribute it and/or modify
*  it under the terms of the GNU General Public License as published by
*  the Free Software Foundation, either version 3 of the License, or
*  (at your option) any later version.
*
*  This program is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU General Public License for more details.
*
*  You should have received a copy of the GNU General Public License
*  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
import java.awt.Dimension;
import java.io.*;
import java.text.ParseException;
import java.util.Date;
import java.math.BigDecimal;
import net.sourceforge.gpstools.gpx.Wpt;

import org.apache.sanselan.ImageReadException;
import org.apache.sanselan.ImageWriteException;
import org.apache.sanselan.Sanselan;
import org.apache.sanselan.formats.jpeg.JpegImageMetadata;
import org.apache.sanselan.formats.tiff.TiffImageMetadata;
import org.apache.sanselan.formats.tiff.TiffField;
import org.apache.sanselan.formats.tiff.constants.TiffConstants;
import org.apache.sanselan.formats.tiff.TiffDirectory;

final class SanselanExifReader extends AbstractExifReader{

    static TiffImageMetadata getExif(File jpegImageFile)
    throws IOException, ImageReadException, ImageWriteException{
        TiffImageMetadata exif = null;
        JpegImageMetadata jpegMetadata = (JpegImageMetadata) Sanselan.getMetadata(jpegImageFile);
        if (null != jpegMetadata) {
            // note that exif might be null if no Exif metadata is found.
            exif = jpegMetadata.getExif();
        }
        return exif;
    }

    public SanselanExifReader(){
        // explicit default constructor.
    }

    @Override
    public Date readOriginalTime(File jpeg) throws IOException, ParseException{
        try{
            final TiffImageMetadata exif = SanselanExifReader.getExif(jpeg);
            String dateString = (String) exif.findField(TiffConstants.EXIF_TAG_DATE_TIME_ORIGINAL).getValue();
            //interpret the dateString as an UTC dateTime value
            return parseExifDate(dateString);
        } catch (ImageReadException irx){
            throw toIOException(irx, jpeg);
        } catch (ImageWriteException iwx){
            throw toIOException(iwx, jpeg);
        }
    }

    private static IOException toIOException(Throwable t, File f){
        IOException ex = new IOException("Error reading exif tag from file " + f.getPath());
        ex.initCause(t);
        return ex;
    }

    @Override
    public Dimension readJPEGDimension(File jpeg) throws IOException{
        try{
            return Sanselan.getImageSize(jpeg);
        } catch (Exception ex){
            throw toIOException(ex, jpeg);
        }
    }

    @Override
    public Wpt readGPSTag(File jpeg) throws IOException, ParseException{
        Wpt result = null;
        try{
            final TiffDirectory gpsIfd =
                SanselanExifReader.getExif(jpeg).findDirectory(
                    TiffConstants.DIRECTORY_TYPE_GPS);
            result = wptFromGpsTag(gpsIfd);
        } catch (MetadataException ex){
            throw toIOException(ex, jpeg);
        } catch (ImageReadException irx){
            throw toIOException(irx, jpeg);
        } catch (ImageWriteException iwx){
            throw toIOException(iwx, jpeg);
        }
        if(result == null){
            throw new ParseException("No GPS information found in " + jpeg.getPath(),0);
        }
        return result;
    }

    private static Wpt wptFromGpsTag(TiffDirectory gpsIfd)
    throws MetadataException, ParseException,
    ImageReadException, ImageWriteException{
        if(gpsIfd == null){
            return null;
        }

        Wpt result = new Wpt();
        Number[] r3;
        TiffField e;

        /* map datum */
        e = gpsIfd.findField(TiffConstants.GPS_TAG_GPS_MAP_DATUM);
        if(e == null){
            warn("GPS datum missing. Assuming WGS84.");
        } else {
            String svalue = (String) e.getValue();
            if(svalue.equals("")){
                System.err.println("Warning: GPS datum missing. Assuming WGS84.");
            } else if(!svalue.toUpperCase().replaceAll("[^0-9A-Z]", "").equals("WGS84")){
                throw new MetadataException("GPS datum is " + svalue +
                    ". Currently only coordinates in the WGS84 "+
                    "map datum can be handled.");
            }
        }

        /* latitude */
        e = gpsIfd.findField(TiffConstants.GPS_TAG_GPS_LATITUDE);
        if(e == null){
           throw new MetadataException("GPS latitude missing.");
        }
        r3 = (Number[]) e.getValue();
        e = gpsIfd.findField(TiffConstants.GPS_TAG_GPS_LATITUDE_REF);
        if(e == null){
            String sysprop = System.getProperty("DefaultGPSLatitudeRef");
            char s0 = (sysprop == null || sysprop.length() == 0)
            ? 'X'
            : sysprop.toUpperCase().charAt(0);
            if(s0 != 'N' && s0 != 'S'){
                throw new MetadataException("GPS latitude found but GPS latitude reference missing or invalid.\n"+
                    "    To use the GPS latitude information set the DefaultGPSLatitudeRef system property to N or S, e. g.\n"+
                    "    java -DDefaultGPSLatitudeRef=N -jar gpsdings.jar ...");
            }
            result.setLat(asBigDecimalDegrees(r3, String.valueOf(s0)));
        } else {
            result.setLat(asBigDecimalDegrees(r3, (String) e.getValue()));
        }

        /* longitude */
        e = gpsIfd.findField(TiffConstants.GPS_TAG_GPS_LONGITUDE);
        if(e == null){
           throw new MetadataException("GPS longitude missing.");
        }
        r3 = (Number[]) e.getValue();
        e = gpsIfd.findField(TiffConstants.GPS_TAG_GPS_LONGITUDE_REF);
        if(e == null){
            String sysprop = System.getProperty("DefaultGPSLongitudeRef");
            final char s0 = (sysprop == null || sysprop.length() == 0)
            ? 'X'
            : sysprop.toUpperCase().charAt(0);
            if(s0 != 'E' && s0 != 'W'){
                throw new MetadataException("GPS longitude found but GPS longitude reference missing or invalid.\n"+
                    "    To use the GPS longitude information set the DefaultGPSLongitudeRef system property to W or E, e. g.\n"+
                    "    java -DDefaultGPSLongitudeRef=E -jar gpsdings.jar ...");
            }
            result.setLon(asBigDecimalDegrees(r3, String.valueOf(s0)));
        } else {
            result.setLon(asBigDecimalDegrees(r3, (String) e.getValue()));
        }

        /* elevation */
        e = gpsIfd.findField(TiffConstants.GPS_TAG_GPS_ALTITUDE);
        if(e != null){
            double alti = ((Number) e.getValue()).doubleValue();
            e = gpsIfd.findField(TiffConstants.GPS_TAG_GPS_ALTITUDE_REF);
            if (e == null){
                warn("GPSAltitudeRef missing. Assuming above sea level.");
            } else {
                int altref = ((Number) e.getValue()).intValue() * (-2) + 1; // 0 -> 1 && 1 -> -1
                if (Math.abs(altref) != 1 ){
                    System.err.printf("WARNING: illegal GPSAltitudeRef %d. Assuming above sea level.\n",
                        altref);
                    altref = 1;
                }
                alti *= altref;
            }
            result.setEle(new BigDecimal(alti));
        }

        /* dateTime */
        e = gpsIfd.findField(TiffConstants.GPS_TAG_GPS_TIME_STAMP);
        if(e != null){
            r3 = (Number[]) e.getValue();
            long millis = Math.round(asDouble(r3, 3.6e6));
            e = gpsIfd.findField(TiffConstants.GPS_TAG_GPS_DATE_STAMP);
            if (e != null){
                Date d = null;
                try{
                    d = AbstractExecExifWriter.parseExifDate((String) e.getValue());
                    d = new Date(d.getTime() + millis);
                    result.setTime(d);
                } catch (ParseException ex){
                    System.err.println(ex);
                }
                if(d == null) {
                    warn("Exif GPSDateStamp is not in ASCII YYYY:MM:DD format.\n" +
                        "Ignoring Exif GPSDateStamp and Exif GPSTimeStamp.");
                }
            }
        }
        return result;
    }

    private static void warn(String str){
        System.err.println("WARNING: " + str);
    }

    private static BigDecimal asBigDecimalDegrees(Number[] latlon,
                String ref){
        double result = asDouble(latlon, 1.0);
        if("W".equals(ref) || "S".equals(ref)){
            result = -result;
        }
        return new BigDecimal(result);
    }

    private static double asDouble(Number[] latlon, double maxFactor){
        double factor = maxFactor;
        double result = 0;
        for(Number r : latlon){
            result += r.floatValue() * factor;
            factor /= 60.;
        }
        return result;
    }
}
TOP

Related Classes of net.sourceforge.gpstools.exif.SanselanExifReader

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.