changeset 2385:a7a8cacff188

Map image direction If an image has a valid Exif.GPSInfo.GPSImgDirection tag, and the icon on the map is clicked, a line showing camera direction is displayed also.
author Colin Clark <cclark@mcb.net>
date Wed, 24 Aug 2016 17:19:04 +0100
parents 82d8d3deae03
children a22a815359f9
files src/bar_gps.c src/metadata.c src/metadata.h
diffstat 3 files changed, 109 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- a/src/bar_gps.c	Wed Aug 24 17:01:32 2016 +0100
+++ b/src/bar_gps.c	Wed Aug 24 17:19:04 2016 +0100
@@ -43,6 +43,8 @@
 #define THUMB_COLOUR 0xff, 0xff, 0xff, 0xff
 #define THUMB_SIZE 100
 
+#define DIRECTION_SIZE 300
+
 /*
  *-------------------------------------------------------------------
  * GPS Map utils
@@ -72,6 +74,20 @@
 	gboolean enable_markers_checked;
 };
 
+static gboolean bar_gps_draw_direction (ClutterCanvas *canvas,
+				cairo_t *cr, gpointer data)
+{
+	cairo_set_source_rgb(cr, 255, 0, 0);
+
+	cairo_set_line_width(cr, 2);
+	cairo_move_to(cr, 0, 1);
+	cairo_line_to(cr, DIRECTION_SIZE, 1);
+
+	cairo_stroke(cr);
+
+	return TRUE;
+}
+
 static void bar_pane_gps_thumb_done_cb(ThumbLoader *tl, gpointer data)
 {
 	FileData *fd;
@@ -98,12 +114,12 @@
 {
 	//PaneGPSData *pgd = data;
 	FileData *fd;
-	ClutterActor *marker;
+	ClutterActor *label_marker, *parent_marker;
 	ClutterColor marker_colour = { MARKER_COLOUR };
 	ClutterColor text_colour = { TEXT_COLOUR };
 	ClutterColor thumb_colour = { THUMB_COLOUR };
 	gchar *current_text;
-	ClutterActor *actor;
+	ClutterActor *actor, *direction;
 	ClutterActor *current_image;
 	GString *text;
 	gint height, width, rotate;
@@ -112,19 +128,19 @@
 
 	if (bevent->button == MOUSE_BUTTON_LEFT)
 		{
-		marker = CLUTTER_ACTOR(widget);
-		fd = g_object_get_data(G_OBJECT(marker), "file_fd");
+		label_marker = CLUTTER_ACTOR(widget);
+		fd = g_object_get_data(G_OBJECT(label_marker), "file_fd");
 
 		/* If the marker is showing a thumbnail, delete it
 		 */
-		current_image = champlain_label_get_image(CHAMPLAIN_LABEL(marker));
+		current_image = champlain_label_get_image(CHAMPLAIN_LABEL(label_marker));
 		if (current_image != NULL)
 			{
 			clutter_actor_destroy(CLUTTER_ACTOR(current_image));
-		 	champlain_label_set_image(CHAMPLAIN_LABEL(marker), NULL);
+		 	champlain_label_set_image(CHAMPLAIN_LABEL(label_marker), NULL);
 			}
 
