changeset 2801:3e9ca298bb1d

Fix #251: Crop simulation Menu option to draw a rectangle. Rectangle co-ordinates can be obtained with the remote command: --remote --get-rectangle
author Colin Clark <colin.clark@cclark.uk>
date Fri, 20 Jul 2018 17:45:10 +0100
parents 0ecd4885dc09
children 34fd30078c53
files src/icons/Makefile.am src/icons/icon_draw_rectangle.png src/image.c src/image.h src/layout_util.c src/options.h src/pixbuf-renderer.c src/pixbuf_util.c src/pixbuf_util.h src/remote.c src/toolbar.c
diffstat 11 files changed, 189 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/src/icons/Makefile.am	Thu Jul 19 10:56:46 2018 +0100
+++ b/src/icons/Makefile.am	Fri Jul 20 17:45:10 2018 +0100
@@ -32,7 +32,8 @@
 	icon_marks.png	\
 	icon_info.png	\
 	icon_sort.png	\
-	icon_pdf.png
+	icon_pdf.png	\
+	icon_draw_rectangle.png
 
 ICONS_INLINE_PAIRS = \
 	folder_closed		$(srcdir)/folder_closed.png	\
@@ -63,7 +64,8 @@
 	icon_marks	$(srcdir)/icon_marks.png	\
 	icon_info	$(srcdir)/icon_info.png	\
 	icon_sort	$(srcdir)/icon_sort.png	\
-	icon_pdf	$(srcdir)/icon_pdf.png
+	icon_pdf	$(srcdir)/icon_pdf.png \
+	icon_draw_rectangle	$(srcdir)/icon_draw_rectangle.png
 
 icons_inline.h: $(ICONS_INLINE) Makefile.in
 	@sh -ec "echo '/* Auto generated file, do not edit */'; echo; \
Binary file src/icons/icon_draw_rectangle.png has changed
--- a/src/image.c	Thu Jul 19 10:56:46 2018 +0100
+++ b/src/image.c	Fri Jul 20 17:45:10 2018 +0100
@@ -48,6 +48,14 @@
 static void image_read_ahead_start(ImageWindow *imd);
 static void image_cache_set(ImageWindow *imd, FileData *fd);
 
