static void run_noninteractive(FacetsArgs *args, GwyContainer *data, GwyContainer *fdata, GwyDataField *dfield, GwyDataField *mfield, GQuark mquark) { GwyDataField *dtheta, *dphi, *mask; gwy_app_undo_qcheckpointv(data, 1, &mquark); mask = create_mask_field(dfield); dtheta = GWY_DATA_FIELD(gwy_container_get_object_by_name(fdata, "/theta")); dphi = GWY_DATA_FIELD(gwy_container_get_object_by_name(fdata, "/phi")); gwy_data_field_mark_facets(dtheta, dphi, args->theta0, args->phi0, args->tolerance, mask); if (mfield && args->combine) { if (args->combine_type == GWY_MERGE_UNION) gwy_data_field_grains_add(mfield, mask); else if (args->combine_type == GWY_MERGE_INTERSECTION) gwy_data_field_grains_intersect(mfield, mask); gwy_data_field_data_changed(mfield); } else if (mfield) { gwy_data_field_copy(mask, mfield, FALSE); gwy_data_field_data_changed(mfield); } else { gwy_container_set_object(data, mquark, mask); } g_object_unref(mask); }
static void rotate_counterclockwise_90(GwyContainer *data, GwyRunType run) { GwyDataField *dfields[3], *newfield; GQuark quarks[3]; gint i, id; 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_KEY, quarks + 0, GWY_APP_MASK_FIELD_KEY, quarks + 1, GWY_APP_SHOW_FIELD_KEY, quarks + 2, GWY_APP_DATA_FIELD_ID, &id, 0); clean_quarks(G_N_ELEMENTS(quarks), quarks, dfields); gwy_app_undo_qcheckpointv(data, G_N_ELEMENTS(quarks), quarks); for (i = 0; i < G_N_ELEMENTS(dfields); i++) { if (dfields[i]) { newfield = gwy_data_field_new_alike(dfields[i], FALSE); flip_xy(dfields[i], newfield, TRUE); gwy_container_set_object(data, quarks[i], newfield); g_object_unref(newfield); } } gwy_app_data_clear_selections(data, id); gwy_app_channel_log_add_proc(data, id, id); }
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_images(const X3PFile *x3pfile, GwyContainer *container) { gint id; for (id = 0; id < x3pfile->zres; id++) { GwyContainer *meta; guint n = x3pfile->xres*x3pfile->yres, k; GwyDataField *dfield, *mask; const gboolean *valid = x3pfile->valid + id*n; GQuark quark; gchar buf[40]; dfield = gwy_data_field_new(x3pfile->xres, x3pfile->yres, x3pfile->xres*x3pfile->dx, x3pfile->yres*x3pfile->dy, FALSE); memcpy(dfield->data, x3pfile->values + id*n, n*sizeof(gdouble)); for (k = 0; k < n; k++) { if (!valid[k]) dfield->data[k] = NAN; } quark = gwy_app_get_data_key_for_id(id); gwy_container_set_object(container, quark, dfield); gwy_si_unit_set_from_string(gwy_data_field_get_si_unit_xy(dfield), "m"); gwy_si_unit_set_from_string(gwy_data_field_get_si_unit_z(dfield), "m"); gwy_app_channel_title_fall_back(container, id); gwy_app_channel_check_nonsquare(container, id); if ((mask = gwy_app_channel_mask_of_nans(dfield, TRUE))) { quark = gwy_app_get_mask_key_for_id(id); gwy_container_set_object(container, quark, mask); g_object_unref(mask); } g_object_unref(dfield); if ((meta = get_meta(x3pfile))) { g_snprintf(buf, sizeof(buf), "/%u/meta", id); gwy_container_set_object_by_name(container, buf, meta); g_object_unref(meta); } } }
static void laplace(GwyContainer *data, GwyRunType run) { GwyDataField *dfield, *mfield, *buffer; GQuark dquark; gdouble error, cor, maxer, lastfrac, frac, starter; gint i, id; gboolean cancelled = FALSE; g_return_if_fail(run & LAPLACE_RUN_MODES); gwy_app_data_browser_get_current(GWY_APP_DATA_FIELD_KEY, &dquark, GWY_APP_DATA_FIELD, &dfield, GWY_APP_MASK_FIELD, &mfield, GWY_APP_DATA_FIELD_ID, &id, 0); g_return_if_fail(dfield && dquark && mfield); maxer = gwy_data_field_get_rms(dfield)/1.0e4; gwy_app_wait_start(gwy_app_find_window_for_channel(data, id), _("Laplace interpolation...")); dfield = gwy_data_field_duplicate(dfield); buffer = gwy_data_field_new_alike(dfield, TRUE); gwy_data_field_correct_average(dfield, mfield); cor = 0.2; error = 0.0; lastfrac = 0.0; starter = 0.0; for (i = 0; i < 5000; i++) { gwy_data_field_correct_laplace_iteration(dfield, mfield, buffer, cor, &error); if (error < maxer) break; if (!i) starter = error; frac = log(error/starter)/log(maxer/starter); if ((i/(gdouble)(5000)) > frac) frac = i/(gdouble)(5000); if (lastfrac > frac) frac = lastfrac; if (!gwy_app_wait_set_fraction(frac)) { cancelled = TRUE; break; } lastfrac = frac; } gwy_app_wait_finish(); if (!cancelled) { gwy_app_undo_qcheckpointv(data, 1, &dquark); gwy_container_set_object(data, dquark, dfield); gwy_app_channel_log_add_proc(data, id, id); } g_object_unref(dfield); g_object_unref(buffer); }
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 run_noninteractive(GEdgeArgs *args, GwyContainer *data, GwyDataField *dfield, GQuark mquark) { GwyDataField *mfield; gwy_app_undo_qcheckpointv(data, 1, &mquark); mfield = create_mask_field(dfield); gedge_process(dfield, mfield, args); gwy_container_set_object(data, mquark, mfield); g_object_unref(mfield); }
static void presentation_attach_do(const GwyAppDataId *source, const GwyAppDataId *target) { GwyContainer *sourcedata, *targetdata; GwyDataField *dfield; GQuark quark; sourcedata = gwy_app_data_browser_get(source->datano); targetdata = gwy_app_data_browser_get(target->datano); quark = gwy_app_get_data_key_for_id(source->id); dfield = GWY_DATA_FIELD(gwy_container_get_object(sourcedata, quark)); dfield = gwy_data_field_duplicate(dfield); quark = gwy_app_get_show_key_for_id(target->id); gwy_app_undo_qcheckpointv(targetdata, 1, &quark); gwy_container_set_object(targetdata, quark, dfield); g_object_unref(dfield); }
static void run_noninteractive(FacetsArgs *args, GwyContainer *data, GwyContainer *fdata, GwyDataField *dfield, GwyDataField *mfield, GQuark mquark) { GwyDataField *dtheta, *dphi; gwy_app_undo_qcheckpointv(data, 1, &mquark); if (!mfield) { mfield = create_mask_field(dfield); gwy_container_set_object(data, mquark, mfield); g_object_unref(mfield); } dtheta = GWY_DATA_FIELD(gwy_container_get_object_by_name(fdata, "/theta")); dphi = GWY_DATA_FIELD(gwy_container_get_object_by_name(fdata, "/phi")); gwy_data_field_mark_facets(dtheta, dphi, args->theta0, args->phi0, args->tolerance, mfield); gwy_data_field_data_changed(mfield); }
static GwyContainer* sly_load(const gchar *filename, G_GNUC_UNUSED GwyRunType mode, GError **error) { GwyContainer *container = NULL, *meta = NULL; gchar *buffer = NULL; GError *err = NULL; GHashTable *hash = NULL; gchar *p, *line, *value; guint expecting_data = 0; SensolyticsChannel *channels = NULL; Dimensions dimensions; gint ndata = 0, i; if (!g_file_get_contents(filename, &buffer, NULL, &err)) { err_GET_FILE_CONTENTS(error, &err); return NULL; } p = buffer; line = gwy_str_next_line(&p); g_strstrip(line); if (!gwy_strequal(line, MAGIC)) { err_FILE_TYPE(error, "Sensolytics"); goto fail; } hash = g_hash_table_new(g_str_hash, g_str_equal); for (line = gwy_str_next_line(&p); line; line = gwy_str_next_line(&p)) { if (!line[0]) continue; if (expecting_data) { expecting_data--; /* The columns are comma-separated and numbers use decimal points. * Do not tempt the number parsing functions more than necessary * and fix commas to tab characters. */ g_strdelimit(line, ",", '\t'); /* Ignore X, Y and Z, each is two values */ for (i = 0; i < 6; i++) g_ascii_strtod(line, &line); for (i = 0; i < ndata; i++) channels[i].data[expecting_data] = channels[i].q * g_ascii_strtod(line, &line); } else { g_strstrip(line); if (line[0] != '#') { g_warning("Comment line does not start with #."); continue; } do { line++; } while (g_ascii_isspace(*line)); if (g_str_has_prefix(line, "X [")) { if (channels) { g_warning("Multiple data headers!?"); continue; } if (!read_dimensions(hash, &ndata, &dimensions, error) || !(channels = create_fields(hash, line, ndata, &dimensions))) goto fail; expecting_data = dimensions.xres * dimensions.yres; continue; } value = strchr(line, ':'); if (!value) { if (!gwy_strequal(line, "ArrayScan")) g_warning("Non-parameter-like line %s", line); continue; } *value = '\0'; g_strchomp(line); do { value++; } while (g_ascii_isspace(*value)); if (gwy_strequal(line, "Warning")) continue; gwy_debug("<%s>=<%s>", line, value); g_hash_table_insert(hash, line, value); } } if (!channels) { err_NO_DATA(error); goto fail; } container = gwy_container_new(); for (i = 0; i < ndata; i++) { GQuark key = gwy_app_get_data_key_for_id(i); gwy_data_field_invert(channels[i].dfield, FALSE, TRUE, FALSE); gwy_container_set_object(container, key, channels[i].dfield); gwy_app_channel_check_nonsquare(container, i); if (channels[i].name) { gchar *s = g_strconcat(g_quark_to_string(key), "/title", NULL); gwy_container_set_string_by_name(container, s, g_strdup(channels[i].name)); g_free(s); } else gwy_app_channel_title_fall_back(container, i); gwy_file_channel_import_log_add(container, i, NULL, filename); } meta = get_meta(hash); clone_meta(container, meta, ndata); g_object_unref(meta); fail: g_free(buffer); if (hash) g_hash_table_destroy(hash); if (channels) { for (i = 0; i < ndata; i++) g_object_unref(channels[i].dfield); g_free(channels); } return container; }
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); }
static GwyContainer* sensofar_load(const gchar *filename, G_GNUC_UNUSED GwyRunType mode, GError **error) { SensofarDataDesc data_desc; GwyContainer *container = NULL; GwyDataField *dfield, *mfield; GwyGraphModel *gmodel; guchar *buffer = NULL; gsize size = 0; GError *err = NULL; const guchar *p; if (!gwy_file_get_contents(filename, &buffer, &size, &err)) { err_GET_FILE_CONTENTS(error, &err); return NULL; } if (size < HEADER_SIZE + 12) { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA, _("File header is truncated")); gwy_file_abandon_contents(buffer, size, NULL); return NULL; } /* Date block */ p = buffer; memcpy(&data_desc.date.str, p, DATE_SIZE); data_desc.date.str[DATE_SIZE-1] = '\0'; p += DATE_SIZE; data_desc.date.t = gwy_get_guint32_le(&p); /* Comment block */ memcpy(&data_desc.user_comment, p, COMMENT_SIZE); data_desc.user_comment[COMMENT_SIZE-1] = '\0'; p += COMMENT_SIZE; /* Calbration block */ data_desc.axes_config.yres = gwy_get_guint32_le(&p); data_desc.axes_config.xres = gwy_get_guint32_le(&p); data_desc.axes_config.N_tall = gwy_get_guint32_le(&p); data_desc.axes_config.dy_multip = gwy_get_gfloat_le(&p); data_desc.axes_config.mppx = gwy_get_gfloat_le(&p); data_desc.axes_config.mppy = gwy_get_gfloat_le(&p); data_desc.axes_config.x_0 = gwy_get_gfloat_le(&p); data_desc.axes_config.y_0 = gwy_get_gfloat_le(&p); data_desc.axes_config.mpp_tall = gwy_get_gfloat_le(&p); data_desc.axes_config.z_0 = gwy_get_gfloat_le(&p); /* Measurement block */ data_desc.measure_config.type = gwy_get_guint32_le(&p); data_desc.measure_config.algorithm = gwy_get_guint32_le(&p); data_desc.measure_config.method = gwy_get_guint32_le(&p); data_desc.measure_config.objective = gwy_get_guint32_le(&p); data_desc.measure_config.area = gwy_get_guint32_le(&p); data_desc.measure_config.xres_area = gwy_get_guint32_le(&p); data_desc.measure_config.yres_area = gwy_get_guint32_le(&p); data_desc.measure_config.xres = gwy_get_guint32_le(&p); data_desc.measure_config.yres = gwy_get_guint32_le(&p); data_desc.measure_config.na = gwy_get_guint32_le(&p); data_desc.measure_config.incr_z = gwy_get_gdouble_le(&p); data_desc.measure_config.range = gwy_get_gfloat_le(&p); data_desc.measure_config.n_planes = gwy_get_guint32_le(&p); data_desc.measure_config.tpc_umbral_F = gwy_get_guint32_le(&p); data_desc.measure_config.restore = gwy_get_gboolean8(&p); data_desc.measure_config.num_layers = *(p++); data_desc.measure_config.version = *(p++); data_desc.measure_config.config_hardware = *(p++); data_desc.measure_config.stack_im_num = *(p++); data_desc.measure_config.reserved = *(p++); p += 2; // struct padding data_desc.measure_config.factor_delmacio = gwy_get_guint32_le(&p); gwy_debug("File date=<%s>, data type=%d, xres=%d, yres=%d, version=%d", data_desc.date.str, data_desc.measure_config.type, data_desc.measure_config.xres, data_desc.measure_config.yres, data_desc.measure_config.version); switch (data_desc.measure_config.type) { case MES_TOPO: case MES_IMATGE: dfield = sensofar_read_data_field(&data_desc, &mfield, &p, size - (p - buffer), error); if (!dfield) { gwy_file_abandon_contents(buffer, size, NULL); return NULL; } container = gwy_container_new(); gwy_container_set_object(container, gwy_app_get_data_key_for_id(0), dfield); g_object_unref(dfield); if (mfield) { gwy_container_set_object(container, gwy_app_get_mask_key_for_id(0), mfield); g_object_unref(mfield); } gwy_app_channel_title_fall_back(container, 0); break; case MES_PERFIL: case MES_GRUIX: gmodel = sensofar_read_profile(&data_desc, &p, size - (p - buffer), error); if (!gmodel) { gwy_file_abandon_contents(buffer, size, NULL); return NULL; } container = gwy_container_new(); gwy_container_set_object(container, gwy_app_get_graph_key_for_id(0), gmodel); g_object_unref(gmodel); break; default: err_DATA_TYPE(error, data_desc.measure_config.type); break; } return container; }
static GwyContainer* hitachi_load(const gchar *filename, G_GNUC_UNUSED GwyRunType mode, GError **error) { GwyContainer *container = NULL, *meta; GdkPixbuf *pixbuf = NULL; GwyDataField *dfield = NULL; gchar *value, *imagename = NULL, *header = NULL; guchar *pixels; GHashTable *hash = NULL; GError *err = NULL; gdouble dx; gint pxres, pyres, hxres, hyres, rowstride, nchannels, i, j; gdouble *data; if (!(hash = hitachi_load_header(filename, &header, error))) return NULL; if (!require_keys(hash, error, "ImageName", "DataSize", "PixelSize", NULL)) goto fail; value = g_hash_table_lookup(hash, "ImageName"); if (!(imagename = hitachi_find_data_name(filename, value))) { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA, _("No corresponding data file was found for header file.")); goto fail; } if (!(pixbuf = gdk_pixbuf_new_from_file(imagename, &err))) { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_IO, _("Cannot load image: %s"), err->message); g_clear_error(&err); goto fail; } /* We know the image dimensions so check them. */ pxres = gdk_pixbuf_get_width(pixbuf); pyres = gdk_pixbuf_get_height(pixbuf); value = g_hash_table_lookup(hash, "DataSize"); if (sscanf(value, "%ux%u", &hxres, &hyres) != 2) { err_INVALID(error, "DataSize"); goto fail; } if (hxres != pxres || hyres != pyres) { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA, _("Field DataSize %ux%u does not match image dimensions " "%ux%u."), hxres, hyres, pxres, pyres); goto fail; } if (err_DIMENSION(error, hxres) || err_DIMENSION(error, hyres)) goto fail; dx = g_ascii_strtod(g_hash_table_lookup(hash, "PixelSize"), NULL); /* Use negated positive conditions to catch NaNs */ if (!((dx = fabs(dx)) > 0)) { g_warning("Pixel size is 0.0, fixing to 1.0"); dx = 1.0; } dx *= Nanometre; dfield = gwy_data_field_new(hxres, hyres, hxres*dx, hyres*dx, FALSE); gwy_si_unit_set_from_string(gwy_data_field_get_si_unit_xy(dfield), "m"); data = gwy_data_field_get_data(dfield); pixels = gdk_pixbuf_get_pixels(pixbuf); rowstride = gdk_pixbuf_get_rowstride(pixbuf); nchannels = gdk_pixbuf_get_n_channels(pixbuf); for (i = 0; i < hyres; i++) { gdouble *drow = data + i*hxres; guchar *p = pixels + i*rowstride; for (j = 0; j < hxres; j++, p += nchannels) drow[j] = (p[0] + p[1] + p[2])/765.0; } container = gwy_container_new(); gwy_container_set_object(container, gwy_app_get_data_key_for_id(0), dfield); g_object_unref(dfield); if ((value = g_hash_table_lookup(hash, "SampleName")) && *value) gwy_container_set_string_by_name(container, "/0/data/title", g_strdup(value)); else gwy_container_set_string_by_name(container, "/0/data/title", g_strdup("SEM")); meta = gwy_container_new(); g_hash_table_foreach(hash, store_meta, meta); gwy_container_set_object_by_name(container, "/0/meta", meta); g_object_unref(meta); gwy_file_channel_import_log_add(container, 0, NULL, filename); fail: gwy_object_unref(pixbuf); g_free(imagename); g_free(header); g_hash_table_destroy(hash); return container; }
static void facets_dialog(FacetsArgs *args, GwyContainer *data, GwyContainer *fdata, GwyDataField *dfield, GwyDataField *mfield, gint id, GQuark mquark) { GtkWidget *dialog, *table, *hbox, *hbox2, *vbox, *label, *scale, *button; GtkWidget *spin; FacetsControls controls; enum { RESPONSE_RESET = 1, RESPONSE_PREVIEW = 2 }; gint response; GwyPixmapLayer *layer; GwyVectorLayer *vlayer; GwySelection *selection; gint row; memset(&controls, 0, sizeof(FacetsControls)); controls.args = args; dialog = gtk_dialog_new_with_buttons(_("Mark Facets"), NULL, GTK_DIALOG_DESTROY_WITH_PARENT, _("_Mark"), RESPONSE_PREVIEW, _("_Reset"), RESPONSE_RESET, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OK, GTK_RESPONSE_OK, NULL); gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE); gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK); controls.dialog = dialog; /* Shallow-copy stuff to temporary container */ controls.fdata = fdata; controls.mydata = gwy_container_new(); gwy_container_set_object_by_name(controls.mydata, "/0/data", dfield); gwy_app_sync_data_items(data, controls.mydata, id, 0, FALSE, GWY_DATA_ITEM_PALETTE, GWY_DATA_ITEM_RANGE, GWY_DATA_ITEM_MASK_COLOR, GWY_DATA_ITEM_REAL_SQUARE, 0); hbox = gtk_hbox_new(FALSE, 2); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), hbox, FALSE, FALSE, 4); controls.view = gwy_data_view_new(controls.mydata); layer = gwy_layer_basic_new(); g_object_set(layer, "data-key", "/0/data", "gradient-key", "/0/base/palette", "range-type-key", "/0/base/range-type", "min-max-key", "/0/base", NULL); gwy_data_view_set_data_prefix(GWY_DATA_VIEW(controls.view), "/0/data"); gwy_data_view_set_base_layer(GWY_DATA_VIEW(controls.view), layer); gwy_set_data_preview_size(GWY_DATA_VIEW(controls.view), PREVIEW_SIZE); vlayer = g_object_new(g_type_from_name("GwyLayerPoint"), NULL); gwy_vector_layer_set_selection_key(vlayer, "/0/select/pointer"); gwy_data_view_set_top_layer(GWY_DATA_VIEW(controls.view), vlayer); selection = gwy_vector_layer_ensure_selection(vlayer); g_signal_connect(selection, "changed", G_CALLBACK(preview_selection_updated), &controls); gtk_box_pack_start(GTK_BOX(hbox), controls.view, FALSE, FALSE, 4); vbox = gtk_vbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, TRUE, 0); hbox2 = gtk_hbox_new(FALSE, 4); gtk_box_pack_start(GTK_BOX(vbox), hbox2, FALSE, FALSE, 0); /* Slope view */ controls.fview = gwy_data_view_new(controls.fdata); gtk_box_pack_start(GTK_BOX(hbox2), controls.fview, FALSE, FALSE, 0); 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.fview), layer); vlayer = g_object_new(g_type_from_name("GwyLayerPoint"), NULL); gwy_vector_layer_set_selection_key(vlayer, "/0/select/pointer"); gwy_data_view_set_top_layer(GWY_DATA_VIEW(controls.fview), GWY_VECTOR_LAYER(vlayer)); selection = gwy_vector_layer_ensure_selection(vlayer); g_signal_connect(selection, "changed", G_CALLBACK(facet_view_selection_updated), &controls); /* Info table */ table = gtk_table_new(7, 2, 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(hbox2), table, TRUE, TRUE, 4); row = 0; label = gwy_label_new_header(gwy_sgettext("noun|Normal")); gtk_table_attach(GTK_TABLE(table), label, 0, 2, row, row+1, GTK_FILL, 0, 0, 0); row++; controls.theta_label = add_angle_label(table, _("θ:"), &row); controls.phi_label = add_angle_label(table, _("φ:"), &row); button = gtk_button_new_with_mnemonic(_("_Find Maximum")); gtk_table_attach(GTK_TABLE(table), button, 0, 2, row, row+1, GTK_FILL, 0, 0, 0); g_signal_connect_swapped(button, "clicked", G_CALLBACK(facet_view_reset_maximum), &controls); gtk_table_set_row_spacing(GTK_TABLE(table), row, 8); row++; label = gwy_label_new_header(_("Mean Normal")); gtk_table_attach(GTK_TABLE(table), label, 0, 2, row, row+1, GTK_FILL, 0, 0, 0); row++; controls.mtheta_label = add_angle_label(table, _("θ:"), &row); controls.mphi_label = add_angle_label(table, _("φ:"), &row); gtk_table_set_row_spacing(GTK_TABLE(table), row-1, 8); label = gtk_label_new_with_mnemonic(_("Facet plane size:")); gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); gtk_table_attach(GTK_TABLE(table), label, 0, 2, row, row+1, GTK_FILL, 0, 0, 0); row++; controls.kernel_size = gtk_adjustment_new(args->kernel_size, 0.0, MAX_PLANE_SIZE, 1.0, 1.0, 0); spin = gtk_spin_button_new(GTK_ADJUSTMENT(controls.kernel_size), 0.0, 0); gtk_label_set_mnemonic_widget(GTK_LABEL(label), spin); gtk_table_attach(GTK_TABLE(table), spin, 0, 1, row, row+1, 0, 0, 0, 0); g_signal_connect(controls.kernel_size, "value-changed", G_CALLBACK(facet_view_recompute), &controls); row++; table = gtk_table_new(9, 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(vbox), table, TRUE, TRUE, 4); row = 0; controls.tolerance = gtk_adjustment_new(args->tolerance*180.0/G_PI, 0.0, 15.0, 0.01, 0.1, 0); scale = gwy_table_attach_hscale(table, row++, _("_Tolerance:"), _("deg"), controls.tolerance, 0); gtk_spin_button_set_digits(GTK_SPIN_BUTTON(scale), 3); g_signal_connect(controls.tolerance, "value-changed", G_CALLBACK(facets_tolerance_changed), &controls); controls.color_button = gwy_color_button_new(); gwy_color_button_set_use_alpha(GWY_COLOR_BUTTON(controls.color_button), TRUE); load_mask_color(controls.color_button, gwy_data_view_get_data(GWY_DATA_VIEW(controls.view))); gwy_table_attach_hscale(table, row++, _("_Mask color:"), NULL, GTK_OBJECT(controls.color_button), GWY_HSCALE_WIDGET_NO_EXPAND); g_signal_connect(controls.color_button, "clicked", G_CALLBACK(mask_color_change_cb), &controls); if (!gwy_si_unit_equal(gwy_data_field_get_si_unit_xy(dfield), gwy_data_field_get_si_unit_z(dfield))) { gtk_table_set_row_spacing(GTK_TABLE(table), row-1, 8); label = gtk_label_new(_("Warning: Lateral and value units differ. " "Angles are not physically meaningful.")); gtk_label_set_line_wrap(GTK_LABEL(label), TRUE); gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); gtk_table_attach(GTK_TABLE(table), label, 0, 4, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); row++; } facets_invalidate(&controls); gtk_widget_show_all(dialog); facet_view_select_angle(&controls, args->theta0, args->phi0); 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: g_object_unref(controls.mydata); return; break; case GTK_RESPONSE_OK: break; case RESPONSE_RESET: args->tolerance = facets_defaults.tolerance; args->kernel_size = facets_defaults.kernel_size; facets_dialog_update_controls(&controls, args); break; case RESPONSE_PREVIEW: preview(&controls, args); update_average_angle(&controls, args); break; default: g_assert_not_reached(); break; } } while (response != GTK_RESPONSE_OK); gwy_app_sync_data_items(controls.mydata, data, 0, id, FALSE, GWY_DATA_ITEM_MASK_COLOR, 0); gtk_widget_destroy(dialog); if (controls.computed) { mfield = gwy_container_get_object_by_name(controls.mydata, "/0/mask"); gwy_app_undo_qcheckpointv(data, 1, &mquark); gwy_container_set_object(data, mquark, mfield); g_object_unref(controls.mydata); } else { g_object_unref(controls.mydata); run_noninteractive(args, data, fdata, dfield, mfield, mquark); } }
static GwyContainer* int_load(const gchar *filename, G_GNUC_UNUSED GwyRunType mode, GError **error) { GwyContainer *container = NULL, *meta; GwyDataField *dfield = NULL, *mfield = NULL; CodeVGridDataType type; gchar *line, *p, *comment, *end, *buffer = NULL; const gchar *unit, *title; gchar **fields = NULL; gsize size; GError *err = NULL; gdouble xreal, yreal; gint i, xres, yres, no_data_value = 32767; guint fi; gdouble scale_size, wavelength, q = 1.0, x_scale = 1.0; gboolean nearest_neighbour = FALSE; gdouble *data, *mdata; if (!g_file_get_contents(filename, &buffer, &size, &err)) { err_GET_FILE_CONTENTS(error, &err); goto fail; } /* Skip comments. */ p = buffer; for (line = gwy_str_next_line(&p); line && line[0] == '!'; line = gwy_str_next_line(&p)) { gwy_debug("comment <%s>", line); } if (!line) { err_FILE_TYPE(error, "Code V INT"); goto fail; } /* The title. */ comment = line; if (!(line = gwy_str_next_line(&p))) { err_FILE_TYPE(error, "Code V INT"); goto fail; } gwy_debug("comment <%s>", comment); fields = split_line_in_place(line); if (!fields || g_strv_length(fields) < 8 || !gwy_strequal(fields[0], "GRD") || !(xres = atoi(fields[1])) || !(yres = atoi(fields[2])) || !(type = gwy_stramong(fields[3], "SUR", "WFR", "FIL", "THV", "BIR", "CAO", NULL)) || !gwy_strequal(fields[4], "WVL") || (!(wavelength = g_ascii_strtod(fields[5], &end)) && end == fields[5])) { err_FILE_TYPE(error, "Code V INT"); goto fail; } gwy_debug("type %u (%s)", type, fields[3]); gwy_debug("xres %d, yres %d", xres, yres); gwy_debug("wavelength %g", wavelength); fi = 6; if (gwy_strequal(fields[fi], "NNB")) { nearest_neighbour = TRUE; fi++; } gwy_debug("nearest_neighbour %d", nearest_neighbour); if (!fields[fi] || !gwy_strequal(fields[fi], "SSZ")) { err_FILE_TYPE(error, "Code V INT"); goto fail; } fi++; if (!(scale_size = g_ascii_strtod(fields[fi], &end)) && end == fields[fi]) { err_FILE_TYPE(error, "Code V INT"); goto fail; } gwy_debug("scale_size %g", scale_size); if (!scale_size) { g_warning("Zero SSZ, fixing to 1.0"); scale_size = 1.0; } fi++; if (fields[fi] && gwy_strequal(fields[fi], "NDA")) { fi++; if (!fields[fi]) { err_FILE_TYPE(error, "Code V INT"); goto fail; } no_data_value = atoi(fields[fi]); fi++; } gwy_debug("no_data_value %d", no_data_value); if (fields[fi] && gwy_strequal(fields[fi], "XSC")) { fi++; if (!fields[fi]) { err_FILE_TYPE(error, "Code V INT"); goto fail; } if (!(x_scale = g_ascii_strtod(fields[fi], &end)) && end == fields[fi]) { err_FILE_TYPE(error, "Code V INT"); goto fail; } fi++; } gwy_debug("x_scale %g", x_scale); if (!x_scale) { g_warning("Zero XSC, fixing to 1.0"); x_scale = 1.0; } /* There may be more stuff but we do not know anything about it. */ if (err_DIMENSION(error, xres) || err_DIMENSION(error, yres)) goto fail; yreal = 1.0; xreal = x_scale*yreal; dfield = gwy_data_field_new(xres, yres, xreal, yreal, TRUE); if (type == CODEV_INT_SURFACE_DEFORMATION) { q = 1e-6*wavelength/scale_size; unit = "m"; title = "Surface"; } else if (type == CODEV_INT_WAVEFRONT_DEFORMATION) { q = 1e-6*wavelength/scale_size; unit = "m"; title = "Wavefront"; } else { g_warning("Don't know how to convert this grid data type to physical " "units."); title = fields[3]; } gwy_si_unit_set_from_string(gwy_data_field_get_si_unit_z(dfield), unit); mfield = gwy_data_field_new_alike(dfield, TRUE); data = gwy_data_field_get_data(dfield); mdata = gwy_data_field_get_data(mfield); for (i = 0; i < xres*yres; i++, p = end) { gint value = strtol(p, &end, 10); if (value != no_data_value && (type != CODEV_INT_INTENSITY_FILTER || value >= 0)) { mdata[i] = 1.0; data[i] = q*value; } } if (!gwy_app_channel_remove_bad_data(dfield, mfield)) gwy_object_unref(mfield); container = gwy_container_new(); /* gwy_data_field_invert(dfield, TRUE, FALSE, FALSE); from F. Riguet : apparently no flip is needed (the raw data import module gives the correct orientation without further flipping) */ gwy_container_set_object(container, gwy_app_get_data_key_for_id(0), dfield); g_object_unref(dfield); gwy_app_channel_check_nonsquare(container, 0); gwy_container_set_string_by_name(container, "/0/data/title", g_strdup(title)); if (mfield) { /* gwy_data_field_invert(mfield, FALSE, TRUE, FALSE); */ gwy_container_set_object(container, gwy_app_get_mask_key_for_id(0), mfield); g_object_unref(mfield); } meta = gwy_container_new(); gwy_container_set_string_by_name(meta, "Comment", g_strdup(comment)); gwy_container_set_string_by_name(meta, "Interpolation", g_strdup(nearest_neighbour ? "NNB" : "Linear")); gwy_container_set_string_by_name(meta, "Wavelength", g_strdup_printf("%g μm", wavelength)); gwy_container_set_object_by_name(container, "/0/meta", meta); g_object_unref(meta); gwy_file_channel_import_log_add(container, 0, NULL, filename); fail: g_free(fields); g_free(buffer); return container; }
static gboolean read_aist_curve(const guchar **p, gsize *size, AistContext *context) { AistCurve curve; GwyGraphModel *gmodel; GwyGraphCurveModel *gcmodel; GwySIUnit *xunit, *yunit; gboolean ok = FALSE; guint len, viewlen, i; const guchar *data, *viewdata; const gdouble *xdata, *ydata; gdouble *xdatacal, *ydatacal; gdouble *must_free = NULL; gdouble qx, qy; GQuark quark; gwy_clear(&curve, 1); gwy_debug("reading common"); if (!read_aist_common(p, size, &curve.common)) goto fail; gwy_debug("reading curve"); if (!read_qt_int(p, size, &curve.res)) goto fail; if (!read_qt_byte_array(p, size, &len, &data)) goto fail; if (len != 2*curve.res*sizeof(gdouble)) goto fail; /* Again something called view data. Skip it. The units follow. */ if (!read_qt_byte_array(p, size, &viewlen, &viewdata)) goto fail; if (!read_qt_string(p, size, &curve.xunits) || !read_qt_string(p, size, &curve.yunits)) goto fail; xunit = extract_units(curve.xunits, &qx); yunit = extract_units(curve.yunits, &qy); /* The data are already stored as doubles in the correct order, so save * work if also the endianess matches. */ if (G_BYTE_ORDER == G_BIG_ENDIAN) { must_free = g_new(gdouble, 2*curve.res); xdata = must_free; ydata = xdata + curve.res; gwy_memcpy_byte_swap(data, (guchar*)must_free, 8, 2*curve.res, 7); } else if (G_BYTE_ORDER == G_LITTLE_ENDIAN) { xdata = (const gdouble *)data; ydata = xdata + curve.res; } xdatacal = g_new(gdouble, curve.res); ydatacal = g_new(gdouble, curve.res); for (i = 0; i < curve.res; i++) { xdatacal[i] = xdata[i]*qx; ydatacal[i] = ydata[i]*qy; } gcmodel = gwy_graph_curve_model_new(); gwy_graph_curve_model_set_data(gcmodel, xdatacal, ydatacal, curve.res); g_object_set(gcmodel, "mode", GWY_GRAPH_CURVE_LINE, "description", curve.common.description, NULL); g_free(must_free); g_free(xdatacal); g_free(ydatacal); gmodel = gwy_graph_model_new(); gwy_graph_model_add_curve(gmodel, gcmodel); g_object_unref(gcmodel); g_object_set(gmodel, "title", curve.common.name, "si-unit-x", xunit, "si-unit-y", yunit, NULL); g_object_unref(xunit); g_object_unref(yunit); quark = gwy_app_get_graph_key_for_id(context->graph_id+1); gwy_container_set_object(context->container, quark, gmodel); g_object_unref(gmodel); context->graph_id++; ok = TRUE; fail: free_aist_common(&curve.common); g_free(curve.xunits); g_free(curve.yunits); return ok; }
static GwyContainer* shimadzu_load(const gchar *filename, G_GNUC_UNUSED GwyRunType mode, GError **error) { GwyContainer *meta, *container = NULL; GwyDataField *dfield = NULL; GError *err = NULL; gchar *buffer = NULL; GHashTable *hash; gchar *head; gsize size = 0; gboolean ok; gint text_data_start; if (!g_file_get_contents(filename, &buffer, &size, &err)) { err_GET_FILE_CONTENTS(error, &err); return NULL; } if (size < HEADER_SIZE + 2) { err_TOO_SHORT(error); return NULL; } if (memcmp(buffer, MAGIC, MAGIC_SIZE) != 0 && !(memcmp(buffer, MAGIC_ASCII, MAGIC_ASCII_SIZE) == 0 && (memcmp(buffer + MAGIC_ASCII_SIZE+1, MAGIC, MAGIC_SIZE) == 0 || memcmp(buffer + MAGIC_ASCII_SIZE+2, MAGIC, MAGIC_SIZE) == 0))) { err_FILE_TYPE(error, "Shimadzu"); g_free(buffer); return NULL; } head = g_memdup(buffer, HEADER_SIZE+1); head[HEADER_SIZE] = '\0'; /* text_data_start is set to nonzero if data are text */ hash = read_hash(head, &text_data_start, error); ok = !!hash; if (ok) { if (text_data_start) dfield = read_text_data(buffer, text_data_start, hash, error); else dfield = read_binary_data(buffer, size, hash, error); ok = !!dfield; } if (ok) { GQuark quark; const gchar *title; container = gwy_container_new(); quark = gwy_app_get_data_key_for_id(0); gwy_container_set_object(container, quark, dfield); g_object_unref(dfield); meta = shimadzu_get_metadata(hash); gwy_container_set_object_by_name(container, "/0/meta", meta); g_object_unref(meta); title = g_hash_table_lookup(hash, "Channel"); if (title && *title) gwy_container_set_string_by_name(container, "/0/data/title", g_strdup(title)); else gwy_app_channel_title_fall_back(container, 0); gwy_file_channel_import_log_add(container, 0, NULL, filename); } g_free(head); g_free(buffer); g_hash_table_destroy(hash); return container; }
static void create_profiles(const X3PFile *x3pfile, GwyContainer *container) { GwyGraphModel *gmodel; GwySIUnit *siunitx, *siunity; GArray *validx, *validy; GQuark quark; gint id; gmodel = gwy_graph_model_new(); siunitx = gwy_si_unit_new("m"); siunity = gwy_si_unit_new("m"); g_object_set(gmodel, "title", "Profiles", "si-unit-x", siunitx, "si-unit-y", siunity, NULL); g_object_unref(siunity); g_object_unref(siunitx); validx = g_array_new(FALSE, FALSE, sizeof(gdouble)); validy = g_array_new(FALSE, FALSE, sizeof(gdouble)); for (id = 0; id < x3pfile->zres; id++) { guint n = x3pfile->xres; GwyGraphCurveModel *gcmodel; gchar *title; guint j; g_array_set_size(validx, 0); g_array_set_size(validy, 0); for (j = 0; j < x3pfile->xres; j++) { gdouble v = x3pfile->values[id*n + j]; if (gwy_isnan(v) || gwy_isinf(v) || !x3pfile->valid[id*n + j]) continue; g_array_append_val(validy, v); v = j*x3pfile->dx; g_array_append_val(validx, v); } if (!validx->len) continue; gcmodel = gwy_graph_curve_model_new(); title = g_strdup_printf("Profile %u", id+1); g_object_set(gcmodel, "mode", GWY_GRAPH_CURVE_LINE, "description", title, "color", gwy_graph_get_preset_color(id), NULL); g_free(title); gwy_graph_curve_model_set_data(gcmodel, (gdouble*)validx->data, (gdouble*)validy->data, validx->len); gwy_graph_model_add_curve(gmodel, gcmodel); g_object_unref(gcmodel); } g_array_free(validy, TRUE); g_array_free(validx, TRUE); quark = gwy_app_get_graph_key_for_id(0); gwy_container_set_object(container, quark, gmodel); g_object_unref(gmodel); }
/** * proc_plugin_proxy_run: * @data: A data container. * @run: Run mode. * @name: Plug-in name (i.e. data processing function) to run. * * The plug-in proxy itself, runs plug-in @name on @data. * * Returns: Whether it succeeded running the plug-in. **/ static void proc_plugin_proxy_run(GwyContainer *data, GwyRunType run, const gchar *name) { ProcPluginInfo *info; GwyContainer *newdata; gchar *filename, *buffer = NULL; GError *err = NULL; gint exit_status, id, newid; gsize size = 0; FILE *fh; gchar *args[] = { NULL, "run", NULL, NULL, NULL }; GQuark dquark, mquark, squark; gboolean ok; gwy_app_data_browser_get_current(GWY_APP_DATA_FIELD_KEY, &dquark, GWY_APP_MASK_FIELD_KEY, &mquark, GWY_APP_DATA_FIELD_ID, &id, 0); gwy_debug("called as %s with run mode %d", name, run); if (!(info = proc_find_plugin(name, run))) return; fh = text_dump_export(data, dquark, mquark, &filename, NULL); g_return_if_fail(fh); args[0] = info->file; args[2] = g_strdup(gwy_enum_to_string(run, run_mode_names, -1)); args[3] = decode_glib_encoded_filename(filename); gwy_debug("%s %s %s %s", args[0], args[1], args[2], args[3]); ok = g_spawn_sync(NULL, args, NULL, 0, NULL, NULL, NULL, NULL, &exit_status, &err); if (!err) ok &= g_file_get_contents(filename, &buffer, &size, &err); g_unlink(filename); fclose(fh); gwy_debug("ok = %d, exit_status = %d, err = %p", ok, exit_status, err); ok &= !exit_status; if (ok && (newdata = text_dump_import(buffer, size, NULL))) { GwyDataField *dfield; /* Merge data */ if (gwy_container_gis_object_by_name(newdata, "/0/data", &dfield)) g_object_ref(dfield); else { dfield = gwy_container_get_object(data, dquark); dfield = gwy_data_field_duplicate(dfield); } newid = gwy_app_data_browser_add_data_field(dfield, data, TRUE); /* Merge mask */ if (gwy_container_gis_object_by_name(newdata, "/0/mask", &dfield)) g_object_ref(dfield); else if (gwy_container_gis_object(data, mquark, &dfield)) dfield = gwy_data_field_duplicate(dfield); else dfield = NULL; if (dfield) { mquark = gwy_app_get_mask_key_for_id(newid); gwy_container_set_object(data, mquark, dfield); g_object_unref(dfield); } /* Merge presentation */ if (gwy_container_gis_object_by_name(newdata, "/0/show", &dfield)) { squark = gwy_app_get_show_key_for_id(newid); gwy_container_set_object(data, squark, dfield); } /* Merge stuff. XXX: This is brutal and incomplete. */ gwy_app_sync_data_items(data, data, id, newid, FALSE, GWY_DATA_ITEM_GRADIENT, GWY_DATA_ITEM_RANGE_TYPE, GWY_DATA_ITEM_MASK_COLOR, GWY_DATA_ITEM_REAL_SQUARE, 0); gwy_app_sync_data_items(newdata, data, 0, newid, FALSE, GWY_DATA_ITEM_GRADIENT, GWY_DATA_ITEM_RANGE_TYPE, 0); g_object_unref(newdata); } else { g_warning("Cannot run plug-in %s: %s", info->file, err ? err->message : "it returned garbage."); } g_free(args[3]); g_free(args[2]); g_clear_error(&err); g_free(buffer); g_free(filename); }
static GwyContainer* asc_load(const gchar *filename, G_GNUC_UNUSED GwyRunType mode, GError **error) { GwyContainer *container = NULL; GwyDataField *dfield = NULL, *mfield = NULL; GwyTextHeaderParser parser; GwySIUnit *unit; gchar *line, *p, *value, *buffer = NULL; GHashTable *hash = NULL; gsize size; GError *err = NULL; gdouble xreal, yreal, q; gint i, xres, yres; gdouble *data; if (!g_file_get_contents(filename, &buffer, &size, &err)) { err_GET_FILE_CONTENTS(error, &err); goto fail; } p = buffer; line = gwy_str_next_line(&p); if (!gwy_strequal(line, MAGIC_BARE)) { err_FILE_TYPE(error, "SPIP ASCII data"); goto fail; } gwy_clear(&parser, 1); parser.line_prefix = "#"; parser.key_value_separator = "="; parser.terminator = "# Start of Data:"; parser.error = &header_error; parser.end = &header_end; if (!(hash = gwy_text_header_parse(p, &parser, &p, &err))) { g_propagate_error(error, err); goto fail; } if (!require_keys(hash, error, "x-pixels", "y-pixels", "x-length", "y-length", NULL)) goto fail; xres = atoi(g_hash_table_lookup(hash, "x-pixels")); yres = atoi(g_hash_table_lookup(hash, "y-pixels")); if (err_DIMENSION(error, xres) || err_DIMENSION(error, yres)) goto fail; xreal = Nanometer * g_ascii_strtod(g_hash_table_lookup(hash, "x-length"), NULL); yreal = Nanometer * g_ascii_strtod(g_hash_table_lookup(hash, "y-length"), NULL); /* Use negated positive conditions to catch NaNs */ if (!((xreal = fabs(xreal)) > 0)) { g_warning("Real x size is 0.0, fixing to 1.0"); xreal = 1.0; } if (!((yreal = fabs(yreal)) > 0)) { g_warning("Real y size is 0.0, fixing to 1.0"); yreal = 1.0; } dfield = gwy_data_field_new(xres, yres, xreal, yreal, FALSE); unit = gwy_si_unit_new("m"); gwy_data_field_set_si_unit_xy(dfield, unit); g_object_unref(unit); if ((value = g_hash_table_lookup(hash, "z-unit"))) { gint power10; unit = gwy_si_unit_new_parse(value, &power10); gwy_data_field_set_si_unit_z(dfield, unit); g_object_unref(unit); q = pow10(power10); } else if ((value = g_hash_table_lookup(hash, "Bit2nm"))) { q = Nanometer * g_ascii_strtod(value, NULL); unit = gwy_si_unit_new("m"); gwy_data_field_set_si_unit_z(dfield, unit); g_object_unref(unit); } else q = 1.0; data = gwy_data_field_get_data(dfield); value = p; for (i = 0; i < xres*yres; i++) { data[i] = q*g_ascii_strtod(value, &p); if (p == value && (!*p || g_ascii_isspace(*p))) { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA, _("End of file reached when reading sample #%d of %d"), i, xres*yres); goto fail; } if (p == value) { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA, _("Malformed data encountered when reading sample " "#%d of %d"), i, xres*yres); goto fail; } value = p; } if ((value = g_hash_table_lookup(hash, "voidpixels")) && atoi(value)) { mfield = gwy_data_field_new_alike(dfield, FALSE); data = gwy_data_field_get_data(mfield); value = p; for (i = 0; i < xres*yres; i++) { data[i] = 1.0 - g_ascii_strtod(value, &p); value = p; } if (!gwy_app_channel_remove_bad_data(dfield, mfield)) GWY_OBJECT_UNREF(mfield); } container = gwy_container_new(); gwy_container_set_object(container, gwy_app_get_data_key_for_id(0), dfield); if (mfield) { gwy_container_set_object(container, gwy_app_get_mask_key_for_id(0), mfield); g_object_unref(mfield); } gwy_file_channel_import_log_add(container, 0, NULL, filename); fail: GWY_OBJECT_UNREF(dfield); g_free(buffer); if (hash) g_hash_table_destroy(hash); return container; }
static GwyContainer* plt_load(const gchar *filename, G_GNUC_UNUSED GwyRunType mode, GError **error) { GwyContainer *container = NULL; GwyDataField *dfield = NULL; GwyTextHeaderParser parser; GwySIUnit *xunit, *yunit, *zunit; gchar *p, *value, *buffer = NULL; GHashTable *hash = NULL; gsize size; GError *err = NULL; G_GNUC_UNUSED gdouble xreal, yreal, zreal; gint i, xres, yres; gdouble *data; if (!g_file_get_contents(filename, &buffer, &size, &err)) { err_GET_FILE_CONTENTS(error, &err); goto fail; } if (strncmp(buffer, MAGIC1, MIN(size, sizeof(MAGIC1)-1))) { err_FILE_TYPE(error, "Nanosurf PLT"); goto fail; } /* Find the first line not starting with '#' */ for (p = buffer; (p - buffer) + 1 < size; p++) { if ((p[0] == '\n' || p[0] == '\r') && (p[1] != '\n' && p[1] != '#')) { break; } } *p = '\0'; p++; gwy_clear(&parser, 1); parser.line_prefix = "#"; parser.key_value_separator = ":"; hash = gwy_text_header_parse(buffer, &parser, NULL, NULL); if (!require_keys(hash, error, "Channel", "Lines", "Points", "XRange", "YRange", "ZRange", NULL)) goto fail; xres = atoi(g_hash_table_lookup(hash, "Points")); yres = atoi(g_hash_table_lookup(hash, "Lines")); if (err_DIMENSION(error, xres) || err_DIMENSION(error, yres)) goto fail; value = g_hash_table_lookup(hash, "XRange"); xreal = g_ascii_strtod(value, &value); xunit = gwy_si_unit_new(value); value = g_hash_table_lookup(hash, "YRange"); yreal = g_ascii_strtod(value, &value); yunit = gwy_si_unit_new(value); value = g_hash_table_lookup(hash, "ZRange"); zreal = g_ascii_strtod(value, &value); zunit = gwy_si_unit_new(value); /* Use negated positive conditions to catch NaNs */ if (!((xreal = fabs(xreal)) > 0)) { g_warning("Real x size is 0.0, fixing to 1.0"); xreal = 1.0; } if (!((yreal = fabs(yreal)) > 0)) { g_warning("Real y size is 0.0, fixing to 1.0"); yreal = 1.0; } if (!gwy_si_unit_equal(xunit, yunit)) g_warning("X and Y units differ, using X"); dfield = gwy_data_field_new(xres, yres, xreal, yreal, FALSE); gwy_data_field_set_si_unit_xy(dfield, xunit); gwy_data_field_set_si_unit_z(dfield, zunit); g_object_unref(xunit); g_object_unref(yunit); g_object_unref(zunit); data = gwy_data_field_get_data(dfield); value = p; for (i = 0; i < xres*yres; i++) { data[i] = g_ascii_strtod(value, &p); value = p; } container = gwy_container_new(); gwy_container_set_object(container, gwy_app_get_data_key_for_id(0), dfield); g_object_unref(dfield); if ((value = g_hash_table_lookup(hash, "Channel"))) gwy_container_set_string_by_name(container, "/0/data/title", g_strdup(value)); else gwy_app_channel_title_fall_back(container, 0); gwy_file_channel_import_log_add(container, 0, NULL, filename); fail: g_free(buffer); g_hash_table_destroy(hash); return container; }
static GwyContainer* omicron_load(const gchar *filename, G_GNUC_UNUSED GwyRunType mode, GError **error) { OmicronFile ofile; GwyContainer *container = NULL, *meta; gchar *text = NULL; GError *err = NULL; GwyDataField *dfield = NULL; GwySpectra *spectra = NULL; gchar key[32]; guint i; /* @text must not be destroyed while @ofile is still in used because * all strings are only references there */ if (!g_file_get_contents(filename, &text, NULL, &err)) { err_GET_FILE_CONTENTS(error, &err); return NULL; } gwy_clear(&ofile, 1); ofile.filename = filename; if (!omicron_read_header(text, &ofile, error)) goto fail; if (!ofile.topo_channels || !ofile.topo_channels->len) { err_NO_DATA(error); goto fail; } container = gwy_container_new(); /* First Load the Topographic Data */ for (i = 0; i < ofile.topo_channels->len; i++) { OmicronTopoChannel *channel; channel = g_ptr_array_index(ofile.topo_channels, i); dfield = omicron_read_data(&ofile, channel, error); if (!dfield) { gwy_object_unref(container); goto fail; } g_snprintf(key, sizeof(key), "/%u/data", i); gwy_container_set_object_by_name(container, key, dfield); g_object_unref(dfield); if (channel->name) { gchar *s; g_snprintf(key, sizeof(key), "/%u/data/title", i); if (channel->scandir == SCAN_FORWARD) s = g_strdup_printf("%s (Forward)", channel->name); else if (channel->scandir == SCAN_BACKWARD) s = g_strdup_printf("%s (Backward)", channel->name); else s = g_strdup(channel->name); gwy_container_set_string_by_name(container, key, s); } if ((meta = omicron_make_meta(&ofile))) { g_snprintf(key, sizeof(key), "/%u/meta", i); gwy_container_set_object_by_name(container, key, meta); g_object_unref(meta); } } /* Then load the spectroscopy data. */ /* * There are two types of spectroscopy file: * * a) Single Point Spectroscopy Files * Single point which is stored by SCALA as an ascii file. Any number of * single point spectrums may be aquired, but the number is normally * quite small. These files are identified by their filename *.cs[0..3] * * b) Binary Spectroscopy Files * When large numbers of spectra are aquired on a regular grid they are * stored in BE binary. These data are aquired during the scan, and so * can be aquired during the forward scan or the backward scan. * * Forwards scan files can be indentified from their filename *.sf[0..3] * Backward scan files can be indentified from their filename *.sb[0..3] */ if (ofile.spectro_channels) { for (i = 0; i < ofile.spectro_channels->len; i++) { OmicronSpectroChannel *channel; channel = g_ptr_array_index(ofile.spectro_channels, i); if (omicron_has_extension(channel->filename, "cs")) { gchar *t; GQuark quark; spectra = omicron_read_cs_data(&ofile, channel, error); if (!spectra) { gwy_object_unref(container); goto fail; } if (!gwy_spectra_get_n_spectra(spectra)) { gwy_debug("Spectra %u is empty, ignoring", i); g_object_unref(spectra); continue; } /* FIXME */ t = g_strconcat(channel->chan, "-", channel->param, NULL); gwy_spectra_set_title(spectra, t); g_free(t); quark = gwy_app_get_spectra_key_for_id(i); gwy_container_set_object(container, quark, spectra); g_object_unref(spectra); } else if (omicron_has_extension(channel->filename, "sf") || omicron_has_extension(channel->filename, "sb")) { /* FIXME */ } else { g_warning("Cannot determine spectra type of %s", channel->filename); } } } fail: omicron_file_free(&ofile); g_free(text); return container; }
static GwyContainer* rhk_sm4_load(const gchar *filename, G_GNUC_UNUSED GwyRunType mode, GError **error) { RHKFile rhkfile; RHKObject *obj, o; GwyContainer *meta, *container = NULL; guchar *buffer = NULL; gsize size = 0; GError *err = NULL; const guchar *p; GString *key = NULL; guint i, imageid = 0, graphid = 0; if (!gwy_file_get_contents(filename, &buffer, &size, &err)) { err_GET_FILE_CONTENTS(error, &err); return NULL; } gwy_clear(&rhkfile, 1); if (size < HEADER_SIZE) { err_TOO_SHORT(error); goto fail; } /* File header */ p = buffer + MAGIC_OFFSET + MAGIC_TOTAL_SIZE; rhkfile.page_count = gwy_get_guint32_le(&p); rhkfile.object_count = gwy_get_guint32_le(&p); rhkfile.object_field_size = gwy_get_guint32_le(&p); gwy_debug("page_count: %u, object_count: %u, object_field_size: %u", rhkfile.page_count, rhkfile.object_count, rhkfile.object_field_size); if (rhkfile.object_field_size != OBJECT_SIZE) g_warning("Object field size %u differs from %u", rhkfile.object_field_size, OBJECT_SIZE); rhkfile.reserved1 = gwy_get_guint32_le(&p); rhkfile.reserved2 = gwy_get_guint32_le(&p); /* Header objects */ if (!(rhkfile.objects = rhk_sm4_read_objects(buffer, p, size, rhkfile.object_count, RHK_OBJECT_FILE_HEADER, error))) goto fail; /* Find page index header */ if (!(obj = rhk_sm4_find_object(rhkfile.objects, rhkfile.object_count, RHK_OBJECT_PAGE_INDEX_HEADER, RHK_OBJECT_FILE_HEADER, error)) || !rhk_sm4_read_page_index_header(&rhkfile.page_index_header, obj, buffer, size, error)) goto fail; /* There, find the page index array. That's a single object in the object * list but it contains a page_count-long sequence of page indices. */ rhkfile.page_indices = g_new0(RHKPageIndex, rhkfile.page_index_header.page_count); if (!(obj = rhk_sm4_find_object(rhkfile.page_index_header.objects, rhkfile.page_index_header.object_count, RHK_OBJECT_PAGE_INDEX_ARRAY, RHK_OBJECT_PAGE_INDEX_HEADER, error))) goto fail; o = *obj; for (i = 0; i < rhkfile.page_index_header.page_count; i++) { if (!rhk_sm4_read_page_index(rhkfile.page_indices + i, &o, buffer, size, error)) goto fail; /* Carefully move to the next page index */ o.offset += o.size + OBJECT_SIZE*rhkfile.page_indices[i].object_count; } container = gwy_container_new(); key = g_string_new(NULL); /* Read pages */ for (i = 0; i < rhkfile.page_index_header.page_count; i++) { RHKPageIndex *pi = rhkfile.page_indices + i; RHKPage *page = &pi->page; /* Page must contain header */ if (!(obj = rhk_sm4_find_object(pi->objects, pi->object_count, RHK_OBJECT_PAGE_HEADER, RHK_OBJECT_PAGE_INDEX, error)) || !rhk_sm4_read_page_header(page, obj, buffer, size, error)) goto fail; /* Page must contain data */ if (!(obj = rhk_sm4_find_object(pi->objects, pi->object_count, RHK_OBJECT_PAGE_DATA, RHK_OBJECT_PAGE_INDEX, error)) || !rhk_sm4_read_page_data(page, obj, buffer, error)) goto fail; /* Page may contain strings */ if (!(obj = rhk_sm4_find_object(page->objects, page->object_count, RHK_OBJECT_STRING_DATA, RHK_OBJECT_PAGE_HEADER, NULL)) || !rhk_sm4_read_string_data(page, obj, pi->page.string_count, buffer)) { g_warning("Failed to read string data in page %u", i); } /* Read the data */ if (pi->data_type == RHK_DATA_IMAGE) { GwyDataField *dfield = rhk_sm4_page_to_data_field(page); GQuark quark = gwy_app_get_data_key_for_id(imageid); const gchar *scandir, *name; gchar *title; gwy_container_set_object(container, quark, dfield); g_object_unref(dfield); if ((name = page->strings[RHK_STRING_LABEL])) { scandir = gwy_enum_to_string(page->scan_dir, scan_directions, G_N_ELEMENTS(scan_directions)); g_string_assign(key, g_quark_to_string(quark)); g_string_append(key, "/title"); if (scandir && *scandir) title = g_strdup_printf("%s [%s]", name, scandir); else title = g_strdup(name); gwy_container_set_string_by_name(container, key->str, title); } meta = rhk_sm4_get_metadata(pi, page); g_string_printf(key, "/%u/meta", imageid); gwy_container_set_object_by_name(container, key->str, meta); g_object_unref(meta); imageid++; } else if (pi->data_type == RHK_DATA_LINE) { GwyGraphModel *gmodel; RHKSpecDriftHeader drift_header; RHKSpecInfo spec_info; G_GNUC_UNUSED gboolean have_header = FALSE, have_info = FALSE; gwy_debug("page_type %u", page->page_type); gwy_debug("line_type %u", page->line_type); gwy_debug("page_sizes %u %u", page->x_size, page->y_size); /* Page may contain drift header */ if ((obj = rhk_sm4_find_object(page->objects, page->object_count, RHK_OBJECT_SPEC_DRIFT_HEADER, RHK_OBJECT_PAGE_HEADER, NULL)) && rhk_sm4_read_drift_header(&drift_header, obj, buffer)) { gwy_debug("drift_header OK"); have_header = TRUE; } if ((obj = rhk_sm4_find_object(page->objects, page->object_count, RHK_OBJECT_SPEC_DRIFT_DATA, RHK_OBJECT_PAGE_HEADER, NULL)) && rhk_sm4_read_spec_info(&spec_info, obj, buffer)) { gwy_debug("spec_info OK"); have_info = TRUE; } /* FIXME: RHK_STRING_PLL_PRO_STATUS may contain interesting * metadata. But we have not place where to put it. */ if ((gmodel = rhk_sm4_page_to_graph_model(page))) { graphid++; gwy_container_set_object(container, gwy_app_get_graph_key_for_id(graphid), gmodel); g_object_unref(gmodel); } } } if (!imageid && !graphid) err_NO_DATA(error); fail: gwy_file_abandon_contents(buffer, size, NULL); rhk_sm4_free(&rhkfile); if (!imageid && !graphid) { gwy_object_unref(container); } if (key) g_string_free(key, TRUE); return container; }
static void rotate(GwyContainer *data, GwyRunType run) { GwyDataField *dfields[3]; GQuark quark; gint oldid, newid; RotateArgs args; gboolean ok; g_return_if_fail(run & ROTATE_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); g_return_if_fail(dfields[0]); rotate_load_args(gwy_app_settings_get(), &args); if (run == GWY_RUN_INTERACTIVE) { ok = rotate_dialog(&args, data); rotate_save_args(gwy_app_settings_get(), &args); if (!ok) return; } dfields[0] = gwy_data_field_duplicate(dfields[0]); rotate_datafield(dfields[0], &args); if (dfields[1]) { GwyInterpolationType interp = args.interp; dfields[1] = gwy_data_field_duplicate(dfields[1]); args.interp = GWY_INTERPOLATION_ROUND; rotate_datafield(dfields[1], &args); args.interp = interp; } if (dfields[2]) { dfields[2] = gwy_data_field_duplicate(dfields[2]); rotate_datafield(dfields[2], &args); } 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_set_data_field_title(data, newid, _("Rotated Data")); gwy_app_channel_log_add_proc(data, oldid, newid); }
static void gfilter_dialog(GFilterArgs *args, GwyContainer *data, GwyDataField *dfield, GwyDataField *mfield, gint id, GQuark mquark) { GtkWidget *dialog, *table, *vbox, *hbox, *scwin, *hbox2, *label; GtkTreeView *treeview; GtkTreeSelection *selection; GFilterControls controls; gint response, row, i; GwySIUnit *siunit; GwyPixmapLayer *layer; controls.args = args; controls.mask = mfield; controls.in_init = TRUE; controls.computed = FALSE; siunit = gwy_si_unit_new(NULL); for (i = 0; i < NQUANTITIES; i++) { controls.vf[i] = gwy_si_unit_get_format_with_digits(siunit, GWY_SI_UNIT_FORMAT_VFMARKUP, 1.0, 4, NULL); } g_object_unref(siunit); dialog = gtk_dialog_new_with_buttons(_("Filter Grains"), 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), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL); gtk_dialog_add_button(GTK_DIALOG(dialog), GTK_STOCK_OK, GTK_RESPONSE_OK); gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK); gtk_dialog_set_response_sensitive(GTK_DIALOG(dialog), RESPONSE_PREVIEW, !args->update); gwy_help_add_to_proc_dialog(GTK_DIALOG(dialog), GWY_HELP_DEFAULT); controls.dialog = dialog; hbox = gtk_hbox_new(FALSE, 2); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), hbox, TRUE, TRUE, 4); vbox = gtk_vbox_new(FALSE, 4); gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 4); controls.mydata = gwy_container_new(); gwy_container_set_object_by_name(controls.mydata, "/0/data", dfield); mfield = gwy_data_field_duplicate(mfield); gwy_container_set_object_by_name(controls.mydata, "/0/mask", mfield); g_object_unref(mfield); gwy_app_sync_data_items(data, controls.mydata, id, 0, FALSE, GWY_DATA_ITEM_PALETTE, GWY_DATA_ITEM_MASK_COLOR, GWY_DATA_ITEM_RANGE, GWY_DATA_ITEM_REAL_SQUARE, 0); controls.view = gwy_data_view_new(controls.mydata); layer = gwy_layer_basic_new(); g_object_set(layer, "data-key", "/0/data", "gradient-key", "/0/base/palette", "range-type-key", "/0/base/range-type", "min-max-key", "/0/base", NULL); gwy_data_view_set_data_prefix(GWY_DATA_VIEW(controls.view), "/0/data"); gwy_data_view_set_base_layer(GWY_DATA_VIEW(controls.view), layer); layer = gwy_layer_mask_new(); gwy_pixmap_layer_set_data_key(layer, "/0/mask"); gwy_layer_mask_set_color_key(GWY_LAYER_MASK(layer), "/0/mask"); gwy_data_view_set_alpha_layer(GWY_DATA_VIEW(controls.view), layer); gwy_set_data_preview_size(GWY_DATA_VIEW(controls.view), PREVIEW_SIZE); gtk_box_pack_start(GTK_BOX(vbox), controls.view, FALSE, FALSE, 0); controls.update = gtk_check_button_new_with_mnemonic(_("I_nstant updates")); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(controls.update), args->update); gtk_box_pack_start(GTK_BOX(vbox), controls.update, FALSE, FALSE, 0); g_signal_connect_swapped(controls.update, "toggled", G_CALLBACK(update_changed), &controls); hbox2 = gtk_hbox_new(FALSE, 6); gtk_box_pack_start(GTK_BOX(vbox), hbox2, FALSE, FALSE, 0); label = gtk_label_new_with_mnemonic(_("_Mask color:")); gtk_box_pack_start(GTK_BOX(hbox2), label, FALSE, FALSE, 0); controls.color_button = gwy_color_button_new(); gwy_color_button_set_use_alpha(GWY_COLOR_BUTTON(controls.color_button), TRUE); load_mask_color(controls.color_button, gwy_data_view_get_data(GWY_DATA_VIEW(controls.view))); gtk_label_set_mnemonic_widget(GTK_LABEL(label), controls.color_button); gtk_box_pack_start(GTK_BOX(hbox2), controls.color_button, FALSE, FALSE, 0); g_signal_connect(controls.color_button, "clicked", G_CALLBACK(mask_color_changed), &controls); table = gtk_table_new(10, 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, TRUE, TRUE, 4); controls.table = table; row = 0; scwin = gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scwin), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); gtk_table_attach(GTK_TABLE(table), scwin, 0, 4, row, row+1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); controls.values = gwy_grain_value_tree_view_new(FALSE, "name", "symbol_markup", NULL); treeview = GTK_TREE_VIEW(controls.values); gtk_widget_set_size_request(scwin, -1, 120); gtk_tree_view_set_headers_visible(treeview, FALSE); selection = gtk_tree_view_get_selection(treeview); gtk_tree_selection_set_mode(selection, GTK_SELECTION_BROWSE); gwy_grain_value_tree_view_set_same_units(treeview, args->units_equal); gwy_grain_value_tree_view_set_expanded_groups(treeview, args->expanded); gtk_container_add(GTK_CONTAINER(scwin), controls.values); row++; hbox2 = gtk_hbox_new(FALSE, 0); for (i = 0; i < NQUANTITIES; i++) { gchar buf[2]; buf[0] = 'A' + i; buf[1] = '\0'; controls.set_as[i] = gtk_button_new_with_label(buf); gtk_box_pack_start(GTK_BOX(hbox2), controls.set_as[i], FALSE, FALSE, 0); g_object_set_data(G_OBJECT(controls.set_as[i]), "id", GUINT_TO_POINTER(i)); g_signal_connect_swapped(controls.set_as[i], "clicked", G_CALLBACK(set_as_clicked), &controls); } gwy_table_attach_hscale(table, row++, _("Set selected as:"), NULL, GTK_OBJECT(hbox2), GWY_HSCALE_WIDGET_NO_EXPAND); controls.logical_op = gwy_enum_combo_box_newl(G_CALLBACK(logical_op_changed), &controls, args->logical, "A", GRAIN_LOGICAL_A, "A ∧ B", GRAIN_LOGICAL_A_AND_B, "A ∨ B", GRAIN_LOGICAL_A_OR_B, "A ∧ B ∧ C", GRAIN_LOGICAL_A_AND_B_AND_C, "A ∨ B ∨ C", GRAIN_LOGICAL_A_OR_B_OR_C, "(A ∧ B) ∨ C", GRAIN_LOGICAL_A_AND_B_OR_C, "(A ∨ B) ∧ C", GRAIN_LOGICAL_A_OR_B_AND_C, NULL); gwy_table_attach_hscale(table, row++, _("Keep grains satisfying:"), NULL, GTK_OBJECT(controls.logical_op), GWY_HSCALE_WIDGET); for (i = 0; i < NQUANTITIES; i++) { gtk_table_set_row_spacing(GTK_TABLE(table), row-1, 8); controls.header[i] = gtk_label_new(NULL); gtk_misc_set_alignment(GTK_MISC(controls.header[i]), 0.0, 0.5); gtk_table_attach(GTK_TABLE(table), controls.header[i], 0, 4, row, row+1, GTK_FILL, 0, 0, 0); row++; /* The values are set properly later. */ controls.lower_label[i] = gtk_label_new(_("Lower threshold:")); gtk_misc_set_alignment(GTK_MISC(controls.lower_label[i]), 0.0, 0.5); gtk_table_attach(GTK_TABLE(table), controls.lower_label[i], 0, 1, row, row+1, GTK_FILL, 0, 0, 0); controls.lower[i] = gtk_adjustment_new(0.0, 0.0, 0.0, 1.0, 10.0, 0.0); g_object_set_data(G_OBJECT(controls.lower[i]), "id", GUINT_TO_POINTER(i)); g_signal_connect_swapped(controls.lower[i], "value-changed", G_CALLBACK(threshold_changed), &controls); controls.lower_scale[i] = gtk_hscale_new(GTK_ADJUSTMENT(controls.lower[i])); gtk_scale_set_draw_value(GTK_SCALE(controls.lower_scale[i]), FALSE); gtk_widget_set_size_request(controls.lower_scale[i], GWY_HSCALE_WIDTH, -1); gtk_table_attach(GTK_TABLE(table), controls.lower_scale[i], 1, 2, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); controls.lower_entry[i] = gtk_entry_new(); gtk_entry_set_width_chars(GTK_ENTRY(controls.lower_entry[i]), 8); gtk_table_attach(GTK_TABLE(table), controls.lower_entry[i], 2, 3, row, row+1, GTK_FILL, 0, 0, 0); gwy_widget_set_activate_on_unfocus(controls.lower_entry[i], TRUE); g_object_set_data(G_OBJECT(controls.lower_entry[i]), "id", GUINT_TO_POINTER(i)); g_signal_connect_swapped(controls.lower_entry[i], "activate", G_CALLBACK(threshold_activated), &controls); controls.lower_units[i] = gtk_label_new(NULL); gtk_misc_set_alignment(GTK_MISC(controls.lower_units[i]), 0.0, 0.5); gtk_table_attach(GTK_TABLE(table), controls.lower_units[i], 3, 4, row, row+1, GTK_FILL, 0, 0, 0); row++; controls.upper_label[i] = gtk_label_new(_("Upper threshold:")); gtk_misc_set_alignment(GTK_MISC(controls.upper_label[i]), 0.0, 0.5); gtk_table_attach(GTK_TABLE(table), controls.upper_label[i], 0, 1, row, row+1, GTK_FILL, 0, 0, 0); controls.upper[i] = gtk_adjustment_new(0.0, 0.0, 0.0, 1.0, 10.0, 0.0); g_object_set_data(G_OBJECT(controls.upper[i]), "id", GUINT_TO_POINTER(i | IS_UPPER)); g_signal_connect_swapped(controls.upper[i], "value-changed", G_CALLBACK(threshold_changed), &controls); controls.upper_scale[i] = gtk_hscale_new(GTK_ADJUSTMENT(controls.upper[i])); gtk_scale_set_draw_value(GTK_SCALE(controls.upper_scale[i]), FALSE); gtk_widget_set_size_request(controls.upper_scale[i], GWY_HSCALE_WIDTH, -1); gtk_table_attach(GTK_TABLE(table), controls.upper_scale[i], 1, 2, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); controls.upper_entry[i] = gtk_entry_new(); gtk_entry_set_width_chars(GTK_ENTRY(controls.upper_entry[i]), 8); gtk_table_attach(GTK_TABLE(table), controls.upper_entry[i], 2, 3, row, row+1, GTK_FILL, 0, 0, 0); gwy_widget_set_activate_on_unfocus(controls.upper_entry[i], TRUE); g_object_set_data(G_OBJECT(controls.upper_entry[i]), "id", GUINT_TO_POINTER(i | IS_UPPER)); g_signal_connect_swapped(controls.upper_entry[i], "activate", G_CALLBACK(threshold_activated), &controls); controls.upper_units[i] = gtk_label_new(NULL); gtk_misc_set_alignment(GTK_MISC(controls.upper_units[i]), 0.0, 0.5); gtk_table_attach(GTK_TABLE(table), controls.upper_units[i], 3, 4, row, row+1, GTK_FILL, 0, 0, 0); row++; } for (i = 0; i < NQUANTITIES; i++) { GwyInventory *inventory; GwyGrainValue *gvalue; inventory = gwy_grain_values(); gvalue = gwy_inventory_get_item(inventory, args->ranges[i].quantity); set_up_quantity(&controls, gvalue, i); } logical_op_changed(GTK_COMBO_BOX(controls.logical_op), &controls); /* finished initializing, allow instant updates */ controls.in_init = FALSE; gfilter_invalidate(&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: args->expanded = gwy_grain_value_tree_view_get_expanded_groups (GTK_TREE_VIEW(controls.values)); for (i = 0; i < NQUANTITIES; i++) gwy_si_unit_value_format_free(controls.vf[i]); gtk_widget_destroy(dialog); case GTK_RESPONSE_NONE: g_object_unref(controls.mydata); gfilter_save_args(gwy_app_settings_get(), args); return; break; case GTK_RESPONSE_OK: break; case RESPONSE_PREVIEW: preview(&controls); break; default: g_assert_not_reached(); break; } } while (response != GTK_RESPONSE_OK); for (i = 0; i < NQUANTITIES; i++) gwy_si_unit_value_format_free(controls.vf[i]); args->expanded = gwy_grain_value_tree_view_get_expanded_groups (GTK_TREE_VIEW(controls.values)); gwy_app_sync_data_items(controls.mydata, data, 0, id, FALSE, GWY_DATA_ITEM_MASK_COLOR, 0); gtk_widget_destroy(dialog); gfilter_save_args(gwy_app_settings_get(), args); if (controls.computed) { mfield = gwy_container_get_object_by_name(controls.mydata, "/0/mask"); gwy_app_undo_qcheckpointv(data, 1, &mquark); gwy_container_set_object(data, mquark, mfield); g_object_unref(controls.mydata); } else { g_object_unref(controls.mydata); run_noninteractive(args, data, controls.mask, mquark); } gwy_app_channel_log_add_proc(data, id, id); }
static void run_noninteractive(NoiseSynthArgs *args, const GwyDimensionArgs *dimsargs, GwyContainer *data, GwyDataField *dfield, gint oldid, GQuark quark) { GwySIUnit *siunit; gboolean replace = dimsargs->replace && dfield; gboolean add = dimsargs->add && dfield; gint newid; if (args->randomize) args->seed = g_random_int() & 0x7fffffff; if (replace) { /* Always take a reference so that we can always unref. */ g_object_ref(dfield); gwy_app_undo_qcheckpointv(data, 1, &quark); if (!add) gwy_data_field_clear(dfield); gwy_app_channel_log_add_proc(data, oldid, oldid); } else { if (add) dfield = gwy_data_field_duplicate(dfield); else { gdouble mag = pow10(dimsargs->xypow10) * dimsargs->measure; dfield = gwy_data_field_new(dimsargs->xres, dimsargs->yres, mag*dimsargs->xres, mag*dimsargs->yres, TRUE); siunit = gwy_data_field_get_si_unit_xy(dfield); gwy_si_unit_set_from_string(siunit, dimsargs->xyunits); siunit = gwy_data_field_get_si_unit_z(dfield); gwy_si_unit_set_from_string(siunit, dimsargs->zunits); } } noise_synth_do(args, dimsargs, dfield); if (replace) gwy_data_field_data_changed(dfield); else { if (data) { newid = gwy_app_data_browser_add_data_field(dfield, data, TRUE); if (oldid != -1) gwy_app_sync_data_items(data, data, oldid, newid, FALSE, GWY_DATA_ITEM_GRADIENT, 0); } else { newid = 0; data = gwy_container_new(); gwy_container_set_object(data, gwy_app_get_data_key_for_id(newid), dfield); gwy_app_data_browser_add(data); gwy_app_data_browser_reset_visibility(data, GWY_VISIBILITY_RESET_SHOW_ALL); g_object_unref(data); } gwy_app_set_data_field_title(data, newid, _("Generated")); gwy_app_channel_log_add_proc(data, add ? oldid : -1, newid); } g_object_unref(dfield); }
static void scale(GwyContainer *data, GwyRunType run) { GwyDataField *dfields[3]; GQuark quark; gint oldid, newid; ScaleArgs args; gboolean ok; g_return_if_fail(run & SCALE_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); g_return_if_fail(dfields[0]); scale_load_args(gwy_app_settings_get(), &args); args.org_xres = gwy_data_field_get_xres(dfields[0]); args.org_yres = gwy_data_field_get_yres(dfields[0]); args.xres = ROUND(args.ratio*args.org_xres); if (args.proportional) args.aspectratio = 1.0; args.yres = ROUND(args.aspectratio*args.ratio*args.org_yres); if (run == GWY_RUN_INTERACTIVE) { ok = scale_dialog(&args); scale_save_args(gwy_app_settings_get(), &args); if (!ok) return; } dfields[0] = gwy_data_field_new_resampled(dfields[0], ROUND(args.xres), ROUND(args.yres), args.interp); if (dfields[1]) { dfields[1] = gwy_data_field_new_resampled(dfields[1], ROUND(args.xres), ROUND(args.yres), args.interp); } if (dfields[2]) { dfields[2] = gwy_data_field_new_resampled(dfields[2], ROUND(args.xres), ROUND(args.yres), args.interp); } 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_set_data_field_title(data, newid, _("Scaled Data")); }
static GwyContainer* mif_load(const gchar *filename, G_GNUC_UNUSED GwyRunType mode, GError **error) { GwyContainer *container = NULL; guchar *buffer = NULL; gsize size = 0; GError *err = NULL; MIFFile mfile; GwyDataField *dfield; guint i; if (!gwy_file_get_contents(filename, &buffer, &size, &err)) { err_GET_FILE_CONTENTS(error, &err); return NULL; } if (!mif_read_header(buffer, size, &mfile.header, error)) { gwy_file_abandon_contents(buffer, size, NULL); return NULL; } /* TODO: Check file version */ if (!mif_read_image_items(mfile.images, buffer, size, &mfile.header.info, error)) { gwy_file_abandon_contents(buffer, size, NULL); return NULL; } /* FIXME: Only v1.7! */ for (i = 0; i < mfile.header.nimages; i++) { MIFInfoItem *item = mfile.images + i; MIFImageHeader image_header; MIFBlock raster, macro_geometry, preview, image, curve, calc; guint ncalculations; const guchar *p = buffer + item->image.offset; GQuark quark; if (!item->image.size) continue; if (item->image.offset > size || item->image.size > size || item->image.offset + item->image.size > size) { continue; } /* XXX: We cannot use item->image.size because it's bogus, i.e. * too short. Apparently there is some unaccounted-for space until * the next block starts, 120 bytes for v1.7 files, after the image * header which is in fact still occupied by the image header. * MIFBlock says 714 bytes but the true size is 834 = 714 + 120. */ if (!mif_read_image_header(&image_header, &p, size - (p - buffer), mfile.header.file_version, error)) continue; if (p - buffer + 52 > size) continue; mif_read_block(&raster, "raster", &p); mif_read_block(¯o_geometry, "macro_geometry", &p); mif_read_block(&preview, "preview", &p); mif_read_block(&image, "image", &p); mif_read_block(&curve, "curve", &p); ncalculations = gwy_get_guint32_le(&p); mif_read_block(&calc, "calc", &p); gwy_debug("image header true size: %zu", (gsize)(p - (buffer + item->image.offset))); dfield = mif_read_data_field(&image_header, &image, buffer, size, NULL); if (!dfield) continue; if (!container) container = gwy_container_new(); quark = gwy_app_get_data_key_for_id(i); gwy_container_set_object(container, quark, dfield); g_object_unref(dfield); gwy_app_channel_title_fall_back(container, i); } if (!container) err_NO_DATA(error); gwy_file_abandon_contents(buffer, size, NULL); return container; }
static GwyContainer* burleigh_exp_load(const gchar *filename, G_GNUC_UNUSED GwyRunType mode, GError **error) { GwyContainer *container = NULL; gchar *buffer = NULL; BurleighExpHeader header; gsize size = 0; GError *err = NULL; GwyDataField *dfield; gdouble *data; guint i, n; if (!g_file_get_contents(filename, &buffer, &size, &err)) { err_GET_FILE_CONTENTS(error, &err); return NULL; } if (size < MIN_FILE_SIZE + 2) { err_TOO_SHORT(error); g_free(buffer); return NULL; } if (!burleigh_exp_read_header(&header, buffer, error)) goto fail; n = header.xres * header.yres; if (header.binary) { if (header.bpp != 16) { err_BPP(error, header.bpp); goto fail; } else if (err_SIZE_MISMATCH(error, header.length + 2*n, size, TRUE)) goto fail; } dfield = gwy_data_field_new(header.xres, header.yres, header.xscale, header.yscale, FALSE); data = gwy_data_field_get_data(dfield); if (header.binary) { const gint16 *d16 = (const gint16*)(buffer + header.length); for (i = 0; i < n; i++) data[i] = GINT16_FROM_LE(d16[i]); } else { gchar *p = buffer + header.length; for (i = 0; i < n; i++) data[i] = strtol(p, &p, 10); } gwy_data_field_multiply(dfield, header.zscale/32768.0); /* Units references released in free_header() */ gwy_data_field_set_si_unit_xy(dfield, header.xyunits); gwy_data_field_set_si_unit_z(dfield, header.zunits); container = gwy_container_new(); gwy_container_set_object(container, gwy_app_get_data_key_for_id(0), dfield); g_object_unref(dfield); gwy_app_channel_title_fall_back(container, 0); gwy_file_channel_import_log_add(container, 0, NULL, filename); fail: free_header(&header); g_free(buffer); return container; }
static GwyContainer* rawxyz_load(const gchar *filename, GwyRunType mode, GError **error) { GwyContainer *settings, *container = NULL; GwySurface *surface = NULL; RawXYZArgs args; GwySIUnit *unit; gint power10; gdouble q; gchar *buffer = NULL; gsize size; GError *err = NULL; gboolean ok; guint k; if (!g_file_get_contents(filename, &buffer, &size, &err)) { err_GET_FILE_CONTENTS(error, &err); goto fail; } surface = read_xyz_points(buffer); g_free(buffer); if (!surface->n) { err_NO_DATA(error); goto fail; } settings = gwy_app_settings_get(); rawxyz_load_args(settings, &args); if (mode == GWY_RUN_INTERACTIVE) { ok = rawxyz_dialog(&args, surface); rawxyz_save_args(settings, &args); if (!ok) { err_CANCELLED(error); goto fail; } } unit = gwy_si_unit_new_parse(args.xy_units, &power10); if (power10) { q = pow10(power10); for (k = 0; k < surface->n; k++) { surface->data[k].x *= q; surface->data[k].y *= q; } gwy_surface_invalidate(surface); } gwy_serializable_clone(G_OBJECT(unit), G_OBJECT(gwy_surface_get_si_unit_xy(surface))); unit = gwy_si_unit_new_parse(args.z_units, &power10); if (power10) { q = pow10(power10); for (k = 0; k < surface->n; k++) surface->data[k].z *= q; gwy_surface_invalidate(surface); } gwy_serializable_clone(G_OBJECT(unit), G_OBJECT(gwy_surface_get_si_unit_z(surface))); container = gwy_container_new(); gwy_container_set_object(container, gwy_app_get_surface_key_for_id(0), surface); gwy_app_xyz_title_fall_back(container, 0); gwy_file_xyz_import_log_add(container, 0, NULL, filename); fail: g_free(args.xy_units); g_free(args.z_units); GWY_OBJECT_UNREF(surface); return container; }