/**
* GeoDress - A program for reverse geocoding
* Copyright (C) 2010 Stefan T.
*
* See COPYING for Details.
*
* 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/>.
*/
package geodress.model.reader;
import geodress.exceptions.FileTypeNotSupportedException;
import geodress.exceptions.NoMetaDataException;
import geodress.main.InfoConstants;
import geodress.main.Logging;
import geodress.model.PictureFilter;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.filechooser.FileFilter;
import org.apache.sanselan.ImageReadException;
import org.apache.sanselan.Sanselan;
import org.apache.sanselan.formats.jpeg.JpegImageMetadata;
import org.apache.sanselan.formats.tiff.TiffField;
import org.apache.sanselan.formats.tiff.constants.GPSTagConstants;
import org.apache.sanselan.formats.tiff.constants.TiffConstants;
import org.apache.sanselan.formats.tiff.constants.TiffDirectoryConstants;
/**
* A reader for EXIF data from files using <a
* href="http://commons.apache.org/sanselan">Sanselan</a>.
*
* @author Stefan T.
*/
public class SanselanReader implements MetaDataReader {
/** Logger object */
private Logger logger = null;
/** the file where data should be read from */
private File file;
/** the EXIF meta data of this file */
private JpegImageMetadata jpegMetadata;
/** this image is returned if there's no thumbnail */
private final Image NO_THUMBNAIL = new BufferedImage(10, 10,
BufferedImage.TYPE_USHORT_GRAY);
/** the file filter for picture files that can be read */
private final FileFilter PIC_FILTER = new PictureFilter();
/**
* Initializes class and logger.
*/
public SanselanReader() {
logger = Logging.getLogger(this.getClass().getName());
}
/**
* @throws NoMetaDataException
* thrown if the picture file contains no meta data
*/
@Override
public String getData(int field) throws NoMetaDataException {
logger.log(Level.FINEST, "get data " + field + " from "
+ file.getPath());
String value = null;
TiffField valueField;
if (jpegMetadata != null && jpegMetadata.getExif() != null) {
switch (field) {
case InfoConstants.GPS_LATITUDE:
try {
if (jpegMetadata.getExif() != null
&& jpegMetadata.getExif().getGPS() != null) {
value = String.valueOf(jpegMetadata.getExif().getGPS()
.getLatitudeAsDegreesNorth());
if (jpegMetadata.getExif().getGPS().latitudeRef == GPSTagConstants.GPS_TAG_GPS_DEST_LATITUDE_REF_VALUE_SOUTH) {
value = "-" + value;
}
} else {
logger.log(Level.FINER,
"no meta data for latitude exist in "
+ getFile().getPath());
throw new NoMetaDataException(
"no meta data for latitude exist in "
+ getFile().getPath());
}
} catch (ImageReadException ire) {
logger.log(Level.WARNING,
"error while reading latitude from "
+ file.getName(), ire);
}
break;
case InfoConstants.GPS_LONGITUDE:
try {
if (jpegMetadata.getExif() != null
&& jpegMetadata.getExif().getGPS() != null) {
value = String.valueOf(jpegMetadata.getExif().getGPS()
.getLongitudeAsDegreesEast());
if (jpegMetadata.getExif().getGPS().longitudeRef == GPSTagConstants.GPS_TAG_GPS_DEST_LONGITUDE_REF_VALUE_WEST) {
value = "-" + value;
}
} else {
logger.log(Level.FINER,
"no meta data for longitude exist in "
+ getFile().getPath());
throw new NoMetaDataException(
"no meta data for longitude exist in "
+ getFile().getPath());
}
} catch (ImageReadException ire) {
logger.log(Level.WARNING,
"error while reading longitude from "
+ file.getName(), ire);
}
break;
case InfoConstants.DATE_TIME:
/* format 'yyyy:MM:dd kk:mm:ss' */
valueField = jpegMetadata
.findEXIFValue(TiffConstants.EXIF_TAG_CREATE_DATE);
if (valueField != null) {
value = valueField.getValueDescription();
value = value.substring(1, value.length() - 1);
}
break;
case InfoConstants.USER_COMMENT:
valueField = jpegMetadata
.findEXIFValue(TiffConstants.EXIF_TAG_USER_COMMENT);
if (valueField != null) {
value = valueField.getValueDescription();
value = value.substring(1, value.length() - 1);
}
break;
case InfoConstants.IMAGE_DESCRIPTION:
valueField = jpegMetadata
.findEXIFValue(TiffConstants.TIFF_TAG_IMAGE_DESCRIPTION);
if (valueField != null) {
value = valueField.getValueDescription();
value = value.substring(1, value.length() - 1);
}
break;
}
} else {
logger.log(Level.FINER, "no meta data exist in "
+ getFile().getPath());
throw new NoMetaDataException("no meta data exist in "
+ getFile().getPath());
}
return value;
}
/**
* @see geodress.model.reader.MetaDataReader#getThumbnail()
* @return the thumbnail picture or a 10x10 gray image if there's no
* thumbnail picture
*/
@Override
public Image getThumbnail() {
if (jpegMetadata != null
&& jpegMetadata.getExif() != null
&& jpegMetadata.getExif().findDirectory(
TiffDirectoryConstants.DIRECTORY_TYPE_THUMBNAIL) != null) {
try {
return jpegMetadata.getExif().findDirectory(
TiffDirectoryConstants.DIRECTORY_TYPE_THUMBNAIL)
.getTiffImage();
} catch (ImageReadException ire) {
logger.log(Level.INFO, "error while reading thumbnail for "
+ getFile(), ire);
} catch (IOException ioe) {
logger.log(Level.INFO, "I/O error while reading thumbnail for "
+ getFile(), ioe);
}
}
return NO_THUMBNAIL;
}
/**
* @param file
* the file to set
* @throws IOException
* thrown if an I/O error occurs
* @throws FileTypeNotSupportedException
* if the given file is not supported by this reader
*/
@Override
public void setFile(File file) throws IOException,
FileTypeNotSupportedException {
this.file = file;
if (!PIC_FILTER.accept(file)) {
throw new FileTypeNotSupportedException("the type of file "
+ file.getAbsolutePath()
+ " is not supported for reading EXIF data");
}
/* catch the meta data from JPEG */
try {
jpegMetadata = (JpegImageMetadata) Sanselan.getMetadata(file);
} catch (ImageReadException ire) {
/* do nothing */
logger.log(Level.FINE, "error while reading meta data", ire);
}
}
/**
* Gets the file that is used to read EXIF data from.
*
* @return the file
*/
public File getFile() {
return file;
}
}