-		current_text = g_strdup(champlain_label_get_text(CHAMPLAIN_LABEL(marker)));
+		current_text = g_strdup(champlain_label_get_text(CHAMPLAIN_LABEL(label_marker)));
 
 		/* If the marker is showing only the text character, replace it with a
 		 * thumbnail and date and altitude
@@ -139,7 +155,7 @@
 				{
 				actor = gtk_clutter_texture_new();
 				gtk_clutter_texture_set_from_pixbuf(GTK_CLUTTER_TEXTURE(actor), fd->thumb_pixbuf, NULL);
-				champlain_label_set_image(CHAMPLAIN_LABEL(marker), actor);
+				champlain_label_set_image(CHAMPLAIN_LABEL(label_marker), actor);
 				}
 			else if (fd->pixbuf != NULL)
 				{
@@ -164,7 +180,7 @@
 					gtk_clutter_texture_set_from_pixbuf(GTK_CLUTTER_TEXTURE(actor),
 										gdk_pixbuf_rotate_simple(gdk_pixbuf_scale_simple(fd->pixbuf, THUMB_SIZE, height * THUMB_SIZE / width,
 										GDK_INTERP_NEAREST), rotate), NULL);
-					champlain_label_set_image(CHAMPLAIN_LABEL(marker), actor);
+					champlain_label_set_image(CHAMPLAIN_LABEL(label_marker), actor);
 				}
 			else
 				{
@@ -173,7 +189,7 @@
 											bar_pane_gps_thumb_done_cb,
 											bar_pane_gps_thumb_error_cb,
 											NULL,
-											marker);
+											label_marker);
 				thumb_loader_start(tl, fd);
 				}
 
@@ -187,22 +203,30 @@
 				g_string_append(text, altitude);
 				}
 
-			champlain_label_set_text(CHAMPLAIN_LABEL(marker), text->str);
-			champlain_label_set_color(CHAMPLAIN_LABEL(marker), &thumb_colour);
-			champlain_label_set_text_color(CHAMPLAIN_LABEL(marker), &text_colour);
-			champlain_label_set_font_name(CHAMPLAIN_LABEL(marker), "sans 8");
+			champlain_label_set_text(CHAMPLAIN_LABEL(label_marker), text->str);
+			champlain_label_set_font_name(CHAMPLAIN_LABEL(label_marker), "sans 8");
+			champlain_marker_set_selection_color(&thumb_colour);
+			champlain_marker_set_selection_text_color(&text_colour);
 
 			g_free(altitude);
 			g_string_free(text, TRUE);
+
+			parent_marker = clutter_actor_get_parent(label_marker);
+			direction = clutter_actor_get_child_at_index(parent_marker, 0);
+			clutter_actor_set_opacity(direction, 255);
 			}
 		/* otherwise, revert to the hidden text marker
 		 */
 		else
 			{
-			champlain_label_set_text(CHAMPLAIN_LABEL(marker), "i");
-			champlain_label_set_color(CHAMPLAIN_LABEL(marker), &marker_colour);
-			champlain_label_set_text_color(CHAMPLAIN_LABEL(marker), &marker_colour);
-			champlain_label_set_font_name(CHAMPLAIN_LABEL(marker), "courier 5");
+			champlain_label_set_text(CHAMPLAIN_LABEL(label_marker), "i");
+			champlain_label_set_font_name(CHAMPLAIN_LABEL(label_marker), "courier 5");
+			champlain_marker_set_selection_color(&marker_colour);
+			champlain_marker_set_selection_text_color(&marker_colour);
+
+			parent_marker = clutter_actor_get_parent(label_marker);
+			direction = clutter_actor_get_child_at_index(parent_marker, 0);
+			clutter_actor_set_opacity(direction, 0);
 			}
 
 		g_free(current_text);
@@ -217,10 +241,14 @@
 	PaneGPSData *pgd = data;
 	gdouble latitude;
 	gdouble longitude;
-	ClutterActor *marker;
+	gdouble compass;
 	FileData *fd;
+	ClutterActor *parent_marker, *label_marker;
+	ClutterActor *direction;
 	ClutterColor marker_colour = { MARKER_COLOUR };
+	ClutterColor thumb_colour = { THUMB_COLOUR };
 	GString *message;
+	ClutterContent *canvas;
 
 	gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(pgd->progress),
 							(gdouble)(pgd->selection_count - g_list_length(pgd->not_added)) /
@@ -239,23 +267,47 @@
 
 		latitude = metadata_read_GPS_coord(fd, "Xmp.exif.GPSLatitude", 0);
 		longitude = metadata_read_GPS_coord(fd, "Xmp.exif.GPSLongitude", 0);
