[Rawstudio-commit] r869 - trunk/src
Anders Brander
anders at brander.dk
Tue Oct 17 22:55:09 CEST 2006
Author: abrander
Date: 2006-10-17 22:55:09 +0200 (Tue, 17 Oct 2006)
New Revision: 869
Modified:
trunk/src/drawingarea.c
trunk/src/gtk-interface.c
trunk/src/rawstudio.c
trunk/src/rawstudio.h
trunk/src/toolbox.c
Log:
Added GUI for crop.
Modified: trunk/src/drawingarea.c
===================================================================
--- trunk/src/drawingarea.c 2006-10-17 20:07:58 UTC (rev 868)
+++ trunk/src/drawingarea.c 2006-10-17 20:55:09 UTC (rev 869)
@@ -23,17 +23,67 @@
#include "rawstudio.h"
#include "color.h"
#include "gtk-interface.h"
+#include "gtk-helper.h"
#include "conf_interface.h"
+#include "rs-image.h"
static gint start_x, start_y;
+static void draw_region_crop(RS_BLOB *rs, RS_RECT *region);
static gboolean drawingarea_expose (GtkWidget *widget, GdkEventExpose *event, RS_BLOB *rs);
static gboolean drawingarea_configure (GtkWidget *widget, GdkEventExpose *event, RS_BLOB *rs);
static gboolean gui_drawingarea_move_callback(GtkWidget *widget, GdkEventMotion *event, RS_BLOB *rs);
static gboolean gui_drawingarea_button(GtkWidget *widget, GdkEventButton *event, RS_BLOB *rs);
+static GdkPixmap *blitter = NULL;
+
+static void
+draw_region_crop(RS_BLOB *rs, RS_RECT *region)
+{
+ /* FIXME: This is so fucking unbelievable slow! */
+ gdk_draw_drawable(blitter,
+ rs->preview_drawingarea->style->fg_gc[GTK_WIDGET_STATE (rs->preview_drawingarea)],
+ rs->preview_backing_crop,
+ rs->preview_exposed->x1, rs->preview_exposed->y1,
+ rs->preview_exposed->x1, rs->preview_exposed->y1,
+ rs->preview_exposed->x2-rs->preview_exposed->x1,
+ rs->preview_exposed->y2-rs->preview_exposed->y1);
+ gdk_draw_drawable(blitter, /* FIXME: backing store may not be ready? */
+ rs->preview_drawingarea->style->fg_gc[GTK_WIDGET_STATE (rs->preview_drawingarea)],
+ rs->preview_backing,
+ rs->roi_scaled.x1, rs->roi_scaled.y1,
+ rs->roi_scaled.x1, rs->roi_scaled.y1,
+ rs->roi_scaled.x2-rs->roi_scaled.x1, rs->roi_scaled.y2-rs->roi_scaled.y1);
+ gdk_draw_line(blitter,
+ rs->preview_drawingarea->style->fg_gc[GTK_WIDGET_STATE (rs->preview_drawingarea)],
+ rs->roi_scaled.x1, rs->roi_scaled.y1,
+ rs->roi_scaled.x2, rs->roi_scaled.y1);
+ gdk_draw_line(blitter,
+ rs->preview_drawingarea->style->fg_gc[GTK_WIDGET_STATE (rs->preview_drawingarea)],
+ rs->roi_scaled.x2, rs->roi_scaled.y1,
+ rs->roi_scaled.x2, rs->roi_scaled.y2);
+ gdk_draw_line(blitter,
+ rs->preview_drawingarea->style->fg_gc[GTK_WIDGET_STATE (rs->preview_drawingarea)],
+ rs->roi_scaled.x2, rs->roi_scaled.y2,
+ rs->roi_scaled.x1, rs->roi_scaled.y2);
+ gdk_draw_line(blitter,
+ rs->preview_drawingarea->style->fg_gc[GTK_WIDGET_STATE (rs->preview_drawingarea)],
+ rs->roi_scaled.x1, rs->roi_scaled.y2,
+ rs->roi_scaled.x1, rs->roi_scaled.y1);
+ /* blit to screen */
+ gdk_draw_drawable(rs->preview_drawingarea->window,
+ rs->preview_drawingarea->style->fg_gc[GTK_WIDGET_STATE (rs->preview_drawingarea)],
+ blitter,
+ rs->preview_exposed->x1, rs->preview_exposed->y1,
+ rs->preview_exposed->x1, rs->preview_exposed->y1,
+ rs->preview_exposed->x2-rs->preview_exposed->x1,
+ rs->preview_exposed->y2-rs->preview_exposed->y1);
+ return;
+}
+
gboolean
drawingarea_expose (GtkWidget *widget, GdkEventExpose *event, RS_BLOB *rs)
{
+ extern gint state;
GtkAdjustment *vadj;
GtkAdjustment *hadj;
vadj = gtk_viewport_get_vadjustment((GtkViewport *) widget->parent->parent);
@@ -42,26 +92,46 @@
rs->preview_exposed->y1 = (gint) vadj->value;
rs->preview_exposed->x2 = ((gint) hadj->page_size)+rs->preview_exposed->x1;
rs->preview_exposed->y2 = ((gint) vadj->page_size)+rs->preview_exposed->y1;
- if (rs->preview_done)
- gdk_draw_drawable(widget->window, widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
- rs->preview_backing,
- event->area.x, event->area.y,
- event->area.x, event->area.y,
- event->area.width, event->area.height);
- else
- update_preview_region(rs, rs->preview_exposed);
+ switch (state)
+ {
+ case STATE_NORMAL:
+ if (rs->preview_done)
+ gdk_draw_drawable(widget->window, widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
+ rs->preview_backing,
+ event->area.x, event->area.y,
+ event->area.x, event->area.y,
+ event->area.width, event->area.height);
+ else
+ update_preview_region(rs, rs->preview_exposed);
+ default:
+ update_preview_region(rs, rs->preview_exposed);
+ break;
+ }
return(TRUE);
}
gboolean
drawingarea_configure (GtkWidget *widget, GdkEventExpose *event, RS_BLOB *rs)
{
+ extern gint state;
if (rs->preview_backing)
g_object_unref(rs->preview_backing);
rs->preview_backing = gdk_pixmap_new(widget->window,
widget->allocation.width,
widget->allocation.height, -1);
- update_preview(rs, TRUE); /* evil hack to catch bogus configure events */
+ if (blitter)
+ g_object_unref(blitter);
+ blitter = gdk_pixmap_new(widget->window,
+ widget->allocation.width,
+ widget->allocation.height, -1);
+ if (state==STATE_CROP) /* is this the only state where we can expect configure? */
+ {
+ g_object_unref(rs->preview_backing_crop);
+ rs->preview_backing_crop = gdk_pixmap_new(widget->window,
+ widget->allocation.width,
+ widget->allocation.height, -1);
+ }
+ update_preview(rs, TRUE, FALSE); /* evil hack to catch bogus configure events */
return(TRUE);
}
@@ -106,64 +176,283 @@
}
gboolean
-gui_drawingarea_button(GtkWidget *widget, GdkEventButton *event, RS_BLOB *rs)
+gui_drawingarea_crop_motion_callback(GtkWidget *widget, GdkEventMotion *event, RS_BLOB *rs)
{
- static GdkCursor *cursor;
- static gint operation = OP_NONE;
- static gint signal;
+ extern gint state;
gint x,y;
+ static RS_RECT last = {0,0,0,0};
+ RS_RECT region;
x = (gint) event->x;
y = (gint) event->y;
- if (event->type == GDK_BUTTON_PRESS)
- { /* start */
- switch(event->button)
+ switch (state)
+ {
+ case STATE_CROP_MOVE_N:
+ rs->roi_scaled.y1 = y;
+ break;
+ case STATE_CROP_MOVE_E:
+ rs->roi_scaled.x2 = x;
+ break;
+ case STATE_CROP_MOVE_S:
+ rs->roi_scaled.y2 = y;
+ break;
+ case STATE_CROP_MOVE_W:
+ rs->roi_scaled.x1 = x;
+ break;
+ case STATE_CROP_MOVE_NW:
+ rs->roi_scaled.x1 = x;
+ rs->roi_scaled.y1 = y;
+ break;
+ case STATE_CROP_MOVE_NE:
+ rs->roi_scaled.x2 = x;
+ rs->roi_scaled.y1 = y;
+ break;
+ case STATE_CROP_MOVE_SE:
+ rs->roi_scaled.x2 = x;
+ rs->roi_scaled.y2 = y;
+ break;
+ case STATE_CROP_MOVE_SW:
+ rs->roi_scaled.x1 = x;
+ rs->roi_scaled.y2 = y;
+ break;
+ }
+ if (rs->roi_scaled.x1 < 0)
+ rs->roi_scaled.x1 = 0;
+ if (rs->roi_scaled.x2 < 0)
+ rs->roi_scaled.x2 = 0;
+ if (rs->roi_scaled.y1 < 0)
+ rs->roi_scaled.y1 = 0;
+ if (rs->roi_scaled.y2 < 0)
+ rs->roi_scaled.y2 = 0;
+
+ if (rs->roi_scaled.x1 > rs->photo->preview->w)
+ rs->roi_scaled.x1 = rs->photo->preview->w-1;
+ if (rs->roi_scaled.x2 > rs->photo->preview->w)
+ rs->roi_scaled.x2 = rs->photo->preview->w-1;
+ if (rs->roi_scaled.y1 > rs->photo->preview->h)
+ rs->roi_scaled.y1 = rs->photo->preview->h-1;
+ if (rs->roi_scaled.y2 > rs->photo->preview->h)
+ rs->roi_scaled.y2 = rs->photo->preview->h-1;
+
+ if (rs->roi_scaled.x1 > rs->roi_scaled.x2)
+ {
+ SWAP(rs->roi_scaled.x1, rs->roi_scaled.x2);
+ switch (state)
{
- case 1:
- rs_set_wb_from_pixels(rs, x, y);
+ case STATE_CROP_MOVE_E:
+ state = STATE_CROP_MOVE_W;
break;
- case 2:
- if (!gui_is_busy())
- {
- operation = OP_MOVE;
- cursor = gdk_cursor_new(GDK_FLEUR);
- gdk_window_set_cursor(rs->preview_drawingarea->window, cursor);
- start_x = (gint) event->x_root;
- start_y = (gint) event->y_root;
- signal = g_signal_connect (G_OBJECT (rs->preview_drawingarea), "motion_notify_event",
- G_CALLBACK (gui_drawingarea_move_callback), rs);
- }
- else
- {
- operation = OP_BUSY;
- cursor = gdk_cursor_new(GDK_WATCH);
- gdk_window_set_cursor(rs->preview_drawingarea->window, cursor);
- }
+ case STATE_CROP_MOVE_W:
+ state = STATE_CROP_MOVE_E;
break;
+ case STATE_CROP_MOVE_NW:
+ state = STATE_CROP_MOVE_NE;
+ break;
+ case STATE_CROP_MOVE_NE:
+ state = STATE_CROP_MOVE_NW;
+ break;
+ case STATE_CROP_MOVE_SW:
+ state = STATE_CROP_MOVE_SE;
+ break;
+ case STATE_CROP_MOVE_SE:
+ state = STATE_CROP_MOVE_SW;
+ break;
}
}
- else
- { /* end */
- switch(operation)
+ if (rs->roi_scaled.y1 > rs->roi_scaled.y2)
+ {
+ SWAP(rs->roi_scaled.y1, rs->roi_scaled.y2);
+ switch (state)
{
- case OP_MOVE:
- g_signal_handler_disconnect(rs->preview_drawingarea, signal);
- update_preview_region(rs, rs->preview_exposed);
- gdk_window_set_cursor(rs->preview_drawingarea->window, NULL);
- gdk_cursor_unref(cursor);
- operation = OP_NONE;
+ case STATE_CROP_MOVE_N:
+ state = STATE_CROP_MOVE_S;
break;
- case OP_BUSY:
- gdk_window_set_cursor(rs->preview_drawingarea->window, NULL);
- gdk_cursor_unref(cursor);
- operation = OP_NONE;
+ case STATE_CROP_MOVE_S:
+ state = STATE_CROP_MOVE_N;
break;
+ case STATE_CROP_MOVE_NW:
+ state = STATE_CROP_MOVE_SW;
+ break;
+ case STATE_CROP_MOVE_NE:
+ state = STATE_CROP_MOVE_SE;
+ break;
+ case STATE_CROP_MOVE_SW:
+ state = STATE_CROP_MOVE_NW;
+ break;
+ case STATE_CROP_MOVE_SE:
+ state = STATE_CROP_MOVE_NE;
+ break;
}
}
+ region.x1 = (rs->roi_scaled.x1 < last.x1) ? rs->roi_scaled.x1 : last.x1;
+ region.x2 = (rs->roi_scaled.x2 > last.x2) ? rs->roi_scaled.x2 : last.x2;
+ region.y1 = (rs->roi_scaled.y1 < last.y1) ? rs->roi_scaled.y1 : last.y1;
+ region.y2 = (rs->roi_scaled.y2 > last.y2) ? rs->roi_scaled.y2 : last.y2;
+ last.x1 = rs->roi_scaled.x1;
+ last.x2 = rs->roi_scaled.x2;
+ last.y1 = rs->roi_scaled.y1;
+ last.y2 = rs->roi_scaled.y2;
+
+ rs_rect_scale(&rs->roi_scaled, &rs->roi, 1.0/GETVAL(rs->scale));
+ draw_region_crop(rs, ®ion);
return(TRUE);
}
+/* callbacks from popup-menu */
+static void
+gui_drawingarea_popup_crop(GtkMenuItem *menuitem, RS_BLOB *rs)
+{
+ rs_crop_start(rs);
+ return;
+}
+
+static void
+gui_drawingarea_popup_uncrop(GtkMenuItem *menuitem, RS_BLOB *rs)
+{
+ rs_crop_uncrop(rs);
+ return;
+}
+
+gboolean
+gui_drawingarea_button(GtkWidget *widget, GdkEventButton *event, RS_BLOB *rs)
+{
+ extern gint state;
+ static GdkCursor *cursor;
+ static gint operation = OP_NONE;
+ static gint signal;
+ gint x,y;
+
+ x = (gint) event->x;
+ y = (gint) event->y;
+
+ switch (state)
+ {
+ case STATE_NORMAL:
+ if (event->type == GDK_BUTTON_PRESS)
+ { /* start */
+ switch(event->button)
+ {
+ case 1:
+ rs_set_wb_from_pixels(rs, x, y);
+ break;
+ case 2:
+ if (!gui_is_busy())
+ {
+ operation = OP_MOVE;
+ cursor = gdk_cursor_new(GDK_FLEUR);
+ gdk_window_set_cursor(rs->preview_drawingarea->window, cursor);
+ start_x = (gint) event->x_root;
+ start_y = (gint) event->y_root;
+ signal = g_signal_connect (G_OBJECT (rs->preview_drawingarea), "motion_notify_event",
+ G_CALLBACK (gui_drawingarea_move_callback), rs);
+ }
+ else
+ {
+ operation = OP_BUSY;
+ cursor = gdk_cursor_new(GDK_WATCH);
+ gdk_window_set_cursor(rs->preview_drawingarea->window, cursor);
+ }
+ break;
+ case 3:
+ if (!gui_is_busy())
+ {
+ GtkWidget *i, *menu = gtk_menu_new();
+
+ i = gtk_menu_item_new_with_label ("Crop");
+ gtk_widget_show (i);
+ gtk_menu_attach (GTK_MENU (menu), i, 0, 1, 0, 1);
+ g_signal_connect (i, "activate", G_CALLBACK (gui_drawingarea_popup_crop), rs);
+ if (rs->photo->input->parent)
+ {
+ i = gtk_menu_item_new_with_label ("Uncrop");
+ gtk_widget_show (i);
+ gtk_menu_attach (GTK_MENU (menu), i, 0, 1, 1, 2);
+ g_signal_connect (i, "activate", G_CALLBACK (gui_drawingarea_popup_uncrop), rs);
+ }
+ gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 0, GDK_CURRENT_TIME);
+ }
+ break;
+ }
+ }
+ else
+ { /* end */
+ switch(operation)
+ {
+ case OP_MOVE:
+ g_signal_handler_disconnect(rs->preview_drawingarea, signal);
+ update_preview_region(rs, rs->preview_exposed);
+ gdk_window_set_cursor(rs->preview_drawingarea->window, NULL);
+ gdk_cursor_unref(cursor);
+ operation = OP_NONE;
+ break;
+ case OP_BUSY:
+ gdk_window_set_cursor(rs->preview_drawingarea->window, NULL);
+ gdk_cursor_unref(cursor);
+ operation = OP_NONE;
+ break;
+ }
+ }
+ break;
+ case STATE_CROP:
+ if (event->type == GDK_BUTTON_PRESS)
+ switch(event->button)
+ {
+ case 1:
+ if (abs(x-rs->roi_scaled.x1)<10) /* west block */
+ {
+ if (abs(y-rs->roi_scaled.y1)<10)
+ state = STATE_CROP_MOVE_NW;
+ else if (abs(y-rs->roi_scaled.y2)<10)
+ state = STATE_CROP_MOVE_SW;
+ else if ((y>rs->roi_scaled.y1) && (y<rs->roi_scaled.y2))
+ state = STATE_CROP_MOVE_W;
+ }
+ else if (abs(x-rs->roi_scaled.x2)<10) /* east block */
+ {
+ if (abs(y-rs->roi_scaled.y1)<10)
+ state = STATE_CROP_MOVE_NE;
+ else if (abs(y-rs->roi_scaled.y2)<10)
+ state = STATE_CROP_MOVE_SE;
+ else if ((y>rs->roi_scaled.y1) && (y<rs->roi_scaled.y2))
+ state = STATE_CROP_MOVE_E;
+ }
+ else if ((x>rs->roi_scaled.x1) && (x<rs->roi_scaled.x2)) /* poles */
+ {
+ if (abs(y-rs->roi_scaled.y1)<10)
+ state = STATE_CROP_MOVE_N;
+ else if (abs(y-rs->roi_scaled.y2)<10)
+ state = STATE_CROP_MOVE_S;
+ }
+ if (state!=STATE_CROP)
+ signal = g_signal_connect (G_OBJECT (rs->preview_drawingarea),
+ "motion_notify_event",
+ G_CALLBACK (gui_drawingarea_crop_motion_callback), rs);
+ break;
+ case 3:
+ /* DO IT */
+ if (((x>rs->roi_scaled.x1) && (x<rs->roi_scaled.x2)) && ((y>rs->roi_scaled.y1) && (y<rs->roi_scaled.y2)))
+ rs_crop_end(rs, TRUE);
+ else
+ rs_crop_end(rs, FALSE);
+ break;
+ }
+ break;
+ case STATE_CROP_MOVE_N:
+ case STATE_CROP_MOVE_E:
+ case STATE_CROP_MOVE_S:
+ case STATE_CROP_MOVE_W:
+ case STATE_CROP_MOVE_NW:
+ case STATE_CROP_MOVE_NE:
+ case STATE_CROP_MOVE_SE:
+ case STATE_CROP_MOVE_SW:
+ g_signal_handler_disconnect(rs->preview_drawingarea, signal);
+ state = STATE_CROP;
+ break;
+ }
+ return(TRUE);
+}
+
/* hack to resize a bit nicer */
gboolean
zoom_to_fit_helper(RS_BLOB *rs)
Modified: trunk/src/gtk-interface.c
===================================================================
--- trunk/src/gtk-interface.c 2006-10-17 20:07:58 UTC (rev 868)
+++ trunk/src/gtk-interface.c 2006-10-17 20:55:09 UTC (rev 869)
@@ -153,7 +153,7 @@
if (rs->photo)
{
rs_settings_to_rs_settings_double(rs->settings[rs->current_setting], rs->photo->settings[rs->photo->current_setting]);
- update_preview(rs, FALSE);
+ update_preview(rs, FALSE, FALSE);
gui_set_values(rs, -1, -1);
}
return(FALSE);
@@ -165,7 +165,7 @@
if (rs->photo)
{
rs_settings_to_rs_settings_double(rs->settings[rs->current_setting], rs->photo->settings[rs->photo->current_setting]);
- update_preview(rs, TRUE);
+ update_preview(rs, TRUE, FALSE);
gui_set_values(rs, -1, -1);
}
return(FALSE);
@@ -382,6 +382,7 @@
rs_photo_free(rs->photo);
rs->photo = NULL;
rs_reset(rs);
+ rs_state_reset(rs);
photo = filetype->load(name);
if (!photo)
{
@@ -1602,7 +1603,7 @@
rs->in_use = FALSE;
rs_settings_reset(rs->settings[rs->current_setting], MASK_ALL);
rs->in_use = in_use;
- update_preview(rs, TRUE);
+ update_preview(rs, TRUE, FALSE);
return;
}
@@ -1628,7 +1629,7 @@
else
gui_status_push(_("Hiding exposure mask"));
rs->show_exposure_overlay = GTK_CHECK_MENU_ITEM(widget)->active;
- update_preview(rs, FALSE);
+ update_preview(rs, FALSE, FALSE);
return;
}
@@ -1648,7 +1649,7 @@
rs->settings[rs->photo->current_setting]);
photo->filename = NULL;
rs_photo_free(photo);
- update_preview(rs, TRUE);
+ update_preview(rs, TRUE, FALSE);
return;
}
@@ -1745,7 +1746,7 @@
rs->in_use = FALSE;
rs_apply_settings_from_double(rs->settings[rs->photo->current_setting], rs->settings_buffer, mask);
rs->in_use = in_use;
- update_preview(rs, TRUE);
+ update_preview(rs, TRUE, FALSE);
gui_status_push(_("Pasted settings"));
}
Modified: trunk/src/rawstudio.c
===================================================================
--- trunk/src/rawstudio.c 2006-10-17 20:07:58 UTC (rev 868)
+++ trunk/src/rawstudio.c 2006-10-17 20:55:09 UTC (rev 869)
@@ -41,6 +41,7 @@
#include "rs-render.h"
#include "rs-arch.h"
+gint state;
static gushort loadtable[65536];
static cmsHPROFILE testProfile = NULL;
@@ -53,7 +54,7 @@
static cmsHTRANSFORM srgbTransform = NULL;
inline void rs_photo_prepare(RS_PHOTO *photo);
-static void update_scaled(RS_BLOB *rs);
+static void update_scaled(RS_BLOB *rs, gboolean force);
static inline void rs_render_mask(guchar *pixels, guchar *mask, guint length);
static gboolean rs_render_idle(RS_BLOB *rs);
static void rs_render_overlay(RS_PHOTO *photo, gint width, gint height, gushort *in,
@@ -148,15 +149,16 @@
}
void
-update_scaled(RS_BLOB *rs)
+update_scaled(RS_BLOB *rs, gboolean force)
{
/* scale if needed */
- if (rs->preview_scale != GETVAL(rs->scale))
+ if ((rs->preview_scale != GETVAL(rs->scale)) || force)
{
rs->preview_scale = GETVAL(rs->scale);
if (rs->photo->scaled)
rs_image16_free(rs->photo->scaled);
rs->photo->scaled = rs_image16_scale(rs->photo->input, NULL, rs->preview_scale);
+ rs_rect_scale(&rs->roi, &rs->roi_scaled, rs->preview_scale);
rs->preview_done = TRUE; /* stop rs_render_idle() */
}
@@ -200,13 +202,13 @@
}
void
-update_preview(RS_BLOB *rs, gboolean update_table)
+update_preview(RS_BLOB *rs, gboolean update_table, gboolean update_scale)
{
if(unlikely(!rs->photo)) return;
if (update_table)
rs_render_previewtable(rs->photo->settings[rs->photo->current_setting]->contrast);
- update_scaled(rs);
+ update_scaled(rs, update_scale);
rs_photo_prepare(rs->photo);
update_preview_region(rs, rs->preview_exposed);
@@ -235,36 +237,97 @@
{
guchar *pixels;
gushort *in;
- gint x1 = region->x1;
- gint y1 = region->y1;
- gint x2 = region->x2;
- gint y2 = region->y2;
-
+ gint w, h;
if (unlikely(!rs->in_use)) return;
- _CLAMP(x2, rs->photo->scaled->w);
- _CLAMP(y2, rs->photo->scaled->h);
+ _CLAMP(region->x2, rs->photo->scaled->w);
+ _CLAMP(region->y2, rs->photo->scaled->h);
+ w = region->x2-region->x1;
+ h = region->y2-region->y1;
/* evil hack to fix crash after zoom */
- if (unlikely(y2<y1)) /* FIXME: this is not good */
+ if (unlikely(region->y2 < region->y2)) /* FIXME: this is not good */
return;
- pixels = rs->photo->preview->pixels+(y1*rs->photo->preview->rowstride+x1*rs->photo->preview->pixelsize);
- in = rs->photo->scaled->pixels+(y1*rs->photo->scaled->rowstride+x1*rs->photo->scaled->pixelsize);
+ pixels = rs->photo->preview->pixels+(region->y1*rs->photo->preview->rowstride
+ + region->x1*rs->photo->preview->pixelsize);
+ in = rs->photo->scaled->pixels+(region->y1*rs->photo->scaled->rowstride
+ + region->x1*rs->photo->scaled->pixelsize);
if (unlikely(rs->show_exposure_overlay))
{
- guchar *mask = rs->photo->mask->pixels+(y1*rs->photo->mask->rowstride+x1*rs->photo->mask->pixelsize);
- rs_render_overlay(rs->photo, x2-x1, y2-y1, in, rs->photo->scaled->rowstride,
+ guchar *mask = rs->photo->mask->pixels+(region->y1*rs->photo->mask->rowstride
+ +region->x1*rs->photo->mask->pixelsize);
+ rs_render_overlay(rs->photo, w, h, in, rs->photo->scaled->rowstride,
rs->photo->scaled->pixelsize, pixels, rs->photo->preview->rowstride,
mask, rs->photo->mask->rowstride);
}
else
- rs_render(rs->photo, x2-x1, y2-y1, in, rs->photo->scaled->rowstride,
- rs->photo->scaled->pixelsize, pixels, rs->photo->preview->rowstride, displayTransform);
- gdk_draw_rgb_image(rs->preview_drawingarea->window,
- rs->preview_drawingarea->style->fg_gc[GTK_STATE_NORMAL],
- x1, y1, x2-x1, y2-y1,
- GDK_RGB_DITHER_NONE, pixels, rs->photo->preview->rowstride);
+ rs_render(rs->photo, w, h, in, rs->photo->scaled->rowstride,
+ rs->photo->scaled->pixelsize, pixels, rs->photo->preview->rowstride,
+ displayTransform);
+
+ if (rs->mark_roi) /* FIXME: This is SLOOOOOOOOOOOW */
+ {
+ gint size = rs->photo->preview->h * rs->photo->preview->rowstride;
+ guchar *buffer;
+ guchar *pixels_roi, *pixels_notroi;
+
+ buffer = g_malloc(size); /* FIXME: renders WAY too much */
+ while(size--) /* render backing store for pixels outside crop */
+ buffer[size] = ((rs->photo->preview->pixels[size]+63)*3)>>3;
+
+ pixels_roi = rs->photo->preview->pixels+(rs->roi_scaled.y1*rs->photo->preview->rowstride
+ + rs->roi_scaled.x1*rs->photo->preview->pixelsize);
+ pixels_notroi = buffer+(region->y1*rs->photo->preview->rowstride
+ + region->x1*rs->photo->preview->pixelsize);
+ /* draw all our stuff to backing-store */
+ gdk_draw_rgb_image(rs->preview_backing, /* not ROI */
+ rs->preview_drawingarea->style->fg_gc[GTK_STATE_NORMAL],
+ region->x1, region->y1, w, h,
+ GDK_RGB_DITHER_NONE, pixels_notroi, rs->photo->preview->rowstride);
+ gdk_draw_rgb_image(rs->preview_backing, /* ROI */
+ rs->preview_drawingarea->style->fg_gc[GTK_STATE_NORMAL],
+ rs->roi_scaled.x1, rs->roi_scaled.y1,
+ rs->roi_scaled.x2-rs->roi_scaled.x1,
+ rs->roi_scaled.y2-rs->roi_scaled.y1,
+ GDK_RGB_DITHER_NONE, pixels_roi, rs->photo->preview->rowstride);
+ gdk_draw_line(rs->preview_backing,
+ rs->preview_drawingarea->style->fg_gc[GTK_WIDGET_STATE (rs->preview_drawingarea)],
+ rs->roi_scaled.x1, rs->roi_scaled.y1,
+ rs->roi_scaled.x2, rs->roi_scaled.y1);
+ gdk_draw_line(rs->preview_backing,
+ rs->preview_drawingarea->style->fg_gc[GTK_WIDGET_STATE (rs->preview_drawingarea)],
+ rs->roi_scaled.x2, rs->roi_scaled.y1,
+ rs->roi_scaled.x2, rs->roi_scaled.y2);
+ gdk_draw_line(rs->preview_backing,
+ rs->preview_drawingarea->style->fg_gc[GTK_WIDGET_STATE (rs->preview_drawingarea)],
+ rs->roi_scaled.x2, rs->roi_scaled.y2,
+ rs->roi_scaled.x1, rs->roi_scaled.y2);
+ gdk_draw_line(rs->preview_backing,
+ rs->preview_drawingarea->style->fg_gc[GTK_WIDGET_STATE (rs->preview_drawingarea)],
+ rs->roi_scaled.x1, rs->roi_scaled.y2,
+ rs->roi_scaled.x1, rs->roi_scaled.y1);
+ /* blit to screen */
+ gdk_draw_drawable(rs->preview_drawingarea->window,
+ rs->preview_drawingarea->style->fg_gc[GTK_WIDGET_STATE (rs->preview_drawingarea)],
+ rs->preview_backing,
+ region->x1, region->y1,
+ region->x1, region->y1,
+ w, h);
+ /* update backing store for non-ROI */
+ gdk_draw_rgb_image(rs->preview_backing_crop,
+ rs->preview_drawingarea->style->fg_gc[GTK_STATE_NORMAL],
+ region->x1, region->y1, w, h,
+ GDK_RGB_DITHER_NONE, pixels_notroi, rs->photo->preview->rowstride);
+ g_free(buffer);
+ }
+ else
+ {
+ gdk_draw_rgb_image(rs->preview_drawingarea->window,
+ rs->preview_drawingarea->style->fg_gc[GTK_STATE_NORMAL],
+ region->x1, region->y1, w, h,
+ GDK_RGB_DITHER_NONE, pixels, rs->photo->preview->rowstride);
+ }
return;
}
@@ -432,7 +495,7 @@
for(c=0;c<3;c++)
rs_settings_reset(rs->settings[c], MASK_ALL);
rs->in_use = in_use;
- update_preview(rs, TRUE);
+ update_preview(rs, TRUE, FALSE);
return;
}
@@ -717,6 +780,7 @@
rs->preview_idle_render = FALSE;
rs->settings_buffer = NULL;
rs->in_use = FALSE;
+ rs->mark_roi = FALSE;
rs->show_exposure_overlay = FALSE;
rs->photo = NULL;
rs->queue = batch_new_queue();
@@ -1206,6 +1270,121 @@
return;
}
+void
+rs_rect_scale(RS_RECT *in, RS_RECT *out, gdouble scale)
+{
+ out->x1 = (gint) (((gdouble) in->x1)*scale);
+ out->x2 = (gint) (((gdouble) in->x2)*scale);
+ out->y1 = (gint) (((gdouble) in->y1)*scale);
+ out->y2 = (gint) (((gdouble) in->y2)*scale);
+ return;
+}
+
+void
+rs_roi_orientation(RS_BLOB *rs)
+{
+ gint x1,x2,y1,y2;
+ const gint rot = (rs->photo->orientation&3)%4;
+ x1 = rs->roi.x1;
+ y1 = rs->roi.y1;
+ x2 = rs->roi.x2;
+ y2 = rs->roi.y2;
+
+ /* rotate and flip */
+ switch(rot)
+ {
+ case 1:
+ x1 = rs->roi.y1;
+ y1 = rs->photo->input->h - rs->roi.x1;
+ x2 = rs->roi.y2;
+ y2 = rs->photo->input->h - rs->roi.x2;
+ break;
+ case 2:
+ x1 = rs->photo->input->w - rs->roi.x2;
+ y1 = rs->photo->input->h - rs->roi.y2;
+ x2 = rs->photo->input->w - rs->roi.x1;
+ y2 = rs->photo->input->h - rs->roi.y1;
+ break;
+ case 3:
+ x1 = rs->photo->input->w - rs->roi.y1;
+ y1 = rs->roi.x1;
+ x2 = rs->photo->input->w - rs->roi.y2;
+ y2 = rs->roi.x2;
+ break;
+ }
+
+ if (rs->photo->orientation&4)
+ {
+ y1 = rs->photo->input->h-y1;
+ y2 = rs->photo->input->h-y2;
+ }
+
+ rs->roi.x1 = x1;
+ rs->roi.y1 = y1;
+ rs->roi.x2 = x2;
+ rs->roi.y2 = y2;
+
+ /* normalize */
+ if (rs->roi.x1 > rs->roi.x2)
+ SWAP(rs->roi.x1, rs->roi.x2);
+ if (rs->roi.y1 > rs->roi.y2)
+ SWAP(rs->roi.y1, rs->roi.y2);
+ return;
+}
+
+void
+rs_crop_start(RS_BLOB *rs)
+{
+ rs->roi.x1 = 20;
+ rs->roi.y1 = 20;
+ rs->roi.x2 = rs->photo->input->w-20;
+ rs->roi.y2 = rs->photo->input->h-20;
+ rs_rect_scale(&rs->roi, &rs->roi_scaled, GETVAL(rs->scale));
+
+ rs->preview_backing_crop = gdk_pixmap_new(rs->preview_drawingarea->window,
+ rs->preview_drawingarea->allocation.width,
+ rs->preview_drawingarea->allocation.height, -1);
+
+ rs->mark_roi = TRUE;
+ state = STATE_CROP;
+ update_preview(rs, FALSE, FALSE);
+ return;
+}
+
+void
+rs_crop_end(RS_BLOB *rs, gboolean accept)
+{
+ if (accept)
+ {
+ rs_roi_orientation(rs);
+ rs_image16_crop(&rs->photo->input, &rs->roi);
+ }
+ rs->mark_roi = FALSE;
+ state = STATE_NORMAL;
+ update_preview(rs, FALSE, TRUE);
+ g_object_unref(rs->preview_backing_crop);
+ return;
+}
+
+void
+rs_crop_uncrop(RS_BLOB *rs)
+{
+ rs_image16_uncrop(&rs->photo->input);
+ update_preview(rs, FALSE, TRUE);
+ return;
+}
+
+void
+rs_state_reset(RS_BLOB *rs)
+{
+ switch (state)
+ {
+ case STATE_CROP:
+ rs_crop_end(rs, FALSE);
+ break;
+ }
+}
+
gchar *
rs_get_profile(gint type)
{
@@ -1477,6 +1656,7 @@
textdomain(GETTEXT_PACKAGE);
#endif
RS_BLOB *rs;
+ state = STATE_NORMAL;
rs_init_filetypes();
gtk_init(&argc, &argv);
rs = rs_new();
Modified: trunk/src/rawstudio.h
===================================================================
--- trunk/src/rawstudio.h 2006-10-17 20:07:58 UTC (rev 868)
+++ trunk/src/rawstudio.h 2006-10-17 20:55:09 UTC (rev 869)
@@ -47,6 +47,19 @@
gtk_adjustment_set_value((GtkAdjustment *) adjustment, value)
enum {
+ STATE_NORMAL,
+ STATE_CROP,
+ STATE_CROP_MOVE_N,
+ STATE_CROP_MOVE_E,
+ STATE_CROP_MOVE_S,
+ STATE_CROP_MOVE_W,
+ STATE_CROP_MOVE_NW,
+ STATE_CROP_MOVE_NE,
+ STATE_CROP_MOVE_SE,
+ STATE_CROP_MOVE_SW,
+};
+
+enum {
MASK_EXPOSURE = 1,
MASK_SATURATION = 2,
MASK_HUE = 4,
@@ -175,10 +188,13 @@
typedef struct {
gboolean in_use;
RS_PHOTO *photo;
+ RS_RECT roi;
+ RS_RECT roi_scaled;
RS_SETTINGS_DOUBLE *settings_buffer;
RS_SETTINGS *settings[3];
gint current_setting;
GtkObject *scale;
+ gboolean mark_roi;
gdouble preview_scale;
gboolean zoom_to_fit;
RS_RECT *preview_exposed;
@@ -191,6 +207,7 @@
gboolean preview_idle_render;
gboolean preview_done;
GdkPixmap *preview_backing;
+ GdkPixmap *preview_backing_crop;
gint preview_idle_render_lastrow;
gboolean show_exposure_overlay;
GArray *batch_queue;
@@ -225,7 +242,7 @@
void rs_local_cachedir(gboolean new_value);
void rs_load_gdk(gboolean new_value);
-void update_preview(RS_BLOB *rs, gboolean update_table);
+void update_preview(RS_BLOB *rs, gboolean update_table, gboolean update_scale);
void update_preview_region(RS_BLOB *rs, RS_RECT *region);
gboolean rs_run_batch_idle(RS_QUEUE *queue);
void rs_reset(RS_BLOB *rs);
@@ -253,6 +270,12 @@
void rs_set_wb(RS_BLOB *rs, gfloat warmth, gfloat tint);
void rs_render_pixel_to_srgb(RS_BLOB *rs, gint x, gint y, guchar *dest);
void rs_apply_settings_from_double(RS_SETTINGS *rss, RS_SETTINGS_DOUBLE *rsd, gint mask);
+void rs_rect_scale(RS_RECT *in, RS_RECT *out, gdouble scale);
+void rs_roi_orientation(RS_BLOB *rs);
+void rs_crop_start(RS_BLOB *rs);
+void rs_crop_end(RS_BLOB *rs, gboolean accept);
+void rs_crop_uncrop(RS_BLOB *rs);
+void rs_state_reset(RS_BLOB *rs);
gchar *rs_get_profile(gint type);
gboolean rs_cms_is_profile_valid(const gchar *path);
void rs_cms_prepare_transforms(RS_BLOB *rs);
Modified: trunk/src/toolbox.c
===================================================================
--- trunk/src/toolbox.c 2006-10-17 20:07:58 UTC (rev 868)
+++ trunk/src/toolbox.c 2006-10-17 20:55:09 UTC (rev 869)
@@ -103,35 +103,35 @@
gui_transform_rot90_clicked(GtkWidget *w, RS_BLOB *rs)
{
ORIENTATION_90(rs->photo->orientation);
- update_preview(rs, FALSE);
+ update_preview(rs, FALSE, FALSE);
}
void
gui_transform_rot180_clicked(GtkWidget *w, RS_BLOB *rs)
{
ORIENTATION_180(rs->photo->orientation);
- update_preview(rs, FALSE);
+ update_preview(rs, FALSE, FALSE);
}
void
gui_transform_rot270_clicked(GtkWidget *w, RS_BLOB *rs)
{
ORIENTATION_270(rs->photo->orientation);
- update_preview(rs, FALSE);
+ update_preview(rs, FALSE, FALSE);
}
void
gui_transform_mirror_clicked(GtkWidget *w, RS_BLOB *rs)
{
ORIENTATION_MIRROR(rs->photo->orientation);
- update_preview(rs, FALSE);
+ update_preview(rs, FALSE, FALSE);
}
void
gui_transform_flip_clicked(GtkWidget *w, RS_BLOB *rs)
{
ORIENTATION_FLIP(rs->photo->orientation);
- update_preview(rs, FALSE);
+ update_preview(rs, FALSE, FALSE);
}
GtkWidget *
More information about the Rawstudio-commit
mailing list