static void merge_do_none(MergeArgs *args) { GwyDataField *dfield1, *dfield2; gint xres1, xres2, yres1, yres2; gint px1, py1, px2, py2; GwyContainer *data1, *data2; GQuark quark; data1 = gwy_app_data_browser_get(args->op1.datano); quark = gwy_app_get_data_key_for_id(args->op1.id); dfield1 = GWY_DATA_FIELD(gwy_container_get_object(data1, quark)); data2 = gwy_app_data_browser_get(args->op2.datano); quark = gwy_app_get_data_key_for_id(args->op2.id); dfield2 = GWY_DATA_FIELD(gwy_container_get_object(data2, quark)); xres1 = gwy_data_field_get_xres(dfield1); xres2 = gwy_data_field_get_xres(dfield2); yres1 = gwy_data_field_get_yres(dfield1); yres2 = gwy_data_field_get_yres(dfield2); if (args->direction == GWY_MERGE_DIRECTION_UP) { px1 = px2 = 0; py1 = yres2; py2 = 0; } else if (args->direction == GWY_MERGE_DIRECTION_DOWN) { px1 = px2 = 0; py1 = 0; py2 = yres1; } else if (args->direction == GWY_MERGE_DIRECTION_LEFT) { py1 = py2 = 0; px1 = xres2; px2 = 0; } else if (args->direction == GWY_MERGE_DIRECTION_RIGHT) { py1 = py2 = 0; px1 = 0; px2 = xres1; } else { g_assert_not_reached(); } create_merged_field(data1, args->op1.id, dfield1, dfield2, px1, py1, px2, py2, args->boundary, args->direction, args->create_mask, args->crop_to_rectangle); }
static gboolean immerse_data_filter(GwyContainer *data, gint id, gpointer user_data) { GwyAppDataId *object = (GwyAppDataId*)user_data; GwyDataField *image, *detail; GQuark quark; quark = gwy_app_get_data_key_for_id(id); detail = GWY_DATA_FIELD(gwy_container_get_object(data, quark)); data = gwy_app_data_browser_get(object->datano); quark = gwy_app_get_data_key_for_id(object->id); image = GWY_DATA_FIELD(gwy_container_get_object(data, quark)); /* It does not make sense to immerse itself */ if (detail == image) return FALSE; if (gwy_data_field_check_compatibility(image, detail, GWY_DATA_COMPATIBILITY_LATERAL | GWY_DATA_COMPATIBILITY_VALUE)) return FALSE; if (gwy_data_field_get_xreal(image) < gwy_data_field_get_xreal(detail) || gwy_data_field_get_xreal(image) < gwy_data_field_get_xreal(detail)) return FALSE; return TRUE; }
static gboolean xydenoise_data_filter(GwyContainer *data, gint id, gpointer user_data) { GwyAppDataId *object = (GwyAppDataId*)user_data; GwyDataField *op1, *op2; GQuark quark; quark = gwy_app_get_data_key_for_id(id); op1 = GWY_DATA_FIELD(gwy_container_get_object(data, quark)); data = gwy_app_data_browser_get(object->datano); quark = gwy_app_get_data_key_for_id(object->id); op2 = GWY_DATA_FIELD(gwy_container_get_object(data, quark)); /* It does not make sense to xydenoiserelate with itself */ if (op1 == op2) return FALSE; return !gwy_data_field_check_compatibility(op1, op2, GWY_DATA_COMPATIBILITY_RES | GWY_DATA_COMPATIBILITY_REAL | GWY_DATA_COMPATIBILITY_LATERAL | GWY_DATA_COMPATIBILITY_VALUE); }
static gboolean maskcor_kernel_filter(GwyContainer *data, gint id, gpointer user_data) { GwyAppDataId *object = (GwyAppDataId*)user_data; GwyDataField *kernel, *dfield; GQuark quark; quark = gwy_app_get_data_key_for_id(id); kernel = GWY_DATA_FIELD(gwy_container_get_object(data, quark)); data = gwy_app_data_browser_get(object->datano); quark = gwy_app_get_data_key_for_id(object->id); dfield = GWY_DATA_FIELD(gwy_container_get_object(data, quark)); if (gwy_data_field_get_xreal(kernel) <= gwy_data_field_get_xreal(dfield)/4 && gwy_data_field_get_yreal(kernel) <= gwy_data_field_get_yreal(dfield)/4 && !gwy_data_field_check_compatibility(kernel, dfield, GWY_DATA_COMPATIBILITY_LATERAL | GWY_DATA_COMPATIBILITY_VALUE)) return TRUE; return FALSE; }
static void presentation_attach_do(const GwyAppDataId *source, const GwyAppDataId *target) { GwyContainer *sourcedata, *targetdata; GwyDataField *dfield; GQuark quark; sourcedata = gwy_app_data_browser_get(source->datano); targetdata = gwy_app_data_browser_get(target->datano); quark = gwy_app_get_data_key_for_id(source->id); dfield = GWY_DATA_FIELD(gwy_container_get_object(sourcedata, quark)); dfield = gwy_data_field_duplicate(dfield); quark = gwy_app_get_show_key_for_id(target->id); gwy_app_undo_qcheckpointv(targetdata, 1, &quark); gwy_container_set_object(targetdata, quark, dfield); g_object_unref(dfield); }
static void immerse_detail_cb(GwyDataChooser *chooser, ImmerseControls *controls) { GwyDataField *dfield, *ifield; GwyContainer *data; GQuark quark; GwyAppDataId *object; object = &controls->args->detail; gwy_data_chooser_get_active_id(chooser, object); gwy_debug("data: %d %d", object->datano, object->id); data = gwy_app_data_browser_get(object->datano); gtk_dialog_set_response_sensitive(GTK_DIALOG(controls->dialog), GTK_RESPONSE_OK, data != NULL); gtk_dialog_set_response_sensitive(GTK_DIALOG(controls->dialog), RESPONSE_ESTIMATE, data != NULL); gtk_dialog_set_response_sensitive(GTK_DIALOG(controls->dialog), RESPONSE_REFINE, data != NULL); if (data) { quark = gwy_app_get_data_key_for_id(object->id); dfield = gwy_container_get_object(data, quark); quark = gwy_app_get_data_key_for_id(controls->args->image.id); data = gwy_app_data_browser_get(controls->args->image.datano); ifield = gwy_container_get_object(data, quark); controls->xmax = (gwy_data_field_get_xreal(ifield) - gwy_data_field_get_xreal(dfield) + gwy_data_field_get_xmeasure(ifield)/2.0); controls->ymax = (gwy_data_field_get_yreal(ifield) - gwy_data_field_get_yreal(dfield) + gwy_data_field_get_ymeasure(ifield)/2.0); } immerse_update_detail_pixbuf(controls); immerse_clamp_detail_offset(controls, controls->args->xpos, controls->args->ypos); if (GTK_WIDGET_DRAWABLE(controls->view)) gtk_widget_queue_draw(controls->view); }
static void immerse_update_detail_pixbuf(ImmerseControls *controls) { GwyContainer *data; GwyDataField *dfield; GwyGradient *gradient; GdkPixbuf *pixbuf; const guchar *name; gchar *key; GQuark quark; gint w, h, xres, yres; GWY_OBJECT_UNREF(controls->detail); data = gwy_app_data_browser_get(controls->args->detail.datano); if (!data) return; quark = gwy_app_get_data_key_for_id(controls->args->detail.id); dfield = gwy_container_get_object(data, quark); gwy_data_view_coords_real_to_xy(GWY_DATA_VIEW(controls->view), gwy_data_field_get_xreal(dfield), gwy_data_field_get_yreal(dfield), &w, &h); gwy_debug("%dx%d", w, h); w = MAX(w, 2); h = MAX(h, 2); key = g_strdup_printf("/%d/base/palette", controls->args->image.id); name = NULL; data = gwy_app_data_browser_get(controls->args->image.datano); gwy_container_gis_string_by_name(data, key, &name); g_free(key); gradient = gwy_gradients_get_gradient(name); /* Handle real-square properly by using an intermediate * pixel-square pixbuf with sufficient resolution */ xres = gwy_data_field_get_xres(dfield); yres = gwy_data_field_get_yres(dfield); pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, xres, yres); gwy_pixbuf_draw_data_field(pixbuf, dfield, gradient); controls->detail = gdk_pixbuf_scale_simple(pixbuf, w, h, GDK_INTERP_TILES); g_object_unref(pixbuf); }
/** * gwy_app_data_id_verify_spectra: * @id: Numerical identifiers of spectra in data managed by the data browser. * * Checks if numerical spectra identifiers correspond to existing spectra. * * If either the data contained referenced in @id or the spectra does not * exist the structure is cleared to %GWY_APP_DATA_ID_NONE and the function * returns %FALSE. If it represents existing spectra it is kept intact and * the function return %TRUE. * * Returns: Whether @id refers to existing spectra now. * * Since: 2.41 **/ gboolean gwy_app_data_id_verify_spectra(GwyAppDataId *id) { GwyContainer *container; GObject *object; GQuark quark; g_return_val_if_fail(id, FALSE); container = gwy_app_data_browser_get(id->datano); if (!container) return clear_data_id(id); quark = gwy_app_get_spectra_key_for_id(id->id); if (!gwy_container_gis_object(container, quark, &object)) return clear_data_id(id); return GWY_IS_SPECTRA(object); }
static gboolean tip_blind_source_filter(GwyContainer *data, gint id, gpointer user_data) { GwyAppDataId *object = (GwyAppDataId*)user_data; GwyDataField *source, *orig; GQuark quark; quark = gwy_app_get_data_key_for_id(id); source = GWY_DATA_FIELD(gwy_container_get_object(data, quark)); data = gwy_app_data_browser_get(object->datano); quark = gwy_app_get_data_key_for_id(object->id); orig = GWY_DATA_FIELD(gwy_container_get_object(data, quark)); return !gwy_data_field_check_compatibility(source, orig, GWY_DATA_COMPATIBILITY_MEASURE | GWY_DATA_COMPATIBILITY_LATERAL | GWY_DATA_COMPATIBILITY_VALUE); }
/* compute corelation */ static gboolean get_score_iteratively(GwyDataField *data_field, GwyDataField *kernel_field, GwyDataField *score, MergeArgs *args) { enum { WORK_PER_UPDATE = 50000000 }; GwyComputationState *state; GwyContainer *data; gboolean ok = FALSE; int work, wpi; work = 0; wpi = gwy_data_field_get_xres(kernel_field) *gwy_data_field_get_yres(kernel_field); wpi = MIN(wpi, WORK_PER_UPDATE); state = gwy_data_field_correlate_init(data_field, kernel_field, score); /* FIXME */ data = gwy_app_data_browser_get(args->op1.datano); gwy_app_wait_start(gwy_app_find_window_for_channel(data, args->op1.id), _("Initializing...")); gwy_data_field_correlate_iteration(state); if (!gwy_app_wait_set_message(_("Correlating..."))) goto get_score_fail; do { gwy_data_field_correlate_iteration(state); work += wpi; if (work > WORK_PER_UPDATE) { work -= WORK_PER_UPDATE; if (!gwy_app_wait_set_fraction(state->fraction)) goto get_score_fail; } } while (state->state != GWY_COMPUTATION_STATE_FINISHED); ok = TRUE; get_score_fail: gwy_data_field_correlate_finalize(state); gwy_app_wait_finish(); return ok; }
static gboolean merge_data_filter(GwyContainer *data, gint id, gpointer user_data) { MergeArgs *args = (MergeArgs*)user_data; GwyDataCompatibilityFlags compatflags; GwyDataField *op1, *op2; gboolean ok; GQuark quark; quark = gwy_app_get_data_key_for_id(id); op2 = GWY_DATA_FIELD(gwy_container_get_object(data, quark)); data = gwy_app_data_browser_get(args->op1.datano); quark = gwy_app_get_data_key_for_id(args->op1.id); op1 = GWY_DATA_FIELD(gwy_container_get_object(data, quark)); if (op1 == op2) return FALSE; compatflags = (GWY_DATA_COMPATIBILITY_MEASURE | GWY_DATA_COMPATIBILITY_LATERAL | GWY_DATA_COMPATIBILITY_VALUE); ok = !gwy_data_field_check_compatibility(op1, op2, compatflags); if (args->mode == GWY_MERGE_MODE_JOIN) { if (args->direction == GWY_MERGE_DIRECTION_UP || args->direction == GWY_MERGE_DIRECTION_DOWN) { if (op1->xres != op2->xres) ok = FALSE; } if (args->direction == GWY_MERGE_DIRECTION_LEFT || args->direction == GWY_MERGE_DIRECTION_RIGHT) { if (op1->yres != op2->yres) ok = FALSE; } } return ok; }
static gboolean presentation_attach_filter(GwyContainer *source, gint id, gpointer user_data) { const GwyAppDataId *target = (const GwyAppDataId*)user_data; GwyDataField *source_dfield, *target_dfield; GwyContainer *data; GQuark quark; quark = gwy_app_get_data_key_for_id(id); source_dfield = GWY_DATA_FIELD(gwy_container_get_object(source, quark)); data = gwy_app_data_browser_get(target->datano); quark = gwy_app_get_data_key_for_id(target->id); target_dfield = GWY_DATA_FIELD(gwy_container_get_object(data, quark)); return !gwy_data_field_check_compatibility(source_dfield, target_dfield, GWY_DATA_COMPATIBILITY_RES | GWY_DATA_COMPATIBILITY_REAL | GWY_DATA_COMPATIBILITY_LATERAL); }
/** * gwy_app_add_graph_or_curves: * @gmodel: A graph model with curves to add. * @data: Data container where the graph would be added. * @target_graph: Graph where curves would be added. * @colorstep: Curve block size as in gwy_graph_model_append_curves(). * * Puts the curves of a graph to another graph if possible, or adds the graph * as new. * * If the units of @gmodel are compatible with the units of the graph * identified by @target_graph the curves are copied to the target graph with * gwy_graph_model_append_curves(). * * In all other cases, including when @target_graph does not refer to any * existing graph, the graph model is added to @data as a new graph. * * Either way, the caller usually need to release its own reference afterwards. * * This function is useful particularly in modules that create graphs and can * be run non-interactively. * * Returns: The numerical identifier of the newly-created graph of one was * created. Value -1 is returned if curves were added to * @target_graph. * * Since: 2.41 **/ gint gwy_app_add_graph_or_curves(GwyGraphModel *gmodel, GwyContainer *data, const GwyAppDataId *target_graph, gint colorstep) { GwyAppDataId tgtgraph = *target_graph; if (gwy_app_data_id_verify_graph(&tgtgraph)) { GQuark quark = gwy_app_get_graph_key_for_id(tgtgraph.id); GwyContainer *data2 = gwy_app_data_browser_get(tgtgraph.datano); GwyGraphModel *target_gmodel = gwy_container_get_object(data2, quark); g_return_val_if_fail(GWY_IS_GRAPH_MODEL(target_gmodel), -1); if (gwy_graph_model_units_are_compatible(gmodel, target_gmodel)) { gwy_graph_model_append_curves(target_gmodel, gmodel, colorstep); return -1; } } g_return_val_if_fail(GWY_IS_CONTAINER(data), FALSE); return gwy_app_data_browser_add_graph_model(gmodel, data, TRUE); }
static gboolean xydenoise_do(XYdenoiseArgs *args) { GwyContainer *data; GwyDataField *dfieldx, *rx, *ix, *dfieldy, *ry, *iy, *result, *iresult; gint i, newid, xres, yres; gdouble *rxdata, *rydata, *ixdata, *iydata; GwyWindowingType window = GWY_WINDOWING_NONE; GwyInterpolationType interp = GWY_INTERPOLATION_LINEAR; GQuark quark; data = gwy_app_data_browser_get(args->op1.datano); gwy_app_wait_start(gwy_app_find_window_for_channel(data, args->op1.id), _("Initializing...")); quark = gwy_app_get_data_key_for_id(args->op1.id); dfieldx = GWY_DATA_FIELD(gwy_container_get_object(data, quark)); data = gwy_app_data_browser_get(args->op2.datano); quark = gwy_app_get_data_key_for_id(args->op2.id); dfieldy = GWY_DATA_FIELD(gwy_container_get_object(data, quark)); xres = gwy_data_field_get_xres(dfieldx); yres = gwy_data_field_get_yres(dfieldy); result = gwy_data_field_new_alike(dfieldx, TRUE); iresult = gwy_data_field_new_alike(dfieldx, TRUE); rx = gwy_data_field_new_alike(dfieldx, TRUE); ix = gwy_data_field_new_alike(dfieldx, TRUE); ry = gwy_data_field_new_alike(dfieldx, TRUE); iy = gwy_data_field_new_alike(dfieldx, TRUE); gwy_app_wait_set_fraction(0.1); gwy_app_wait_set_message(_("Computing forward FFTs...")); gwy_data_field_2dfft(dfieldx, NULL, rx, ix, window, GWY_TRANSFORM_DIRECTION_FORWARD, interp, FALSE, 0); gwy_data_field_2dfft(dfieldy, NULL, ry, iy, window, GWY_TRANSFORM_DIRECTION_FORWARD, interp, FALSE, 0); rxdata = gwy_data_field_get_data(rx); rydata = gwy_data_field_get_data(ry); ixdata = gwy_data_field_get_data(ix); iydata = gwy_data_field_get_data(iy); gwy_app_wait_set_fraction(0.3); gwy_app_wait_set_message(_("Computing image...")); for (i = 0; i < xres*yres; i++) { gdouble xmodule = sqrt(rxdata[i]*rxdata[i] + ixdata[i]*ixdata[i]); gdouble xphase = atan2(ixdata[i],rxdata[i]); gdouble ymodule = sqrt(rydata[i]*rydata[i] + iydata[i]*iydata[i]); /*gdouble yphase = atan2(iydata[i],rydata[i]);*/ rxdata[i] = MIN(xmodule, ymodule)*cos(xphase); ixdata[i] = MIN(xmodule, ymodule)*sin(xphase); } gwy_app_wait_set_fraction(0.7); gwy_app_wait_set_message(_("Computing backward FFT...")); gwy_data_field_2dfft(rx, ix, result, iresult, window, GWY_TRANSFORM_DIRECTION_BACKWARD, interp, FALSE, 0); gwy_app_wait_set_fraction(0.9); data = gwy_app_data_browser_get(args->op1.datano); newid = gwy_app_data_browser_add_data_field(result, data, TRUE); gwy_app_sync_data_items(data, data, args->op1.id, newid, FALSE, GWY_DATA_ITEM_GRADIENT, 0); gwy_app_set_data_field_title(data, newid, _("Denoised")); gwy_app_channel_log_add_proc(data, -1, newid); gwy_app_wait_finish(); g_object_unref(result); g_object_unref(iresult); g_object_unref(rx); g_object_unref(ix); g_object_unref(ry); g_object_unref(iy); return TRUE; }
static void tip_blind_dialog(TipBlindArgs *args) { GtkWidget *dialog, *table, *hbox, *vbox, *label; GwyContainer *data; GwyGraphModel *gmodel; GwyGraphArea *area; TipBlindControls controls; GwyPixmapLayer *layer; GwyDataField *dfield; GQuark quark; GwySIUnit *unit; gint response, row; dialog = gtk_dialog_new_with_buttons(_("Blind Tip Estimation"), NULL, 0, _("Run _Partial"), RESPONSE_ESTIMATE, _("Run _Full"), RESPONSE_REFINE, _("_Reset Tip"), RESPONSE_RESET, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OK, GTK_RESPONSE_OK, NULL); gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK); gwy_help_add_to_proc_dialog(GTK_DIALOG(dialog), GWY_HELP_DEFAULT); controls.args = args; controls.in_update = TRUE; controls.good_tip = FALSE; controls.dialog = dialog; gtk_dialog_set_response_sensitive(GTK_DIALOG(dialog), GTK_RESPONSE_OK, controls.good_tip); hbox = gtk_hbox_new(FALSE, 4); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), hbox, FALSE, FALSE, 4); controls.vxres = 240; controls.vyres = 240; controls.oldnstripes = args->nstripes; /* set initial tip properties */ data = gwy_app_data_browser_get(args->source.datano); quark = gwy_app_get_data_key_for_id(args->source.id); dfield = GWY_DATA_FIELD(gwy_container_get_object(data, quark)); controls.tip = gwy_data_field_new_alike(dfield, TRUE); gwy_data_field_resample(controls.tip, args->xres, args->yres, GWY_INTERPOLATION_NONE); gwy_data_field_clear(controls.tip); /* set up data of rescaled image of the tip */ controls.vtip = gwy_container_new(); gwy_app_sync_data_items(data, controls.vtip, args->source.id, 0, FALSE, GWY_DATA_ITEM_PALETTE, 0); dfield = gwy_data_field_new_alike(controls.tip, TRUE); gwy_data_field_resample(dfield, controls.vxres, controls.vyres, GWY_INTERPOLATION_ROUND); gwy_container_set_object_by_name(controls.vtip, "/0/data", dfield); g_object_unref(dfield); /* set up rescaled image of the tip */ vbox = gtk_vbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 4); controls.view = gwy_data_view_new(controls.vtip); layer = gwy_layer_basic_new(); gwy_pixmap_layer_set_data_key(layer, "/0/data"); gwy_layer_basic_set_gradient_key(GWY_LAYER_BASIC(layer), "/0/base/palette"); gwy_data_view_set_base_layer(GWY_DATA_VIEW(controls.view), layer); /* set up tip estimation controls */ gtk_box_pack_start(GTK_BOX(vbox), controls.view, FALSE, FALSE, 0); gmodel = gwy_graph_model_new(); controls.graph = gwy_graph_new(gmodel); g_object_unref(gmodel); gwy_axis_set_visible(gwy_graph_get_axis(GWY_GRAPH(controls.graph), GTK_POS_LEFT), FALSE); gwy_axis_set_visible(gwy_graph_get_axis(GWY_GRAPH(controls.graph), GTK_POS_BOTTOM), FALSE); area = GWY_GRAPH_AREA(gwy_graph_get_area(GWY_GRAPH(controls.graph))); gtk_widget_set_no_show_all(gwy_graph_area_get_label(area), TRUE); g_signal_connect_after(gwy_graph_area_get_label(area), "map", G_CALLBACK(gtk_widget_hide), NULL); gtk_box_pack_start(GTK_BOX(vbox), controls.graph, TRUE, TRUE, 0); table = gtk_table_new(13, 4, FALSE); gtk_table_set_row_spacings(GTK_TABLE(table), 2); gtk_table_set_col_spacings(GTK_TABLE(table), 6); gtk_container_set_border_width(GTK_CONTAINER(table), 4); gtk_box_pack_start(GTK_BOX(hbox), table, FALSE, FALSE, 4); row = 0; controls.data = gwy_data_chooser_new_channels(); gwy_data_chooser_set_filter(GWY_DATA_CHOOSER(controls.data), tip_blind_source_filter, &args->orig, NULL); gwy_data_chooser_set_active_id(GWY_DATA_CHOOSER(controls.data), &args->source); g_signal_connect(controls.data, "changed", G_CALLBACK(data_changed), &args->source); gwy_table_attach_hscale(table, row, _("Related _data:"), NULL, GTK_OBJECT(controls.data), GWY_HSCALE_WIDGET); gtk_table_set_row_spacing(GTK_TABLE(table), row, 8); row++; label = gtk_label_new(_("Estimated Tip Size")); gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); gtk_table_attach(GTK_TABLE(table), label, 0, 4, row, row+1, GTK_FILL, 0, 0, 0); row++; controls.xres = gtk_adjustment_new(args->xres, MIN_RES, MAX_RES, 1, 10, 0); gwy_table_attach_hscale(table, row, _("_Width:"), "px", controls.xres, 0); g_object_set_data(G_OBJECT(controls.xres), "controls", &controls); g_signal_connect(controls.xres, "value-changed", G_CALLBACK(width_changed), &controls); row++; controls.yres = gtk_adjustment_new(args->yres, MIN_RES, MAX_RES, 1, 10, 0); gwy_table_attach_hscale(table, row, _("_Height:"), "px", controls.yres, 0); g_object_set_data(G_OBJECT(controls.yres), "controls", &controls); g_signal_connect(controls.yres, "value-changed", G_CALLBACK(height_changed), &controls); row++; controls.same_resolution = gtk_check_button_new_with_mnemonic(_("_Same resolution")); gtk_table_attach(GTK_TABLE(table), controls.same_resolution, 0, 4, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(controls.same_resolution), args->same_resolution); g_signal_connect(controls.same_resolution, "toggled", G_CALLBACK(same_resolution_changed), &controls); gtk_table_set_row_spacing(GTK_TABLE(table), row, 8); row++; gtk_table_attach(GTK_TABLE(table), gwy_label_new_header(_("Options")), 0, 4, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); row++; controls.threshold = gtk_adjustment_new(1.0, 0.01, 1000.0, 0.01, 1.0, 0.0); controls.threshold_spin = gtk_spin_button_new(GTK_ADJUSTMENT(controls.threshold), 0.1, 2); gtk_table_attach(GTK_TABLE(table), controls.threshold_spin, 2, 3, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); label = gtk_label_new_with_mnemonic(_("Noise suppression t_hreshold:")); gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); gtk_label_set_mnemonic_widget(GTK_LABEL(label), controls.threshold_spin); gtk_table_attach(GTK_TABLE(table), label, 0, 2, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); unit = gwy_data_field_get_si_unit_z(dfield); controls.threshold_unit = gwy_combo_box_metric_unit_new(G_CALLBACK(thresh_changed), &controls, -12, -3, unit, -9); gtk_table_attach(GTK_TABLE(table), controls.threshold_unit, 3, 4, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); g_signal_connect(controls.threshold, "value-changed", G_CALLBACK(thresh_changed), &controls); sci_entry_set_value(GTK_ADJUSTMENT(controls.threshold), GTK_COMBO_BOX(controls.threshold_unit), args->thresh); row++; controls.boundaries = gtk_check_button_new_with_mnemonic(_("Use _boundaries")); gtk_table_attach(GTK_TABLE(table), controls.boundaries, 0, 4, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(controls.boundaries), args->use_boundaries); g_signal_connect(controls.boundaries, "toggled", G_CALLBACK(bound_changed), args); gtk_table_set_row_spacing(GTK_TABLE(table), row, 8); row++; gtk_table_attach(GTK_TABLE(table), gwy_label_new_header(_("Stripes")), 0, 4, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); row++; controls.nstripes = gtk_adjustment_new(args->nstripes, MIN_STRIPES, MAX_STRIPES, 1, 10, 0); gwy_table_attach_hscale(table, row, _("_Split to stripes:"), NULL, controls.nstripes, GWY_HSCALE_CHECK); controls.split_to_stripes = gwy_table_hscale_get_check(controls.nstripes); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(controls.split_to_stripes), !args->split_to_stripes); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(controls.split_to_stripes), args->split_to_stripes); g_signal_connect(controls.split_to_stripes, "toggled", G_CALLBACK(split_to_stripes_changed), &controls); g_signal_connect(controls.nstripes, "value-changed", G_CALLBACK(nstripes_changed), &controls); row++; controls.stripeno = gtk_adjustment_new(1, 1, args->nstripes, 1, 10, 0); gwy_table_attach_hscale(table, row, _("_Preview stripe:"), NULL, controls.stripeno, GWY_HSCALE_DEFAULT); g_signal_connect(controls.stripeno, "value-changed", G_CALLBACK(stripeno_changed), &controls); row++; controls.plot_size_graph = gtk_check_button_new_with_mnemonic(_("Plot size _graph")); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(controls.plot_size_graph), args->plot_size_graph); gtk_table_attach(GTK_TABLE(table), controls.plot_size_graph, 0, 4, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); g_signal_connect(controls.plot_size_graph, "toggled", G_CALLBACK(plot_size_graph_changed), &controls); row++; controls.create_images = gtk_check_button_new_with_mnemonic(_("Create tip i_mages")); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(controls.create_images), args->create_images); gtk_table_attach(GTK_TABLE(table), controls.create_images, 0, 4, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); g_signal_connect(controls.create_images, "toggled", G_CALLBACK(create_images_changed), &controls); row++; controls.tipdone = FALSE; controls.in_update = FALSE; split_to_stripes_changed(GTK_TOGGLE_BUTTON(controls.split_to_stripes), &controls); gtk_widget_show_all(dialog); do { response = gtk_dialog_run(GTK_DIALOG(dialog)); switch (response) { case GTK_RESPONSE_CANCEL: case GTK_RESPONSE_DELETE_EVENT: gtk_widget_destroy(dialog); case GTK_RESPONSE_NONE: tip_blind_dialog_abandon(&controls); tip_blind_save_args(gwy_app_settings_get(), args); return; break; case GTK_RESPONSE_OK: tip_blind_save_args(gwy_app_settings_get(), args); tip_blind_do(&controls, args); break; case RESPONSE_RESET: reset(&controls, args); break; case RESPONSE_ESTIMATE: tip_blind_run(&controls, args, FALSE); break; case RESPONSE_REFINE: tip_blind_run(&controls, args, TRUE); break; default: g_assert_not_reached(); break; } } while (response != GTK_RESPONSE_OK); gtk_widget_destroy(dialog); tip_blind_dialog_abandon(&controls); return; }
static void immerse_do(ImmerseArgs *args) { GwyDataField *resampled, *image, *detail, *result; GwyContainer *data; gint newid; gint kxres, kyres; gint x, y, w, h; gdouble iavg, davg; GQuark quark; data = gwy_app_data_browser_get(args->image.datano); quark = gwy_app_get_data_key_for_id(args->image.id); image = GWY_DATA_FIELD(gwy_container_get_object(data, quark)); data = gwy_app_data_browser_get(args->detail.datano); quark = gwy_app_get_data_key_for_id(args->detail.id); detail = GWY_DATA_FIELD(gwy_container_get_object(data, quark)); davg = gwy_data_field_get_avg(detail); kxres = gwy_data_field_get_xres(detail); kyres = gwy_data_field_get_yres(detail); switch (args->sampling) { case GWY_IMMERSE_SAMPLING_DOWN: result = gwy_data_field_duplicate(image); x = gwy_data_field_rtoj(image, args->xpos); y = gwy_data_field_rtoi(image, args->ypos); w = GWY_ROUND(gwy_data_field_get_xreal(detail) /gwy_data_field_get_xmeasure(image)); h = GWY_ROUND(gwy_data_field_get_yreal(detail) /gwy_data_field_get_ymeasure(image)); w = MAX(w, 1); h = MAX(h, 1); gwy_debug("w: %d, h: %d", w, h); resampled = gwy_data_field_new_resampled(detail, w, h, GWY_INTERPOLATION_LINEAR); if (args->leveling == GWY_IMMERSE_LEVEL_MEAN) { iavg = gwy_data_field_area_get_avg(result, NULL, x, y, w, h); gwy_data_field_add(resampled, iavg - davg); } gwy_data_field_area_copy(resampled, result, 0, 0, w, h, x, y); g_object_unref(resampled); break; case GWY_IMMERSE_SAMPLING_UP: w = GWY_ROUND(gwy_data_field_get_xreal(image) /gwy_data_field_get_xmeasure(detail)); h = GWY_ROUND(gwy_data_field_get_yreal(image) /gwy_data_field_get_ymeasure(detail)); gwy_debug("w: %d, h: %d", w, h); result = gwy_data_field_new_resampled(image, w, h, GWY_INTERPOLATION_LINEAR); x = gwy_data_field_rtoj(result, args->xpos); y = gwy_data_field_rtoi(result, args->ypos); if (args->leveling == GWY_IMMERSE_LEVEL_MEAN) { iavg = gwy_data_field_area_get_avg(result, NULL, x, y, kxres, kyres); gwy_data_field_area_copy(detail, result, 0, 0, kxres, kyres, x, y); gwy_data_field_area_add(result, x, y, kxres, kyres, iavg - davg); } else gwy_data_field_area_copy(detail, result, 0, 0, kxres, kyres, x, y); break; default: g_return_if_reached(); break; } gwy_app_data_browser_get_current(GWY_APP_CONTAINER, &data, 0); newid = gwy_app_data_browser_add_data_field(result, data, TRUE); gwy_app_set_data_field_title(data, newid, _("Immersed detail")); g_object_unref(result); gwy_app_channel_log_add_proc(data, args->image.id, newid); }
static void immerse_search(ImmerseControls *controls, gint search_type) { GwyDataField *dfield, *dfieldsub, *ifield, *iarea; gdouble wr, hr, xpos, ypos, deltax, deltay; gint w, h, xfrom, xto, yfrom, yto, ixres, iyres, col, row; GwyContainer *data; GQuark quark; data = gwy_app_data_browser_get(controls->args->detail.datano); quark = gwy_app_get_data_key_for_id(controls->args->detail.id); dfield = gwy_container_get_object(data, quark); data = gwy_app_data_browser_get(controls->args->image.datano); quark = gwy_app_get_data_key_for_id(controls->args->image.id); ifield = gwy_container_get_object(data, quark); ixres = gwy_data_field_get_xres(ifield); iyres = gwy_data_field_get_yres(ifield); wr = gwy_data_field_get_xreal(dfield)/gwy_data_field_get_xmeasure(ifield); hr = gwy_data_field_get_yreal(dfield)/gwy_data_field_get_ymeasure(ifield); if (wr*hr < 6.0) { g_warning("Detail image is too small for correlation"); return; } w = GWY_ROUND(MAX(wr, 1.0)); h = GWY_ROUND(MAX(hr, 1.0)); gwy_debug("w: %d, h: %d", w, h); g_assert(w <= ixres && h <= iyres); if (search_type == RESPONSE_REFINE) { xfrom = gwy_data_field_rtoj(ifield, controls->args->xpos); yfrom = gwy_data_field_rtoi(ifield, controls->args->ypos); /* Calculate the area we will search the detail in */ deltax = improve_search_window(w, ixres); deltay = improve_search_window(h, iyres); gwy_debug("deltax: %g, deltay: %g", deltax, deltay); xto = MIN(xfrom + w + deltax, ixres); yto = MIN(yfrom + h + deltay, iyres); xfrom = MAX(xfrom - deltax, 0); yfrom = MAX(yfrom - deltay, 0); } else { xfrom = yfrom = 0; xto = ixres; yto = iyres; } gwy_debug("x: %d..%d, y: %d..%d", xfrom, xto, yfrom, yto); /* Cut out only the interesting part from the image data field */ if (xfrom == 0 && yfrom == 0 && xto == ixres && yto == iyres) iarea = g_object_ref(ifield); else iarea = gwy_data_field_area_extract(ifield, xfrom, yfrom, xto - xfrom, yto - yfrom); dfieldsub = gwy_data_field_new_resampled(dfield, w, h, GWY_INTERPOLATION_LINEAR); immerse_correlate(iarea, dfieldsub, &col, &row); gwy_debug("[c] col: %d, row: %d", col, row); col += xfrom; row += yfrom; xpos = gwy_data_field_jtor(dfieldsub, col + 0.5); ypos = gwy_data_field_itor(dfieldsub, row + 0.5); g_object_unref(iarea); g_object_unref(dfieldsub); gwy_debug("[C] col: %d, row: %d", col, row); /* Upsample and refine */ xfrom = MAX(col - 1, 0); yfrom = MAX(row - 1, 0); xto = MIN(col + w + 1, ixres); yto = MIN(row + h + 1, iyres); gwy_debug("x: %d..%d, y: %d..%d", xfrom, xto, yfrom, yto); iarea = gwy_data_field_area_extract(ifield, xfrom, yfrom, xto - xfrom, yto - yfrom); wr = gwy_data_field_get_xreal(iarea)/gwy_data_field_get_xmeasure(dfield); hr = gwy_data_field_get_yreal(iarea)/gwy_data_field_get_ymeasure(dfield); gwy_data_field_resample(iarea, GWY_ROUND(wr), GWY_ROUND(hr), GWY_INTERPOLATION_LINEAR); immerse_correlate(iarea, dfield, &col, &row); gwy_debug("[U] col: %d, row: %d", col, row); xpos = gwy_data_field_jtor(dfield, col + 0.5) + gwy_data_field_jtor(ifield, xfrom); ypos = gwy_data_field_itor(dfield, row + 0.5) + gwy_data_field_itor(ifield, yfrom); g_object_unref(iarea); immerse_clamp_detail_offset(controls, xpos, ypos); }
static void merge_do_correlate(MergeArgs *args) { GwyDataField *dfield1, *dfield2; GwyDataField *correlation_data, *correlation_kernel, *correlation_score; GwyRectangle cdata, kdata; gint max_col, max_row; gint xres1, xres2, yres1, yres2; GwyMergeDirectionType real_dir = args->direction; GwyMergeBoundaryType real_boundary = args->boundary; gint px1, py1, px2, py2; GwyContainer *data1, *data2; GQuark quark; data1 = gwy_app_data_browser_get(args->op1.datano); quark = gwy_app_get_data_key_for_id(args->op1.id); dfield1 = GWY_DATA_FIELD(gwy_container_get_object(data1, quark)); data2 = gwy_app_data_browser_get(args->op2.datano); quark = gwy_app_get_data_key_for_id(args->op2.id); dfield2 = GWY_DATA_FIELD(gwy_container_get_object(data2, quark)); if ((dfield1->xres*dfield1->yres) < (dfield2->xres*dfield2->yres)) { GWY_SWAP(GwyDataField*, dfield1, dfield2); if (args->direction == GWY_MERGE_DIRECTION_UP) real_dir = GWY_MERGE_DIRECTION_DOWN; else if (args->direction == GWY_MERGE_DIRECTION_DOWN) real_dir = GWY_MERGE_DIRECTION_UP; else if (args->direction == GWY_MERGE_DIRECTION_LEFT) real_dir = GWY_MERGE_DIRECTION_RIGHT; else if (args->direction == GWY_MERGE_DIRECTION_RIGHT) real_dir = GWY_MERGE_DIRECTION_LEFT; else g_return_if_reached(); if (args->boundary == GWY_MERGE_BOUNDARY_FIRST) real_boundary = GWY_MERGE_BOUNDARY_SECOND; else if (args->boundary == GWY_MERGE_BOUNDARY_SECOND) real_boundary = GWY_MERGE_BOUNDARY_FIRST; } xres1 = gwy_data_field_get_xres(dfield1); xres2 = gwy_data_field_get_xres(dfield2); yres1 = gwy_data_field_get_yres(dfield1); yres2 = gwy_data_field_get_yres(dfield2); /*cut data for correlation*/ switch (real_dir) { case GWY_MERGE_DIRECTION_UP: cdata.x = 0; cdata.y = 0; cdata.width = xres1; cdata.height = yres1/2; kdata.width = MIN(xres2, cdata.width/2); kdata.height = MIN(yres2, cdata.height/3); kdata.x = MAX(0, xres2/2 - kdata.width/2); kdata.y = MAX(0, yres2 - cdata.height/3); break; case GWY_MERGE_DIRECTION_DOWN: cdata.x = 0; cdata.y = yres1 - (yres1/2); cdata.width = xres1; cdata.height = yres1/2; kdata.width = MIN(xres2, cdata.width/2); kdata.height = MIN(yres2, cdata.height/3); kdata.x = MAX(0, xres2/2 - kdata.width/2); kdata.y = 0; break; case GWY_MERGE_DIRECTION_RIGHT: cdata.x = xres1 - (xres1/2); cdata.y = 0; cdata.width = xres1/2; cdata.height = yres1; kdata.width = MIN(xres2, cdata.width/3); kdata.height = MIN(yres2, cdata.height/2); kdata.x = 0; kdata.y = MAX(0, yres2/2 - kdata.height/2); break; case GWY_MERGE_DIRECTION_LEFT: cdata.x = 0; cdata.y = 0; cdata.width = xres1/2; cdata.height = yres1; kdata.width = MIN(xres2, cdata.width/3); kdata.height = MIN(yres2, cdata.height/2); kdata.x = MAX(0, xres2 - cdata.width/3); kdata.y = MAX(0, yres2/2 - kdata.height/2); break; default: g_assert_not_reached(); break; } correlation_data = gwy_data_field_area_extract(dfield1, cdata.x, cdata.y, cdata.width, cdata.height); correlation_kernel = gwy_data_field_area_extract(dfield2, kdata.x, kdata.y, kdata.width, kdata.height); correlation_score = gwy_data_field_new_alike(correlation_data, FALSE); /* get appropriate correlation score */ if (!get_score_iteratively(correlation_data, correlation_kernel, correlation_score, args)) goto end; find_score_maximum(correlation_score, &max_col, &max_row); gwy_debug("c: %d %d %dx%d k: %d %d %dx%d res: %d %d", cdata.x, cdata.y, cdata.width, cdata.height, kdata.x, kdata.y, kdata.width, kdata.height, max_col, max_row); px1 = 0; px2 = (max_col - (kdata.width-1)/2) + cdata.x - kdata.x; py1 = 0; py2 = (max_row - (kdata.height-1)/2) + cdata.y - kdata.y; if (px2 < 0) { px1 = -px2; px2 = 0; } if (py2 < 0) { py1 = -py2; py2 = 0; } create_merged_field(data1, args->op1.id, dfield1, dfield2, px1, py1, px2, py2, real_boundary, real_dir, args->create_mask, args->crop_to_rectangle); end: g_object_unref(correlation_data); g_object_unref(correlation_kernel); g_object_unref(correlation_score); }
static void maskcor_do(MaskcorArgs *args) { enum { WORK_PER_UPDATE = 50000000 }; GwyDataField *dfield, *kernel, *retfield, *score; GwyContainer *data, *kerneldata; GwyComputationState *state; GQuark quark; gint newid, work, wpi; kerneldata = gwy_app_data_browser_get(args->kernel.datano); quark = gwy_app_get_data_key_for_id(args->kernel.id); kernel = GWY_DATA_FIELD(gwy_container_get_object(kerneldata, quark)); data = gwy_app_data_browser_get(args->data.datano); quark = gwy_app_get_data_key_for_id(args->data.id); dfield = GWY_DATA_FIELD(gwy_container_get_object(data, quark)); retfield = gwy_data_field_new_alike(dfield, FALSE); /* FIXME */ if (args->method == GWY_CORRELATION_NORMAL) { gwy_app_wait_start(gwy_app_find_window_for_channel(data, args->data.id), _("Initializing...")); state = gwy_data_field_correlate_init(dfield, kernel, retfield); gwy_app_wait_set_message(_("Correlating...")); work = 0; wpi = gwy_data_field_get_xres(kernel)*gwy_data_field_get_yres(kernel); wpi = MIN(wpi, WORK_PER_UPDATE); do { gwy_data_field_correlate_iteration(state); work += wpi; if (work > WORK_PER_UPDATE) { work -= WORK_PER_UPDATE; if (!gwy_app_wait_set_fraction(state->fraction)) { gwy_data_field_correlate_finalize(state); gwy_app_wait_finish(); g_object_unref(retfield); return; } } } while (state->state != GWY_COMPUTATION_STATE_FINISHED); gwy_data_field_correlate_finalize(state); gwy_app_wait_finish(); } else gwy_data_field_correlate(dfield, kernel, retfield, args->method); /* score - do new data with score */ if (args->result == GWY_MASKCOR_SCORE) { score = gwy_data_field_duplicate(retfield); newid = gwy_app_data_browser_add_data_field(score, data, TRUE); gwy_app_sync_data_items(data, data, args->data.id, newid, FALSE, GWY_DATA_ITEM_GRADIENT, 0); gwy_app_set_data_field_title(data, newid, _("Correlation score")); g_object_unref(score); gwy_app_channel_log_add_proc(data, args->data.id, newid); } else { /* add mask */ quark = gwy_app_get_mask_key_for_id(args->data.id); gwy_app_undo_qcheckpointv(data, 1, &quark); if (args->result == GWY_MASKCOR_OBJECTS) plot_correlated(retfield, gwy_data_field_get_xres(kernel), gwy_data_field_get_yres(kernel), args->threshold); else if (args->result == GWY_MASKCOR_MAXIMA) gwy_data_field_threshold(retfield, args->threshold, 0.0, 1.0); gwy_container_set_object(data, quark, retfield); gwy_app_channel_log_add_proc(data, args->data.id, args->data.id); } g_object_unref(retfield); }
static gboolean immerse_dialog(ImmerseArgs *args) { ImmerseControls controls; GwyContainer *data; GtkDialog *dialog; GtkWidget *table, *chooser, *hbox, *alignment, *label, *button, *vbox; GtkTooltips *tooltips; GdkDisplay *display; GwyDataField *dfield; gint response, row, id; gboolean ok; memset(&controls, 0, sizeof(ImmerseControls)); controls.args = args; tooltips = gwy_app_get_tooltips(); controls.dialog = gtk_dialog_new_with_buttons(_("Immerse Detail"), NULL, 0, NULL); dialog = GTK_DIALOG(controls.dialog); button = gtk_dialog_add_button(dialog, _("_Locate"), RESPONSE_ESTIMATE); gtk_tooltips_set_tip(tooltips, button, _("Locate detail by full image correlation search"), NULL); button = gtk_dialog_add_button(dialog, _("_Improve"), RESPONSE_REFINE); gtk_tooltips_set_tip(tooltips, button, _("Improve detail position by " "correlation search in neighborhood"), NULL); gtk_dialog_add_button(dialog, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL); gtk_dialog_add_button(dialog, GTK_STOCK_OK, GTK_RESPONSE_OK); gtk_dialog_set_default_response(dialog, GTK_RESPONSE_OK); gwy_help_add_to_proc_dialog(GTK_DIALOG(dialog), GWY_HELP_DEFAULT); hbox = gtk_hbox_new(FALSE, 2); gtk_box_pack_start(GTK_BOX(dialog->vbox), hbox, FALSE, FALSE, 4); /* Preview */ data = gwy_app_data_browser_get(args->image.datano); id = args->image.id; dfield = gwy_container_get_object(data, gwy_app_get_data_key_for_id(id)); controls.vf = gwy_data_field_get_value_format_xy(dfield, GWY_SI_UNIT_FORMAT_VFMARKUP, NULL); controls.mydata = gwy_container_new(); gwy_container_set_object_by_name(controls.mydata, "/0/data", dfield); gwy_app_sync_data_items(data, controls.mydata, id, 0, FALSE, GWY_DATA_ITEM_PALETTE, GWY_DATA_ITEM_MASK_COLOR, GWY_DATA_ITEM_RANGE, 0); gwy_container_set_boolean_by_name(controls.mydata, "/0/data/realsquare", TRUE); controls.view = create_preview(controls.mydata, 0, PREVIEW_SIZE, FALSE); alignment = GTK_WIDGET(gtk_alignment_new(0.5, 0, 0, 0)); gtk_container_add(GTK_CONTAINER(alignment), controls.view); gtk_box_pack_start(GTK_BOX(hbox), alignment, FALSE, FALSE, 4); g_signal_connect_after(controls.view, "expose-event", G_CALLBACK(immerse_view_expose), &controls); g_signal_connect(controls.view, "button-press-event", G_CALLBACK(immerse_view_button_press), &controls); g_signal_connect(controls.view, "button-release-event", G_CALLBACK(immerse_view_button_release), &controls); g_signal_connect(controls.view, "motion-notify-event", G_CALLBACK(immerse_view_motion_notify), &controls); vbox = gtk_vbox_new(FALSE, 8); gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 4); /* Parameters table */ table = gtk_table_new(8, 4, FALSE); gtk_table_set_row_spacings(GTK_TABLE(table), 2); gtk_table_set_col_spacings(GTK_TABLE(table), 6); gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 4); row = 0; /* Detail to immerse */ chooser = gwy_data_chooser_new_channels(); gwy_data_chooser_set_active_id(GWY_DATA_CHOOSER(chooser), &args->detail); gwy_data_chooser_set_filter(GWY_DATA_CHOOSER(chooser), immerse_data_filter, &args->image, NULL); gwy_data_chooser_get_active_id(GWY_DATA_CHOOSER(chooser), &args->detail); g_signal_connect(chooser, "changed", G_CALLBACK(immerse_detail_cb), &controls); gwy_table_attach_hscale(table, row, _("_Detail image:"), NULL, GTK_OBJECT(chooser), GWY_HSCALE_WIDGET_NO_EXPAND); row++; /* Detail position */ label = gtk_label_new(_("Position:")); gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row+1, GTK_FILL, 0, 0, 0); controls.pos = gtk_label_new(NULL); gtk_misc_set_alignment(GTK_MISC(controls.pos), 0.0, 0.5); gtk_table_attach(GTK_TABLE(table), controls.pos, 1, 3, row, row+1, GTK_FILL, 0, 0, 0); gtk_table_set_row_spacing(GTK_TABLE(table), row, 8); row++; /* Sampling */ label = gtk_label_new(_("Result Sampling")); gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); gtk_table_attach(GTK_TABLE(table), label, 0, 3, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); row++; controls.sampling = gwy_radio_buttons_createl(G_CALLBACK(immerse_sampling_changed), &controls, args->sampling, _("_Upsample large image"), GWY_IMMERSE_SAMPLING_UP, _("_Downsample detail"), GWY_IMMERSE_SAMPLING_DOWN, NULL); row = gwy_radio_buttons_attach_to_table(controls.sampling, GTK_TABLE(table), 4, row); gtk_table_set_row_spacing(GTK_TABLE(table), row-1, 8); /* Leveling */ label = gtk_label_new(_("Detail Leveling")); gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); gtk_table_attach(GTK_TABLE(table), label, 0, 3, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); row++; controls.leveling = gwy_radio_buttons_createl(G_CALLBACK(immerse_leveling_changed), &controls, args->leveling, gwy_sgettext("levelling|_None"), GWY_IMMERSE_LEVEL_NONE, _("_Mean value"), GWY_IMMERSE_LEVEL_MEAN, NULL); row = gwy_radio_buttons_attach_to_table(controls.leveling, GTK_TABLE(table), 4, row); gtk_table_set_row_spacing(GTK_TABLE(table), row-1, 8); /* Draw frame */ controls.draw_frame = gtk_check_button_new_with_mnemonic(_("Show _frame")); gtk_table_attach(GTK_TABLE(table), controls.draw_frame, 0, 3, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(controls.draw_frame), args->draw_frame); g_signal_connect(controls.draw_frame, "toggled", G_CALLBACK(immerse_frame_toggled), &controls); gtk_widget_show_all(controls.dialog); display = gtk_widget_get_display(controls.dialog); controls.near_cursor = gdk_cursor_new_for_display(display, GDK_FLEUR); controls.move_cursor = gdk_cursor_new_for_display(display, GDK_CROSS); immerse_detail_cb(GWY_DATA_CHOOSER(chooser), &controls); ok = FALSE; do { response = gtk_dialog_run(dialog); switch (response) { case GTK_RESPONSE_CANCEL: case GTK_RESPONSE_DELETE_EVENT: case GTK_RESPONSE_NONE: immerse_controls_destroy(&controls); immerse_save_args(gwy_app_settings_get(), args); return FALSE; break; case RESPONSE_ESTIMATE: case RESPONSE_REFINE: immerse_search(&controls, response); break; case GTK_RESPONSE_OK: ok = TRUE; break; default: g_assert_not_reached(); break; } } while (!ok); immerse_controls_destroy(&controls); immerse_save_args(gwy_app_settings_get(), args); return TRUE; }
static void merge_do_join(MergeArgs *args) { GwyDataField *dfield1, *dfield2; gint xres1, xres2, yres1, yres2; gint maxover, i, off = 0; gint px1, py1, px2, py2; GwyContainer *data1, *data2; gdouble s, smin = G_MAXDOUBLE; GwyMergeBoundaryType real_boundary = args->boundary; GwyMergeDirectionType real_dir = args->direction; GQuark quark; data1 = gwy_app_data_browser_get(args->op1.datano); quark = gwy_app_get_data_key_for_id(args->op1.id); dfield1 = GWY_DATA_FIELD(gwy_container_get_object(data1, quark)); data2 = gwy_app_data_browser_get(args->op2.datano); quark = gwy_app_get_data_key_for_id(args->op2.id); dfield2 = GWY_DATA_FIELD(gwy_container_get_object(data2, quark)); /* Reduce joining to two cases. */ if (args->direction == GWY_MERGE_DIRECTION_UP || args->direction == GWY_MERGE_DIRECTION_LEFT) { GWY_SWAP(GwyDataField*, dfield1, dfield2); if (args->direction == GWY_MERGE_DIRECTION_UP) real_dir = GWY_MERGE_DIRECTION_DOWN; else if (args->direction == GWY_MERGE_DIRECTION_LEFT) real_dir = GWY_MERGE_DIRECTION_RIGHT; else { g_assert_not_reached(); } if (args->boundary == GWY_MERGE_BOUNDARY_FIRST) real_boundary = GWY_MERGE_BOUNDARY_SECOND; else if (args->boundary == GWY_MERGE_BOUNDARY_SECOND) real_boundary = GWY_MERGE_BOUNDARY_FIRST; } xres1 = gwy_data_field_get_xres(dfield1); yres1 = gwy_data_field_get_yres(dfield1); xres2 = gwy_data_field_get_xres(dfield2); yres2 = gwy_data_field_get_yres(dfield2); if (real_dir == GWY_MERGE_DIRECTION_DOWN) { g_return_if_fail(xres1 == xres2); maxover = 2*MIN(yres1, yres2)/5; for (i = 1; i <= maxover; i++) { s = get_row_difference(dfield1, 0, yres1 - i, dfield2, 0, 0, xres1, i); if (s < smin) { off = i; smin = s; } } /* Turn one-pixel overlap to no overlap. */ if (off == 1) off = 0; px1 = px2 = 0; py1 = 0; py2 = yres1 - off; } else if (real_dir == GWY_MERGE_DIRECTION_RIGHT) { g_return_if_fail(yres1 == yres2); maxover = 2*MIN(xres1, xres2)/5; for (i = 1; i <= maxover; i++) { s = get_column_difference(dfield1, xres1 - i, 0, dfield2, 0, 0, i, yres1); if (s < smin) { off = i; smin = s; } } /* Turn one-pixel overlap to no overlap. */ if (off == 1) off = 0; py1 = py2 = 0; px1 = 0; px2 = xres1 - off; } else { g_assert_not_reached(); } create_merged_field(data1, args->op1.id, dfield1, dfield2, px1, py1, px2, py2, real_boundary, real_dir, FALSE, FALSE); }