eu.hydrologis.jgrass.geonotes.util.ExifHandler.java Source code

Java tutorial

Introduction

Here is the source code for eu.hydrologis.jgrass.geonotes.util.ExifHandler.java

Source

/*
 * JGrass - Free Open Source Java GIS http://www.jgrass.org 
 * (C) HydroloGIS - www.hydrologis.com 
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser 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 Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package eu.hydrologis.jgrass.geonotes.util;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.HashMap;

import org.apache.commons.io.FileUtils;
import org.apache.sanselan.ImageReadException;
import org.apache.sanselan.Sanselan;
import org.apache.sanselan.common.IImageMetadata;
import org.apache.sanselan.formats.jpeg.JpegImageMetadata;
import org.apache.sanselan.formats.jpeg.exifRewrite.ExifRewriter;
import org.apache.sanselan.formats.tiff.TiffField;
import org.apache.sanselan.formats.tiff.TiffImageMetadata;
import org.apache.sanselan.formats.tiff.constants.TagInfo;
import org.apache.sanselan.formats.tiff.constants.TiffConstants;
import org.apache.sanselan.formats.tiff.write.TiffOutputSet;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

/**
 * A class that handles exif operation.
 * 
 * <p>Adapted from various sanselan docs and snippets.
 * 
 * @author Andrea Antonello (www.hydrologis.com)
 *
 */
@SuppressWarnings("nls")
public class ExifHandler {

    public static final String GPS_DESCRIPTION = "GPS Description";
    public static final String GPS_LATITUDE_DEGREES_NORTH = "GPS Latitude (Degrees North)";
    public static final String GPS_LONGITUDE_DEGREES_EAST = "GPS Longitude (Degrees East)";

    /**
     * Read exif tags into a {@link HashMap}.
     * 
     * <p>Current extracted tags are:
     * <ul>
     * <li>TiffConstants.TIFF_TAG_XRESOLUTION</li>
     * <li>TiffConstants.TIFF_TAG_DATE_TIME</li>
     * <li>TiffConstants.EXIF_TAG_DATE_TIME_ORIGINAL</li>
     * <li>TiffConstants.EXIF_TAG_CREATE_DATE</li>
     * <li>TiffConstants.EXIF_TAG_ISO</li>
     * <li>TiffConstants.EXIF_TAG_SHUTTER_SPEED_VALUE</li>
     * <li>TiffConstants.EXIF_TAG_APERTURE_VALUE</li>
     * <li>TiffConstants.EXIF_TAG_BRIGHTNESS_VALUE</li>
     * </ul>
     * 
     * @param jpegImageFile the image file to read the tags from.
     * @return the map of tag names and values.
     * @throws Exception
     */
    public static HashMap<String, String> readMetaData(File jpegImageFile) throws Exception {
        HashMap<String, String> metadataMap = new HashMap<String, String>(30);

        IImageMetadata metadata = Sanselan.getMetadata(jpegImageFile);
        if (metadata instanceof JpegImageMetadata) {
            JpegImageMetadata jpegMetadata = (JpegImageMetadata) metadata;
            addTagToMap(jpegMetadata, TiffConstants.TIFF_TAG_XRESOLUTION, metadataMap);
            addTagToMap(jpegMetadata, TiffConstants.TIFF_TAG_DATE_TIME, metadataMap);
            addTagToMap(jpegMetadata, TiffConstants.EXIF_TAG_DATE_TIME_ORIGINAL, metadataMap);
            addTagToMap(jpegMetadata, TiffConstants.EXIF_TAG_CREATE_DATE, metadataMap);
            addTagToMap(jpegMetadata, TiffConstants.EXIF_TAG_ISO, metadataMap);
            addTagToMap(jpegMetadata, TiffConstants.EXIF_TAG_SHUTTER_SPEED_VALUE, metadataMap);
            addTagToMap(jpegMetadata, TiffConstants.EXIF_TAG_APERTURE_VALUE, metadataMap);
            addTagToMap(jpegMetadata, TiffConstants.EXIF_TAG_BRIGHTNESS_VALUE, metadataMap);

            TiffImageMetadata exifMetadata = jpegMetadata.getExif();
            if (exifMetadata != null) {
                try {
                    TiffImageMetadata.GPSInfo gpsInfo = exifMetadata.getGPS();
                    if (null != gpsInfo) {
                        double longitude = gpsInfo.getLongitudeAsDegreesEast();
                        double latitude = gpsInfo.getLatitudeAsDegreesNorth();
                        metadataMap.put(GPS_DESCRIPTION, gpsInfo.toString());
                        metadataMap.put(GPS_LONGITUDE_DEGREES_EAST, String.valueOf(longitude));
                        metadataMap.put(GPS_LATITUDE_DEGREES_NORTH, String.valueOf(latitude));
                    }
                } catch (ImageReadException e) {
                    e.printStackTrace();
                }
            }

            // ArrayList items = jpegMetadata.getItems();
            // for( int i = 0; i < items.size(); i++ ) {
            // Object item = items.get(i);
            // mdataList.add("    " + "item: " + item);
            // }
        }

        return metadataMap;
    }

