Fix #251: Crop simulation
authorColin Clark <colin.clark@cclark.uk>
Fri, 20 Jul 2018 16:45:10 +0000 (17:45 +0100)
committerColin Clark <colin.clark@cclark.uk>
Fri, 20 Jul 2018 16:45:10 +0000 (17:45 +0100)
Menu option to draw a rectangle.
Rectangle co-ordinates can be obtained with the remote command:
--remote --get-rectangle

src/icons/Makefile.am
src/icons/icon_draw_rectangle.png [new file with mode: 0644]
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

index bd71013..0e6efe9 100644 (file)
@@ -32,7 +32,8 @@ ICONS_INLINE = \
        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 @@ ICONS_INLINE_PAIRS = \
        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; \
diff --git a/src/icons/icon_draw_rectangle.png b/src/icons/icon_draw_rectangle.png
new file mode 100644 (file)
index 0000000..d7da8f3
Binary files /dev/null and b/src/icons/icon_draw_rectangle.png differ
index c84e818..ffe36cf 100644 (file)
@@ -48,6 +48,14 @@ static void image_update_title(ImageWindow *imd);
 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 image_click_cb(PixbufRenderer *pr, GdkEventButton *event, gpointer d
                }
 }
 
+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 @@ static void image_drag_cb(PixbufRenderer *pr, GdkEventMotion *event, gpointer da
 {
        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 @@ ImageWindow *image_new(gboolean frame)
 
        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: */
index 00e90dd..f3c48cb 100644 (file)
@@ -150,6 +150,7 @@ void image_set_image_as_tiles(ImageWindow *imd, gint width, gint height,
 /* 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: */
index 396fc25..993794c 100644 (file)
@@ -508,6 +508,13 @@ static void layout_menu_exif_rotate_cb(GtkToggleAction *action, gpointer data)
        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 @@ static GtkToggleActionEntry menu_toggle_entries[] = {
   { "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 @@ static const gchar *menu_ui_description =
 "      <menuitem action='SaveMetadata'/>"
 "      <placeholder name='PropertiesSection'/>"
 "      <separator/>"
+"      <menuitem action='DrawRectangle'/>"
+"      <separator/>"
 "      <menuitem action='Preferences'/>"
 "      <menuitem action='Plugins'/>"
 "      <menuitem action='LayoutConfig'/>"
@@ -3044,6 +3054,9 @@ static void layout_util_sync_views(LayoutWindow *lw)
        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);
 
index abaf8b2..2a94f39 100644 (file)
@@ -36,6 +36,7 @@ struct _ConfOptions
        gboolean show_icon_names;
        gboolean show_star_rating;
        gboolean show_guidelines;
+       gboolean draw_rectangle;
 
        /* various */
        gboolean tree_descend_subdirs;
index 9c3cb1c..12756be 100644 (file)
@@ -2047,10 +2047,12 @@ static gboolean pr_mouse_motion_cb(GtkWidget *widget, GdkEventMotion *event, gpo
                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;
index 9b10376..3c69fa9 100644 (file)
@@ -131,6 +131,7 @@ static PixbufInline inline_pixbuf_data[] = {
        { 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 }
 };
 
index d033464..145224e 100644 (file)
@@ -65,6 +65,7 @@ gboolean pixbuf_scale_aspect(gint req_w, gint req_h, gint old_w, gint old_h, gin
 #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);
index 4324575..f5c58e5 100644 (file)
@@ -690,6 +690,33 @@ static void gr_pixel_info(const gchar *text, GIOChannel *channel, gpointer data)
                }
 }
 
+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 @@ static RemoteCommandEntry remote_commands[] = {
        { 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") },
index edf8624..4c22cac 100644 (file)
@@ -112,6 +112,7 @@ static const UseableToolbarItems useable_toolbar_items[] = {
        {"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},