Package net.sourceforge.gpstools.exif

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

package net.sourceforge.gpstools.exif;

/* gpsdings
* Copyright (C) 2006-2009 Moritz Ringler
* $Id: MediaUtilExifReader.java 441 2010-12-13 20:04:20Z 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 mediautil.gen.*;
import mediautil.image.jpeg.*;
import net.sourceforge.gpstools.gpx.Wpt;

final class MediaUtilExifReader extends AbstractExifReader{

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

    @Override
    public Date readOriginalTime(File jpeg) throws IOException, ParseException{
        int oldDebugLevel = mediautil.gen.Log.debugLevel;
        mediautil.gen.Log.debugLevel = mediautil.gen.Log.LEVEL_NONE;
        String dateString = null;
        InputStream fip = null;
        LLJTran llj = null;
        try {
            fip = new BufferedInputStream(new FileInputStream(jpeg)); // No need to buffer
            llj = new LLJTran(fip);
            llj.read(LLJTran.READ_INFO, true);
        } catch (LLJTranException e) {
            throw toIOException(e, jpeg);
        } finally {
            mediautil.gen.Log.debugLevel = oldDebugLevel;
            if(fip != null){
                fip.close();
            }
        }

        AbstractImageInfo<?> imageInfo = llj.getImageInfo();

        if(! (imageInfo instanceof Exif))
        {
            throw new IOException("Image " + jpeg + " does not have an Exif header.");
        }

        Exif exif = (Exif) imageInfo;
        dateString = exif.getDataTimeOriginalString();
        if(dateString == null)
        {
            throw new IOException(jpeg + " : OriginalDateTime Exif tag is missing or invalid.");
        }


        //interpret the dateString as an UTC dateTime value
        return parseExifDate(dateString);
    }

    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{
        Dimension result = null;
        InputStream fip = null;
        int oldDebugLevel = mediautil.gen.Log.debugLevel;
        mediautil.gen.Log.debugLevel = mediautil.gen.Log.LEVEL_NONE;
        try{
            fip = new BufferedInputStream(new FileInputStream(jpeg)); // No need to buffer
            LLJTran llj = new LLJTran(fip);
            try {
                llj.read(LLJTran.READ_HEADER, true);
            } catch (LLJTranException e) {
                throw toIOException(e, jpeg);
            }
            int height = llj.getHeight();
            int width =  llj.getWidth();
            result = new Dimension(width, height);
        } finally {
            mediautil.gen.Log.debugLevel = oldDebugLevel;
            if(fip != null){
                fip.close();
            }
        }
        return result;
    }

    @Override
    public Wpt readGPSTag(File jpeg) throws IOException, ParseException{
        Wpt result = null;
        InputStream fip = null;
        int oldDebugLevel = mediautil.gen.Log.debugLevel;
        mediautil.gen.Log.debugLevel = mediautil.gen.Log.LEVEL_NONE;
        try{
            fip = new BufferedInputStream(new FileInputStream(jpeg)); // No need to buffer
            LLJTran llj = new LLJTran(fip);
            try {
                llj.read(LLJTran.READ_INFO, true);
            } catch (LLJTranException e) {
                throw toIOException(e, jpeg);
            }

            AbstractImageInfo<?> imageInfo = llj.getImageInfo();

            if(! (imageInfo instanceof Exif))
            {
                throw new IOException("Image " + jpeg + "does not have Exif.");
            }

            Exif exif = (Exif) imageInfo;
            IFD mainIfd = exif.getIFDs()[0];
            IFD gpsIfd = mainIfd.getIFD(Exif.GPSINFO);
            result = wptFromGpsTag(gpsIfd);
        } catch (MetadataException ex){
            throw toIOException(ex, jpeg);
        } finally {
            mediautil.gen.Log.debugLevel = oldDebugLevel;
            if(fip != null){
                fip.close();
            }
        }
        if(result == null){
            throw new ParseException("No GPS information found in " + jpeg.getPath(),0);
        }
        return result;
    }

    private static BigDecimal asBigDecimalDegrees(Rational[] 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(Rational[] latlon, double maxFactor){
        double factor = maxFactor;
        double result = 0;
        for(Rational r : latlon){
            result += r.floatValue() * factor;
            factor /= 60.;
        }
        return result;
    }

    private static Rational[] getRationalTripleValue(Entry e, Rational[] r){
        Rational[] result = (r == null)? new Rational[3] : r;
        for(int i=0; i<3; i++){
            result[i] = (Rational) e.getValue(i);
        }
        return result;
    }

    private static Wpt wptFromGpsTag(IFD gps) throws MetadataException, ParseException{
        if(gps == null){
            return null;
        }

        Wpt result = new Wpt();
        Rational[] r3 = new Rational[3];

        /* map datum */
        Entry e = gps.getEntry(Exif.GPSMapDatum, 0);
        if(e == null){
            warn("GPS datum missing. Assuming WGS84.");
        } else {
            Object value = e.getValue(0);
            String svalue = String.valueOf(value);
            if(value == null || 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 " + value.toString() +
                    ". Currently only coordinates in the WGS84 "+
                    "map datum can be handled.");
            }
        }

        /* latitude */
        e = gps.getEntry(Exif.GPSLatitude, 0);
        if(e == null){
           throw new MetadataException("GPS latitude missing.");
        }
        r3 = getRationalTripleValue(e, r3);
        e = gps.getEntry(Exif.GPSLatitudeRef, 0);
        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.valueOf(e.getValue(0))));
    }

        /* longitude */
        e = gps.getEntry(Exif.GPSLongitude, 0);
        if(e == null){
           throw new MetadataException("GPS longtude missing.");
        }
        r3 = getRationalTripleValue(e, r3);
        e = gps.getEntry(Exif.GPSLongitudeRef, 0);
        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.valueOf(e.getValue(0))));
    }


        /* elevation */
        if(gps.getEntry(Exif.GPSAltitude, 0) != null){
            double alti = 1;
            if (gps.getEntry(Exif.GPSAltitudeRef, 0) == null){
                warn("GPSAltitudeRef missing. Assuming above sea level.");
            } else {
                e = gps.getEntry(Exif.GPSAltitudeRef, 0);
                alti *= ((Integer) e.getValue(0)).intValue() * (-2) + 1; // 0 -> 1 && 1 -> -1
                if (Math.abs(alti) != 1 ){
                    alti = 1;
                    System.err.printf("WARNING: illegal GPSAltitudeRef %d. Assuming above sea level.\n",
                        ((Integer) e.getValue(0)).intValue());
                }
            }

            e = gps.getEntry(Exif.GPSAltitude, 0);
            alti *= ((Rational) e.getValue(0)).floatValue();
            result.setEle(new BigDecimal(alti));
        }

        /* dateTime */
        if(gps.getEntry(Exif.GPSTimeStamp, 0) != null &&
            gps.getEntry(Exif.GPSDateStamp, 0) != null){
            e = gps.getEntry(Exif.GPSTimeStamp, 0);
            r3 = getRationalTripleValue(e, r3);
            long millis = Math.round(asDouble(r3, 3.6e6));

            e = gps.getEntry(Exif.GPSDateStamp, 0);
            Date d = null;
            if(e.getType() == Exif.ASCII){
            try{
                d = AbstractExecExifWriter.parseExifDate(String.valueOf(e.getValue(0)));
                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);
    }
}
TOP

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

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.