From 426377d9ce95606bac741d99b5b0a3e2038924fe Mon Sep 17 00:00:00 2001 From: The Android Open Source Project Date: Tue, 21 Oct 2008 07:00:00 -0700 Subject: Initial Contribution --- gpsinfo.c | 299 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 299 insertions(+) create mode 100644 gpsinfo.c (limited to 'gpsinfo.c') diff --git a/gpsinfo.c b/gpsinfo.c new file mode 100644 index 0000000..2a25368 --- /dev/null +++ b/gpsinfo.c @@ -0,0 +1,299 @@ +//-------------------------------------------------------------------------- +// Parsing of GPS info from exif header. +// +// Matthias Wandel, Dec 1999 - Dec 2002 +//-------------------------------------------------------------------------- +#include "jhead.h" + +#include +#include + + +#define TAG_GPS_LAT_REF 1 +#define TAG_GPS_LAT 2 +#define TAG_GPS_LONG_REF 3 +#define TAG_GPS_LONG 4 +#define TAG_GPS_ALT_REF 5 +#define TAG_GPS_ALT 6 + + +static TagTable_t GpsTags[]= { + { 0x00, "GPSVersionID", FMT_BYTE, 4}, + { 0x01, "GPSLatitudeRef", FMT_STRING, 2}, + { 0x02, "GPSLatitude", FMT_URATIONAL, 3}, + { 0x03, "GPSLongitudeRef", FMT_STRING, 2}, + { 0x04, "GPSLongitude", FMT_URATIONAL, 3}, + { 0x05, "GPSAltitudeRef", FMT_BYTE, 1}, + { 0x06, "GPSAltitude", FMT_SRATIONAL, 1}, + { 0x07, "GPSTimeStamp", FMT_SRATIONAL, 3}, + { 0x08, "GPSSatellites", FMT_STRING, -1}, + { 0x09, "GPSStatus", FMT_STRING, 2}, + { 0x0A, "GPSMeasureMode", FMT_STRING, 2}, + { 0x0B, "GPSDOP", FMT_SRATIONAL, 1}, + { 0x0C, "GPSSpeedRef", FMT_STRING, 2}, + { 0x0D, "GPSSpeed", FMT_SRATIONAL, 1}, + { 0x0E, "GPSTrackRef", FMT_STRING, 2}, + { 0x0F, "GPSTrack", FMT_SRATIONAL, 1}, + { 0x10, "GPSImgDirectionRef", FMT_STRING, -1}, + { 0x11, "GPSImgDirection", FMT_SRATIONAL, 1}, + { 0x12, "GPSMapDatum", FMT_STRING, -1}, + { 0x13, "GPSDestLatitudeRef", FMT_STRING, 2}, + { 0x14, "GPSDestLatitude", FMT_SRATIONAL, 3}, + { 0x15, "GPSDestLongitudeRef", FMT_STRING, 2}, + { 0x16, "GPSDestLongitude", FMT_SRATIONAL, 3}, + { 0x17, "GPSDestBearingRef", FMT_STRING, 1}, + { 0x18, "GPSDestBearing", FMT_SRATIONAL, 1}, + { 0x19, "GPSDestDistanceRef", FMT_STRING, 2}, + { 0x1A, "GPSDestDistance", FMT_SRATIONAL, 1}, + { 0x1B, "GPSProcessingMethod", FMT_STRING, -1}, + { 0x1C, "GPSAreaInformation", FMT_STRING, -1}, + { 0x1D, "GPSDateStamp", FMT_STRING, 11}, + { 0x1E, "GPSDifferential", FMT_SSHORT, 1}, +}; + +#define MAX_GPS_TAG (sizeof(GpsTags) / sizeof(TagTable_t)) + +// Define the line below to turn on poor man's debugging output +#undef SUPERDEBUG + +#ifdef SUPERDEBUG +#define printf LOGE +#endif + + +int IsGpsTag(const char* tag) { + return strstr(tag, "GPS") == tag; +} + +TagTable_t* GpsTagToTagTableEntry(unsigned short tag) +{ + unsigned int i; + for (i = 0; i < MAX_GPS_TAG; i++) { + if (GpsTags[i].Tag == tag) { + printf("found tag %d", tag); + int format = GpsTags[i].Format; + if (format == 0) { + printf("tag %s format not defined", GpsTags[i].Desc); + return NULL; + } + return &GpsTags[i]; + } + } + printf("tag %d NOT FOUND", tag); + return NULL; +} + +int GpsTagToFormatType(unsigned short tag) +{ + unsigned int i; + for (i = 0; i < MAX_GPS_TAG; i++) { + if (GpsTags[i].Tag == tag) { + printf("found tag %d", tag); + int format = GpsTags[i].Format; + if (format == 0) { + printf("tag %s format not defined", GpsTags[i].Desc); + return -1; + } + return format; + } + } + printf("tag %d NOT FOUND", tag); + return -1; +} + +int GpsTagNameToValue(const char* tagName) +{ + unsigned int i; + for (i = 0; i < MAX_GPS_TAG; i++) { + if (strcmp(GpsTags[i].Desc, tagName) == 0) { + printf("found GPS tag %s val %d", GpsTags[i].Desc, GpsTags[i].Tag); + return GpsTags[i].Tag; + } + } + printf("GPS tag %s NOT FOUND", tagName); + return -1; +} + + +//-------------------------------------------------------------------------- +// Process GPS info directory +//-------------------------------------------------------------------------- +void ProcessGpsInfo(unsigned char * DirStart, int ByteCountUnused, unsigned char * OffsetBase, unsigned ExifLength) +{ + int de; + unsigned a; + int NumDirEntries; + + NumDirEntries = Get16u(DirStart); + #define DIR_ENTRY_ADDR(Start, Entry) (Start+2+12*(Entry)) + + if (ShowTags){ + printf("(dir has %d entries)\n",NumDirEntries); + } + + ImageInfo.GpsInfoPresent = TRUE; + strcpy(ImageInfo.GpsLat, "? ?"); + strcpy(ImageInfo.GpsLong, "? ?"); + ImageInfo.GpsAlt[0] = 0; + + for (de=0;de OffsetBase+ExifLength){ + ErrNonfatal("GPS info directory goes past end of exif",0,0); + return; + } + + Tag = Get16u(DirEntry); + Format = Get16u(DirEntry+2); + Components = Get32u(DirEntry+4); + + if ((Format-1) >= NUM_FORMATS) { + // (-1) catches illegal zero case as unsigned underflows to positive large. + ErrNonfatal("Illegal number format %d for tag %04x", Format, Tag); + continue; + } + + ComponentSize = BytesPerFormat[Format]; + ByteCount = Components * ComponentSize; + +#ifdef SUPERDEBUG + printf("GPS tag %x format %s #components %d componentsize %d bytecount %d", Tag, formatStr(Format), Components, ComponentSize, + ByteCount); +#endif + + if (ByteCount > 4){ + unsigned OffsetVal; + OffsetVal = Get32u(DirEntry+8); + // If its bigger than 4 bytes, the dir entry contains an offset. + if (OffsetVal+ByteCount > ExifLength){ + // Bogus pointer offset and / or bytecount value + ErrNonfatal("Illegal value pointer for tag %04x", Tag,0); + continue; + } + ValuePtr = OffsetBase+OffsetVal; + }else{ + // 4 bytes or less and value is in the dir entry itself + ValuePtr = DirEntry+8; + } + + switch(Tag){ + char FmtString[21]; + char TempString[50]; + double Values[3]; + + case TAG_GPS_LAT_REF: + ImageInfo.GpsLat[0] = ValuePtr[0]; + ImageInfo.GpsLatRef[0] = ValuePtr[0]; + ImageInfo.GpsLatRef[1] = '\0'; + break; + + case TAG_GPS_LONG_REF: + ImageInfo.GpsLong[0] = ValuePtr[0]; + ImageInfo.GpsLongRef[0] = ValuePtr[0]; + ImageInfo.GpsLongRef[1] = '\0'; + break; + + case TAG_GPS_LAT: + case TAG_GPS_LONG: + if (Format != FMT_URATIONAL){ + ErrNonfatal("Inappropriate format (%d) for GPS coordinates!", Format, 0); + } + strcpy(FmtString, "%0.0fd %0.0fm %0.0fs"); + + for (a=0;a<3;a++){ + int den, digits; + + den = Get32s(ValuePtr+4+a*ComponentSize); + digits = 0; + while (den > 1){ + den = den / 10; + digits += 1; + } + FmtString[1+a*7] = (char)('2'+digits+(digits ? 1 : 0)); + FmtString[3+a*7] = (char)('0'+digits); + + Values[a] = ConvertAnyFormat(ValuePtr+a*ComponentSize, Format); + } + sprintf(TempString, FmtString, Values[0], Values[1], Values[2]); + + if (Tag == TAG_GPS_LAT){ + strncpy(ImageInfo.GpsLat+2, TempString, 29); + }else{ + strncpy(ImageInfo.GpsLong+2, TempString, 29); + } + + sprintf(TempString, "%d/%d,%d/%d,%d/%d", + Get32s(ValuePtr), Get32s(4+(char*)ValuePtr), + Get32s(8+(char*)ValuePtr), Get32s(12+(char*)ValuePtr), + Get32s(16+(char*)ValuePtr), Get32s(20+(char*)ValuePtr)); + if (Tag == TAG_GPS_LAT){ + strncpy(ImageInfo.GpsLatRaw, TempString, 31); + }else{ + strncpy(ImageInfo.GpsLongRaw, TempString, 31); + } + break; + + case TAG_GPS_ALT_REF: + ImageInfo.GpsAlt[0] = (char)(ValuePtr[0] ? '-' : ' '); + break; + + case TAG_GPS_ALT: + sprintf(ImageInfo.GpsAlt + 1, "%dm", Get32s(ValuePtr)); + break; + } + + if (ShowTags){ + // Show tag value. + if (Tag < MAX_GPS_TAG){ + printf(" %s =", GpsTags[Tag].Desc); + }else{ + // Show unknown tag + printf(" Illegal GPS tag %04x=", Tag); + } + + switch(Format){ + case FMT_UNDEFINED: + // Undefined is typically an ascii string. + + case FMT_STRING: + // String arrays printed without function call (different from int arrays) + { + printf("\""); + for (a=0;a= 32){ + if (ZeroSkipped){ + printf("?"); + ZeroSkipped = 0; + } + putchar(ValuePtr[a]); + }else{ + if (ValuePtr[a] == 0){ + ZeroSkipped = 1; + } + } + } + printf("\"\n"); + } + break; + + default: + // Handle arrays of numbers later (will there ever be?) + for (a=0;;){ + PrintFormatNumber(ValuePtr+a*ComponentSize, Format, ByteCount); + if (++a >= Components) break; + printf(", "); + } + printf("\n"); + } + } + } +} + + -- cgit v1.2.3