+// For draw rectangle function
+static gint pixbuf_start_x;
+static gint pixbuf_start_y;
+static gint image_start_x;
+static gint image_start_y;
+static gint rect_x1, rect_x2, rect_y1, rect_y2;
+static gint rect_id = 0;
+
 /*
  *-------------------------------------------------------------------
  * 'signals'
@@ -68,10 +76,92 @@
 		}
 }
 
+static void switch_coords_orientation(ImageWindow *imd, gint x, gint y, gint width, gint height)
+{
+	switch (imd->orientation)
+		{
+		case EXIF_ORIENTATION_TOP_LEFT:
+			/* normal -- nothing to do */
+			rect_x1 = image_start_x;
+			rect_y1 = image_start_y;
+			rect_x2 = x;
+			rect_y2 = y;
+			break;
+		case EXIF_ORIENTATION_TOP_RIGHT:
+			/* mirrored */
+			rect_x1 = width - x;
+			rect_y1 = image_start_y;
+			rect_x2 = width - image_start_x;
+			rect_y2 = y;
+			break;
+		case EXIF_ORIENTATION_BOTTOM_RIGHT:
+			/* upside down */
+			rect_x1 = width - x;
+			rect_y1 = height - y;
+			rect_x2 = width - image_start_x;
+			rect_y2 = height - image_start_y;
+			break;
+		case EXIF_ORIENTATION_BOTTOM_LEFT:
+			/* flipped */
+			rect_x1 = image_start_x;
+			rect_y1 = height - y;
+			rect_x2 = x;
+			rect_y2 = height - image_start_y;
+			break;
+		case EXIF_ORIENTATION_LEFT_TOP:
+			/* left mirrored */
+			rect_x1 = image_start_y;
+			rect_y1 = image_start_x;
+			rect_x2 = y;
+			rect_y2 = x;
+			break;
+		case EXIF_ORIENTATION_RIGHT_TOP:
+			/* rotated -90 (270) */
+			rect_x1 = image_start_y;
+			rect_y1 = width - x;
+			rect_x2 = y;
+			rect_y2 = width - image_start_x;
+			break;
+		case EXIF_ORIENTATION_RIGHT_BOTTOM:
+			/* right mirrored */
+			rect_x1 = height - y;
+			rect_y1 = width - x;
+			rect_x2 = height - image_start_y;
+			rect_y2 = width - image_start_x;
+			break;
+		case EXIF_ORIENTATION_LEFT_BOTTOM:
+			/* rotated 90 */
+			rect_x1 = height - y;
+			rect_y1 = image_start_x;
+			rect_x2 = height - image_start_y;
+			rect_y2 = x;
+			break;
+		default:
+			/* The other values are out of range */
+			break;
+		}
+}
+
 static void image_press_cb(PixbufRenderer *pr, GdkEventButton *event, gpointer data)
 {
 	ImageWindow *imd = data;
 	LayoutWindow *lw;
+	gint x_pixel, y_pixel;
+
+	if(options->draw_rectangle)
+		{
+		pixbuf_renderer_get_mouse_position(pr, &x_pixel, &y_pixel);
+
+		pixbuf_start_x = event->x;
+		pixbuf_start_y = event->y;
+		image_start_x = x_pixel;
+		image_start_y = y_pixel;
+		}
+
+	if (rect_id)
+		{
+		pixbuf_renderer_overlay_remove((PixbufRenderer *)imd->pr, rect_id);
+		}
 
 	lw = layout_find_by_image(imd);
 	if (lw && event->button == MOUSE_BUTTON_LEFT && event->type == GDK_2BUTTON_PRESS
@@ -86,6 +176,40 @@
 {
 	ImageWindow *imd = data;
 	gint width, height;
+	gint rect_width;
+	gint rect_height;
+	GdkPixbuf *rect_pixbuf;
+	gint x_pixel, y_pixel;
+
+	if (options->draw_rectangle)
+		{
+		pixbuf_renderer_get_image_size(pr, &width, &height);
+		pixbuf_renderer_get_mouse_position(pr, &x_pixel, &y_pixel);
+		switch_coords_orientation(imd, x_pixel, y_pixel, width, height);
+
+		if (rect_id)
+			{
+			pixbuf_renderer_overlay_remove((PixbufRenderer *)imd->pr, rect_id);
+			}
+
+		rect_width = pr->drag_last_x - pixbuf_start_x;
+		if (rect_width <= 0)
+			{
+			rect_width = 1;
+			}
+		rect_height = pr->drag_last_y - pixbuf_start_y;
+		if (rect_height <= 0)
+			{
+			rect_height = 1;
+			}
+
+		rect_pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, rect_width, rect_height);
+		pixbuf_set_rect_fill(rect_pixbuf, 0, 0, rect_width, rect_height, 255, 255, 255, 0);
+		pixbuf_set_rect(rect_pixbuf, 1, 1, rect_width-2, rect_height - 2, 0, 0, 0, 255, 1, 1, 1, 1);
+		pixbuf_set_rect(rect_pixbuf, 2, 2, rect_width-4, rect_height - 4, 255, 255, 255, 255, 1, 1, 1, 1);
+
+		rect_id = pixbuf_renderer_overlay_add((PixbufRenderer *)imd->pr, rect_pixbuf, pixbuf_start_x, pixbuf_start_y, OVL_NORMAL);
+		}
 
 	pixbuf_renderer_get_scaled_size(pr, &width, &height);
 
@@ -2024,4 +2148,13 @@
 
 	return imd;
 }
+
+void image_get_rectangle(gint *x1, gint *y1, gint *x2, gint *y2)
+{
+	*x1 = rect_x1;
+	*y1 = rect_y1;
+	*x2 = rect_x2;
+	*y2 = rect_y2;
+}
+
 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */
--- a/src/image.h	Thu Jul 19 10:56:46 2018 +0100
+++ b/src/image.h	Fri Jul 20 17:45:10 2018 +0100
@@ -150,6 +150,7 @@
 /* reset default options */
 void image_options_sync(void);
 
+void image_get_rectangle(gint *x1, gint *y1, gint *x2, gint *y2);
 
 #endif
 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */
--- a/src/layout_util.c	Thu Jul 19 10:56:46 2018 +0100
+++ b/src/layout_util.c	Fri Jul 20 17:45:10 2018 +0100
@@ -508,6 +508,13 @@
 	layout_image_reset_orientation(lw);
 }
 