+		compass = metadata_read_GPS_direction(fd, "Xmp.exif.GPSImgDirection", 1000);
 
 		if (!(latitude == 0 && longitude == 0))
 			{
 			pgd->num_added++;
 
-			marker = champlain_label_new_with_text("i","courier 5", &marker_colour, &marker_colour);
+			parent_marker = champlain_marker_new();
+			clutter_actor_set_reactive(parent_marker, FALSE);
+			label_marker = champlain_label_new_with_text("i","courier 5", &marker_colour, &marker_colour);
+			clutter_actor_set_reactive(label_marker, TRUE);
+			champlain_marker_set_selection_color(&thumb_colour);
 
-			champlain_location_set_location(CHAMPLAIN_LOCATION(marker), latitude, longitude);
-			champlain_marker_layer_add_marker(pgd->icon_layer, CHAMPLAIN_MARKER(marker));
-			clutter_actor_set_reactive(marker, TRUE);
+			if (compass != 1000)
+				{
+				canvas = clutter_canvas_new();
+				clutter_canvas_set_size(CLUTTER_CANVAS (canvas), DIRECTION_SIZE, 3);
+				g_signal_connect(canvas, "draw", G_CALLBACK(bar_gps_draw_direction), NULL);
+				direction = clutter_actor_new();
+				clutter_actor_set_size(direction, DIRECTION_SIZE, 3);
+				clutter_actor_set_position(direction, 0, 0);
+				clutter_actor_set_rotation_angle(direction, CLUTTER_Z_AXIS, compass -90.00);
+				clutter_actor_set_content(direction, canvas);
+				clutter_content_invalidate(canvas);
+				g_object_unref(canvas);
 
-			g_signal_connect(G_OBJECT(marker), "button_release_event",
+				clutter_actor_add_child(parent_marker, direction);
+				clutter_actor_set_opacity(direction, 0);
+				}
+
+			clutter_actor_add_child(parent_marker, label_marker);
+
+			champlain_location_set_location(CHAMPLAIN_LOCATION(parent_marker), latitude, longitude);
+			champlain_marker_layer_add_marker(pgd->icon_layer, CHAMPLAIN_MARKER(parent_marker));
+
+			g_signal_connect(G_OBJECT(label_marker), "button_release_event",
 	 				G_CALLBACK(bar_pane_gps_marker_keypress_cb), pgd);
 
-			g_object_set_data(G_OBJECT(marker), "file_fd", fd);
+			g_object_set_data(G_OBJECT(label_marker), "file_fd", fd);
 
 			champlain_bounding_box_extend(pgd->bbox, latitude, longitude);
+
 			}
 		return TRUE;
 		}
--- a/src/metadata.c	Wed Aug 24 17:01:32 2016 +0100
+++ b/src/metadata.c	Wed Aug 24 17:19:04 2016 +0100
@@ -784,6 +784,37 @@
 	return coord;
 }
 
+gdouble metadata_read_GPS_direction(FileData *fd, const gchar *key, gdouble fallback)
+{
+	gchar *endptr;
+	gdouble deg;
+	gboolean ok = FALSE;
+	gchar *string = metadata_read_string(fd, key, METADATA_PLAIN);
+	if (!string) return fallback;
+
+	DEBUG_3("GPS_direction: %s\n", string);
+	deg = g_ascii_strtod(string, &endptr);
+
+	/* Expected text string is of the format e.g.:
+	 * 18000/100
+	 */
+	if (*endptr == '/')
+		{
+		deg = deg/100;
+		ok = TRUE;
+		}
+
+	if (!ok)
+		{
+		deg = fallback;
+		log_printf("unable to parse GPS direction '%s: %f'\n", string, deg);
+		}
+
+	g_free(string);
+
+	return deg;
+}
+
 gboolean metadata_append_string(FileData *fd, const gchar *key, const char *value)
 {
 	gchar *str = metadata_read_string(fd, key, METADATA_PLAIN);
--- a/src/metadata.h	Wed Aug 24 17:01:32 2016 +0100
+++ b/src/metadata.h	Wed Aug 24 17:19:04 2016 +0100
@@ -45,6 +45,7 @@
 gchar *metadata_read_string(FileData *fd, const gchar *key, MetadataFormat format);
 guint64 metadata_read_int(FileData *fd, const gchar *key, guint64 fallback);
 gdouble metadata_read_GPS_coord(FileData *fd, const gchar *key, gdouble fallback);
+gdouble metadata_read_GPS_direction(FileData *fd, const gchar *key, gdouble fallback);
 
 gboolean metadata_append_string(FileData *fd, const gchar *key, const char *value);
 gboolean metadata_append_list(FileData *fd, const gchar *key, const GList *values);