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); }
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 void crop_result(GwyDataField *result, GwyDataField *dfield1, GwyDataField *dfield2, GwyOrientation orientation, gint px1, gint py1, gint px2, gint py2) { if (orientation == GWY_ORIENTATION_HORIZONTAL) { gint top = MAX(MAX(py1, py2), 0); gint bot = MIN(MIN(dfield1->yres + py1, dfield2->yres + py2), result->yres); gdouble yreal = (bot - top)*gwy_data_field_get_ymeasure(result); g_return_if_fail(bot > top); gwy_data_field_resize(result, 0, top, result->xres, bot); gwy_data_field_set_yreal(result, yreal); } else { gint left = MAX(MAX(px1, px2), 0); gint right = MIN(MIN(dfield1->xres + px1, dfield2->xres + px2), result->xres); gdouble xreal = (right - left)*gwy_data_field_get_xmeasure(result); g_return_if_fail(right > left); gwy_data_field_resize(result, left, 0, right, result->yres); gwy_data_field_set_xreal(result, xreal); } }
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 tilt(GwyContainer *data, GwyRunType run) { GwyDataField *dfield; GQuark quark; TiltArgs args; gboolean ok; g_return_if_fail(run & TILT_RUN_MODES); gwy_app_data_browser_get_current(GWY_APP_DATA_FIELD, &dfield, GWY_APP_DATA_FIELD_KEY, &quark, 0); g_return_if_fail(dfield); tilt_load_args(gwy_app_settings_get(), &args); if (run == GWY_RUN_INTERACTIVE) { ok = tilt_dialog(&args, dfield); tilt_save_args(gwy_app_settings_get(), &args); if (!ok) return; } gwy_app_undo_qcheckpointv(data, 1, &quark); { /* Use negative values since the module says `Tilt', * not `Remove tilt' */ double bx = -args.dx*gwy_data_field_get_xmeasure(dfield); double by = -args.dy*gwy_data_field_get_ymeasure(dfield); double c = -0.5*(bx*gwy_data_field_get_xres(dfield) + by*gwy_data_field_get_yres(dfield)); gwy_data_field_plane_level(dfield, c, bx, by); } gwy_data_field_data_changed(dfield); }
/* XXX: This replicates straighten_path.c */ static GwyXY* rescale_points(GwySelection *selection, GwyDataField *dfield, gboolean realsquare, gdouble *pdx, gdouble *pdy, gdouble *pqx, gdouble *pqy) { gdouble dx, dy, qx, qy, h; GwyXY *points; guint n, i; dx = gwy_data_field_get_xmeasure(dfield); dy = gwy_data_field_get_ymeasure(dfield); h = MIN(dx, dy); if (realsquare) { qx = h/dx; qy = h/dy; dx = dy = h; } else qx = qy = 1.0; n = gwy_selection_get_data(selection, NULL); points = g_new(GwyXY, n); for (i = 0; i < n; i++) { gdouble xy[2]; gwy_selection_get_object(selection, i, xy); points[i].x = xy[0]/dx; points[i].y = xy[1]/dy; } *pdx = dx; *pdy = dy; *pqx = qx; *pqy = qy; return points; }
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 put_fields(GwyDataField *dfield1, GwyDataField *dfield2, GwyDataField *result, GwyDataField *outsidemask, GwyMergeBoundaryType boundary, gint px1, gint py1, gint px2, gint py2) { GwyRectangle res_rect; GwyCoord f1_pos; GwyCoord f2_pos; gint w1, w2, h1, h2; gdouble xreal, yreal; gwy_debug("field1 %dx%d", dfield1->xres, dfield1->yres); gwy_debug("field2 %dx%d", dfield2->xres, dfield2->yres); gwy_debug("result %dx%d", result->xres, result->yres); gwy_debug("px1: %d, py1: %d, px2: %d, py2: %d", px1, py1, px2, py2); gwy_data_field_fill(result, MIN(gwy_data_field_get_min(dfield1), gwy_data_field_get_min(dfield2))); w1 = gwy_data_field_get_xres(dfield1); h1 = gwy_data_field_get_yres(dfield1); w2 = gwy_data_field_get_xres(dfield2); h2 = gwy_data_field_get_yres(dfield2); if (boundary == GWY_MERGE_BOUNDARY_SECOND) { gwy_data_field_area_copy(dfield1, result, 0, 0, w1, h1, px1, py1); gwy_data_field_area_copy(dfield2, result, 0, 0, w2, h2, px2, py2); } else { gwy_data_field_area_copy(dfield2, result, 0, 0, w2, h2, px2, py2); gwy_data_field_area_copy(dfield1, result, 0, 0, w1, h1, px1, py1); } if (outsidemask) { gwy_data_field_fill(outsidemask, 1.0); gwy_data_field_area_clear(outsidemask, px1, py1, w1, h1); gwy_data_field_area_clear(outsidemask, px2, py2, w2, h2); } /* adjust boundary to be as smooth as possible */ if (boundary == GWY_MERGE_BOUNDARY_AVERAGE || boundary == GWY_MERGE_BOUNDARY_INTERPOLATE) { if (px1 < px2) { res_rect.x = px2; res_rect.width = px1 + w1 - px2; } else { res_rect.x = px1; res_rect.width = px2 + w2 - px1; } if (py1 < py2) { res_rect.y = py2; res_rect.height = py1 + h1 - py2; } else { res_rect.y = py1; res_rect.height = py2 + h2 - py1; } res_rect.height = MIN(res_rect.height, MIN(h1, h2)); res_rect.width = MIN(res_rect.width, MIN(w1, w2)); /* This is where the result rectangle is positioned in the fields, * not where the fields themselves are placed! */ f1_pos.x = res_rect.x - px1; f1_pos.y = res_rect.y - py1; f2_pos.x = res_rect.x - px2; f2_pos.y = res_rect.y - py2; merge_boundary(dfield1, dfield2, result, res_rect, f1_pos, f2_pos, boundary); } /* Use the pixels sizes of field 1 -- they must be identical. */ xreal = result->xres * gwy_data_field_get_xmeasure(dfield1); yreal = result->yres * gwy_data_field_get_ymeasure(dfield1); gwy_data_field_set_xreal(result, xreal); gwy_data_field_set_yreal(result, yreal); if (outsidemask) { gwy_data_field_set_xreal(outsidemask, xreal); gwy_data_field_set_yreal(outsidemask, yreal); } }
static void copy_field_to_surface(GwyDataField *field, GwySurface *surface, GwyDataField *mask, GwyMaskingType masking) { gdouble dx = gwy_data_field_get_xmeasure(field), dy = gwy_data_field_get_ymeasure(field); gdouble xoff = 0.5*dx + field->xoff, yoff = 0.5*dy + field->yoff; Surface *priv = surface->priv; guint xres, yres, i, j, n, k; const gdouble *m = NULL, *d; xres = field->xres; yres = field->yres; n = xres*yres; d = field->data; if (mask && masking == GWY_MASK_INCLUDE) { m = mask->data; j = 0; for (k = 0; k < n; k++) { if (m[k] > 0.0) j++; } n = j; } else if (mask && masking == GWY_MASK_EXCLUDE) { m = mask->data; j = 0; for (k = 0; k < n; k++) { if (m[k] <= 0.0) j++; } n = j; } if (surface->n != n) { free_data(surface); surface->n = n; alloc_data(surface); } k = 0; for (i = 0; i < yres; i++) { for (j = 0; j < xres; j++) { if (!mask || masking == GWY_MASK_IGNORE || (masking == GWY_MASK_INCLUDE && m[i*xres + j] > 0.0) || (masking == GWY_MASK_EXCLUDE && m[i*xres + j] <= 0.0)) { surface->data[k].x = dx*j + xoff; surface->data[k].y = dy*i + yoff; surface->data[k].z = d[i*xres + j]; k++; } } } gwy_data_field_copy_units_to_surface(field, surface); gwy_surface_invalidate(surface); if (n == xres*yres) { priv->cached_ranges = TRUE; priv->min.x = xoff; priv->min.y = yoff; priv->max.x = dx*(xres - 1) + xoff; priv->max.y = dy*(yres - 1) + yoff; } gwy_data_field_get_min_max(field, &priv->min.z, &priv->max.z); }
static gboolean sdfile_export_text(G_GNUC_UNUSED GwyContainer *data, const gchar *filename, G_GNUC_UNUSED GwyRunType mode, GError **error) { enum { SCALE = 65535 }; static const gchar header_format[] = "aBCR-0.0\n" "ManufacID = Gwyddion\n" "CreateDate = %02u%02u%04u%02u%02u\n" "ModDate = %02u%02u%04u%02u%02u\n" "NumPoints = %d\n" "NumProfiles = %d\n" "Xscale = %e\n" "Yscale = %e\n" "Zscale = %e\n" "Zresolution = -1\n" /* FIXME: Dunno */ "Compression = 0\n" "DataType = %d\n" "CheckType = 0\n" "NumDataSet = 1\n" "NanPresent = 0\n" "*\n"; GwyDataField *dfield; const gdouble *d; gint xres, yres, i; const struct tm *ttm; gchar buf[24]; time_t t; FILE *fh; gwy_app_data_browser_get_current(GWY_APP_DATA_FIELD, &dfield, 0); if (!dfield) { err_NO_CHANNEL_EXPORT(error); return FALSE; } if (!(fh = g_fopen(filename, "w"))) { err_OPEN_WRITE(error); return FALSE; } d = gwy_data_field_get_data_const(dfield); xres = gwy_data_field_get_xres(dfield); yres = gwy_data_field_get_yres(dfield); /* We do not keep date information, just use the current time */ time(&t); ttm = localtime(&t); fprintf(fh, header_format, ttm->tm_mday, ttm->tm_mon, ttm->tm_year, ttm->tm_hour, ttm->tm_min, ttm->tm_mday, ttm->tm_mon, ttm->tm_year, ttm->tm_hour, ttm->tm_min, xres, yres, gwy_data_field_get_xmeasure(dfield), gwy_data_field_get_ymeasure(dfield), 1.0, SDF_FLOAT); for (i = 0; i < xres*yres; i++) { g_ascii_formatd(buf, sizeof(buf), "%g", d[i]); fputs(buf, fh); fputc('\n', fh); } fclose(fh); return TRUE; }