+static void layout_menu_select_rectangle_cb(GtkToggleAction *action, gpointer data)
+{
+	LayoutWindow *lw = data;
+
+	options->draw_rectangle = gtk_toggle_action_get_active(action);
+}
+
 static void layout_menu_write_rotate(GtkToggleAction *action, gpointer data, gboolean keep_date)
 {
 	LayoutWindow *lw = data;
@@ -1949,6 +1956,7 @@
   { "RectangularSelection",	NULL,			N_("Rectangular Selection"),			"<alt>R",			N_("Rectangular Selection"),			CB(layout_menu_rectangular_selection_cb),	 FALSE },
   { "Animate",	NULL,	N_("GIF _animation"),		"A",			N_("Toggle GIF animation"),			CB(layout_menu_animate_cb),	 FALSE  },
   { "ExifRotate",	GTK_STOCK_ORIENTATION_PORTRAIT,			N_("_Exif rotate"),  		"<alt>X",		N_("Exif rotate"),			CB(layout_menu_exif_rotate_cb), FALSE },
+  { "DrawRectangle",	PIXBUF_INLINE_ICON_DRAW_RECTANGLE,			N_("Draw Rectangle"),  		NULL,		N_("Draw Rectangle"),			CB(layout_menu_select_rectangle_cb), FALSE },
 };
 
 static GtkRadioActionEntry menu_radio_entries[] = {
@@ -2086,6 +2094,8 @@
 "      <menuitem action='SaveMetadata'/>"
 "      <placeholder name='PropertiesSection'/>"
 "      <separator/>"
+"      <menuitem action='DrawRectangle'/>"
+"      <separator/>"
 "      <menuitem action='Preferences'/>"
 "      <menuitem action='Plugins'/>"
 "      <menuitem action='LayoutConfig'/>"
@@ -3044,6 +3054,9 @@
 	action = gtk_action_group_get_action(lw->action_group, "ExifRotate");
 	gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), options->image.exif_rotate_enable);
 
+	action = gtk_action_group_get_action(lw->action_group, "DrawRectangle");
+	gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), options->draw_rectangle);
+
 	action = gtk_action_group_get_action(lw->action_group, "RectangularSelection");
 	gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), options->collections.rectangular_selection);
 
--- a/src/options.h	Thu Jul 19 10:56:46 2018 +0100
+++ b/src/options.h	Fri Jul 20 17:45:10 2018 +0100
@@ -36,6 +36,7 @@
 	gboolean show_icon_names;
 	gboolean show_star_rating;
 	gboolean show_guidelines;
+	gboolean draw_rectangle;
 
 	/* various */
 	gboolean tree_descend_subdirs;
--- a/src/pixbuf-renderer.c	Thu Jul 19 10:56:46 2018 +0100
+++ b/src/pixbuf-renderer.c	Fri Jul 20 17:45:10 2018 +0100
@@ -2047,10 +2047,12 @@
 		accel = 1;
 		}
 
-	/* do the scroll */
-	pixbuf_renderer_scroll(pr, (pr->drag_last_x - event->x) * accel,
-			       (pr->drag_last_y - event->y) * accel);
-
+	/* do the scroll - not when drawing rectangle*/
+	if (!options->draw_rectangle)
+		{
+		pixbuf_renderer_scroll(pr, (pr->drag_last_x - event->x) * accel,
+					(pr->drag_last_y - event->y) * accel);
+		}
 	pr_drag_signal(pr, event);
 
 	pr->drag_last_x = event->x;
--- a/src/pixbuf_util.c	Thu Jul 19 10:56:46 2018 +0100
+++ b/src/pixbuf_util.c	Fri Jul 20 17:45:10 2018 +0100
@@ -131,6 +131,7 @@
 	{ PIXBUF_INLINE_ICON_INFO,	icon_info },
 	{ PIXBUF_INLINE_ICON_SORT,	icon_sort },
 	{ PIXBUF_INLINE_ICON_PDF,	icon_pdf },
+	{ PIXBUF_INLINE_ICON_DRAW_RECTANGLE,	icon_draw_rectangle },
 	{ NULL, NULL }
 };
 
