static GwyDataField* get_right_tip_field(GwyDataField *tip, GwyDataField *surface, gboolean *freetip) { GwyDataField *buffer; gdouble tipxstep, tipystep; gdouble surfxstep, surfystep; *freetip = FALSE; tipxstep = tip->xreal/tip->xres; surfxstep = surface->xreal/surface->xres; tipystep = tip->yreal/tip->yres; surfystep = surface->yreal/surface->yres; if (fabs(tipxstep/surfxstep - 1.0) > 0.01 || fabs(tipystep/surfystep - 1.0) > 0.01) { buffer = GWY_DATA_FIELD(gwy_data_field_new(tip->xres, tip->yres, tip->xreal, tip->yreal, FALSE)); gwy_data_field_copy(tip, buffer); gwy_data_field_resample(buffer, tip->xres/surfxstep*tipxstep, tip->yres/surfystep*tipystep, GWY_INTERPOLATION_BILINEAR); *freetip = TRUE; return buffer; } else return tip; }
static gboolean prepare_fields(GwyDataField *tipfield, GwyDataField *surface, gint xres, gint yres) { gint xoldres, yoldres; /*set real sizes corresponding to actual data*/ gwy_data_field_set_xreal(tipfield, gwy_data_field_get_xmeasure(surface) *gwy_data_field_get_xres(tipfield)); gwy_data_field_set_yreal(tipfield, gwy_data_field_get_ymeasure(surface) *gwy_data_field_get_yres(tipfield)); /*if user has changed tip size, change it*/ if ((xres != gwy_data_field_get_xres(tipfield)) || (yres != gwy_data_field_get_yres(tipfield))) { xoldres = gwy_data_field_get_xres(tipfield); yoldres = gwy_data_field_get_yres(tipfield); gwy_data_field_resample(tipfield, xres, yres, GWY_INTERPOLATION_NONE); gwy_data_field_set_xreal(tipfield, gwy_data_field_get_xreal(tipfield) /xoldres*xres); gwy_data_field_set_yreal(tipfield, gwy_data_field_get_yreal(tipfield) /yoldres*yres); gwy_data_field_clear(tipfield); return FALSE; } return TRUE; }
static gboolean prewitt_vertical(GwyContainer *data, GwyRunType run) { GObject *shadefield; GwyDataField *dfield; g_assert(run & GRADIENT_RUN_MODES); dfield = GWY_DATA_FIELD(gwy_container_get_object_by_name(data, "/0/data")); gwy_app_undo_checkpoint(data, "/0/show", NULL); if (gwy_container_gis_object_by_name(data, "/0/show", &shadefield)) { gwy_data_field_resample(GWY_DATA_FIELD(shadefield), gwy_data_field_get_xres(dfield), gwy_data_field_get_yres(dfield), GWY_INTERPOLATION_NONE); } else { shadefield = gwy_serializable_duplicate(G_OBJECT(dfield)); gwy_container_set_object_by_name(data, "/0/show", shadefield); g_object_unref(shadefield); } gwy_data_field_area_copy(dfield, GWY_DATA_FIELD(shadefield), 0, 0, gwy_data_field_get_xres(dfield), gwy_data_field_get_yres(dfield), 0, 0); gwy_data_field_area_filter_prewitt(GWY_DATA_FIELD(shadefield), GTK_ORIENTATION_VERTICAL, 0, 0, gwy_data_field_get_xres(dfield), gwy_data_field_get_yres(dfield)); return TRUE; }
static void flip_xy(GwyDataField *source, GwyDataField *dest, gboolean minor) { gint xres, yres, i, j; gdouble *dd; const gdouble *sd; xres = gwy_data_field_get_xres(source); yres = gwy_data_field_get_yres(source); gwy_data_field_resample(dest, yres, xres, GWY_INTERPOLATION_NONE); sd = gwy_data_field_get_data_const(source); dd = gwy_data_field_get_data(dest); if (minor) { for (i = 0; i < xres; i++) { for (j = 0; j < yres; j++) { dd[i*yres + j] = sd[j*xres + (xres - 1 - i)]; } } } else { for (i = 0; i < xres; i++) { for (j = 0; j < yres; j++) { dd[i*yres + (yres - 1 - j)] = sd[j*xres + i]; } } } gwy_data_field_set_xreal(dest, gwy_data_field_get_yreal(source)); gwy_data_field_set_yreal(dest, gwy_data_field_get_xreal(source)); }
static void presentation_logscale(GwyContainer *data, GwyRunType run) { GwyDataField *dfield, *sfield; GQuark squark; gdouble *d; gdouble min, max, m0; gint xres, yres, i, zeroes, id; g_return_if_fail(run & PRESENTATIONOPS_RUN_MODES); gwy_app_data_browser_get_current(GWY_APP_DATA_FIELD, &dfield, GWY_APP_SHOW_FIELD_KEY, &squark, GWY_APP_SHOW_FIELD, &sfield, GWY_APP_DATA_FIELD_ID, &id, 0); g_return_if_fail(dfield && squark); xres = gwy_data_field_get_xres(dfield); yres = gwy_data_field_get_yres(dfield); gwy_app_undo_qcheckpointv(data, 1, &squark); if (!sfield) { sfield = gwy_data_field_duplicate(dfield); gwy_container_set_object(data, squark, sfield); g_object_unref(sfield); } else { gwy_data_field_resample(sfield, xres, yres, GWY_INTERPOLATION_NONE); gwy_data_field_copy(dfield, sfield, FALSE); } d = gwy_data_field_get_data(sfield); zeroes = 0; max = 0; min = G_MAXDOUBLE; for (i = 0; i < xres*yres; i++) { d[i] = ABS(d[i]); if (G_UNLIKELY(d[i] > max)) max = d[i]; if (d[i] == 0.0) zeroes++; else if (G_UNLIKELY(d[i] < min)) min = d[i]; } if (min == max || zeroes == xres*yres) return; if (!zeroes) { for (i = 0; i < xres*yres; i++) d[i] = log(d[i]); } else { m0 = log(min) - log(max/min)/512.0; for (i = 0; i < xres*yres; i++) d[i] = d[i] ? log(d[i]) : m0; } gwy_data_field_data_changed(sfield); gwy_app_channel_log_add_proc(data, id, id); }
static void create_merged_field(GwyContainer *data, gint id1, GwyDataField *dfield1, GwyDataField *dfield2, gint px1, gint py1, gint px2, gint py2, GwyMergeBoundaryType boundary, GwyMergeDirectionType dir, gboolean create_mask, gboolean crop_to_rectangle) { GwyDataField *result, *outsidemask = NULL; gint newxres, newyres, newid; gwy_debug("field1 %dx%d", dfield1->xres, dfield1->yres); gwy_debug("field2 %dx%d", dfield2->xres, dfield2->yres); gwy_debug("px1: %d, py1: %d, px2: %d, py2: %d", px1, py1, px2, py2); result = gwy_data_field_new_alike(dfield1, FALSE); newxres = MAX(dfield1->xres + px1, dfield2->xres + px2); newyres = MAX(dfield1->yres + py1, dfield2->yres + py2); gwy_data_field_resample(result, newxres, newyres, GWY_INTERPOLATION_NONE); if (create_mask && !crop_to_rectangle) { outsidemask = gwy_data_field_new_alike(result, FALSE); gwy_si_unit_set_from_string(gwy_data_field_get_si_unit_z(outsidemask), NULL); } put_fields(dfield1, dfield2, result, outsidemask, boundary, px1, py1, px2, py2); if (crop_to_rectangle) { GwyOrientation orientation = GWY_ORIENTATION_HORIZONTAL; if (dir == GWY_MERGE_DIRECTION_UP || dir == GWY_MERGE_DIRECTION_DOWN) orientation = GWY_ORIENTATION_VERTICAL; crop_result(result, dfield1, dfield2, orientation, px1, py1, px2, py2); } 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, _("Merged images")); gwy_app_sync_data_items(data, data, id1, newid, FALSE, GWY_DATA_ITEM_PALETTE, GWY_DATA_ITEM_MASK_COLOR, GWY_DATA_ITEM_RANGE, 0); if (outsidemask) { if (gwy_data_field_get_max(outsidemask) > 0.0) { GQuark quark = gwy_app_get_mask_key_for_id(newid); gwy_container_set_object(data, quark, outsidemask); } g_object_unref(outsidemask); } gwy_app_channel_log_add_proc(data, -1, newid); g_object_unref(result); }
static void tip_process(TipModelArgs *args, TipModelControls *controls) { const GwyTipModelPreset *preset; GwyDataField *dfield; GwyDataField *sfield; GQuark quark; gchar label[64]; gint xres, yres; gdouble xstep, ystep, min, max, zrange; gdouble params[2]; preset = gwy_tip_model_get_preset(args->type); g_return_if_fail(preset); tip_model_dialog_update_values(controls, args); /* estimate x and y size */ dfield = controls->tip; quark = gwy_app_get_data_key_for_id(args->object.id); sfield = GWY_DATA_FIELD(gwy_container_get_object(args->object.data, quark)); gwy_data_field_set_xreal(dfield, gwy_data_field_get_xmeasure(sfield) *gwy_data_field_get_xres(dfield)); gwy_data_field_set_yreal(dfield, gwy_data_field_get_ymeasure(sfield) *gwy_data_field_get_yres(dfield)); params[0] = args->nsides; params[1] = args->angle*G_PI/180; gwy_data_field_get_min_max(sfield, &min, &max); zrange = max - min; preset->guess(sfield, zrange, args->radius, params, &xres, &yres); /* process tip */ /* FIXME: this must be solved within guess functions */ xres = CLAMP(xres, 20, 1000); yres = CLAMP(yres, 20, 1000); g_snprintf(label, sizeof(label), _("Tip resolution: %d × %d pixels"), xres, yres); gtk_label_set_text(GTK_LABEL(controls->labsize), label); xstep = gwy_data_field_get_xmeasure(dfield); ystep = gwy_data_field_get_ymeasure(dfield); gwy_data_field_resample(dfield, xres, yres, GWY_INTERPOLATION_NONE); gwy_data_field_set_xreal(dfield, xstep*xres); gwy_data_field_set_yreal(dfield, ystep*yres); preset->func(dfield, zrange, args->radius, args->theta*G_PI/180, params); tip_update(controls, args); }
/** * gwy_tip_erosion: * @tip: Tip data. * @surface: Surface to be eroded. * @result: Data field where to store dilated surface to. * @set_fraction: Function that sets fraction to output (or %NULL). * @set_message: Function that sets message to output (or %NULL). * * Performs surface reconstruction (erosion) algorithm published by * Villarrubia. This function converts all fields into form requested by * "morph_lib.c" library, that is almost identical with original Villarubia's * library. * * Returns: Reconstructed (eroded) surface, i.e. @result, on success. May * return %NULL if aborted. **/ GwyDataField* gwy_tip_erosion(GwyDataField *tip, GwyDataField *surface, GwyDataField *result, GwySetFractionFunc set_fraction, GwySetMessageFunc set_message) { gdouble **ftip; gdouble **fsurface; gdouble **fresult; GwyDataField *buffertip; gboolean freetip; /*if tip and surface have different spacings, make new, resampled tip*/ buffertip = get_right_tip_field(tip, surface, &freetip); /*invert tip (as necessary by dilation algorithm)*/ gwy_data_field_invert(buffertip, TRUE, TRUE, FALSE); /*make auxiliary data arrays expected by Villarubia's algorithms*/ ftip = datafield_to_field(buffertip, TRUE); fsurface = datafield_to_field(surface, FALSE); fresult = _gwy_morph_lib_derosion(fsurface, surface->yres, surface->xres, ftip, buffertip->yres, buffertip->xres, buffertip->yres/2, buffertip->xres/2, set_fraction, set_message); /*convert result back from auxiliary array*/ if (fresult) { gwy_data_field_resample(result, surface->xres, surface->yres, GWY_INTERPOLATION_NONE); result = field_to_datafield(fresult, result); } else result = NULL; /*free auxiliary data arrays*/ _gwy_morph_lib_dfreematrix(ftip, buffertip->xres); _gwy_morph_lib_dfreematrix(fsurface, surface->xres); if (fresult) _gwy_morph_lib_dfreematrix(fresult, result->xres); if (freetip) g_object_unref(buffertip); else gwy_data_field_invert(buffertip, TRUE, TRUE, FALSE); return result; }
static void tip_update(TipModelControls *controls, G_GNUC_UNUSED TipModelArgs *args) { GwyDataField *vtipfield, *buffer; buffer = gwy_data_field_duplicate(controls->tip); gwy_data_field_resample(buffer, controls->vxres, controls->vyres, GWY_INTERPOLATION_ROUND); vtipfield = GWY_DATA_FIELD(gwy_container_get_object_by_name(controls->vtip, "/0/data")); gwy_data_field_copy(buffer, vtipfield, FALSE); g_object_unref(buffer); gwy_data_field_data_changed(vtipfield); }
static void preview(WshedControls *controls, WshedArgs *args) { GwyDataField *maskfield, *dfield; GwyPixmapLayer *layer; dfield = GWY_DATA_FIELD(gwy_container_get_object_by_name(controls->mydata, "/0/data")); /*set up the mask*/ if (gwy_container_contains_by_name(controls->mydata, "/0/mask")) { maskfield = GWY_DATA_FIELD(gwy_container_get_object_by_name(controls->mydata, "/0/mask")); gwy_data_field_resample(maskfield, gwy_data_field_get_xres(dfield), gwy_data_field_get_yres(dfield), GWY_INTERPOLATION_NONE); gwy_data_field_copy(dfield, maskfield); if (!gwy_data_view_get_alpha_layer(GWY_DATA_VIEW(controls->view))) { layer = GWY_PIXMAP_LAYER(gwy_layer_mask_new()); gwy_data_view_set_alpha_layer(GWY_DATA_VIEW(controls->view), layer); } } else { maskfield = GWY_DATA_FIELD(gwy_serializable_duplicate(G_OBJECT(dfield))); gwy_container_set_object_by_name(controls->mydata, "/0/mask", G_OBJECT(maskfield)); g_object_unref(maskfield); layer = GWY_PIXMAP_LAYER(gwy_layer_mask_new()); gwy_data_view_set_alpha_layer(GWY_DATA_VIEW(controls->view), layer); } wshed_dialog_update_values(controls, args); controls->computed = mask_process(dfield, maskfield, args, controls->dialog); if (controls->computed) gwy_data_view_update(GWY_DATA_VIEW(controls->view)); }
static void rotate_datafield(GwyDataField *dfield, RotateArgs *args) { gint xres, yres, xborder, yborder; gdouble xreal, yreal, phi, min; GwyDataField *df; if (!args->expand) { gwy_data_field_rotate(dfield, args->angle, args->interp); return; } xres = gwy_data_field_get_xres(dfield); yres = gwy_data_field_get_yres(dfield); xreal = gwy_data_field_get_xreal(dfield); yreal = gwy_data_field_get_yreal(dfield); min = gwy_data_field_get_min(dfield); phi = args->angle; xborder = fabs(xres/2.0 * cos(phi)) + fabs(yres/2.0 * sin(phi)); xborder -= xres/2; yborder = fabs(yres/2.0 * cos(phi)) + fabs(xres/2.0 * sin(phi)); yborder -= yres/2; df = gwy_data_field_new(xres + fabs(2*xborder), yres + fabs(2*yborder), 1.0, 1.0, FALSE); gwy_data_field_fill(df, min); gwy_data_field_area_copy(dfield, df, 0, 0, xres, yres, fabs(xborder), fabs(yborder)); gwy_data_field_rotate(df, args->angle, args->interp); gwy_data_field_resample(dfield, xres + 2*xborder, yres + 2*yborder, GWY_INTERPOLATION_NONE); if (xborder <= 0) gwy_data_field_area_copy(df, dfield, fabs(2*xborder), 0, xres + 2*xborder, yres + 2*yborder, 0, 0); else { if (yborder <= 0) gwy_data_field_area_copy(df, dfield, 0, fabs(2*yborder), xres + 2*xborder, yres + 2*yborder, 0, 0); else gwy_data_field_area_copy(df, dfield, 0, 0, xres + 2*xborder, yres + 2*yborder, 0, 0); } gwy_data_field_set_xreal(dfield, xreal*(xres + 2.0*xborder)/xres); gwy_data_field_set_yreal(dfield, yreal*(yres + 2.0*yborder)/yres); g_object_unref(df); }
static void read_data_field(GwyDataField *dfield, EZDSection *section) { gdouble *data; gdouble q, z0; guint i, j; gint xres, yres; g_assert(section->data); xres = section->xres; yres = section->yres; gwy_data_field_resample(dfield, xres, yres, GWY_INTERPOLATION_NONE); data = gwy_data_field_get_data(dfield); q = 1 << section->bitdepth; z0 = q/2.0; if (section->bitdepth == 8) { const gchar *p = section->data; for (i = 0; i < yres; i++) { for (j = 0; j < xres; j++) data[i*xres + j] = (p[(yres-1 - i)*xres + j] + z0)/q; } } else if (section->bitdepth == 16) { const gint16 *p = (const gint16*)section->data; for (i = 0; i < yres; i++) { for (j = 0; j < xres; j++) { data[i*xres + j] = GINT16_FROM_LE(p[(yres-1 - i)*xres + j]); data[i*xres + j] = (data[i*xres + j] + z0)/q; } } } else g_warning("Damn! Bit depth %d is not implemented", section->bitdepth); }
/* create a smaller copy of data */ static GwyContainer* create_preview_data(GwyContainer *data) { GwyContainer *preview; GwyDataField *dfield, *dfield_show; gint oldid; gint xres, yres; gdouble zoomval; preview = gwy_container_new(); gwy_app_data_browser_get_current(GWY_APP_DATA_FIELD, &dfield, GWY_APP_DATA_FIELD_ID, &oldid, 0); dfield = gwy_data_field_duplicate(dfield); dfield_show = gwy_data_field_duplicate(dfield); xres = gwy_data_field_get_xres(dfield); yres = gwy_data_field_get_yres(dfield); zoomval = (gdouble)PREVIEW_SIZE/MAX(xres, yres); gwy_data_field_resample(dfield, xres*zoomval, yres*zoomval, GWY_INTERPOLATION_LINEAR); dfield_show = gwy_data_field_duplicate(dfield); gwy_container_set_object_by_name(preview, "/0/data", dfield); g_object_unref(dfield); gwy_container_set_object_by_name(preview, "/0/show", dfield_show); g_object_unref(dfield_show); gwy_app_sync_data_items(data, preview, oldid, 0, FALSE, GWY_DATA_ITEM_GRADIENT, GWY_DATA_ITEM_RANGE, GWY_DATA_ITEM_MASK_COLOR, 0); return preview; }
static void fill_data_fields(SurfFile *surffile, const guchar *buffer) { gdouble *data; guint i, j; surffile->dfield = GWY_DATA_FIELD(gwy_data_field_new(surffile->xres, surffile->yres, surffile->xres*surffile->dx, surffile->yres*surffile->dy, TRUE)); data = gwy_data_field_get_data(surffile->dfield); switch (surffile->pointsize) { case 16: { const gint16 *row, *d16 = (const gint16*)buffer; for (i = 0; i < surffile->xres; i++) { row = d16 + i*surffile->yres; for (j = 0; j < surffile->yres; j++) *(data++) = GINT16_FROM_LE(row[j]) * surffile->dz; } } break; case 32: { const gint32 *row, *d32 = (const gint32*)buffer; for (i = 0; i < surffile->xres; i++) { row = d32 + i*surffile->yres; for (j = 0; j < surffile->yres; j++) *(data++) = GINT32_FROM_LE(row[j]) * surffile->dz; } } break; default: g_warning("Wrong data size: %d", surffile->pointsize); break; } /* data = gwy_data_field_get_data(surffile->dfield); for (i = 0; i < surffile->xres; i++) { for (j = 0; j < surffile->yres; j++) { if (surffile->pointsize == 16) { *(data++) = (gdouble)*(gint16*)buffer*surffile->dz; buffer += 2; } else { *(data++) = ((gdouble)*(gint32*)buffer)*surffile->dz; buffer += 4; } } } */ if (surffile->dx > surffile->dy) gwy_data_field_resample(surffile->dfield, (gint)((gdouble)(surffile->xres)*surffile->dx/surffile->dy), surffile->yres, GWY_INTERPOLATION_BILINEAR); else if (surffile->dy > surffile->dx) gwy_data_field_resample(surffile->dfield, surffile->xres, (gint)((gdouble)(surffile->yres)*surffile->dy/surffile->dx), GWY_INTERPOLATION_BILINEAR); }
static void tip_model_dialog(TipModelArgs *args) { enum { RESPONSE_RESET = 1, RESPONSE_PREVIEW = 2 }; GtkWidget *dialog, *table, *hbox, *spin; TipModelControls controls; GwyPixmapLayer *layer; GwyDataField *dfield; GwySIUnit *unit; GQuark quark; gint response, row; dialog = gtk_dialog_new_with_buttons(_("Model Tip"), NULL, 0, NULL); gtk_dialog_add_action_widget(GTK_DIALOG(dialog), gwy_stock_like_button_new(_("_Update"), GTK_STOCK_EXECUTE), RESPONSE_PREVIEW); gtk_dialog_add_button(GTK_DIALOG(dialog), _("_Reset"), RESPONSE_RESET); gtk_dialog_add_button(GTK_DIALOG(dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL); gtk_dialog_add_button(GTK_DIALOG(dialog), GTK_STOCK_OK, GTK_RESPONSE_OK); gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE); gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK); hbox = gtk_hbox_new(FALSE, 3); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), hbox, FALSE, FALSE, 4); controls.args = args; controls.vxres = 200; controls.vyres = 200; /* set up initial tip field */ quark = gwy_app_get_data_key_for_id(args->object.id); dfield = GWY_DATA_FIELD(gwy_container_get_object(args->object.data, quark)); controls.tip = gwy_data_field_new_alike(dfield, TRUE); gwy_data_field_resample(controls.tip, controls.vxres, controls.vyres, 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(args->object.data, controls.vtip, args->object.id, 0, FALSE, GWY_DATA_ITEM_PALETTE, 0); dfield = gwy_data_field_new_alike(controls.tip, TRUE); gwy_container_set_object_by_name(controls.vtip, "/0/data", dfield); g_object_unref(dfield); /* set up resampled view */ 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 model controls */ gtk_box_pack_start(GTK_BOX(hbox), controls.view, FALSE, FALSE, 4); table = gtk_table_new(6, 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.type = create_preset_menu(G_CALLBACK(tip_type_cb), &controls, args->type); gwy_table_attach_hscale(table, row, _("Tip _type:"), NULL, GTK_OBJECT(controls.type), GWY_HSCALE_WIDGET); row++; controls.nsides = gtk_adjustment_new(args->nsides, 3, 24, 1, 5, 0); gwy_table_attach_hscale(table, row, _("_Number of sides:"), NULL, controls.nsides, 0); row++; controls.angle = gtk_adjustment_new(args->angle, 0.1, 89.9, 0.1, 1, 0); spin = gwy_table_attach_hscale(table, row, _("Tip _slope:"), _("deg"), controls.angle, 0); gtk_spin_button_set_digits(GTK_SPIN_BUTTON(spin), 2); row++; controls.theta = gtk_adjustment_new(args->theta, 0, 360, 0.1, 1, 0); spin = gwy_table_attach_hscale(table, row, _("Tip _rotation:"), _("deg"), controls.theta, 0); gtk_spin_button_set_digits(GTK_SPIN_BUTTON(spin), 2); row++; controls.radius = gtk_adjustment_new(1.0, 0.01, 1000.0, 0.01, 1.0, 0.0); controls.radius_spin = gtk_spin_button_new(GTK_ADJUSTMENT(controls.radius), 0.1, 2); gtk_table_attach(GTK_TABLE(table), controls.radius_spin, 2, 3, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); controls.radius_label = gtk_label_new_with_mnemonic(_("Tip _apex radius:")); gtk_misc_set_alignment(GTK_MISC(controls.radius_label), 0.0, 0.5); gtk_label_set_mnemonic_widget(GTK_LABEL(controls.radius_label), controls.radius_spin); gtk_table_attach(GTK_TABLE(table), controls.radius_label, 0, 1, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); unit = gwy_data_field_get_si_unit_xy(dfield); controls.radius_unit = gwy_combo_box_metric_unit_new(G_CALLBACK(radius_changed_cb), &controls, -12, -3, unit, -9); gtk_table_attach(GTK_TABLE(table), controls.radius_unit, 3, 4, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); g_signal_connect(controls.radius, "value-changed", G_CALLBACK(radius_changed_cb), &controls); row++; controls.labsize = gtk_label_new(NULL); gtk_misc_set_alignment(GTK_MISC(controls.labsize), 0.0, 0.5); gtk_table_attach(GTK_TABLE(table), controls.labsize, 0, 3, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); row++; controls.tipdone = FALSE; tip_model_dialog_update_controls(&controls, args); preview(&controls, args); gtk_widget_show_all(dialog); do { response = gtk_dialog_run(GTK_DIALOG(dialog)); switch (response) { case GTK_RESPONSE_CANCEL: case GTK_RESPONSE_DELETE_EVENT: tip_model_dialog_update_values(&controls, args); gtk_widget_destroy(dialog); tip_model_dialog_abandon(&controls); case GTK_RESPONSE_NONE: return; break; case GTK_RESPONSE_OK: tip_model_do(args, &controls); break; case RESPONSE_RESET: args->nsides = tip_model_defaults.nsides; args->angle = tip_model_defaults.angle; args->radius = tip_model_defaults.radius; args->theta = tip_model_defaults.theta; args->type = tip_model_defaults.type; tip_model_dialog_update_controls(&controls, args); break; case RESPONSE_PREVIEW: tip_model_dialog_update_values(&controls, args); preview(&controls, args); break; default: g_assert_not_reached(); break; } } while (response != GTK_RESPONSE_OK); tip_model_dialog_update_values(&controls, args); gtk_widget_destroy(dialog); tip_model_dialog_abandon(&controls); }
static void dwt_denoise(GwyContainer *data, GwyRunType run) { GtkWidget *dialog; GwyDataField *dfield; GwyDataLine *wtcoefs; DWTDenoiseArgs args; gboolean ok; gint xsize, ysize, newsize; gint oldid, newid; g_return_if_fail(run & DWT_DENOISE_RUN_MODES); gwy_app_data_browser_get_current(GWY_APP_DATA_FIELD, &dfield, GWY_APP_DATA_FIELD_ID, &oldid, 0); g_return_if_fail(dfield); xsize = gwy_data_field_get_xres(dfield); ysize = gwy_data_field_get_yres(dfield); if (xsize != ysize) { dialog = gtk_message_dialog_new (GTK_WINDOW(gwy_app_data_window_get_current()), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("%s: Data must be square."), _("DWT Denoise")); gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_destroy(dialog); return; } dwt_denoise_load_args(gwy_app_settings_get(), &args); if (run == GWY_RUN_INTERACTIVE) { ok = dwt_denoise_dialog(&args); dwt_denoise_save_args(gwy_app_settings_get(), &args); if (!ok) return; } dfield = gwy_data_field_duplicate(dfield); newsize = gwy_fft_find_nice_size(xsize); gwy_data_field_add(dfield, -gwy_data_field_get_avg(dfield)); gwy_data_field_resample(dfield, newsize, newsize, GWY_INTERPOLATION_BILINEAR); wtcoefs = gwy_data_line_new(10, 10, TRUE); wtcoefs = gwy_dwt_set_coefficients(wtcoefs, args.wavelet); gwy_data_field_dwt_denoise(dfield, wtcoefs, TRUE, 20, args.method); if (args.preserve) gwy_data_field_resample(dfield, xsize, ysize, args.interp); newid = gwy_app_data_browser_add_data_field(dfield, data, TRUE); gwy_app_copy_data_items(data, data, oldid, newid, GWY_DATA_ITEM_GRADIENT, GWY_DATA_ITEM_MASK_COLOR, 0); g_object_unref(dfield); gwy_app_set_data_field_title(data, newid, _("DWT denoised")); g_object_unref(wtcoefs); }
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; }
/** * gwy_data_field_correlate: * @data_field: A data field. * @kernel_field: Correlation kernel. * @score: Data field to store correlation scores to. * @method: Correlation score calculation method. * * Computes correlation score for all positions in a data field. * * Correlation score is compute for all points in data field @data_field * and full size of correlation kernel @kernel_field. * * The points in @score correspond to centers of kernel. More precisely, the * point ((@kxres-1)/2, (@kyres-1)/2) in @score corresponds to kernel field * top left corner coincident with data field top left corner. Points outside * the area where the kernel field fits into the data field completely are * set to -1 for %GWY_CORRELATION_NORMAL. **/ void gwy_data_field_correlate(GwyDataField *data_field, GwyDataField *kernel_field, GwyDataField *score, GwyCorrelationType method) { gint xres, yres, kxres, kyres, i, j, k, fftxres, fftyres; GwyDataField *data_in_re, *data_out_re, *data_out_im; GwyDataField *kernel_in_re, *kernel_out_re, *kernel_out_im; gdouble norm; g_return_if_fail(data_field != NULL && kernel_field != NULL); xres = data_field->xres; yres = data_field->yres; kxres = kernel_field->xres; kyres = kernel_field->yres; if (kxres <= 0 || kyres <= 0) { g_warning("Correlation kernel has nonpositive size."); return; } switch (method) { case GWY_CORRELATION_NORMAL: gwy_data_field_fill(score, -1); /*correlation request outside kernel */ if (kxres > xres || kyres > yres) { return; } { GwyDataField *avg, *rms; gdouble s, davg, drms, kavg, krms; gint xoff, yoff; /* The number of pixels the correlation kernel extends to the * negative direction */ xoff = (kxres - 1)/2; yoff = (kyres - 1)/2; kavg = gwy_data_field_get_avg(kernel_field); krms = gwy_data_field_get_rms(kernel_field); avg = gwy_data_field_duplicate(data_field); rms = gwy_data_field_duplicate(data_field); calculate_normalization(avg, rms, kxres, kyres); for (i = yoff; i + kyres - yoff <= yres; i++) { for (j = xoff; j + kxres - xoff <= xres; j++) { k = i*xres + j; davg = avg->data[k]; drms = rms->data[k]; if (!krms || !drms) { score->data[k] = 0.0; continue; } s = gwy_data_field_get_raw_correlation_score(data_field, kernel_field, j - xoff, i - yoff, 0, 0, kxres, kyres, davg, kavg); score->data[k] = s/(drms*krms); } } g_object_unref(avg); g_object_unref(rms); } break; case GWY_CORRELATION_FFT: case GWY_CORRELATION_POC: fftxres = gwy_fft_find_nice_size(xres); fftyres = gwy_fft_find_nice_size(yres); data_in_re = gwy_data_field_new_resampled(data_field, fftxres, fftyres, GWY_INTERPOLATION_BILINEAR); kernel_in_re = gwy_data_field_new_alike(data_field, TRUE); gwy_data_field_area_copy(kernel_field, kernel_in_re, 0, 0, kernel_field->xres, kernel_field->yres, kernel_in_re->xres/2 - kernel_field->xres/2, kernel_in_re->yres/2 - kernel_field->yres/2); gwy_data_field_resample(kernel_in_re, fftxres, fftyres, GWY_INTERPOLATION_BILINEAR); gwy_data_field_resample(score, fftxres, fftyres, GWY_INTERPOLATION_NONE); data_out_re = gwy_data_field_new_alike(data_in_re, TRUE); data_out_im = gwy_data_field_new_alike(data_in_re, TRUE); kernel_out_re = gwy_data_field_new_alike(data_in_re, TRUE); kernel_out_im = gwy_data_field_new_alike(data_in_re, TRUE); gwy_data_field_2dfft(data_in_re, NULL, data_out_re, data_out_im, GWY_WINDOWING_NONE, GWY_TRANSFORM_DIRECTION_FORWARD, GWY_INTERPOLATION_BILINEAR, FALSE, FALSE); gwy_data_field_2dfft(kernel_in_re, NULL, kernel_out_re, kernel_out_im, GWY_WINDOWING_NONE, GWY_TRANSFORM_DIRECTION_FORWARD, GWY_INTERPOLATION_BILINEAR, FALSE, FALSE); for (i = 0; i < fftxres*fftyres; i++) { /*NOTE: now we construct new "complex field" from data * and kernel fields, just to save memory*/ data_in_re->data[i] = data_out_re->data[i]*kernel_out_re->data[i] + data_out_im->data[i]*kernel_out_im->data[i]; kernel_in_re->data[i] = -data_out_re->data[i]*kernel_out_im->data[i] + data_out_im->data[i]*kernel_out_re->data[i]; if (method == GWY_CORRELATION_POC) { norm = hypot(data_in_re->data[i], kernel_in_re->data[i]); data_in_re->data[i] /= norm; kernel_in_re->data[i] /= norm; } } gwy_data_field_2dfft(data_in_re, kernel_in_re, score, data_out_im, GWY_WINDOWING_NONE, GWY_TRANSFORM_DIRECTION_BACKWARD, GWY_INTERPOLATION_BILINEAR, FALSE, FALSE); gwy_data_field_2dfft_humanize(score); /*TODO compute it and put to score field*/ g_object_unref(data_in_re); g_object_unref(data_out_re); g_object_unref(data_out_im); g_object_unref(kernel_in_re); g_object_unref(kernel_out_re); g_object_unref(kernel_out_im); break; } gwy_data_field_invalidate(score); }
static void cwt(GwyContainer *data, GwyRunType run) { GtkWidget *dialog; GwyDataField *dfield; CWTArgs args; gboolean ok; gint xsize, ysize; gint newsize; gint oldid, newid; g_return_if_fail(run & CWT_RUN_MODES); gwy_app_data_browser_get_current(GWY_APP_DATA_FIELD, &dfield, GWY_APP_DATA_FIELD_ID, &oldid, 0); g_return_if_fail(dfield); xsize = gwy_data_field_get_xres(dfield); ysize = gwy_data_field_get_yres(dfield); if (xsize != ysize) { dialog = gtk_message_dialog_new (gwy_app_find_window_for_channel(data, oldid), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("%s: Data must be square."), "CWT"); gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_destroy(dialog); return; } cwt_load_args(gwy_app_settings_get(), &args); if (run == GWY_RUN_INTERACTIVE) { ok = cwt_dialog(&args); cwt_save_args(gwy_app_settings_get(), &args); if (!ok) return; } dfield = gwy_data_field_duplicate(dfield); newsize = gwy_fft_find_nice_size(xsize); gwy_data_field_resample(dfield, newsize, newsize, args.interp); gwy_data_field_cwt(dfield, args.interp, args.scale, args.wavelet); if (args.preserve) gwy_data_field_resample(dfield, xsize, ysize, args.interp); newid = gwy_app_data_browser_add_data_field(dfield, data, TRUE); gwy_app_sync_data_items(data, data, oldid, newid, FALSE, GWY_DATA_ITEM_GRADIENT, GWY_DATA_ITEM_MASK_COLOR, 0); g_object_unref(dfield); gwy_app_set_data_field_title(data, newid, _("CWT")); }
static void dwt_anisotropy(GwyContainer *data, GwyRunType run) { GtkWidget *dialog; GwyDataField *dfield, *mask; GQuark dquark, mquark; GwyDataLine *wtcoefs; DWTAnisotropyArgs args; gboolean ok; gint xsize, ysize, newsize, limit, id, i; g_return_if_fail(run & DWT_ANISOTROPY_RUN_MODES); gwy_app_data_browser_get_current(GWY_APP_DATA_FIELD_KEY, &dquark, GWY_APP_DATA_FIELD, &dfield, GWY_APP_DATA_FIELD_ID, &id, GWY_APP_MASK_FIELD_KEY, &mquark, GWY_APP_MASK_FIELD, &mask, 0); g_return_if_fail(dfield && dquark); xsize = gwy_data_field_get_xres(dfield); ysize = gwy_data_field_get_yres(dfield); if (xsize != ysize) { dialog = gtk_message_dialog_new (gwy_app_find_window_for_channel(data, id), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("%s: Data must be square."), _("DWT Anisotropy")); gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_destroy(dialog); return; } dwt_anisotropy_load_args(gwy_app_settings_get(), &args); if (run == GWY_RUN_INTERACTIVE) { ok = dwt_anisotropy_dialog(&args); dwt_anisotropy_save_args(gwy_app_settings_get(), &args); if (!ok) return; } for (newsize = 1, i = xsize-1; i; i >>= 1, newsize <<= 1) ; dfield = gwy_data_field_new_resampled(dfield, newsize, newsize, args.interp); gwy_data_field_add(dfield, -gwy_data_field_get_avg(dfield)); gwy_app_undo_qcheckpoint(data, dquark, mquark, 0); if (!mask) { mask = gwy_data_field_new_alike(dfield, FALSE); gwy_container_set_object(data, mquark, mask); g_object_unref(mask); } gwy_data_field_resample(mask, newsize, newsize, GWY_INTERPOLATION_NONE); wtcoefs = gwy_data_line_new(10, 10, TRUE); wtcoefs = gwy_dwt_set_coefficients(wtcoefs, args.wavelet); /*justo for sure clamp the lowlimit again*/ limit = pow(2, CLAMP(args.lowlimit, 1, 20)); gwy_data_field_dwt_mark_anisotropy(dfield, mask, wtcoefs, args.ratio, limit); gwy_data_field_resample(mask, xsize, ysize, GWY_INTERPOLATION_ROUND); g_object_unref(wtcoefs); g_object_unref(dfield); gwy_data_field_data_changed(mask); gwy_app_channel_log_add_proc(data, id, id); }
/** * gwy_tip_cmap: * @tip: Tip data. * @surface: Surface data. * @result: Data field to store ceratainty map data to. * @set_fraction: Function that sets fraction to output (or %NULL). * @set_message: Function that sets message to output (of %NULL). * * Performs certainty map algorithm published by Villarrubia. This function * converts all fields into form requested by "morph_lib.c" library, that is * almost identical with original Villarubia's library. Result certainty map * can be used as a mask of points where tip did not directly touch the * surface. * * Returns: Certainty map, i.e. @result, on success. May return %NULL if * aborted. **/ GwyDataField* gwy_tip_cmap(GwyDataField *tip, GwyDataField *surface, GwyDataField *result, GwySetFractionFunc set_fraction, GwySetMessageFunc set_message) { gint **ftip; gint **fsurface; gint **rsurface; gint **fresult; gint newx, newy; gdouble tipmin, surfacemin, step; GwyDataField *buffertip; gboolean freetip; newx = surface->xres + tip->xres; newy = surface->yres + tip->yres; /*if tip and surface have different spacings, make new, resampled tip*/ buffertip = get_right_tip_field(tip, surface, &freetip); /*invert tip (as necessary by dilation algorithm)*/ gwy_data_field_invert(buffertip, TRUE, TRUE, FALSE); /*convert fields to integer arrays*/ tipmin = gwy_data_field_get_min(buffertip); surfacemin = gwy_data_field_get_min(surface); step = (gwy_data_field_get_max(surface) - surfacemin)/10000; ftip = i_datafield_to_field(buffertip, TRUE, tipmin, step); fsurface = i_datafield_to_largefield(surface, buffertip, surfacemin, step); /*perform erosion as it is necessary parameter of certainty map algorithm*/ rsurface = _gwy_morph_lib_ierosion(fsurface, newy, newx, ftip, buffertip->yres, buffertip->xres, buffertip->yres/2, buffertip->xres/2, set_fraction, set_message); if (!rsurface) { _gwy_morph_lib_ifreematrix(ftip, buffertip->xres); _gwy_morph_lib_ifreematrix(fsurface, newx); if (freetip) g_object_unref(buffertip); return NULL; } /*find certanty map*/ if (rsurface) { fresult = _gwy_morph_lib_icmap(fsurface, newy, newx, ftip, buffertip->yres, buffertip->xres, rsurface, buffertip->yres/2, buffertip->xres/2, set_fraction, set_message); } else fresult = NULL; /*convert result back*/ if (fresult) { gwy_data_field_resample(result, surface->xres, surface->yres, GWY_INTERPOLATION_NONE); result = i_largefield_to_datafield(fresult, result, buffertip, 0.0, 1.0); } else result = NULL; _gwy_morph_lib_ifreematrix(ftip, buffertip->xres); _gwy_morph_lib_ifreematrix(fsurface, newx); _gwy_morph_lib_ifreematrix(rsurface, newx); if (fresult) _gwy_morph_lib_ifreematrix(fresult, result->xres); if (freetip) g_object_unref(buffertip); else gwy_data_field_invert(buffertip, TRUE, TRUE, FALSE); return result; }
static void psdflp_do(const PSDFLPArgs *args, GwyDataField *dfield, GwyDataField *lpsdf) { enum { N = 4 }; GwyDataField *reout, *imout; gint pxres, pyres, fxres, fyres; gint i, j, fi, pi; gdouble *ldata, *redata, *imdata; gdouble *cosphi, *sinphi; gdouble xreal, yreal, f0, f_max, b, p; reout = gwy_data_field_new_alike(dfield, FALSE); imout = gwy_data_field_new_alike(dfield, FALSE); gwy_data_field_2dfft(dfield, NULL, reout, imout, args->window, GWY_TRANSFORM_DIRECTION_FORWARD, GWY_INTERPOLATION_ROUND, /* Ignored */ TRUE, 1); pxres = reout->xres; pyres = reout->yres; redata = gwy_data_field_get_data(reout); imdata = gwy_data_field_get_data(imout); for (i = 0; i < pxres*pyres; i++) redata[i] = redata[i]*redata[i] + imdata[i]*imdata[i]; gwy_data_field_2dfft_humanize(reout); gwy_data_field_filter_gaussian(reout, args->sigma); for (i = 0; i < pxres*pyres; i++) redata[i] = sqrt(redata[i]); fxres = pxres/2; fyres = pyres/2; gwy_data_field_resample(lpsdf, fxres, fyres, GWY_INTERPOLATION_NONE); ldata = gwy_data_field_get_data(lpsdf); xreal = dfield->xreal; yreal = dfield->yreal; f0 = 2.0/MIN(xreal, yreal); f_max = 0.5*MIN(pxres/xreal, pyres/yreal); if (f_max <= f0) { g_warning("Minimum frequency is not smaller than maximum frequency."); } b = log(f_max/f0)/fyres; /* Incorporate some prefactors to sinphi[] and cosphi[], knowing that * cosine is only ever used for x and sine for y frequencies. */ cosphi = g_new(gdouble, (N+1)*fxres); sinphi = g_new(gdouble, (N+1)*fxres); for (j = 0; j < fxres; j++) { gdouble phi_from = 2.0*G_PI*j/fxres; gdouble phi_to = 2.0*G_PI*(j + 1.0)/fxres; for (pi = 0; pi <= N; pi++) { gdouble phi = ((pi + 0.5)*phi_from + (N - 0.5 - pi)*phi_to)/N; cosphi[j*(N+1) + pi] = cos(phi)*xreal; sinphi[j*(N+1) + pi] = sin(phi)*yreal; } } for (i = 0; i < fyres; i++) { gdouble f_from = f0*exp(b*i); gdouble f_to = f0*exp(b*(i + 1.0)); for (j = 0; j < fxres; j++) { const gdouble *cosphi_j = cosphi + j*(N+1); const gdouble *sinphi_j = sinphi + j*(N+1); guint n = 0; gdouble s = 0.0; for (fi = 0; fi <= N; fi++) { gdouble f = ((fi + 0.5)*f_from + (N - 0.5 - fi)*f_to)/N; for (pi = 0; pi <= N; pi++) { gdouble x = f*cosphi_j[pi] + pxres/2.0, y = f*sinphi_j[pi] + pyres/2.0; if (G_UNLIKELY(x < 0.5 || y < 0.5 || x > pxres - 1.5 || y > pyres - 1.5)) continue; p = gwy_data_field_get_dval(reout, x, y, GWY_INTERPOLATION_SCHAUM); s += p; n++; } } if (!n) n = 1; ldata[i*fxres + j] = 2.0*G_PI/fxres * s/n*(f_to - f_from); } } g_object_unref(imout); g_object_unref(reout); gwy_data_field_set_xreal(lpsdf, 2.0*G_PI); gwy_data_field_set_xoffset(lpsdf, 0.0); gwy_data_field_set_yreal(lpsdf, log(f_max/f0)); gwy_data_field_set_yoffset(lpsdf, log(f0)); gwy_si_unit_set_from_string(gwy_data_field_get_si_unit_xy(lpsdf), ""); gwy_si_unit_set_from_string(gwy_data_field_get_si_unit_z(lpsdf), ""); gwy_data_field_normalize(lpsdf); }
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); }