"Fossies" - the Fresh Open Source Software Archive

Member "jhead-3.04/gpsinfo.c" (22 Nov 2019, 7346 Bytes) of package /linux/privat/jhead-3.04.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "gpsinfo.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 3.03_vs_3.04.

    1 //--------------------------------------------------------------------------
    2 // Parsing of GPS info from exif header.
    3 //
    4 // Matthias Wandel,  Dec 1999 - Dec 2002 
    5 //--------------------------------------------------------------------------
    6 #include "jhead.h"
    7 
    8 #define MAX_GPS_TAG 0x1e
    9 
   10 
   11 #define TAG_GPS_LAT_REF    1
   12 #define TAG_GPS_LAT        2
   13 #define TAG_GPS_LONG_REF   3
   14 #define TAG_GPS_LONG       4
   15 #define TAG_GPS_ALT_REF    5
   16 #define TAG_GPS_ALT        6
   17 
   18 
   19 static const char * GpsTags[MAX_GPS_TAG+1]= {
   20     "VersionID       ",//0x00  
   21     "LatitudeRef     ",//0x01  
   22     "Latitude        ",//0x02  
   23     "LongitudeRef    ",//0x03  
   24     "Longitude       ",//0x04  
   25     "AltitudeRef     ",//0x05  
   26     "Altitude        ",//0x06  
   27     "TimeStamp       ",//0x07  
   28     "Satellites      ",//0x08  
   29     "Status          ",//0x09  
   30     "MeasureMode     ",//0x0A  
   31     "DOP             ",//0x0B  
   32     "SpeedRef        ",//0x0C  
   33     "Speed           ",//0x0D  
   34     "TrackRef        ",//0x0E  
   35     "Track           ",//0x0F  
   36     "ImgDirectionRef ",//0x10  
   37     "ImgDirection    ",//0x11  
   38     "MapDatum        ",//0x12  
   39     "DestLatitudeRef ",//0x13  
   40     "DestLatitude    ",//0x14  
   41     "DestLongitudeRef",//0x15  
   42     "DestLongitude   ",//0x16  
   43     "DestBearingRef  ",//0x17  
   44     "DestBearing     ",//0x18  
   45     "DestDistanceRef ",//0x19  
   46     "DestDistance    ",//0x1A  
   47     "ProcessingMethod",//0x1B  
   48     "AreaInformation ",//0x1C  
   49     "DateStamp       ",//0x1D  
   50     "Differential    ",//0x1E
   51 };
   52 
   53 //--------------------------------------------------------------------------
   54 // Process GPS info directory
   55 //--------------------------------------------------------------------------
   56 void ProcessGpsInfo(unsigned char * DirStart, unsigned char * OffsetBase, unsigned ExifLength)
   57 {
   58     int de;
   59     unsigned a;
   60     int NumDirEntries;
   61 
   62     NumDirEntries = Get16u(DirStart);
   63     #define DIR_ENTRY_ADDR(Start, Entry) (Start+2+12*(Entry))
   64 
   65     if (ShowTags){
   66         printf("(dir has %d entries)\n",NumDirEntries);
   67     }
   68 
   69     ImageInfo.GpsInfoPresent = TRUE;
   70     strcpy(ImageInfo.GpsLat, "? ?");
   71     strcpy(ImageInfo.GpsLong, "? ?");
   72     ImageInfo.GpsAlt[0] = 0; 
   73 
   74     for (de=0;de<NumDirEntries;de++){
   75         unsigned Tag, Format, Components;
   76         unsigned char * ValuePtr;
   77         int ComponentSize;
   78         unsigned ByteCount;
   79         unsigned char * DirEntry;
   80         DirEntry = DIR_ENTRY_ADDR(DirStart, de);
   81 
   82         if (DirEntry+12 > OffsetBase+ExifLength){
   83             ErrNonfatal("GPS info directory goes past end of exif",0,0);
   84             return;
   85         }
   86 
   87         Tag = Get16u(DirEntry);
   88         Format = Get16u(DirEntry+2);
   89         Components = Get32u(DirEntry+4);
   90 
   91         if ((Format-1) >= NUM_FORMATS) {
   92             // (-1) catches illegal zero case as unsigned underflows to positive large.
   93             ErrNonfatal("Illegal number format %d for Exif gps tag %04x", Format, Tag);
   94             continue;
   95         }
   96 
   97         ComponentSize = BytesPerFormat[Format];
   98         ByteCount = Components * ComponentSize;
   99 
  100         if (ByteCount > 4){
  101             unsigned OffsetVal;
  102             OffsetVal = Get32u(DirEntry+8);
  103             // If its bigger than 4 bytes, the dir entry contains an offset.
  104             if (OffsetVal > 0x1000000 || OffsetVal+ByteCount > ExifLength){
  105                 // Max exif in jpeg is 64k, so any offset bigger than that is bogus.
  106                 // Bogus pointer offset and / or bytecount value
  107                 ErrNonfatal("Illegal value pointer for Exif gps tag %04x", Tag,0);
  108                 continue;
  109             }
  110             ValuePtr = OffsetBase+OffsetVal;
  111         }else{
  112             // 4 bytes or less and value is in the dir entry itself
  113             ValuePtr = DirEntry+8;
  114         }
  115 
  116         switch(Tag){
  117             char FmtString[21];
  118             char TempString[50];
  119             double Values[3];
  120 
  121             case TAG_GPS_LAT_REF:
  122                 ImageInfo.GpsLat[0] = ValuePtr[0];
  123                 break;
  124 
  125             case TAG_GPS_LONG_REF:
  126                 ImageInfo.GpsLong[0] = ValuePtr[0];
  127                 break;
  128 
  129             case TAG_GPS_LAT:
  130             case TAG_GPS_LONG:
  131                 if (Format != FMT_URATIONAL){
  132                     ErrNonfatal("Inappropriate format (%d) for Exif GPS coordinates!", Format, 0);
  133                 }
  134                 strcpy(FmtString, "%0.0fd %0.0fm %0.0fs");
  135                 for (a=0;a<3;a++){
  136                     int den, digits;
  137 
  138                     den = Get32s(ValuePtr+4+a*ComponentSize);
  139                     digits = 0;
  140                     while (den > 1 && digits <= 6){
  141                         den = den / 10;
  142                         digits += 1;
  143                     }
  144                     if (digits > 6) digits = 6;
  145                     FmtString[1+a*7] = (char)('2'+digits+(digits ? 1 : 0));
  146                     FmtString[3+a*7] = (char)('0'+digits);
  147 
  148                     Values[a] = ConvertAnyFormat(ValuePtr+a*ComponentSize, Format);
  149                 }
  150 
  151                 snprintf(TempString, sizeof(TempString), FmtString, Values[0], Values[1], Values[2]);
  152 
  153                 if (Tag == TAG_GPS_LAT){
  154                     strncpy(ImageInfo.GpsLat+2, TempString, 29);
  155                 }else{
  156                     strncpy(ImageInfo.GpsLong+2, TempString, 29);
  157                 }
  158                 break;
  159 
  160             case TAG_GPS_ALT_REF:
  161                 ImageInfo.GpsAlt[0] = (char)(ValuePtr[0] ? '-' : ' ');
  162                 break;
  163 
  164             case TAG_GPS_ALT:
  165                 snprintf(ImageInfo.GpsAlt+1, sizeof(ImageInfo.GpsAlt)-1,
  166                     "%.2fm", ConvertAnyFormat(ValuePtr, Format));
  167                 break;
  168         }
  169 
  170         if (ShowTags){
  171             // Show tag value.
  172             if (Tag < MAX_GPS_TAG){
  173                 printf("        GPS%s =", GpsTags[Tag]);
  174             }else{
  175                 // Show unknown tag
  176                 printf("        Illegal GPS tag %04x=", Tag);
  177             }
  178 
  179             switch(Format){
  180                 case FMT_UNDEFINED:
  181                     // Undefined is typically an ascii string.
  182 
  183                 case FMT_STRING:
  184                     // String arrays printed without function call (different from int arrays)
  185                     {
  186                         printf("\"");
  187                         for (a=0;a<ByteCount;a++){
  188                             int ZeroSkipped = 0;
  189                             if (ValuePtr[a] >= 32){
  190                                 if (ZeroSkipped){
  191                                     printf("?");
  192                                     ZeroSkipped = 0;
  193                                 }
  194                                 putchar(ValuePtr[a]);
  195                             }else{
  196                                 if (ValuePtr[a] == 0){
  197                                     ZeroSkipped = 1;
  198                                 }
  199                             }
  200                         }
  201                         printf("\"\n");
  202                     }
  203                     break;
  204 
  205                 default:
  206                     // Handle arrays of numbers later (will there ever be?)
  207                     for (a=0;;){
  208                         PrintFormatNumber(ValuePtr+a*ComponentSize, Format, ByteCount);
  209                         if (++a >= Components) break;
  210                         printf(", ");
  211                     }
  212                     printf("\n");
  213             }
  214         }
  215     }
  216 }
  217 
  218