Example #1
0
static void
gwy_hmarker_box_draw_marker(GwyMarkerBox *mbox,
                            gint i)
{
    GtkWidget *widget;
    GtkStateType state, gcstate;
    gboolean ghost, selected;
    GdkPoint points[3];
    gint height, width;
    gdouble pos;
    gint iw, ipos;

    widget = GTK_WIDGET(mbox);
    state = GTK_WIDGET_STATE(widget);
    width = widget->allocation.width;
    height = widget->allocation.height;

    selected = (i == mbox->selected);
    ghost = selected && mbox->ghost;
    selected = selected && mbox->highlight;
    pos = g_array_index(mbox->markers, gdouble, i);

    if (ghost)
        gcstate = GTK_STATE_INSENSITIVE;
    else if (state == GTK_STATE_INSENSITIVE)
        gcstate = state;
    else
        gcstate = GTK_STATE_NORMAL;

    ipos = GWY_ROUND(pos*(width - 1));
    iw = MAX(GWY_ROUND(height/GWY_SQRT3 - 1), 1);
    points[0].x = ipos - iw;
    points[1].x = ipos + iw;
    points[2].x = ipos;
    if (mbox->flipped) {
        points[0].y = 0;
        points[1].y = 0;
        points[2].y = height-1;
    }
    else {
        points[0].y = height-1;
        points[1].y = height-1;
        points[2].y = 0;
    }
    if (selected && !ghost)
        gdk_draw_polygon(widget->window,
                         widget->style->bg_gc[GTK_STATE_SELECTED],
                         TRUE, points, G_N_ELEMENTS(points));
    else
        gdk_draw_polygon(widget->window, widget->style->text_gc[gcstate],
                         TRUE, points, G_N_ELEMENTS(points));

    gdk_draw_polygon(widget->window, widget->style->fg_gc[gcstate],
                     FALSE, points, G_N_ELEMENTS(points));
}
Example #2
0
static void
get_scan_list_res(GHashTable *hash,
                  gint *xres, gint *yres)
{
    NanoscopeValue *val;

    /* XXX: Some observed files contained correct dimensions only in
     * a global section, sizes in `image list' sections were bogus.
     * Version: 0x05300001 */
    if ((val = g_hash_table_lookup(hash, "Samps/line")))
        *xres = GWY_ROUND(val->hard_value);
    if ((val = g_hash_table_lookup(hash, "Lines")))
        *yres = GWY_ROUND(val->hard_value);
    gwy_debug("Global xres, yres = %d, %d", *xres, *yres);
}
Example #3
0
static GwyDataLine*
sphrev_make_sphere(gdouble radius, gint maxres)
{
    GwyDataLine *dline;
    gdouble *data;
    gint i, size;

    size = GWY_ROUND(MIN(radius, maxres));
    dline = gwy_data_line_new(2*size+1, 1.0, FALSE);
    data = gwy_data_line_get_data(dline);

    if (radius/8 > maxres) {
        /* Pathological case: very flat sphere */
        for (i = 0; i <= size; i++) {
            gdouble u = i/radius;

            data[size+i] = data[size-i] = u*u/2.0*(1.0 + u*u/4.0*(1 + u*u/2.0));
        }
    }
    else {
        /* Normal sphere */
        for (i = 0; i <= size; i++) {
            gdouble u = i/radius;

            if (G_UNLIKELY(u > 1.0))
                data[size+i] = data[size-i] = 1.0;
            else
                data[size+i] = data[size-i] = 1.0 - sqrt(1.0 - u*u);
        }
    }

    return dline;
}
Example #4
0
static gint
burleigh_detect(const GwyFileDetectInfo *fileinfo,
                gboolean only_name)
{
    const guchar *buffer;
    guint version_int, xres, yres;
    gdouble version;

    if (only_name)
        return g_str_has_suffix(fileinfo->name_lowercase, EXTENSION) ? 10 : 0;

    if (fileinfo->buffer_len < 4)
        return 0;

    buffer = fileinfo->head;
    version = gwy_get_gfloat_le(&buffer);
    version_int = GWY_ROUND(10*version);
    gwy_debug("Version: %g", version);

    if (version_int == 21) {
        if (fileinfo->file_size < TOTAL_SIZE_V21 + 2)
            return 0;

        xres = gwy_get_guint16_le(&buffer);
        yres = gwy_get_guint16_le(&buffer);
        if (fileinfo->file_size == TOTAL_SIZE_V21 + 2*xres*yres)
            return 100;
        return 0;
    }

    return 0;
}
Example #5
0
static void
prof_update_curve(ProfControls *controls,
                  gint i)
{
    GwyGraphCurveModel *gcmodel;
    gdouble xy[4], h;
    gint xl0, yl0, xl1, yl1;
    gint n, lineres;
    gchar *desc;

    g_return_if_fail(gwy_selection_get_object(controls->selection, i, xy));

    /* The ω=0 pixel is always at res/2, for even dimensions it means it is
     * shifted half-a-pixel to the right from the precise centre. */
    xl0 = gwy_data_field_get_xres(controls->psdffield)/2;
    yl0 = gwy_data_field_get_yres(controls->psdffield)/2;
    xl1 = floor(gwy_data_field_rtoj(controls->psdffield, xy[0]));
    yl1 = floor(gwy_data_field_rtoi(controls->psdffield, xy[1]));
    xy[0] += gwy_data_field_get_xoffset(controls->psdffield);
    xy[1] += gwy_data_field_get_yoffset(controls->psdffield);
    h = hypot(controls->hx*xy[0], controls->hy*xy[1])/hypot(xy[0], xy[1]);

    if (!controls->args->fixres) {
        lineres = GWY_ROUND(hypot(abs(xl0 - xl1) + 1, abs(yl0 - yl1) + 1));
        lineres = MAX(lineres, MIN_RESOLUTION);
    }
    else
        lineres = controls->args->resolution;

    gwy_data_field_get_profile(controls->psdffield, controls->line,
                               xl0, yl0, xl1, yl1,
                               lineres,
                               1,
                               controls->args->interpolation);
    gwy_data_line_multiply(controls->line, h);

    n = gwy_graph_model_get_n_curves(controls->gmodel);
    if (i < n) {
        gcmodel = gwy_graph_model_get_curve(controls->gmodel, i);
    }
    else {
        gcmodel = gwy_graph_curve_model_new();
        g_object_set(gcmodel,
                     "mode", GWY_GRAPH_CURVE_LINE,
                     "color", gwy_graph_get_preset_color(i),
                     NULL);
        gwy_graph_model_add_curve(controls->gmodel, gcmodel);
        g_object_unref(gcmodel);
    }

    gwy_graph_curve_model_set_data_from_dataline(gcmodel, controls->line, 0, 0);
    desc = g_strdup_printf(_("PSDF %.0f°"), 180.0/G_PI*atan2(-xy[1], xy[0]));
    g_object_set(gcmodel, "description", desc, NULL);
    g_free(desc);
}
Example #6
0
static gint
gwy_hmarker_box_find_nearest(GwyMarkerBox *mbox,
                             gint x,
                             gint y)
{
    GtkWidget *widget;
    gint ii, mdist, width, height, ipos;
    gdouble pos;
    guint i;

    widget = GTK_WIDGET(mbox);
    width = widget->allocation.width;
    height = widget->allocation.height;

    ii = -1;
    mdist = G_MAXINT;
    for (i = 0; i < mbox->markers->len; i++) {
        pos = g_array_index(mbox->markers, gdouble, i);
        ipos = GWY_ROUND(pos*(width - 1));
        if (ipos == x)
            return i;

        if (ABS(ipos - x) < mdist) {
            mdist = ABS(ipos - x);
            ii = i;
        }
        else if (ipos > x)
            break;
    }
    if (ii < 0)
        return -1;

    pos = g_array_index(mbox->markers, gdouble, ii);
    ipos = GWY_ROUND(pos*(width - 1));
    if (mbox->flipped)
        y = height-1 - y;

    return ABS(ipos - x) <= y/GWY_SQRT3 ? ii : -1;
}
Example #7
0
static void
poly_level_degree_changed(GtkObject *spin,
                          PolyLevelControls *controls)
{
    PolyLevelArgs *args;
    gdouble v;
    gint degree;
    gboolean update;

    if (controls->in_update)
        return;

    args = controls->args;
    v = gtk_adjustment_get_value(GTK_ADJUSTMENT(spin));
    degree = GWY_ROUND(v);
    if (spin == controls->col_degree) {
        update = args->col_degree != degree;
        args->col_degree = degree;
    }
    else {
        update = args->row_degree != degree;
        args->row_degree = degree;
    }

    if (!args->same_degree) {
        poly_level_update_preview(controls, controls->args);
        return;
    }

    controls->in_update = TRUE;
    if (spin == controls->col_degree) {
        gwy_debug("syncing row := col");
        gtk_adjustment_set_value(GTK_ADJUSTMENT(controls->row_degree), v);
        args->row_degree = args->col_degree;
    }
    else {
        gwy_debug("syncing col := row");
        gtk_adjustment_set_value(GTK_ADJUSTMENT(controls->col_degree), v);
        args->col_degree = args->row_degree;
    }
    gwy_debug("col_degree = %f %d, row_degree = %f %d",
              gtk_adjustment_get_value(GTK_ADJUSTMENT(controls->col_degree)),
              args->col_degree,
              gtk_adjustment_get_value(GTK_ADJUSTMENT(controls->row_degree)),
              args->row_degree);

    if (update)
        poly_level_update_preview(controls, controls->args);
    controls->in_update = FALSE;
}
Example #8
0
static gboolean
gwy_hmarker_box_button_press(GtkWidget *widget,
                             GdkEventButton *event)
{
    GwyMarkerBox *mbox;
    gint x, y, i, ipos, width;
    gdouble pos;

    /* React to left button only */
    mbox = GWY_MARKER_BOX(widget);
    if (event->button != 1)
        return FALSE;

    x = (gint)event->x;
    y = (gint)event->y;
    width = widget->allocation.width;

    i = gwy_hmarker_box_find_nearest(mbox, x, y);
    if (i < 0) {
        /* Control enforces selection, no markers are added */
        if ((event->state & GDK_CONTROL_MASK))
            return FALSE;
        pos = (x - mbox->offset)/(widget->allocation.width - 1.0);
        i = gwy_marker_box_add_marker(mbox, mbox->markers->len, pos);
        if (i < 0)
            return FALSE;
    }
    /* Control deselect a selected marker */
    if ((event->state & GDK_CONTROL_MASK) && i == mbox->selected) {
        gwy_marker_box_set_selected_marker(mbox, -1);
        return FALSE;
    }

    pos = g_array_index(mbox->markers, gdouble, i);
    ipos = GWY_ROUND(pos*(width - 1));
    mbox->button = event->button;
    mbox->offset = x - ipos;
    mbox->moved = FALSE;
    gwy_marker_box_set_selected_marker(mbox, i);

    return FALSE;
}
Example #9
0
static void
poly_level_max_degree_changed(GtkObject *spin,
                              PolyLevelControls *controls)
{
    PolyLevelArgs *args;
    gdouble v;
    gint degree;

    if (controls->in_update)
        return;

    args = controls->args;
    v = gtk_adjustment_get_value(GTK_ADJUSTMENT(spin));
    degree = GWY_ROUND(v);
    if (degree == args->max_degree)
        return;

    args->max_degree = degree;
    poly_level_update_preview(controls, controls->args);
}
Example #10
0
static gint*
median_make_circle(gint radius)
{
    gint *data;
    gint i;

    data = g_new(gint, 2*radius + 1);

    for (i = 0; i <= radius; i++) {
        gdouble u = (gdouble)i/radius;

        if (G_UNLIKELY(u > 1.0))
            data[radius+i] = data[radius-i] = 0;
        else
            data[radius+i] = data[radius-i] = GWY_ROUND(radius*sqrt(1.0 - u*u));

    }

    return data;
}
Example #11
0
static void
height_changed(GtkAdjustment *adj,
               TipBlindControls *controls)
{
    TipBlindArgs *args;
    gdouble v;

    args = controls->args;
    v = gtk_adjustment_get_value(adj);
    args->yres = GWY_ROUND(v);
    if (controls->in_update)
        return;

    if (args->same_resolution) {
        controls->in_update = TRUE;
        gtk_adjustment_set_value(GTK_ADJUSTMENT(controls->xres), v);
        controls->in_update = FALSE;
    }

    tip_update(controls);
}
Example #12
0
static void
median(GwyContainer *data, GwyRunType run)
{
    GwyDataField *dfield, *background = NULL;
    MedianBgArgs args;
    gint oldid, newid;
    GQuark dquark;
    gdouble xr, yr;
    gboolean ok = TRUE;

    g_return_if_fail(run & MEDIANBG_RUN_MODES);
    gwy_app_data_browser_get_current(GWY_APP_DATA_FIELD, &dfield,
                                     GWY_APP_DATA_FIELD_KEY, &dquark,
                                     GWY_APP_DATA_FIELD_ID, &oldid,
                                     0);
    g_return_if_fail(dfield && dquark);

    median_load_args(gwy_app_settings_get(), &args);

    /* FIXME: this is bogus for non-square pixels anyway */
    xr = gwy_data_field_get_xreal(dfield)/gwy_data_field_get_xres(dfield);
    yr = gwy_data_field_get_yreal(dfield)/gwy_data_field_get_yres(dfield);
    args.pixelsize = hypot(xr, yr);
    args.valform
        = gwy_data_field_get_value_format_xy(dfield,
                                             GWY_SI_UNIT_FORMAT_VFMARKUP, NULL);
    gwy_debug("pixelsize = %g, vf = (%g, %d, %s)",
              args.pixelsize, args.valform->magnitude, args.valform->precision,
              args.valform->units);

    if (run == GWY_RUN_INTERACTIVE) {
        ok = median_dialog(&args);
        median_save_args(gwy_app_settings_get(), &args);
    }

    gwy_si_unit_value_format_free(args.valform);
    if (!ok)
        return;

    gwy_app_wait_start(gwy_app_find_window_for_channel(data, oldid),
                       _("Median-leveling..."));
    background = median_background(GWY_ROUND(args.size), dfield);
    gwy_app_wait_finish();
    if (!background)
        return;

    gwy_app_undo_qcheckpointv(data, 1, &dquark);
    gwy_data_field_subtract_fields(dfield, dfield, background);
    gwy_data_field_data_changed(dfield);
    gwy_app_channel_log_add_proc(data, oldid, oldid);

    if (!args.do_extract) {
        g_object_unref(background);
        return;
    }

    newid = gwy_app_data_browser_add_data_field(background, data, TRUE);
    g_object_unref(background);
    gwy_app_sync_data_items(data, data, oldid, newid, FALSE,
                            GWY_DATA_ITEM_GRADIENT,
                            0);
    gwy_app_set_data_field_title(data, newid, _("Background"));
    gwy_app_channel_log_add(data, oldid, newid, NULL, NULL);
}
Example #13
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 #14
0
static GwyDataField*
hash_to_data_field(GHashTable *hash,
                   GHashTable *scannerlist,
                   GHashTable *scanlist,
                   NanoscopeFileType file_type,
                   gboolean has_version,
                   guint bufsize,
                   gchar *buffer,
                   gint gxres,
                   gint gyres,
                   gchar **p,
                   GError **error)
{
    NanoscopeValue *val;
    GwyDataField *dfield;
    GwySIUnit *unitz, *unitxy;
    gchar *s, *end;
    gchar un[5];
    gint xres, yres, bpp, offset, size, power10;
    gdouble xreal, yreal, q;
    gdouble *data;
    gboolean size_ok, use_global;

    if (!require_keys(hash, error, "Samps/line", "Number of lines",
                      "Scan size", "Data offset", "Data length", NULL))
        return NULL;

    val = g_hash_table_lookup(hash, "Samps/line");
    xres = GWY_ROUND(val->hard_value);

    val = g_hash_table_lookup(hash, "Number of lines");
    yres = GWY_ROUND(val->hard_value);

    val = g_hash_table_lookup(hash, "Bytes/pixel");
    bpp = val ? GWY_ROUND(val->hard_value) : 2;

    /* scan size */
    val = g_hash_table_lookup(hash, "Scan size");
    xreal = g_ascii_strtod(val->hard_value_str, &end);
    if (errno || *end != ' ') {
        g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA,
                    _("Cannot parse `Scan size' field."));
        return NULL;
    }
    gwy_debug("xreal = %g", xreal);
    s = end+1;
    yreal = g_ascii_strtod(s, &end);
    if (errno || *end != ' ') {
        /* Old files don't have two numbers here, assume equal dimensions */
        yreal = xreal;
        end = s;
    }
    gwy_debug("yreal = %g", yreal);
    while (g_ascii_isspace(*end))
        end++;
    if (sscanf(end, "%4s", un) != 1) {
        g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA,
                    _("Cannot parse `Scan size' field."));
        return NULL;
    }
    gwy_debug("xy unit: <%s>", un);
    unitxy = gwy_si_unit_new_parse(un, &power10);
    q = pow10(power10);
    xreal *= q;
    yreal *= q;

    offset = size = 0;
    if (file_type == NANOSCOPE_FILE_TYPE_BIN) {
        val = g_hash_table_lookup(hash, "Data offset");
        offset = GWY_ROUND(val->hard_value);

        val = g_hash_table_lookup(hash, "Data length");
        size = GWY_ROUND(val->hard_value);

        size_ok = FALSE;
        use_global = FALSE;

        /* Try channel size and local size */
        if (!size_ok && size == bpp*xres*yres)
            size_ok = TRUE;

        if (!size_ok && size == bpp*gxres*gyres) {
            size_ok = TRUE;
            use_global = TRUE;
        }

        /* If they don't match exactly, try whether they at least fit inside */
        if (!size_ok && size > bpp*MAX(xres*yres, gxres*gyres)) {
            size_ok = TRUE;
            use_global = (xres*yres < gxres*gyres);
        }

        if (!size_ok && size > bpp*MIN(xres*yres, gxres*gyres)) {
            size_ok = TRUE;
            use_global = (xres*yres > gxres*gyres);
        }

        if (!size_ok) {
            err_SIZE_MISMATCH(error, size, bpp*xres*yres);
            return NULL;
        }

        if (use_global) {
            if (gxres) {
                xreal *= (gdouble)gxres/xres;
                xres = gxres;
            }
            if (gyres) {
                yreal *= (gdouble)gyres/yres;
                yres = gyres;
            }
        }

        if (offset + size > (gint)bufsize) {
            err_SIZE_MISMATCH(error, offset + size, bufsize);
            return NULL;
        }
    }

    q = 1.0;
    unitz = get_physical_scale(hash, scannerlist, scanlist, has_version,
                               &q, error);
    if (!unitz)
        return NULL;

    dfield = gwy_data_field_new(xres, yres, xreal, yreal, FALSE);
    data = gwy_data_field_get_data(dfield);
    switch (file_type) {
        case NANOSCOPE_FILE_TYPE_TXT:
        if (!read_ascii_data(xres*yres, data, p, bpp, error)) {
            g_object_unref(dfield);
            return NULL;
        }
        break;

        case NANOSCOPE_FILE_TYPE_BIN:
        if (!read_binary_data(xres*yres, data, buffer + offset, bpp, error)) {
            g_object_unref(dfield);
            return NULL;
        }
        break;

        default:
        g_assert_not_reached();
        break;
    }
    gwy_data_field_multiply(dfield, q);
    gwy_data_field_invert(dfield, TRUE, FALSE, FALSE);
    gwy_data_field_set_si_unit_z(dfield, unitz);
    g_object_unref(unitz);

    gwy_data_field_set_si_unit_xy(dfield, unitxy);
    g_object_unref(unitxy);

    return dfield;
}
Example #15
0
static void
immerse_correlate(GwyDataField *image,
                  GwyDataField *kernel,
                  gint *col,
                  gint *row)
{
    GwyDataField *subimage, *subkernel, *score, *imagearea;
    gdouble factor;
    gint ixres, iyres, kxres, kyres;
    gint sixres, siyres, skxres, skyres;
    gint xfrom, yfrom, xto, yto;
    gint sx, sy, delta;

    ixres = gwy_data_field_get_xres(image);
    iyres = gwy_data_field_get_yres(image);
    kxres = gwy_data_field_get_xres(kernel);
    kyres = gwy_data_field_get_yres(kernel);
    gwy_debug("kernel: %dx%d, image: %dx%d", kxres, kyres, ixres, iyres);

    factor = MAX(downsample_factor, downsample_limit/sqrt(kxres*kyres));
    factor = MIN(factor, 1.0);

    skxres = GWY_ROUND(factor*kxres);
    skyres = GWY_ROUND(factor*kyres);
    sixres = GWY_ROUND(factor*ixres);
    siyres = GWY_ROUND(factor*iyres);
    gwy_debug("skernel: %dx%d, simage: %dx%d", skxres, skyres, sixres, siyres);

    subimage = gwy_data_field_new_resampled(image, sixres, siyres,
                                            GWY_INTERPOLATION_LINEAR);
    score = gwy_data_field_new_alike(subimage, FALSE);
    subkernel = gwy_data_field_new_resampled(kernel, skxres, skyres,
                                             GWY_INTERPOLATION_LINEAR);

    gwy_data_field_correlate(subimage, subkernel, score,
                             GWY_CORRELATION_NORMAL);
    immerse_find_maximum(score, &sx, &sy);
    gwy_debug("sx: %d, sy: %d", sx, sy);
    g_object_unref(score);
    g_object_unref(subkernel);
    g_object_unref(subimage);

    /* Top left corner coordinate */
    sx -= (skxres - 1)/2;
    sy -= (skyres - 1)/2;
    /* Upscaled to original size */
    sx = GWY_ROUND((gdouble)ixres/sixres*sx);
    sy = GWY_ROUND((gdouble)iyres/siyres*sy);
    /* Uncertainty margin */
    delta = GWY_ROUND(1.5/factor + 1);
    /* Subarea to search */
    xfrom = MAX(sx - delta, 0);
    yfrom = MAX(sy - delta, 0);
    xto = MIN(sx + kxres + delta, ixres);
    yto = MIN(sy + kyres + delta, iyres);

    imagearea = gwy_data_field_area_extract(image,
                                            xfrom, yfrom,
                                            xto - xfrom, yto - yfrom);
    score = gwy_data_field_new_alike(imagearea, FALSE);
    gwy_data_field_correlate(imagearea, kernel, score,
                             GWY_CORRELATION_NORMAL);
    immerse_find_maximum(score, &sx, &sy);
    g_object_unref(score);
    g_object_unref(imagearea);

    *col = sx + xfrom - (kxres - 1)/2;
    *row = sy + yfrom - (kyres - 1)/2;
}
Example #16
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 #17
0
static GwyContainer*
burleigh_load(const gchar *filename,
              G_GNUC_UNUSED GwyRunType mode,
              GError **error)
{
    GwySIUnit *unit;
    GwyContainer *container = NULL;
    guchar *buffer = NULL;
    const guchar *p;
    gsize size = 0;
    GError *err = NULL;
    IMGFile imgfile;
    GwyDataField *dfield;
    gdouble *data;
    const gint16 *d;
    gdouble zoom;
    guint i;

    if (!gwy_file_get_contents(filename, &buffer, &size, &err)) {
        err_GET_FILE_CONTENTS(error, &err);
        return NULL;
    }
    if (size < HEADER_SIZE_MIN + 2) {
        err_TOO_SHORT(error);
        gwy_file_abandon_contents(buffer, size, NULL);
        return NULL;
    }

    gwy_clear(&imgfile, 1);
    p = buffer;
    imgfile.version = gwy_get_gfloat_le(&p);
    imgfile.version_int = GWY_ROUND(10*imgfile.version);
    if (imgfile.version_int == 21) {
        d = burleigh_load_v21(&imgfile, buffer, size, error);
        if (!d) {
            gwy_file_abandon_contents(buffer, size, NULL);
            return NULL;
        }
    }
    else {
        g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA,
                    _("File format version %.1f is not supported."),
                    imgfile.version);
        gwy_file_abandon_contents(buffer, size, NULL);
        return NULL;
    }

    zoom = burleigh_get_zoom_v21(&imgfile);
    if (err_DIMENSION(error, imgfile.xres)
        || err_DIMENSION(error, imgfile.yres)) {
        gwy_file_abandon_contents(buffer, size, NULL);
        return NULL;
    }

    dfield = gwy_data_field_new(imgfile.xres, imgfile.yres,
                                Angstrom*imgfile.xrange/zoom,
                                Angstrom*imgfile.yrange/zoom,
                                FALSE);
    data = gwy_data_field_get_data(dfield);
    for (i = 0; i < imgfile.xres*imgfile.yres; i++)
        data[i] = GINT16_FROM_LE(d[i])*imgfile.zrange/4095.0;

    gwy_file_abandon_contents(buffer, size, NULL);

    unit = gwy_si_unit_new("m");
    gwy_data_field_set_si_unit_xy(dfield, unit);
    g_object_unref(unit);

    container = gwy_container_new();
    switch (imgfile.data_type) {
        case BURLEIGH_CURRENT:
        unit = gwy_si_unit_new("A");
        gwy_container_set_string_by_name(container, "/0/data/title",
                                         g_strdup("Current"));
        gwy_data_field_multiply(dfield, Picoampere);
        break;

        case BURLEIGH_TOPOGRAPHY:
        unit = gwy_si_unit_new("m");
        gwy_container_set_string_by_name(container, "/0/data/title",
                                         g_strdup("Topography"));
        gwy_data_field_multiply(dfield, Angstrom);
        break;

        default:
        unit = gwy_si_unit_new("m");
        break;
    }
    gwy_data_field_set_si_unit_z(dfield, unit);
    g_object_unref(unit);

    gwy_container_set_object_by_name(container, "/0/data", dfield);
    g_object_unref(dfield);

    gwy_file_channel_import_log_add(container, 0, NULL, filename);

    return container;
}
Example #18
0
static void
extract_path_do(GwyContainer *data,
                GwyDataField *dfield, gboolean realsquare,
                GwySelection *selection,
                const ExtrPathArgs *args)
{
    GwyGraphModel *gmodel;
    GwySpline *spline;
    GwyXY *points, *tangents;
    GwySIUnit *xyunit;
    gdouble dx, dy, qx, qy, h, l, length, slackness;
    gdouble *xdata, *ydata;
    guint n, i;
    gboolean closed;

    /* This can only be satisfied in non-interactive use.  Doing nothing is
     * the best option in this case. */
    if (!selection || (n = gwy_selection_get_data(selection, NULL)) < 2)
        return;

    points = rescale_points(selection, dfield, realsquare, &dx, &dy, &qx, &qy);
    h = MIN(dx, dy);
    spline = gwy_spline_new_from_points(points, n);
    g_object_get(selection,
                 "slackness", &slackness,
                 "closed", &closed,
                 NULL);
    gwy_spline_set_closed(spline, closed);
    gwy_spline_set_slackness(spline, slackness);
    g_free(points);

    length = gwy_spline_length(spline);

    /* This would give natural sampling for a straight line along some axis. */
    n = GWY_ROUND(length + 1.0);
    points = g_new(GwyXY, n);
    tangents = g_new(GwyXY, n);
    xdata = g_new(gdouble, n);
    ydata = g_new(gdouble, n);
    gwy_spline_sample_uniformly(spline, points, tangents, n);
    qx *= dx;
    qy *= dy;
    for (i = 0; i < n; i++) {
        points[i].x *= qx;
        points[i].y *= qy;
        GWY_SWAP(gdouble, tangents[i].x, tangents[i].y);
        tangents[i].x *= qx;
        tangents[i].y *= -qy;
        l = sqrt(tangents[i].x*tangents[i].x + tangents[i].y*tangents[i].y);
        if (h > 0.0) {
            tangents[i].x /= l;
            tangents[i].y /= l;
        }
        xdata[i] = i/(n - 1.0)*length*h;
    }

    xyunit = gwy_data_field_get_si_unit_xy(dfield);
    if ((gmodel = create_graph_model(points, xdata, ydata, n,
                                     args->x, args->y))) {
        g_object_set(gmodel,
                     "axis-label-left", _("Position"),
                     "axis-label-bottom", _("Distance"),
                     "si-unit-x", xyunit,
                     "si-unit-y", xyunit,
                     NULL);
        gwy_app_data_browser_add_graph_model(gmodel, data, TRUE);
        g_object_unref(gmodel);
    }

    if ((gmodel = create_graph_model(tangents, xdata, ydata, n,
                                     args->vx, args->vy))) {
        g_object_set(gmodel,
                     "axis-label-left", _("Tangent"),
                     "axis-label-bottom", _("Distance"),
                     "si-unit-x", xyunit,
                     NULL);
        gwy_app_data_browser_add_graph_model(gmodel, data, TRUE);
        g_object_unref(gmodel);
    }

    g_free(ydata);
    g_free(xdata);
    g_free(points);
    g_free(tangents);
}
Example #19
0
static gboolean
aafm_export(G_GNUC_UNUSED GwyContainer *data,
            const gchar *filename,
            G_GNUC_UNUSED GwyRunType mode,
            GError **error)
{
    union { guchar pp[4]; float f; } z;
    guint16 res, r;
    gint16 *x;
    gint16 v;
    gint i, j, xres, yres, n;
    GwyDataField *dfield;
    const gdouble *d;
    gdouble min, max, q, z0;
    FILE *fh;
    gboolean ok = TRUE;

    gwy_app_data_browser_get_current(GWY_APP_DATA_FIELD, &dfield, 0);
    if (!dfield) {
        err_NO_CHANNEL_EXPORT(error);
        return FALSE;
    }

    if (!(fh = gwy_fopen(filename, "wb"))) {
        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);
    res = MIN(MIN(xres, yres), 32767);
    n = (gint)res*(gint)res;
    r = GUINT16_TO_LE(res);
    fwrite(&res, 1, sizeof(r), fh);

    gwy_data_field_get_min_max(dfield, &min, &max);
    if (min == max) {
        q = 0.0;
        z0 = 0.0;
    }
    else {
        q = 65533.0/(max - min);
        z0 = -32766.5*(max + min)/(max - min);
    }
    z.f = MIN(gwy_data_field_get_xreal(dfield),
              gwy_data_field_get_yreal(dfield))/Angstrom;
#if (G_BYTE_ORDER == G_BIG_ENDIAN)
    GWY_SWAP(guchar, z.pp[0], z.pp[3]);
    GWY_SWAP(guchar, z.pp[1], z.pp[2]);
#endif
    fwrite(&z, 1, sizeof(z), fh);

    x = g_new(gint16, n);
    for (i = 0; i < res; i++) {
        for (j = 0; j < res; j++) {
            v = GWY_ROUND(d[(res-1 - j)*res + i]*q + z0);
            x[i*res + j] = GINT16_TO_LE(v);
        }
    }

    if (!(ok = (fwrite(x, 1, 2*n, fh) == 2*n))) {
        err_WRITE(error);
        g_unlink(filename);
    }
    else {
        z.f = (max - min)/Angstrom;
#if (G_BYTE_ORDER == G_BIG_ENDIAN)
        GWY_SWAP(guchar, z.pp[0], z.pp[3]);
        GWY_SWAP(guchar, z.pp[1], z.pp[2]);
#endif
        fwrite(&z, 1, sizeof(z), fh);
    }

    fclose(fh);
    g_free(x);

    return ok;
}
Example #20
0
static void
gwy_data_field_facet_distribution(GwyDataField *dfield,
                                  gint kernel_size,
                                  GwyContainer *container)
{
    GwyDataField *dtheta, *dphi, *dist;
    GwySIUnit *siunit;
    gdouble *xd, *yd, *data;
    const gdouble *xdc, *ydc;
    gdouble q, max;
    gint res, hres, i, j, mi, mj, xres, yres;

    if (gwy_container_gis_object_by_name(container, "/theta", &dtheta))
        g_object_ref(dtheta);
    else
        dtheta = gwy_data_field_new_alike(dfield, FALSE);

    if (gwy_container_gis_object_by_name(container, "/phi", &dphi))
        g_object_ref(dphi);
    else
        dphi = gwy_data_field_new_alike(dfield, FALSE);

    compute_slopes(dfield, kernel_size, dtheta, dphi);
    xres = gwy_data_field_get_xres(dfield);
    yres = gwy_data_field_get_yres(dfield);
    xd = gwy_data_field_get_data(dtheta);
    yd = gwy_data_field_get_data(dphi);

    for (i = xres*yres; i; i--, xd++, yd++) {
        gdouble theta, phi;

        slopes_to_angles(*xd, *yd, &theta, &phi);
        *xd = theta;
        *yd = phi;
    }
    q = gwy_data_field_get_max(dtheta);
    q = MIN(q*1.05, G_PI/2.0);
    q = G_SQRT2/(2.0*sin(q/2.0));

    if (gwy_container_gis_object_by_name(container, "/0/data", &dist)) {
        g_object_ref(dist);
        gwy_data_field_clear(dist);
        gwy_data_field_set_xreal(dist, 2.0*G_SQRT2/q);
        gwy_data_field_set_yreal(dist, 2.0*G_SQRT2/q);
    }
    else {
        dist = gwy_data_field_new(FDATA_RES, FDATA_RES,
                                  2.0*G_SQRT2/q, 2.0*G_SQRT2/q,
                                  TRUE);
        siunit = gwy_si_unit_new("");
        gwy_data_field_set_si_unit_z(dist, siunit);
        g_object_unref(siunit);
        /* FIXME */
        siunit = gwy_si_unit_new("");
        gwy_data_field_set_si_unit_xy(dist, siunit);
        g_object_unref(siunit);
    }

    res = FDATA_RES;
    hres = (res - 1)/2;
    data = gwy_data_field_get_data(dist);

    xdc = gwy_data_field_get_data_const(dtheta);
    ydc = gwy_data_field_get_data_const(dphi);
    for (i = xres*yres; i; i--, xdc++, ydc++) {
        gdouble x, y;
        gint xx, yy;

        angles_to_xy(*xdc, *ydc, &x, &y);
        xx = GWY_ROUND(q*x/G_SQRT2*hres) + hres;
        yy = GWY_ROUND(q*y/G_SQRT2*hres) + hres;
        data[yy*res + xx] += 1.0;
    }

    /* Find maxima */
    mi = mj = hres;
    max = 0;
    for (i = 1; i+1 < res; i++) {
        for (j = 1; j+1 < res; j++) {
            gdouble z;

            z = data[i*res + j]
                + 0.3*(data[i*res + j - 1]
                       + data[i*res + j + 1]
                       + data[i*res - res + j]
                       + data[i*res + res + j])
                + 0.1*(data[i*res - res + j - 1]
                       + data[i*res - res + j + 1]
                       + data[i*res + res + j - 1]
                       + data[i*res + res + j + 1]);
            if (G_UNLIKELY(z > max)) {
                max = z;
                mi = i;
                mj = j;
            }
        }
    }

    for (i = res*res; i; i--, data++)
        *data = pow(*data, 0.35);

    gwy_container_set_double_by_name(container, "/q", q);
    {
        gdouble x, y, theta, phi;

        x = (mj - hres)*G_SQRT2/(q*hres);
        y = (mi - hres)*G_SQRT2/(q*hres);
        xy_to_angles(x, y, &theta, &phi);
        gwy_container_set_double_by_name(container, "/theta0", theta);
        gwy_container_set_double_by_name(container, "/phi0", phi);
    }
    gwy_container_set_object_by_name(container, "/0/data", dist);
    g_object_unref(dist);
    gwy_container_set_object_by_name(container, "/theta", dtheta);
    g_object_unref(dtheta);
    gwy_container_set_object_by_name(container, "/phi", dphi);
    g_object_unref(dphi);
    gwy_container_set_string_by_name(container, "/0/base/palette",
                                     g_strdup(FVIEW_GRADIENT));

    gwy_data_field_data_changed(dist);
}
Example #21
0
static void
square_samples(GwyContainer *data, GwyRunType run)
{
    GwyDataField *dfield, *dfields[3];
    gdouble xreal, yreal, qx, qy;
    gint oldid, newid, xres, yres;
    GQuark quark;

    g_return_if_fail(run & BASICOPS_RUN_MODES);
    gwy_app_data_browser_get_current(GWY_APP_DATA_FIELD, dfields + 0,
                                     GWY_APP_MASK_FIELD, dfields + 1,
                                     GWY_APP_SHOW_FIELD, dfields + 2,
                                     GWY_APP_DATA_FIELD_ID, &oldid,
                                     0);
    dfield = dfields[0];
    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);
    qx = xres/xreal;
    qy = yres/yreal;
    if (fabs(log(qx/qy)) > 1.0/hypot(xres, yres)) {
        /* Resample */
        if (qx < qy)
            xres = MAX(GWY_ROUND(xreal*qy), 1);
        else
            yres = MAX(GWY_ROUND(yreal*qx), 1);

        dfields[0] = gwy_data_field_new_resampled(dfields[0], xres, yres,
                                                  GWY_INTERPOLATION_BSPLINE);
        if (dfields[1]) {
            dfields[1]
                = gwy_data_field_new_resampled(dfields[1], xres, yres,
                                               GWY_INTERPOLATION_ROUND);
        }
        if (dfields[2]) {
            dfields[2]
                = gwy_data_field_new_resampled(dfields[2], xres, yres,
                                               GWY_INTERPOLATION_BSPLINE);
        }
    }
    else {
        /* Ratios are equal, just duplicate */
        dfields[0] = gwy_data_field_duplicate(dfields[0]);
        if (dfields[1])
            dfields[1] = gwy_data_field_duplicate(dfields[1]);
        if (dfields[2])
            dfields[2] = gwy_data_field_duplicate(dfields[2]);
    }


    newid = gwy_app_data_browser_add_data_field(dfields[0], data, TRUE);
    g_object_unref(dfields[0]);
    gwy_app_sync_data_items(data, data, oldid, newid, FALSE,
                            GWY_DATA_ITEM_GRADIENT,
                            GWY_DATA_ITEM_RANGE,
                            GWY_DATA_ITEM_MASK_COLOR,
                            0);

    if (dfields[1]) {
        quark = gwy_app_get_mask_key_for_id(newid);
        gwy_container_set_object(data, quark, dfields[1]);
        g_object_unref(dfields[1]);
    }
    if (dfields[2]) {
        quark = gwy_app_get_show_key_for_id(newid);
        gwy_container_set_object(data, quark, dfields[2]);
        g_object_unref(dfields[2]);
    }

    gwy_app_channel_log_add_proc(data, oldid, newid);
}