/* File starts with date, try to parse it. * FIXME: this is stupid */ static gboolean parses_as_date(const gchar *str) { char day_name[4], month_name[4]; int month_day, hour, min, sec, year; if (str[24] != '\0') return FALSE; if (sscanf(str, "%3s %3s %u %u:%u:%u %u", day_name, month_name, &month_day, &hour, &min, &sec, &year) != 7) return FALSE; if (strlen(day_name) != 3 || strlen(month_name) != 3) return FALSE; if (!gwy_stramong(day_name, "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun", NULL)) return FALSE; if (!gwy_stramong(month_name, "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", NULL)) return FALSE; return TRUE; }
static void add_meta_record(gpointer hkey, gpointer hvalue, gpointer user_data) { const gchar *key = (const gchar*)hkey; const gchar *value = (const gchar*)hvalue; GwyContainer *meta = (GwyContainer*)user_data; if (!gwy_stramong(key, "/ISO5436_2/Record1/Revision", "/ISO5436_2/Record1/FeatureType", "/ISO5436_2/Record2/Date", "/ISO5436_2/Record2/Creator", "/ISO5436_2/Record2/Instrument/Manufacturer", "/ISO5436_2/Record2/Instrument/Model", "/ISO5436_2/Record2/Instrument/Serial", "/ISO5436_2/Record2/Instrument/Version", "/ISO5436_2/Record2/CalibrationDate", "/ISO5436_2/Record2/ProbingSystem/Type", "/ISO5436_2/Record2/ProbingSystem/Identification", "/ISO5436_2/Record2/Comment", NULL) && !g_str_has_prefix(key, "/ISO5436_2/Record2/ProbingSystem/Identification/") && !g_str_has_prefix(key, "/ISO5436_2/Record1/Axes/Rotation")) return; key = strrchr(key, '/'); g_return_if_fail(key); key++; gwy_container_set_string_by_name(meta, key, (const guchar*)g_strdup(value)); }
static void add_meta(gpointer hkey, gpointer hvalue, gpointer user_data) { if (gwy_stramong((gchar*)hkey, "XRes", "YRes", "XReal", "YReal", "XOffset", "YOffset", "XYUnits", "ZUnits", "Title", NULL)) return; gwy_container_set_string_by_name(GWY_CONTAINER(user_data), (gchar*)hkey, g_strdup((gchar*)hvalue)); }
static gint aist_detect(const GwyFileDetectInfo *fileinfo, gboolean only_name) { gint score = 0; const guchar *buf = fileinfo->head; gsize size = fileinfo->buffer_len; guint is_data_node; if (only_name) return (g_str_has_suffix(fileinfo->name_lowercase, EXTENSION)) ? 10 : 0; /* The first byte is a boolean, it must be 0 or 1. This is unfortunately * the only quick means to filter-out non-AIST files. */ if (!read_qt_byte(&buf, &size, &is_data_node) || is_data_node > 1) return 0; /* A silly detection method. Try to start reading and check if the stuff * looks like the nodes we expect. Reading the strings looks dangerous. * Fortnately we know buffer_len is small so it won't try to allocate * 2GB of memory for the UTF-8 representation. */ if (is_data_node) { gchar *type = NULL; guint len; if (read_qt_string(&buf, &size, &type) && read_qt_int(&buf, &size, &len)) { if (gwy_stramong(type, "raster", "curve", "settings", NULL)) score = 85; } g_free(type); } else { gchar *name = NULL; guint nchildren; if (read_qt_string(&buf, &size, &name) && read_qt_int(&buf, &size, &nchildren) && read_qt_byte(&buf, &size, &is_data_node)) { if (is_data_node <= 1 && nchildren <= 0xff && strlen(name) <= 0xff) score = 80; } g_free(name); } return score; }
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; }