using System;
using System.Collections;
using System.Text;
using System.IO;
using com.drew.metadata;
using com.drew.lang;
///
/// This class was first written by Drew Noakes in Java.
///
/// This is public domain software - that is, you can do whatever you want
/// with it, and include it software that is licensed under the GNU or the
/// BSD license, or whatever other licence you choose, including proprietary
/// closed source licenses. I do ask that you leave this header in tact.
///
/// If you make modifications to this code that you think would benefit the
/// wider community, please send me a copy and I'll post it on my site.
///
/// If you make use of this code, Drew Noakes will appreciate hearing
/// about it: drew@drewnoakes.com
///
/// Latest Java version of this software kept at
/// http://drewnoakes.com/
///
/// The C# class was made by Ferret Renaud:
/// renaud91@free.fr
/// If you find a bug in the C# code, feel free to mail me.
///
namespace com.drew.metadata.exif
{
///
/// Tag descriptor for GPS
///
public class GpsDescriptor : TagDescriptor
{
///
/// Constructor of the object
///
/// a directory
public GpsDescriptor(Directory directory) : base(directory)
{
}
///
/// Returns a descriptive value of the the specified tag for this image.
/// Where possible, known values will be substituted here in place of the raw tokens actually
/// kept in the Exif segment.
/// If no substitution is available, the value provided by GetString(int) will be returned.
/// This and GetString(int) are the only 'get' methods that won't throw an exception.
///
/// the tag to find a description for
/// a description of the image's value for the specified tag, or null if the tag hasn't been defined.
public override string GetDescription(int tagType)
{
switch(tagType)
{
case GpsDirectory.TAG_GPS_ALTITUDE :
return GetGpsAltitudeDescription();
case GpsDirectory.TAG_GPS_ALTITUDE_REF :
return GetGpsAltitudeRefDescription();
case GpsDirectory.TAG_GPS_STATUS :
return GetGpsStatusDescription();
case GpsDirectory.TAG_GPS_MEASURE_MODE :
return GetGpsMeasureModeDescription();
case GpsDirectory.TAG_GPS_SPEED_REF :
return GetGpsSpeedRefDescription();
case GpsDirectory.TAG_GPS_TRACK_REF :
case GpsDirectory.TAG_GPS_IMG_DIRECTION_REF :
case GpsDirectory.TAG_GPS_DEST_BEARING_REF :
return GetGpsDirectionReferenceDescription(tagType);
case GpsDirectory.TAG_GPS_TRACK :
case GpsDirectory.TAG_GPS_IMG_DIRECTION :
case GpsDirectory.TAG_GPS_DEST_BEARING :
return GetGpsDirectionDescription(tagType);
case GpsDirectory.TAG_GPS_DEST_DISTANCE_REF :
return GetGpsDestinationReferenceDescription();
case GpsDirectory.TAG_GPS_TIME_STAMP :
return GetGpsTimeStampDescription();
// three rational numbers -- displayed in HH"MM"SS.ss
case GpsDirectory.TAG_GPS_LONGITUDE :
return GetGpsLongitudeDescription();
case GpsDirectory.TAG_GPS_LATITUDE :
return GetGpsLatitudeDescription();
default :
return _directory.GetString(tagType);
}
}
///
/// Returns the Gps Latitude Description.
///
/// the Gps Latitude Description.
private string GetGpsLatitudeDescription()
{
if (!_directory.ContainsTag(GpsDirectory.TAG_GPS_LATITUDE))
return null;
return GetHoursMinutesSecondsDescription(GpsDirectory.TAG_GPS_LATITUDE);
}
///
/// Returns the Gps Longitude Description.
///
/// the Gps Longitude Description.
private string GetGpsLongitudeDescription()
{
if (!_directory.ContainsTag(GpsDirectory.TAG_GPS_LONGITUDE))
return null;
return GetHoursMinutesSecondsDescription(
GpsDirectory.TAG_GPS_LONGITUDE);
}
///
/// Returns the Hours Minutes Seconds Description.
///
/// the Hours Minutes Seconds Description.
private string GetHoursMinutesSecondsDescription(int tagType)
{
Rational[] components = _directory.GetRationalArray(tagType);
// TODO create an HoursMinutesSecods class ??
int deg = components[0].IntValue();
float min = components[1].FloatValue();
float sec = components[2].FloatValue();
// carry fractions of minutes into seconds -- thanks Colin Briton
sec += (min % 1) * 60;
string[] tab = new string[] {deg.ToString(), ((int) min).ToString(), sec.ToString()};
return BUNDLE["HOURS_MINUTES_SECONDS", tab];
}
///
/// Returns the Gps Time Stamp Description.
///
/// the Gps Time Stamp Description.
private string GetGpsTimeStampDescription()
{
// time in hour, min, sec
if (!_directory.ContainsTag(GpsDirectory.TAG_GPS_TIME_STAMP))
return null;
int[] timeComponents =
_directory.GetIntArray(GpsDirectory.TAG_GPS_TIME_STAMP);
string[] tab = new string[] {timeComponents[0].ToString(), timeComponents[1].ToString(), timeComponents[2].ToString()};
return BUNDLE["GPS_TIME_STAMP", tab];
}
///
/// Returns the Gps Destination Reference Description.
///
/// the Gps Destination Reference Description.
private string GetGpsDestinationReferenceDescription()
{
if (!_directory.ContainsTag(GpsDirectory.TAG_GPS_DEST_DISTANCE_REF))
return null;
string destRef =
_directory.GetString(GpsDirectory.TAG_GPS_DEST_DISTANCE_REF).Trim().ToUpper();
if ("K".Equals(destRef))
{
return BUNDLE["KILOMETERS"];
}
else if ("M".Equals(destRef))
{
return BUNDLE["MILES"];
}
else if ("N".Equals(destRef))
{
return BUNDLE["KNOTS"];
}
else
{
return BUNDLE["UNKNOWN", destRef];
}
}
///
/// Returns the Gps Direction Description.
///
/// the Gps Direction Description.
private string GetGpsDirectionDescription(int tagType)
{
if (!_directory.ContainsTag(tagType))
return null;
string gpsDirection = _directory.GetString(tagType).Trim();
return BUNDLE["DEGREES", gpsDirection];
}
///
/// Returns the Gps Direction Reference Description.
///
/// the Gps Direction Reference Description.
private string GetGpsDirectionReferenceDescription(int tagType)
{
if (!_directory.ContainsTag(tagType))
return null;
string gpsDistRef = _directory.GetString(tagType).Trim().ToUpper();
if ("T".Equals(gpsDistRef))
{
return BUNDLE["TRUE_DIRECTION"];
}
else if ("M".Equals(gpsDistRef))
{
return BUNDLE["MAGNETIC_DIRECTION"];
}
else
{
return BUNDLE["UNKNOWN", gpsDistRef];
}
}
///
/// Returns the Gps Speed Ref Description.
///
/// the Gps Speed Ref Description.
private string GetGpsSpeedRefDescription()
{
if (!_directory.ContainsTag(GpsDirectory.TAG_GPS_SPEED_REF))
return null;
string gpsSpeedRef =
_directory.GetString(GpsDirectory.TAG_GPS_SPEED_REF).Trim().ToUpper();
if ("K".Equals(gpsSpeedRef))
{
return BUNDLE["KPH"];
}
else if ("M".Equals(gpsSpeedRef))
{
return BUNDLE["MPH"];
}
else if ("N".Equals(gpsSpeedRef))
{
return BUNDLE["KNOTS"];
}
else
{
return BUNDLE["UNKNOWN", gpsSpeedRef];
}
}
///
/// Returns the Gps Measure Mode Description.
///
/// the Gps Measure Mode Description.
private string GetGpsMeasureModeDescription()
{
if (!_directory.ContainsTag(GpsDirectory.TAG_GPS_MEASURE_MODE))
return null;
string gpsSpeedMeasureMode =
_directory.GetString(GpsDirectory.TAG_GPS_MEASURE_MODE).Trim().ToUpper();
if ("2".Equals(gpsSpeedMeasureMode) || "3".Equals(gpsSpeedMeasureMode))
{
return BUNDLE["DIMENSIONAL_MEASUREMENT", gpsSpeedMeasureMode];
}
else
{
return BUNDLE["UNKNOWN", gpsSpeedMeasureMode];
}
}
///
/// Returns the Gps Status Description.
///
/// the Gps Status Description.
private string GetGpsStatusDescription()
{
if (!_directory.ContainsTag(GpsDirectory.TAG_GPS_STATUS))
return null;
string gpsStatus =
_directory.GetString(GpsDirectory.TAG_GPS_STATUS).Trim().ToUpper();
if ("A".Equals(gpsStatus))
{
return BUNDLE["MEASUREMENT_IN_PROGESS"];
}
else if ("V".Equals(gpsStatus))
{
return BUNDLE["MEASUREMENT_INTEROPERABILITY"];
}
else
{
return BUNDLE["UNKNOWN", gpsStatus];
}
}
///
/// Returns the Gps Altitude Ref Description.
///
/// the Gps Altitude Ref Description.
private string GetGpsAltitudeRefDescription()
{
if (!_directory.ContainsTag(GpsDirectory.TAG_GPS_ALTITUDE_REF))
return null;
int alititudeRef = _directory.GetInt(GpsDirectory.TAG_GPS_ALTITUDE_REF);
if (alititudeRef == 0)
{
return BUNDLE["SEA_LEVEL"];
}
else
{
return BUNDLE["UNKNOWN", alititudeRef.ToString()];
}
}
///
/// Returns the Gps Altitude Description.
///
/// the Gps Altitude Description.
private string GetGpsAltitudeDescription()
{
if (!_directory.ContainsTag(GpsDirectory.TAG_GPS_ALTITUDE))
return null;
string alititude =
_directory.GetRational(
GpsDirectory.TAG_GPS_ALTITUDE).ToSimpleString(
true);
return BUNDLE["METRES", alititude];
}
}
}