summaryrefslogtreecommitdiff
path: root/gpsinfo.c
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2009-03-03 19:30:03 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2009-03-03 19:30:03 -0800
commit34a2564d3268a5ca1472c5076675782fbaf724d6 (patch)
tree4ef54cbea93bf6aa7c37ca25add416d126166fa3 /gpsinfo.c
parente0fbb24f6ea00ce3d61b73ef05faa893abf33151 (diff)
downloadjhead-34a2564d3268a5ca1472c5076675782fbaf724d6.tar.gz
auto import from //depot/cupcake/@135843
Diffstat (limited to 'gpsinfo.c')
-rw-r--r--gpsinfo.c299
1 files changed, 299 insertions, 0 deletions
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 <string.h>
+#include <utils/Log.h>
+
+
+#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<NumDirEntries;de++){
+ unsigned Tag, Format, Components;
+ unsigned char * ValuePtr;
+ int ComponentSize;
+ unsigned ByteCount;
+ unsigned char * DirEntry;
+ DirEntry = DIR_ENTRY_ADDR(DirStart, de);
+
+ if (DirEntry+12 > 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<ByteCount;a++){
+ int ZeroSkipped = 0;
+ if (ValuePtr[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");
+ }
+ }
+ }
+}
+
+