--- a/src/pixbuf_util.h	Thu Jul 19 10:56:46 2018 +0100
+++ b/src/pixbuf_util.h	Fri Jul 20 17:45:10 2018 +0100
@@ -65,6 +65,7 @@
 #define PIXBUF_INLINE_ICON_INFO		"icon_info"
 #define PIXBUF_INLINE_ICON_SORT		"icon_sort"
 #define PIXBUF_INLINE_ICON_PDF		"icon_pdf"
+#define PIXBUF_INLINE_ICON_DRAW_RECTANGLE	"icon_draw_rectangle"
 
 GdkPixbuf *pixbuf_copy_rotate_90(GdkPixbuf *src, gboolean counter_clockwise);
 GdkPixbuf *pixbuf_copy_mirror(GdkPixbuf *src, gboolean mirror, gboolean flip);
--- a/src/remote.c	Thu Jul 19 10:56:46 2018 +0100
+++ b/src/remote.c	Fri Jul 20 17:45:10 2018 +0100
@@ -690,6 +690,33 @@
 		}
 }
 
+static void gr_rectangle(const gchar *text, GIOChannel *channel, gpointer data)
+{
+	gchar *rectangle_info;
+	PixbufRenderer *pr;
+	LayoutWindow *lw = NULL;
+	gint x1, y1, x2, y2;
+
+	if (!layout_valid(&lw_id)) return;
+
+	pr = (PixbufRenderer*)lw_id->image->pr;
+
+	if (pr)
+		{
+		image_get_rectangle(&x1, &y1, &x2, &y2);
+		rectangle_info = g_strdup_printf(_("%dx%d+%d+%d"),
+					(x2 > x1) ? x2 - x1 : x1 - x2,
+					(y2 > y1) ? y2 - y1 : y1 - y2,
+					(x2 > x1) ? x1 : x2,
+					(y2 > y1) ? y1 : y2);
+
+		g_io_channel_write_chars(channel, rectangle_info, -1, NULL, NULL);
+		g_io_channel_write_chars(channel, "\n", -1, NULL, NULL);
+
+		g_free(rectangle_info);
+		}
+}
+
 static void gr_file_tell(const gchar *text, GIOChannel *channel, gpointer data)
 {
 	if (!layout_valid(&lw_id)) return;
@@ -881,6 +908,7 @@
 	{ NULL, "File:",                gr_file_load_no_raise,  TRUE,  FALSE, N_("<FILE>"), N_("open FILE, do not bring Geeqie window to the top") },
 	{ NULL, "--tell",               gr_file_tell,           FALSE, FALSE, NULL, N_("print filename of current image") },
 	{ NULL, "--pixel-info",         gr_pixel_info,          FALSE, FALSE, NULL, N_("print pixel info of mouse pointer on current image") },
+	{ NULL, "--get-rectangle",      gr_rectangle,           FALSE, FALSE, NULL, N_("get rectangle co-ordinates") },
 	{ NULL, "view:",                gr_file_view,           TRUE,  FALSE, N_("<FILE>"), N_("open FILE in new window") },
 	{ NULL, "--list-clear",         gr_list_clear,          FALSE, FALSE, NULL, N_("clear command line collection list") },
 	{ NULL, "--list-add:",          gr_list_add,            TRUE,  FALSE, N_("<FILE>"), N_("add FILE to command line collection list") },
--- a/src/toolbar.c	Thu Jul 19 10:56:46 2018 +0100
+++ b/src/toolbar.c	Fri Jul 20 17:45:10 2018 +0100
@@ -112,6 +112,7 @@
 	{"Thumbnails",	N_("Show thumbnails"), PIXBUF_INLINE_ICON_THUMB},
 	{"ShowMarks",	N_("Show marks"), PIXBUF_INLINE_ICON_MARKS},
 	{"ImageGuidelines",	N_("Show guidelines"), PIXBUF_INLINE_ICON_GUIDELINES},
+	{"DrawRectangle",	N_("Draw Rectangle"), PIXBUF_INLINE_ICON_DRAW_RECTANGLE},
 	{"FloatTools",	N_("Float file list"), PIXBUF_INLINE_ICON_FLOAT},
 	{"SBar",	N_("Info sidebar"), PIXBUF_INLINE_ICON_INFO},
 	{"SBarSort",	N_("Sort manager"), PIXBUF_INLINE_ICON_SORT},