/* This is the main verification function that checks we have everything we * need and the data are of a supported type. */ static gboolean data_start(X3PFile *x3pfile, GError **error) { static const GwyEnum features[] = { { "SUR", X3P_FEATURE_SUR, }, { "PRF", X3P_FEATURE_PRF, }, { "PCL", X3P_FEATURE_PCL, }, }; gchar *s; if (x3pfile->values) { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA, _("File main.xml contains multiple data elements.")); return FALSE; } /* First check axes to get meaningful error messages if their types are * not as expected. */ if (!require_keys(x3pfile->hash, error, "/ISO5436_2/Record1/FeatureType", AXES_PREFIX "/CX/AxisType", AXES_PREFIX "/CY/AxisType", AXES_PREFIX "/CZ/AxisType", NULL)) return FALSE; s = (gchar*)g_hash_table_lookup(x3pfile->hash, "/ISO5436_2/Record1/FeatureType"); if ((x3pfile->feature_type = gwy_string_to_enum(s, features, G_N_ELEMENTS(features))) == -1) { err_UNSUPPORTED(error, "/ISO5436_2/Record1/FeatureType"); return FALSE; } if (x3pfile->feature_type != X3P_FEATURE_SUR && x3pfile->feature_type != X3P_FEATURE_PRF) { err_UNSUPPORTED(error, "/ISO5436_2/Record1/FeatureType"); return FALSE; } s = (gchar*)g_hash_table_lookup(x3pfile->hash, AXES_PREFIX "/CX/AxisType"); if (!gwy_strequal(s, "I")) { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA, /* TRANSLATORS: type and axis are symbols such as I, CX, ...*/ _("Only type %s is supported for axis %s."), "I", "CX"); return FALSE; } s = (gchar*)g_hash_table_lookup(x3pfile->hash, AXES_PREFIX "/CY/AxisType"); if (x3pfile->feature_type != X3P_FEATURE_PRF && !gwy_strequal(s, "I")) { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA, _("Only type %s is supported for axis %s."), "I", "CY"); return FALSE; } s = (gchar*)g_hash_table_lookup(x3pfile->hash, AXES_PREFIX "/CZ/AxisType"); if (!gwy_strequal(s, "A")) { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA, _("Only type %s is supported for axis %s."), "A", "CZ"); return FALSE; } /* Then check sizes, offsets and steps when we know the grid is regular. */ if (!require_keys(x3pfile->hash, error, AXES_PREFIX "/CX/Increment", AXES_PREFIX "/CY/Increment", AXES_PREFIX "/CX/Offset", AXES_PREFIX "/CY/Offset", MAT_DIM_PREFIX "/SizeX", MAT_DIM_PREFIX "/SizeY", MAT_DIM_PREFIX "/SizeZ", NULL)) return FALSE; s = (gchar*)g_hash_table_lookup(x3pfile->hash, MAT_DIM_PREFIX "/SizeX"); x3pfile->xres = atoi(s); s = (gchar*)g_hash_table_lookup(x3pfile->hash, MAT_DIM_PREFIX "/SizeY"); x3pfile->yres = atoi(s); s = (gchar*)g_hash_table_lookup(x3pfile->hash, MAT_DIM_PREFIX "/SizeZ"); x3pfile->zres = atoi(s); gwy_debug("xres=%u, yres=%u, zres=%u", x3pfile->xres, x3pfile->yres, x3pfile->zres); if (err_DIMENSION(error, x3pfile->xres) || err_DIMENSION(error, x3pfile->yres) || err_DIMENSION(error, x3pfile->zres)) return FALSE; /* PRF feature types are sets of profiles N×1×M. */ if (x3pfile->feature_type == X3P_FEATURE_PRF && x3pfile->yres != 1) { err_UNSUPPORTED(error, MAT_DIM_PREFIX "/SizeY"); return FALSE; } s = (gchar*)g_hash_table_lookup(x3pfile->hash, AXES_PREFIX "/CX/Increment"); x3pfile->dx = g_ascii_strtod(s, NULL); if (!((x3pfile->dx = fabs(x3pfile->dx)) > 0)) { g_warning("Real x step is 0.0, fixing to 1.0"); x3pfile->dx = 1.0; } s = (gchar*)g_hash_table_lookup(x3pfile->hash, AXES_PREFIX "/CY/Increment"); x3pfile->dy = g_ascii_strtod(s, NULL); if (!((x3pfile->dy = fabs(x3pfile->dy)) > 0)) { g_warning("Real x step is 0.0, fixing to 1.0"); x3pfile->dy = 1.0; } s = (gchar*)g_hash_table_lookup(x3pfile->hash, AXES_PREFIX "/CX/Offset"); x3pfile->xoff = g_ascii_strtod(s, NULL); s = (gchar*)g_hash_table_lookup(x3pfile->hash, AXES_PREFIX "/CY/Offset"); x3pfile->yoff = g_ascii_strtod(s, NULL); /* Defaults that are good for floating point data conversion. If a file * with floating point data specifies Increment and Offset, we apply them * without hesitation. The behaviour is probably undefined. */ x3pfile->dz = 1.0; x3pfile->zoff = 0.0; s = (gchar*)g_hash_table_lookup(x3pfile->hash, AXES_PREFIX "/CZ/Increment"); if (s) x3pfile->dz = g_ascii_strtod(s, NULL); s = (gchar*)g_hash_table_lookup(x3pfile->hash, AXES_PREFIX "/CZ/Offset"); if (s) x3pfile->zoff = g_ascii_strtod(s, NULL); gwy_debug("dz=%g, zoff=%g", x3pfile->dz, x3pfile->zoff); x3pfile->ndata = x3pfile->xres*x3pfile->yres*x3pfile->zres; x3pfile->values = g_new(gdouble, x3pfile->ndata); x3pfile->valid = g_new(gboolean, x3pfile->ndata); x3pfile->datapos = 0; return TRUE; }
static gboolean get_scales(GHashTable *hash, gboolean is_text, gint *xres, gint *yres, gdouble *xreal, gdouble *yreal, gdouble *xoff, gdouble *yoff, GwySIUnit *si_unit_xy, gdouble *zscale, gdouble *zoff, GwySIUnit *si_unit_z, GError **error) { GwySIUnit *unit; gint power10, zp; gchar *p; gboolean has_unit = FALSE; /* Dimensions are mandatory. */ if (!require_keys(hash, error, "SCANNING PARAMS::PixelsX", "SCANNING PARAMS::PixelsY", "SCANNING PARAMS::PixelsZ", "SCANNING PARAMS::SizeX", "SCANNING PARAMS::SizeY", "SCANNING PARAMS::SizeZ", NULL)) return FALSE; *xres = atoi(g_hash_table_lookup(hash, "SCANNING PARAMS::PixelsX")); if (err_DIMENSION(error, *xres)) return FALSE; *yres = atoi(g_hash_table_lookup(hash, "SCANNING PARAMS::PixelsY")); if (err_DIMENSION(error, *yres)) return FALSE; unit = gwy_si_unit_new(NULL); p = g_hash_table_lookup(hash, "SCANNING PARAMS::SizeX"); *xreal = fabs(g_ascii_strtod(p, &p)); if (!*xreal) { g_warning("Real x size is 0.0, fixing to 1.0"); *xreal = 1.0; } gwy_si_unit_set_from_string_parse(si_unit_xy, p, &power10); *xreal *= pow10(power10); p = g_hash_table_lookup(hash, "SCANNING PARAMS::SizeY"); *yreal = fabs(g_ascii_strtod(p, &p)); if (!*yreal) { g_warning("Real y size is 0.0, fixing to 1.0"); *yreal = 1.0; } gwy_si_unit_set_from_string_parse(unit, p, &power10); *yreal *= pow10(power10); if (!gwy_si_unit_equal(unit, si_unit_xy)) { g_warning("X and Y units differ, using X"); } zp = atoi(g_hash_table_lookup(hash, "SCANNING PARAMS::PixelsZ")); if (!zp) { g_warning("Z pixels is 0, fixing to 1"); zp = 1; } p = g_hash_table_lookup(hash, "SCANNING PARAMS::SizeZ"); *zscale = g_ascii_strtod(p, &p); *zoff = 0.0; gwy_si_unit_set_from_string_parse(si_unit_z, p, &power10); *zscale *= pow10(power10)/zp; /* XXX: Version 4 can have UNIT section that takes precedence. The Conv * factor may not be enough. Apparently, binary phase data need * subtracting 180 deg because data are unsinged. Bite me. */ if ((p = g_hash_table_lookup(hash, "UNIT::Unit"))) { const gchar *s = g_hash_table_lookup(hash, "UNIT::Name"); has_unit = TRUE; gwy_si_unit_set_from_string_parse(si_unit_z, p, &power10); *zscale *= pow10(power10); if ((p = g_hash_table_lookup(hash, "UNIT::Conv"))) *zscale *= g_ascii_strtod(p, NULL); if (!is_text && gwy_strequal(s, "Phase")) *zoff = -180.0; } /* Offsets are optional. */ *xoff = 0.0; if ((p = g_hash_table_lookup(hash, "SCANNING PARAMS::OffsetX"))) { *xoff = g_ascii_strtod(p, &p); gwy_si_unit_set_from_string_parse(unit, p, &power10); if (gwy_si_unit_equal(unit, si_unit_xy)) *xoff *= pow10(power10); else { g_warning("X offset units differ from X size units, ignoring."); *xoff = 0.0; } } *yoff = 0.0; if ((p = g_hash_table_lookup(hash, "SCANNING PARAMS::OffsetY"))) { *yoff = g_ascii_strtod(p, &p); gwy_si_unit_set_from_string_parse(unit, p, &power10); if (gwy_si_unit_equal(unit, si_unit_xy)) *yoff *= pow10(power10); else { g_warning("Y offset units differ from Y size units, ignoring."); *yoff = 0.0; } } // Don't know what to do with the offset when UNIT section is present. // It seems to be always 0 in wrong units, so skip it. if (!has_unit) { if ((p = g_hash_table_lookup(hash, "SCANNING PARAMS::OffsetZ"))) { *zoff = g_ascii_strtod(p, &p); gwy_si_unit_set_from_string_parse(unit, p, &power10); if (gwy_si_unit_equal(unit, si_unit_z)) *zoff *= pow10(power10); else { g_warning("Z offset units differ from Z size units, ignoring."); *zoff = 0.0; } } } g_object_unref(unit); return TRUE; }
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* 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* 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 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; }
static GwyContainer* micromap_load(const gchar *filename, G_GNUC_UNUSED GwyRunType mode, GError **error) { SDFile sdfile; GwyContainer *container = NULL; gchar *p, *buffer = NULL; gsize len, size = 0; GError *err = NULL; GwyDataField *dfield = NULL; gdouble objectivemag, tubemag, cameraxpixel, cameraypixel; if (!g_file_get_contents(filename, &buffer, &size, &err)) { err_GET_FILE_CONTENTS(error, &err); return NULL; } len = size; p = buffer; if (sdfile_read_header_text(&p, &len, &sdfile, error)) { if (check_params(&sdfile, len, error)) dfield = sdfile_read_data_text(&sdfile, error); } if (!dfield) { g_free(buffer); return NULL; } if (!sdfile.extras) { err_MISSING_FIELD(error, "OBJECTIVEMAG"); goto fail; } if (!require_keys(sdfile.extras, error, "OBJECTIVEMAG", "TUBEMAG", "CAMERAXPIXEL", "CAMERAYPIXEL", NULL)) goto fail; objectivemag = g_ascii_strtod(g_hash_table_lookup(sdfile.extras, "OBJECTIVEMAG"), NULL); tubemag = g_ascii_strtod(g_hash_table_lookup(sdfile.extras, "TUBEMAG"), NULL); cameraxpixel = g_ascii_strtod(g_hash_table_lookup(sdfile.extras, "CAMERAXPIXEL"), NULL); cameraypixel = g_ascii_strtod(g_hash_table_lookup(sdfile.extras, "CAMERAYPIXEL"), NULL); sdfile_set_units(&sdfile, dfield); gwy_data_field_set_xreal(dfield, Micrometer * sdfile.xres * objectivemag * tubemag * cameraxpixel); gwy_data_field_set_yreal(dfield, Micrometer * sdfile.yres * objectivemag * tubemag * cameraypixel); container = gwy_container_new(); gwy_container_set_object_by_name(container, "/0/data", dfield); gwy_container_set_string_by_name(container, "/0/data/title", g_strdup("Topography")); fail: g_object_unref(dfield); g_free(buffer); if (sdfile.extras) g_hash_table_destroy(sdfile.extras); return container; }