static struct LatLon get_latlon ( ExifData *ed ) { struct LatLon ll = { 0.0, 0.0 }; const struct LatLon ll0 = { 0.0, 0.0 }; gchar str[128]; ExifEntry *ee; // // Lat & Long is necessary to form a waypoint. // ee = exif_content_get_entry (ed->ifd[EXIF_IFD_GPS], EXIF_TAG_GPS_LATITUDE); if ( ! ( ee && ee->components == 3 && ee->format == EXIF_FORMAT_RATIONAL ) ) return ll0; ll.lat = Rational2Double ( ee->data, exif_format_get_size(ee->format), exif_data_get_byte_order(ed) ); ee = exif_content_get_entry (ed->ifd[EXIF_IFD_GPS], EXIF_TAG_GPS_LATITUDE_REF); if ( ee ) { exif_entry_get_value ( ee, str, 128 ); if ( str[0] == 'S' ) ll.lat = -ll.lat; } ee = exif_content_get_entry (ed->ifd[EXIF_IFD_GPS], EXIF_TAG_GPS_LONGITUDE); if ( ! ( ee && ee->components == 3 && ee->format == EXIF_FORMAT_RATIONAL ) ) return ll0; ll.lon = Rational2Double ( ee->data, exif_format_get_size(ee->format), exif_data_get_byte_order(ed) ); ee = exif_content_get_entry (ed->ifd[EXIF_IFD_GPS], EXIF_TAG_GPS_LONGITUDE_REF); if ( ee ) { exif_entry_get_value ( ee, str, 128 ); if ( str[0] == 'W' ) ll.lon = -ll.lon; } return ll; }
LocImageContainer ImageProcessor::process (QString filename) { QImage image (m_data); if (!image.isNull()) { image = image.scaled(720, 500, Qt::KeepAspectRatioByExpanding); } LocImageContainer locImageContainer(image); locImageContainer.setAltitude(3000.00); //get exif data ExifData *ed = exif_data_new_from_file (filename.toLocal8Bit().constData()); if (!ed) { locImageContainer.setLocationAvailable(false); locImageContainer.setExifDataAvailable(false); return locImageContainer; } locImageContainer.setExifDataAvailable(true); //save temp char value[256]={0,}; // Retrieve make QString make; ExifEntry *ee = exif_content_get_entry(ed->ifd[EXIF_IFD_0], EXIF_TAG_MAKE); if (!ee) { make = ""; } else { exif_entry_get_value(ee, value, sizeof(value)); locImageContainer.setMake (QString(value)); } // Retrieve model ee = exif_content_get_entry(ed->ifd[EXIF_IFD_0], EXIF_TAG_MODEL); if (!ee) { locImageContainer.setCameraModel (""); } else { exif_entry_get_value(ee, value, sizeof(value)); locImageContainer.setCameraModel ("Taken with the "+QString(value)); } // Retrieve time ee = exif_content_get_entry(ed->ifd[EXIF_IFD_EXIF], EXIF_TAG_DATE_TIME_ORIGINAL); if (!ee) { locImageContainer.setDateTaken (""); } else { exif_entry_get_value(ee, value, sizeof(value)); QString dateTime(value); QDateTime dateTaken = QDateTime::fromString (dateTime, "yyyy:MM:dd HH:mm:ss"); locImageContainer.setDateTaken (dateTaken.toString("'on 'dddd d, MMMM yyyy 'at' HH:mm")); } // Retrieve LATITUDE ee = exif_content_get_entry (ed->ifd[EXIF_IFD_GPS], (ExifTag)EXIF_TAG_GPS_LATITUDE); if (!ee) { locImageContainer.setLocationAvailable(false); locImageContainer.setLatitude(-9999.99); } else { if ( ( ee && ee->components == 3 && ee->format == EXIF_FORMAT_RATIONAL ) ) { double lat = Rational2Double ( ee->data, exif_format_get_size(ee->format), exif_data_get_byte_order(ed) ); ee = exif_content_get_entry (ed->ifd[EXIF_IFD_GPS], (ExifTag)EXIF_TAG_GPS_LATITUDE_REF); if ( ee ) { exif_entry_get_value ( ee, value, 128 ); if ( value[0] == 'S' ) lat = -lat; } locImageContainer.setLocationAvailable(true); locImageContainer.setLatitude (lat); } } ee = exif_content_get_entry (ed->ifd[EXIF_IFD_GPS], (ExifTag)EXIF_TAG_GPS_LONGITUDE); if (!ee) { locImageContainer.setLocationAvailable(false); locImageContainer.setLongitude(-9999.99); } else { if ( ( ee && ee->components == 3 && ee->format == EXIF_FORMAT_RATIONAL ) ) { double lon = Rational2Double ( ee->data, exif_format_get_size(ee->format), exif_data_get_byte_order(ed) ); ee = exif_content_get_entry (ed->ifd[EXIF_IFD_GPS], (ExifTag)EXIF_TAG_GPS_LONGITUDE_REF); if ( ee ) { exif_entry_get_value ( ee, value, 128 ); if ( value[0] == 'W' ) lon = -lon; } locImageContainer.setLocationAvailable(true); locImageContainer.setLongitude (lon); } } exif_data_free(ed); return locImageContainer; }
/** * a_geotag_create_waypoint_from_file: * @filename: The image file to process * @vcmode: The current location mode to use in the positioning of Waypoint * @name: Returns a name for the Waypoint (can be NULL) * * Returns: An allocated Waypoint or NULL if Waypoint could not be generated (e.g. no EXIF info) * */ VikWaypoint* a_geotag_create_waypoint_from_file ( const gchar *filename, VikCoordMode vcmode, gchar **name ) { // Default return values (for failures) *name = NULL; VikWaypoint *wp = NULL; // TODO use log? //ExifLog *log = NULL; // open image with libexif ExifData *ed = exif_data_new_from_file ( filename ); // Detect EXIF load failure if ( !ed ) // return with no Waypoint return wp; struct LatLon ll; gchar str[128]; ExifEntry *ee; ee = exif_content_get_entry (ed->ifd[EXIF_IFD_GPS], EXIF_TAG_GPS_VERSION_ID); // Confirm this has a GPS Id - normally "2.0.0.0" or "2.2.0.0" if ( ! ( ee && ee->components == 4 ) ) goto MyReturn; // Could test for these versions explicitly but may have byte order issues... //if ( ! ( ee->data[0] == 2 && ee->data[2] == 0 && ee->data[3] == 0 ) ) // goto MyReturn; ee = exif_content_get_entry (ed->ifd[EXIF_IFD_GPS], EXIF_TAG_GPS_MAP_DATUM); if ( ! ( ee && ee->components > 0 && ee->format == EXIF_FORMAT_ASCII ) ) goto MyReturn; // If map datum specified - only deal in WGS-84 - the defacto standard if ( ee && ee->components > 0 ) { exif_entry_get_value ( ee, str, 128 ); if ( strncmp (str, "WGS-84", 6) ) goto MyReturn; } // // Lat & Long is necessary to form a waypoint. // ee = exif_content_get_entry (ed->ifd[EXIF_IFD_GPS], EXIF_TAG_GPS_LATITUDE); if ( ! ( ee && ee->components == 3 && ee->format == EXIF_FORMAT_RATIONAL ) ) goto MyReturn; ll.lat = Rational2Double ( ee->data, exif_format_get_size(ee->format), exif_data_get_byte_order(ed) ); ee = exif_content_get_entry (ed->ifd[EXIF_IFD_GPS], EXIF_TAG_GPS_LATITUDE_REF); if ( ee ) { exif_entry_get_value ( ee, str, 128 ); if ( str[0] == 'S' ) ll.lat = -ll.lat; } ee = exif_content_get_entry (ed->ifd[EXIF_IFD_GPS], EXIF_TAG_GPS_LONGITUDE); if ( ! ( ee && ee->components == 3 && ee->format == EXIF_FORMAT_RATIONAL ) ) goto MyReturn; ll.lon = Rational2Double ( ee->data, exif_format_get_size(ee->format), exif_data_get_byte_order(ed) ); ee = exif_content_get_entry (ed->ifd[EXIF_IFD_GPS], EXIF_TAG_GPS_LONGITUDE_REF); if ( ee ) { exif_entry_get_value ( ee, str, 128 ); if ( str[0] == 'W' ) ll.lon = -ll.lon; } // // Not worried if none of the other fields exist, as can default the values to something // gdouble alt = VIK_DEFAULT_ALTITUDE; ee = exif_content_get_entry (ed->ifd[EXIF_IFD_GPS], EXIF_TAG_GPS_ALTITUDE); if ( ee && ee->components == 1 && ee->format == EXIF_FORMAT_RATIONAL ) { alt = Rational2Double ( ee->data, 0, exif_data_get_byte_order(ed) ); ee = exif_content_get_entry (ed->ifd[EXIF_IFD_GPS], EXIF_TAG_GPS_ALTITUDE_REF); if ( ee && ee->components == 1 && ee->format == EXIF_FORMAT_BYTE && ee->data[0] == 1 ) alt = -alt; } // Name ee = exif_content_get_entry (ed->ifd[EXIF_IFD_0], EXIF_TAG_XP_TITLE); if ( ee ) { exif_entry_get_value ( ee, str, 128 ); *name = g_strdup ( str ); } // // Now create Waypoint with acquired information // wp = vik_waypoint_new(); wp->visible = TRUE; // Set info from exif values // Location vik_coord_load_from_latlon ( &(wp->coord), vcmode, &ll ); // Altitude wp->altitude = alt; wp->comment = geotag_get_exif_comment ( ed ); vik_waypoint_set_image ( wp, filename ); MyReturn: // Finished with EXIF exif_data_free ( ed ); return wp; }
/** * a_geotag_create_waypoint_from_file: * @filename: The image file to process * @vcmode: The current location mode to use in the positioning of Waypoint * @name: Returns a name for the Waypoint (can be NULL) * * Returns: An allocated Waypoint or NULL if Waypoint could not be generated (e.g. no EXIF info) * */ VikWaypoint* a_geotag_create_waypoint_from_file ( const gchar *filename, VikCoordMode vcmode, gchar **name ) { // Default return values (for failures) *name = NULL; VikWaypoint *wp = NULL; #ifdef HAVE_LIBGEXIV2 GExiv2Metadata *gemd = gexiv2_metadata_new (); if ( gexiv2_metadata_open_path ( gemd, filename, NULL ) ) { gdouble lat; gdouble lon; gdouble alt; if ( gexiv2_metadata_get_gps_info ( gemd, &lon, &lat, &alt ) ) { struct LatLon ll; ll.lat = lat; ll.lon = lon; // // Now create Waypoint with acquired information // wp = vik_waypoint_new(); wp->visible = TRUE; // Set info from exif values // Location vik_coord_load_from_latlon ( &(wp->coord), vcmode, &ll ); // Altitude wp->altitude = alt; if ( gexiv2_metadata_has_tag ( gemd, "Exif.Image.XPTitle" ) ) *name = g_strdup ( gexiv2_metadata_get_tag_interpreted_string ( gemd, "Exif.Image.XPTitle" ) ); wp->comment = geotag_get_exif_comment ( gemd ); // Direction VikWaypointImageDirectionRef ref = WP_IMAGE_DIRECTION_REF_TRUE; if ( gexiv2_metadata_has_tag ( gemd, EXIF_GPS_IMGDIR_REF ) ) { gchar* ref_str = gexiv2_metadata_get_tag_interpreted_string(gemd, EXIF_GPS_IMGDIR_REF); if ( ref_str && g_ascii_strncasecmp ("M", ref_str, 1) == 0 ) ref = WP_IMAGE_DIRECTION_REF_MAGNETIC; g_free ( ref_str ); } if ( gexiv2_metadata_has_tag ( gemd, EXIF_GPS_IMGDIR ) ) { gint nom; gint den; gdouble direction = NAN; if ( gexiv2_metadata_get_exif_tag_rational (gemd, EXIF_GPS_IMGDIR, &nom, &den) ) if ( den != 0 ) direction = (gdouble)nom/(gdouble)den; if ( !isnan(direction) ) vik_waypoint_set_image_direction_info ( wp, direction, ref ); } vik_waypoint_set_image ( wp, filename ); } } metadata_free ( gemd ); #else #ifdef HAVE_LIBEXIF // TODO use log? //ExifLog *log = NULL; // open image with libexif ExifData *ed = exif_data_new_from_file ( filename ); // Detect EXIF load failure if ( !ed ) // return with no Waypoint return wp; struct LatLon ll; gchar str[128]; ExifEntry *ee; ee = exif_content_get_entry (ed->ifd[EXIF_IFD_GPS], EXIF_TAG_GPS_VERSION_ID); // Confirm this has a GPS Id - normally "2.0.0.0" or "2.2.0.0" if ( ! ( ee && ee->components == 4 ) ) goto MyReturn; // Could test for these versions explicitly but may have byte order issues... //if ( ! ( ee->data[0] == 2 && ee->data[2] == 0 && ee->data[3] == 0 ) ) // goto MyReturn; ll = get_latlon ( ed ); // Hopefully won't have valid images at 0,0! if ( ll.lat == 0.0 && ll.lon == 0.0 ) goto MyReturn; // // Not worried if none of the other fields exist, as can default the values to something // gdouble alt = VIK_DEFAULT_ALTITUDE; ee = exif_content_get_entry (ed->ifd[EXIF_IFD_GPS], EXIF_TAG_GPS_ALTITUDE); if ( ee && ee->components == 1 && ee->format == EXIF_FORMAT_RATIONAL ) { alt = Rational2Double ( ee->data, 0, exif_data_get_byte_order(ed) ); ee = exif_content_get_entry (ed->ifd[EXIF_IFD_GPS], EXIF_TAG_GPS_ALTITUDE_REF); if ( ee && ee->components == 1 && ee->format == EXIF_FORMAT_BYTE && ee->data[0] == 1 ) alt = -alt; } // Name ee = exif_content_get_entry (ed->ifd[EXIF_IFD_0], EXIF_TAG_XP_TITLE); if ( ee ) { exif_entry_get_value ( ee, str, 128 ); *name = g_strdup ( str ); } // // Now create Waypoint with acquired information // wp = vik_waypoint_new(); wp->visible = TRUE; // Set info from exif values // Location vik_coord_load_from_latlon ( &(wp->coord), vcmode, &ll ); // Altitude wp->altitude = alt; wp->comment = geotag_get_exif_comment ( ed ); vik_waypoint_set_image ( wp, filename ); MyReturn: // Finished with EXIF exif_data_free ( ed ); #endif #endif return wp; }