134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//-------------------------------------------------------------------------- 234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// Parsing of GPS info from exif header. 334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// 4434623a0e87c8e145dbb46917b4ab9777475d9ebRay Chen// Matthias Wandel, Dec 1999 - Dec 2002 534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//-------------------------------------------------------------------------- 634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#include "jhead.h" 734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#include <string.h> 934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#include <utils/Log.h> 1034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 1134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 1234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#define TAG_GPS_LAT_REF 1 1334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#define TAG_GPS_LAT 2 1434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#define TAG_GPS_LONG_REF 3 1534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#define TAG_GPS_LONG 4 1634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#define TAG_GPS_ALT_REF 5 1734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#define TAG_GPS_ALT 6 18a39920ca4b96a456511fa32ba90c77f119a274c3Ray Chen#define TAG_GPS_TIMESTAMP 7 19434623a0e87c8e145dbb46917b4ab9777475d9ebRay Chen#define TAG_GPS_PROCESSING_METHOD 27 20a39920ca4b96a456511fa32ba90c77f119a274c3Ray Chen#define TAG_GPS_DATESTAMP 29 2134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 2234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectstatic TagTable_t GpsTags[]= { 2334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project { 0x00, "GPSVersionID", FMT_BYTE, 4}, 2434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project { 0x01, "GPSLatitudeRef", FMT_STRING, 2}, 2534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project { 0x02, "GPSLatitude", FMT_URATIONAL, 3}, 2634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project { 0x03, "GPSLongitudeRef", FMT_STRING, 2}, 2734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project { 0x04, "GPSLongitude", FMT_URATIONAL, 3}, 2834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project { 0x05, "GPSAltitudeRef", FMT_BYTE, 1}, 291ed8197f0cefb2541f630830993e109c59ba822cWu-cheng Li { 0x06, "GPSAltitude", FMT_URATIONAL, 1}, 3034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project { 0x07, "GPSTimeStamp", FMT_SRATIONAL, 3}, 3134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project { 0x08, "GPSSatellites", FMT_STRING, -1}, 3234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project { 0x09, "GPSStatus", FMT_STRING, 2}, 3334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project { 0x0A, "GPSMeasureMode", FMT_STRING, 2}, 3434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project { 0x0B, "GPSDOP", FMT_SRATIONAL, 1}, 3534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project { 0x0C, "GPSSpeedRef", FMT_STRING, 2}, 3634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project { 0x0D, "GPSSpeed", FMT_SRATIONAL, 1}, 3734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project { 0x0E, "GPSTrackRef", FMT_STRING, 2}, 3834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project { 0x0F, "GPSTrack", FMT_SRATIONAL, 1}, 3934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project { 0x10, "GPSImgDirectionRef", FMT_STRING, -1}, 4034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project { 0x11, "GPSImgDirection", FMT_SRATIONAL, 1}, 4134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project { 0x12, "GPSMapDatum", FMT_STRING, -1}, 4234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project { 0x13, "GPSDestLatitudeRef", FMT_STRING, 2}, 4334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project { 0x14, "GPSDestLatitude", FMT_SRATIONAL, 3}, 4434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project { 0x15, "GPSDestLongitudeRef", FMT_STRING, 2}, 4534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project { 0x16, "GPSDestLongitude", FMT_SRATIONAL, 3}, 4634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project { 0x17, "GPSDestBearingRef", FMT_STRING, 1}, 4734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project { 0x18, "GPSDestBearing", FMT_SRATIONAL, 1}, 4834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project { 0x19, "GPSDestDistanceRef", FMT_STRING, 2}, 4934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project { 0x1A, "GPSDestDistance", FMT_SRATIONAL, 1}, 50bd90094d709a579d8d74c326269e492627be9daaTyler Luu { 0x1B, "GPSProcessingMethod", FMT_UNDEFINED, -1}, 5134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project { 0x1C, "GPSAreaInformation", FMT_STRING, -1}, 5234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project { 0x1D, "GPSDateStamp", FMT_STRING, 11}, 5334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project { 0x1E, "GPSDifferential", FMT_SSHORT, 1}, 5434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project}; 5534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 5634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#define MAX_GPS_TAG (sizeof(GpsTags) / sizeof(TagTable_t)) 57434623a0e87c8e145dbb46917b4ab9777475d9ebRay Chen#define EXIF_ASCII_PREFIX_LEN (sizeof(ExifAsciiPrefix)) 5834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 5934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// Define the line below to turn on poor man's debugging output 6034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#undef SUPERDEBUG 6134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 6234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 637a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block#define printf ALOGE 6434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 6534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 6634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 6734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectint IsGpsTag(const char* tag) { 6834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return strstr(tag, "GPS") == tag; 6934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project} 7034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 7134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source ProjectTagTable_t* GpsTagToTagTableEntry(unsigned short tag) 7234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project{ 7334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project unsigned int i; 7434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project for (i = 0; i < MAX_GPS_TAG; i++) { 7534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (GpsTags[i].Tag == tag) { 7634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("found tag %d", tag); 7734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project int format = GpsTags[i].Format; 7834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (format == 0) { 7934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("tag %s format not defined", GpsTags[i].Desc); 8034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return NULL; 8134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 8234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return &GpsTags[i]; 8334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 8434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 8534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("tag %d NOT FOUND", tag); 8634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return NULL; 8734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project} 8834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 8934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectint GpsTagToFormatType(unsigned short tag) 9034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project{ 9134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project unsigned int i; 9234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project for (i = 0; i < MAX_GPS_TAG; i++) { 9334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (GpsTags[i].Tag == tag) { 9434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("found tag %d", tag); 9534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project int format = GpsTags[i].Format; 9634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (format == 0) { 9734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("tag %s format not defined", GpsTags[i].Desc); 9834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return -1; 9934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 10034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return format; 10134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 10234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 10334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("tag %d NOT FOUND", tag); 10434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return -1; 10534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project} 10634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 10734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectint GpsTagNameToValue(const char* tagName) 10834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project{ 10934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project unsigned int i; 11034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project for (i = 0; i < MAX_GPS_TAG; i++) { 11134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (strcmp(GpsTags[i].Desc, tagName) == 0) { 11234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("found GPS tag %s val %d", GpsTags[i].Desc, GpsTags[i].Tag); 11334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return GpsTags[i].Tag; 11434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 11534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 11634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("GPS tag %s NOT FOUND", tagName); 11734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return -1; 11834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project} 11934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 12034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 12134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//-------------------------------------------------------------------------- 12234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// Process GPS info directory 12334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//-------------------------------------------------------------------------- 12434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectvoid ProcessGpsInfo(unsigned char * DirStart, int ByteCountUnused, unsigned char * OffsetBase, unsigned ExifLength) 12534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project{ 12634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project int de; 12734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project unsigned a; 12834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project int NumDirEntries; 12934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 13034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project NumDirEntries = Get16u(DirStart); 13134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project #define DIR_ENTRY_ADDR(Start, Entry) (Start+2+12*(Entry)) 13234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 13334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ShowTags){ 13434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("(dir has %d entries)\n",NumDirEntries); 13534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 13634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 13734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ImageInfo.GpsInfoPresent = TRUE; 13834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project strcpy(ImageInfo.GpsLat, "? ?"); 13934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project strcpy(ImageInfo.GpsLong, "? ?"); 14034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ImageInfo.GpsAlt[0] = 0; 14134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 14234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project for (de=0;de<NumDirEntries;de++){ 14334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project unsigned Tag, Format, Components; 14434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project unsigned char * ValuePtr; 14534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project int ComponentSize; 14634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project unsigned ByteCount; 14734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project unsigned char * DirEntry; 14834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project DirEntry = DIR_ENTRY_ADDR(DirStart, de); 14934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 15034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (DirEntry+12 > OffsetBase+ExifLength){ 15134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ErrNonfatal("GPS info directory goes past end of exif",0,0); 15234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return; 15334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 15434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 15534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project Tag = Get16u(DirEntry); 15634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project Format = Get16u(DirEntry+2); 15734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project Components = Get32u(DirEntry+4); 15834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 15934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if ((Format-1) >= NUM_FORMATS) { 16034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // (-1) catches illegal zero case as unsigned underflows to positive large. 16134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ErrNonfatal("Illegal number format %d for tag %04x", Format, Tag); 16234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project continue; 16334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 16434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 16534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ComponentSize = BytesPerFormat[Format]; 16634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ByteCount = Components * ComponentSize; 16734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 16834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 16934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("GPS tag %x format %s #components %d componentsize %d bytecount %d", Tag, formatStr(Format), Components, ComponentSize, 17034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ByteCount); 17134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 17234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 17334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ByteCount > 4){ 17434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project unsigned OffsetVal; 17534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project OffsetVal = Get32u(DirEntry+8); 17634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // If its bigger than 4 bytes, the dir entry contains an offset. 17734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (OffsetVal+ByteCount > ExifLength){ 17834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Bogus pointer offset and / or bytecount value 17934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ErrNonfatal("Illegal value pointer for tag %04x", Tag,0); 18034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project continue; 18134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 18234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ValuePtr = OffsetBase+OffsetVal; 18334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project }else{ 18434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // 4 bytes or less and value is in the dir entry itself 18534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ValuePtr = DirEntry+8; 18634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 18734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 18834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project switch(Tag){ 18934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project char FmtString[21]; 1902bfc190bd3be7e1b91fe3d7ca49412ebf0f5ceeeWang Kun char TempString[MAX_BUF_SIZE]; 19134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project double Values[3]; 19234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 19334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case TAG_GPS_LAT_REF: 19434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ImageInfo.GpsLat[0] = ValuePtr[0]; 19534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ImageInfo.GpsLatRef[0] = ValuePtr[0]; 19634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ImageInfo.GpsLatRef[1] = '\0'; 19734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 19834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 19934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case TAG_GPS_LONG_REF: 20034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ImageInfo.GpsLong[0] = ValuePtr[0]; 20134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ImageInfo.GpsLongRef[0] = ValuePtr[0]; 20234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ImageInfo.GpsLongRef[1] = '\0'; 20334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 20434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 20534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case TAG_GPS_LAT: 20634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case TAG_GPS_LONG: 20734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (Format != FMT_URATIONAL){ 20834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ErrNonfatal("Inappropriate format (%d) for GPS coordinates!", Format, 0); 20934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 21034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project strcpy(FmtString, "%0.0fd %0.0fm %0.0fs"); 21134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project for (a=0;a<3;a++){ 21234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project int den, digits; 21334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 21434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project den = Get32s(ValuePtr+4+a*ComponentSize); 21534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project digits = 0; 216d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang while (den > 1 && digits <= 6){ 21734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project den = den / 10; 21834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project digits += 1; 21934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 220d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang if (digits > 6) digits = 6; 22134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project FmtString[1+a*7] = (char)('2'+digits+(digits ? 1 : 0)); 22234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project FmtString[3+a*7] = (char)('0'+digits); 22334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 22434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project Values[a] = ConvertAnyFormat(ValuePtr+a*ComponentSize, Format); 22534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 226d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang 22734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project sprintf(TempString, FmtString, Values[0], Values[1], Values[2]); 22834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 22934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (Tag == TAG_GPS_LAT){ 23034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project strncpy(ImageInfo.GpsLat+2, TempString, 29); 23134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project }else{ 23234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project strncpy(ImageInfo.GpsLong+2, TempString, 29); 23334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 23434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 23534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project sprintf(TempString, "%d/%d,%d/%d,%d/%d", 23634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project Get32s(ValuePtr), Get32s(4+(char*)ValuePtr), 23734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project Get32s(8+(char*)ValuePtr), Get32s(12+(char*)ValuePtr), 23834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project Get32s(16+(char*)ValuePtr), Get32s(20+(char*)ValuePtr)); 23934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (Tag == TAG_GPS_LAT){ 2402bfc190bd3be7e1b91fe3d7ca49412ebf0f5ceeeWang Kun strncpy(ImageInfo.GpsLatRaw, TempString, MAX_BUF_SIZE); 24134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project }else{ 2422bfc190bd3be7e1b91fe3d7ca49412ebf0f5ceeeWang Kun strncpy(ImageInfo.GpsLongRaw, TempString, MAX_BUF_SIZE); 24334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 24434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 24534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 24634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case TAG_GPS_ALT_REF: 24734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ImageInfo.GpsAlt[0] = (char)(ValuePtr[0] ? '-' : ' '); 2481ed8197f0cefb2541f630830993e109c59ba822cWu-cheng Li ImageInfo.GpsAltRef = (char)ValuePtr[0]; 24934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 25034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 25134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case TAG_GPS_ALT: 252d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang sprintf(ImageInfo.GpsAlt + 1, "%.2fm", 253d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang ConvertAnyFormat(ValuePtr, Format)); 2541ed8197f0cefb2541f630830993e109c59ba822cWu-cheng Li ImageInfo.GpsAltRaw.num = Get32u(ValuePtr); 2551ed8197f0cefb2541f630830993e109c59ba822cWu-cheng Li ImageInfo.GpsAltRaw.denom = Get32u(4+(char *)ValuePtr); 25634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 257a39920ca4b96a456511fa32ba90c77f119a274c3Ray Chen 258a39920ca4b96a456511fa32ba90c77f119a274c3Ray Chen case TAG_GPS_TIMESTAMP: 259a39920ca4b96a456511fa32ba90c77f119a274c3Ray Chen snprintf(ImageInfo.GpsTimeStamp, 260a39920ca4b96a456511fa32ba90c77f119a274c3Ray Chen sizeof(ImageInfo.GpsTimeStamp), "%d:%d:%d", 261a39920ca4b96a456511fa32ba90c77f119a274c3Ray Chen (int) ConvertAnyFormat(ValuePtr, Format), 262a39920ca4b96a456511fa32ba90c77f119a274c3Ray Chen (int) ConvertAnyFormat(ValuePtr + 8, Format), 263a39920ca4b96a456511fa32ba90c77f119a274c3Ray Chen (int) ConvertAnyFormat(ValuePtr + 16, Format) 264a39920ca4b96a456511fa32ba90c77f119a274c3Ray Chen ); 265a39920ca4b96a456511fa32ba90c77f119a274c3Ray Chen break; 266a39920ca4b96a456511fa32ba90c77f119a274c3Ray Chen 267a39920ca4b96a456511fa32ba90c77f119a274c3Ray Chen case TAG_GPS_DATESTAMP: 268a39920ca4b96a456511fa32ba90c77f119a274c3Ray Chen strncpy(ImageInfo.GpsDateStamp, (char*)ValuePtr, sizeof(ImageInfo.GpsDateStamp)); 269a39920ca4b96a456511fa32ba90c77f119a274c3Ray Chen break; 270434623a0e87c8e145dbb46917b4ab9777475d9ebRay Chen 271434623a0e87c8e145dbb46917b4ab9777475d9ebRay Chen case TAG_GPS_PROCESSING_METHOD: 2728d61723fea0a5cdcd08e34325123fbd3e0bd41aeRay Chen if (ByteCount > EXIF_ASCII_PREFIX_LEN && 273434623a0e87c8e145dbb46917b4ab9777475d9ebRay Chen memcmp(ValuePtr, ExifAsciiPrefix, EXIF_ASCII_PREFIX_LEN) == 0) { 274434623a0e87c8e145dbb46917b4ab9777475d9ebRay Chen int length = 275434623a0e87c8e145dbb46917b4ab9777475d9ebRay Chen ByteCount < GPS_PROCESSING_METHOD_LEN + EXIF_ASCII_PREFIX_LEN ? 276434623a0e87c8e145dbb46917b4ab9777475d9ebRay Chen ByteCount - EXIF_ASCII_PREFIX_LEN : GPS_PROCESSING_METHOD_LEN; 277434623a0e87c8e145dbb46917b4ab9777475d9ebRay Chen memcpy(ImageInfo.GpsProcessingMethod, 278434623a0e87c8e145dbb46917b4ab9777475d9ebRay Chen (char*)(ValuePtr + EXIF_ASCII_PREFIX_LEN), length); 279434623a0e87c8e145dbb46917b4ab9777475d9ebRay Chen ImageInfo.GpsProcessingMethod[length] = 0; 280434623a0e87c8e145dbb46917b4ab9777475d9ebRay Chen } else { 281d282614624d8e5e6f049bff9af237a76f3b14e31Steve Block ALOGW("Unsupported encoding for GPSProcessingMethod"); 282434623a0e87c8e145dbb46917b4ab9777475d9ebRay Chen } 283434623a0e87c8e145dbb46917b4ab9777475d9ebRay Chen break; 28434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 28534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 28634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ShowTags){ 28734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Show tag value. 28834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (Tag < MAX_GPS_TAG){ 28934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf(" %s =", GpsTags[Tag].Desc); 29034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project }else{ 29134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Show unknown tag 29234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf(" Illegal GPS tag %04x=", Tag); 29334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 294d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang 29534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project switch(Format){ 29634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case FMT_UNDEFINED: 29734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Undefined is typically an ascii string. 29834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 29934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case FMT_STRING: 30034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // String arrays printed without function call (different from int arrays) 30134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project { 30234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("\""); 30334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project for (a=0;a<ByteCount;a++){ 30434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project int ZeroSkipped = 0; 30534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ValuePtr[a] >= 32){ 30634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ZeroSkipped){ 30734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("?"); 30834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ZeroSkipped = 0; 30934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 31034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project putchar(ValuePtr[a]); 31134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project }else{ 31234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ValuePtr[a] == 0){ 31334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ZeroSkipped = 1; 31434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 31534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 31634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 31734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("\"\n"); 31834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 31934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 32034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 32134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project default: 32234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Handle arrays of numbers later (will there ever be?) 32334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project for (a=0;;){ 32434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project PrintFormatNumber(ValuePtr+a*ComponentSize, Format, ByteCount); 32534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (++a >= Components) break; 32634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf(", "); 32734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 32834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("\n"); 32934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 33034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 33134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 33234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project} 33334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 334434623a0e87c8e145dbb46917b4ab9777475d9ebRay Chen 335