Example #1
0
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);
}
Example #2
0
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;
}
Example #3
0
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);
    }
}
Example #4
0
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);
}
Example #5
0
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);
}
Example #6
0
/* 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;
}
Example #7
0
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);
}
Example #8
0
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);
}
Example #9
0
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);
    }
}
Example #10
0
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);
}
Example #11
0
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;
}