    private static void addTagToMap(JpegImageMetadata jpegMetadata, TagInfo tagInfo,
            HashMap<String, String> metadataMap) throws Exception {
        TiffField field = jpegMetadata.findEXIFValue(tagInfo);
        if (field != null) {
            metadataMap.put(tagInfo.name, field.getValueDescription());
        }
    }

    /**
     * Extract the creation {@link DateTime} from the map of tags read by {@link #readMetaData(File)}.
     * 
     * @param tags2ValuesMap the map of tags read by {@link #readMetaData(File)}.
     * @return the datetime.
     */
    public static DateTime getCreationDatetimeUtc(HashMap<String, String> tags2ValuesMap) {
        String creationDate = tags2ValuesMap.get(TiffConstants.EXIF_TAG_CREATE_DATE.name);
        creationDate = creationDate.replaceAll("'", "");
        creationDate = creationDate.replaceFirst(":", "-");
        creationDate = creationDate.replaceFirst(":", "-");

        String dateTimeFormatterYYYYMMDDHHMMSS_string = "yyyy-MM-dd HH:mm:ss";
        DateTimeFormatter dateTimeFormatterYYYYMMDDHHMMSS = DateTimeFormat
                .forPattern(dateTimeFormatterYYYYMMDDHHMMSS_string);

        DateTime parseDateTime = dateTimeFormatterYYYYMMDDHHMMSS.parseDateTime(creationDate);
        DateTime dt = parseDateTime.toDateTime(DateTimeZone.UTC);
        return dt;
    }

    /**
     * Writes the supplied gps tags to the image file.
     * 
     * <p>The tags are written to a new image which then
     * replaces the old image and is then removed.
     * 
     * @param lat the latitude gps entry to add.
     * @param lon the longitude gps entry to add.
     * @param jpegImageFile the image file to update.
     * @throws Exception
     */
    public static void writeGPSTagsToImage(double lat, double lon, File jpegImageFile) throws Exception {
        OutputStream os = null;
        try {
            TiffOutputSet outputSet = null;

            // note that metadata might be null if no metadata is found.
            IImageMetadata metadata = Sanselan.getMetadata(jpegImageFile);
            JpegImageMetadata jpegMetadata = (JpegImageMetadata) metadata;
            if (null != jpegMetadata) {
                TiffImageMetadata exif = jpegMetadata.getExif();
                if (null != exif) {
                    outputSet = exif.getOutputSet();
                }
            }

            if (null == outputSet)
                outputSet = new TiffOutputSet();

            outputSet.setGPSInDegrees(lon, lat);

            File destinationImageFile = new File(jpegImageFile.getAbsolutePath() + ".jpg"); //$NON-NLS-1$

            os = new FileOutputStream(destinationImageFile);
            os = new BufferedOutputStream(os);

            new ExifRewriter().updateExifMetadataLossless(jpegImageFile, os, outputSet);

            os.close();

            FileUtils.copyFile(destinationImageFile, jpegImageFile);
            FileUtils.forceDelete(destinationImageFile);
        } finally {
            if (os != null)
                os.close();
        }
    }

    public static void main(String[] args) throws Exception {
        File imgFile = new File("/home/moovida/Desktop/rilievo_drava/DCIM/100CANON/IMG_3826.JPG");
        dump(imgFile);
        writeGPSTagsToImage(44.12, 11.26, imgFile);
        dump(imgFile);

    }

    private static void dump(File imgFile) throws Exception {
        HashMap<String, String> readMetaData = ExifHandler.readMetaData(imgFile);
        DateTime creationDatetimeUtc = getCreationDatetimeUtc(readMetaData);
        String creationDate = readMetaData.get(TiffConstants.EXIF_TAG_CREATE_DATE.name);
        System.out.println(creationDate + " / " + creationDatetimeUtc);
        String lat = readMetaData.get(ExifHandler.GPS_LATITUDE_DEGREES_NORTH);
        String lon = readMetaData.get(ExifHandler.GPS_LONGITUDE_DEGREES_EAST);

        System.out.println("lat = " + lat + " / lon = " + lon);
    }

}