static gboolean fill_data_fields(SurfFile *surffile, const guchar *buffer, GError **error) { GwySIUnit *siunit; gdouble *data; guint i, j; surffile->dfield = gwy_data_field_new(surffile->xres, surffile->yres, surffile->xres*surffile->dx, surffile->yres*surffile->dy, FALSE); data = gwy_data_field_get_data(surffile->dfield); switch (surffile->pointsize) { case 16: { const gint16 *row, *d16 = (const gint16*)buffer; for (i = 0; i < surffile->xres; i++) { row = d16 + i*surffile->yres; for (j = 0; j < surffile->yres; j++) *(data++) = GINT16_FROM_LE(row[j]) * surffile->dz; } } break; case 32: { const gint32 *row, *d32 = (const gint32*)buffer; for (i = 0; i < surffile->xres; i++) { row = d32 + i*surffile->yres; for (j = 0; j < surffile->yres; j++) *(data++) = GINT32_FROM_LE(row[j]) * surffile->dz; } } break; default: err_BPP(error, surffile->pointsize); return FALSE; break; } siunit = gwy_si_unit_new("m"); gwy_data_field_set_si_unit_xy(surffile->dfield, siunit); g_object_unref(siunit); siunit = gwy_si_unit_new("m"); gwy_data_field_set_si_unit_z(surffile->dfield, siunit); g_object_unref(siunit); return TRUE; }
static void fix_scales(EZDSection *section, gint idx, GwyContainer *container) { GwyDataField *dfield; GwySIUnit *siunit; gchar key[40]; gint power10; gdouble r; g_snprintf(key, sizeof(key), "/%d/data", idx); dfield = GWY_DATA_FIELD(gwy_container_get_object_by_name(container, key)); /* Fix value scale */ siunit = gwy_si_unit_new_parse(section->zrange.unit, &power10); gwy_data_field_set_si_unit_z(dfield, siunit); g_object_unref(siunit); r = pow10(power10); gwy_data_field_multiply(dfield, r*section->zrange.range); gwy_data_field_add(dfield, r*section->zrange.min); /* Fix lateral scale */ siunit = gwy_si_unit_new_parse(section->xrange.unit, &power10); gwy_data_field_set_si_unit_xy(dfield, siunit); g_object_unref(siunit); gwy_data_field_set_xreal(dfield, pow10(power10)*section->xrange.range); siunit = gwy_si_unit_new_parse(section->yrange.unit, &power10); gwy_data_field_set_yreal(dfield, pow10(power10)*section->yrange.range); g_object_unref(siunit); /* Some metadata */ if (section->zrange.name) { const gchar *s; switch (section->direction) { case SCAN_FORWARD: s = " forward"; break; case SCAN_BACKWARD: s = " backward"; break; default: s = ""; break; } g_snprintf(key, sizeof(key), "/%d/data/title", idx); gwy_container_set_string_by_name(container, key, g_strdup_printf("%s%s", section->zrange.name, s)); } }
static GwyDataField* read_text_data(const gchar *buffer, gint text_data_start, GHashTable *hash, GError **error) { const gchar *p; gchar *end; gint xres, yres, i, power10; gdouble xreal, yreal, zscale, xoff, yoff, zoff; GwySIUnit *unitxy, *unitz; GwyDataField *dfield = NULL; gdouble *d; unitxy = gwy_si_unit_new(NULL); unitz = gwy_si_unit_new(NULL); if (!get_scales(hash, TRUE, &xres, &yres, &xreal, &yreal, &xoff, &yoff, unitxy, &zscale, &zoff, unitz, error)) goto fail; p = g_hash_table_lookup(hash, "DATA Unit"); gwy_si_unit_set_from_string_parse(unitz, p, &power10); zscale = pow10(power10); dfield = gwy_data_field_new(xres, yres, xreal, yreal, FALSE); gwy_data_field_set_xoffset(dfield, xoff); gwy_data_field_set_yoffset(dfield, yoff); gwy_data_field_set_si_unit_xy(dfield, unitxy); gwy_data_field_set_si_unit_z(dfield, unitz); d = gwy_data_field_get_data(dfield); p = (const gchar*)buffer + text_data_start; for (i = 0; i < xres*yres; i++) { d[i] = zscale*g_ascii_strtod(p, &end) + zoff; if (end == p) { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA, _("Cannot parse data values after %d of %d."), i, xres*yres); gwy_object_unref(dfield); goto fail; } p = end + (*end == ','); } fail: g_object_unref(unitxy); g_object_unref(unitz); return dfield; }
static GwyDataField* rhk_sm3_page_to_data_field(const RHKPage *page) { GwyDataField *dfield; GwySIUnit *siunit; const gchar *unit; gint xres, yres, i; const gint32 *pdata; gdouble *data; xres = page->x_size; yres = page->y_size; dfield = gwy_data_field_new(xres, yres, xres*fabs(page->x_scale), yres*fabs(page->y_scale), FALSE); data = gwy_data_field_get_data(dfield); pdata = (const gint32*)page->page_data; for (i = 0; i < xres*yres; i++) data[i] = GINT32_FROM_LE(pdata[i])*page->z_scale + page->z_offset; if (page->strings[RHK_STRING_X_UNITS] && page->strings[RHK_STRING_Y_UNITS]) { if (!gwy_strequal(page->strings[RHK_STRING_X_UNITS], page->strings[RHK_STRING_Y_UNITS])) g_warning("X and Y units are different, using X"); unit = page->strings[RHK_STRING_X_UNITS]; } else if (page->strings[RHK_STRING_X_UNITS]) unit = page->strings[RHK_STRING_X_UNITS]; else if (page->strings[RHK_STRING_Y_UNITS]) unit = page->strings[RHK_STRING_Y_UNITS]; else unit = ""; siunit = gwy_si_unit_new(unit); gwy_data_field_set_si_unit_xy(dfield, siunit); g_object_unref(siunit); if (page->strings[RHK_STRING_Z_UNITS]) unit = page->strings[RHK_STRING_Z_UNITS]; else unit = ""; /* Fix some silly units */ if (gwy_strequal(unit, "N/sec")) unit = "s^-1"; siunit = gwy_si_unit_new(unit); gwy_data_field_set_si_unit_z(dfield, siunit); g_object_unref(siunit); return dfield; }
static void sdfile_set_units(SDFile *sdfile, GwyDataField *dfield) { GwySIUnit *siunit; gwy_data_field_multiply(dfield, sdfile->zscale); siunit = gwy_si_unit_new("m"); gwy_data_field_set_si_unit_xy(dfield, siunit); g_object_unref(siunit); siunit = gwy_si_unit_new("m"); gwy_data_field_set_si_unit_z(dfield, siunit); g_object_unref(siunit); }
static SensolyticsChannel* create_fields(GHashTable *hash, /* Can we obtain any useful information from this? */ G_GNUC_UNUSED gchar *line, gint ndata, const Dimensions *dimensions) { SensolyticsChannel *channels; GString *str; const gchar *value; GwySIUnit *unit; gint i, power10; str = g_string_new(NULL); channels = g_new0(SensolyticsChannel, ndata+1); for (i = 0; i < ndata; i++) { channels[i].dfield = gwy_data_field_new(dimensions->xres, dimensions->yres, dimensions->xreal, dimensions->yreal, FALSE); channels[i].data = gwy_data_field_get_data(channels[i].dfield); unit = gwy_si_unit_new("m"); gwy_data_field_set_si_unit_xy(channels[i].dfield, unit); g_object_unref(unit); g_string_printf(str, "Channel %d Unit", i+1); channels[i].q = 1.0; if ((value = g_hash_table_lookup(hash, str->str))) { unit = gwy_si_unit_new_parse(value, &power10); gwy_data_field_set_si_unit_z(channels[i].dfield, unit); g_object_unref(unit); channels[i].q = pow10(power10); } else g_warning("Channel %d has no units", i+1); g_string_printf(str, "Channel %d Name", i+1); if (!(channels[i].name = g_hash_table_lookup(hash, str->str))) g_warning("Channel %d has no name", i+1); } return channels; }
static void set_units(GwyDataField *dfield, const MProFile *mprofile, const gchar *zunit) { GwySIUnit *siunit; if (mprofile->camera_res) siunit = gwy_si_unit_new("m"); else siunit = gwy_si_unit_new(""); gwy_data_field_set_si_unit_xy(dfield, siunit); g_object_unref(siunit); siunit = gwy_si_unit_new(zunit); gwy_data_field_set_si_unit_z(dfield, siunit); g_object_unref(siunit); }
static gboolean fill_data_fields(SurfFile *surffile, const guchar *buffer, GError **error) { gdouble *data; surffile->dfield = gwy_data_field_new(surffile->xres, surffile->yres, surffile->xres*surffile->dx, surffile->yres*surffile->dy, FALSE); data = gwy_data_field_get_data(surffile->dfield); switch (surffile->pointsize) { case 16: gwy_convert_raw_data(buffer, surffile->xres*surffile->yres, 1, GWY_RAW_DATA_SINT16, GWY_BYTE_ORDER_LITTLE_ENDIAN, data, surffile->dz, 0.0); break; case 32: gwy_convert_raw_data(buffer, surffile->xres*surffile->yres, 1, GWY_RAW_DATA_SINT32, GWY_BYTE_ORDER_LITTLE_ENDIAN, data, surffile->dz, 0.0); break; default: err_BPP(error, surffile->pointsize); return FALSE; break; } gwy_data_field_set_si_unit_xy(surffile->dfield, surffile->xyunit); g_object_unref(surffile->xyunit); gwy_data_field_set_si_unit_z(surffile->dfield, surffile->zunit); g_object_unref(surffile->zunit); return TRUE; }
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* zeiss_load_tiff(const GwyTIFF *tiff, GError **error) { GwyContainer *container = NULL, *meta = NULL; GwyDataField *dfield; GwySIUnit *siunit; GwyTIFFImageReader *reader = NULL; GHashTable *hash = NULL; gint i, power10; gchar *value, *end, *comment = NULL; gdouble *data; gboolean new_file; double factor, dx; /* Comment with parameters is common for all data fields */ if (!gwy_tiff_get_string0(tiff, ZEISS_HEADER_TAG, &comment)) { err_FILE_TYPE(error, "Carl Zeiss SEM"); goto fail; } if (strstr(comment, MAGIC_COMMENT)) new_file = TRUE; else if (g_str_has_prefix(comment, SOMEWHAT_LESS_MAGIC_COMMENT)) new_file = FALSE; else { err_FILE_TYPE(error, "Carl Zeiss SEM"); goto fail; } /* Read the comment header. */ if (new_file) { hash = parse_comment(comment); if ((value = g_hash_table_lookup(hash, "Image Pixel Size"))) { gwy_debug("Using dx from Image Pixel Size: %s", value); } else if ((value = g_hash_table_lookup(hash, "Pixel Size"))) { gwy_debug("Using dx from Pixel Size: %s", value); } else { err_MISSING_FIELD(error, "Pixel Size"); goto fail; } } else { /* The first thing is the pixel size, apparently. */ value = comment + strlen(SOMEWHAT_LESS_MAGIC_COMMENT); gwy_debug("Using dx from old-style comment: %s", value); } dx = g_ascii_strtod(value, &end); /* Use negated positive conditions to catch NaNs */ if (!((dx = fabs(dx)) > 0)) { g_warning("Real pixel size is 0.0, fixing to 1.0"); dx = 1.0; } if (!new_file) end = "m"; /* Request a reader, this ensures dimensions and stuff are defined. * NB: Newer versions store the image as RGB. Not useful here; just * average the channels. */ if (!(reader = gwy_tiff_get_image_reader(tiff, 0, 3, error))) goto fail; siunit = gwy_si_unit_new_parse(end, &power10); factor = pow10(power10); dfield = gwy_data_field_new(reader->width, reader->height, reader->width * factor * dx, reader->height * factor * dx, FALSE); gwy_data_field_set_si_unit_xy(dfield, siunit); g_object_unref(siunit); data = gwy_data_field_get_data(dfield); if (reader->samples_per_pixel > 1) { gdouble *datarow = g_new(gdouble, reader->width); gint ch, j, spp = reader->samples_per_pixel; gwy_data_field_clear(dfield); for (i = 0; i < reader->height; i++) { for (ch = 0; ch < spp; ch++) { gwy_tiff_read_image_row(tiff, reader, 0, i, 1.0, 0.0, datarow); for (j = 0; j < reader->width; j++) data[i*reader->width + j] += datarow[j]; } } g_free(datarow); gwy_data_field_multiply(dfield, 1.0/spp); gwy_data_field_invalidate(dfield); } else { for (i = 0; i < reader->height; i++) gwy_tiff_read_image_row(tiff, reader, 0, i, 1.0, 0.0, data + i*reader->width); } container = gwy_container_new(); gwy_container_set_object_by_name(container, "/0/data", dfield); g_object_unref(dfield); gwy_container_set_string_by_name(container, "/0/data/title", g_strdup("Secondary electron count")); if (new_file) { meta = gwy_container_new(); g_hash_table_foreach(hash, add_meta, meta); if (gwy_container_get_n_items(meta)) gwy_container_set_object_by_name(container, "/0/meta", meta); g_object_unref(meta); } fail: if (hash) g_hash_table_destroy(hash); g_free(comment); return container; }
static GwyDataField* sensofar_read_data_field(SensofarDataDesc *data_desc, GwyDataField **maskfield, const guchar **p, gsize size, GError **error) { GwyDataField *dfield, *mfield; guint xres, yres, i, j, mcount; GwySIUnit *units = NULL; gdouble *data, *mdata; if (maskfield) *maskfield = NULL; yres = gwy_get_guint32_le(p); xres = gwy_get_guint32_le(p); gwy_debug("Data size: %dx%d", xres, yres); if (err_SIZE_MISMATCH(error, xres*yres*sizeof(gfloat), size - 2*sizeof(guint32), FALSE)) return NULL; if (err_DIMENSION(error, xres) || err_DIMENSION(error, yres)) return NULL; if (!((data_desc->axes_config.mppx = fabs(data_desc->axes_config.mppx)) > 0)) { g_warning("Real x size is 0.0, fixing to 1.0"); data_desc->axes_config.mppx = 1.0; } if (!((data_desc->axes_config.mppy = fabs(data_desc->axes_config.mppy)) > 0)) { g_warning("Real y size is 0.0, fixing to 1.0"); data_desc->axes_config.mppy = 1.0; } dfield = gwy_data_field_new(xres, yres, data_desc->axes_config.mppx * xres * Micrometer, data_desc->axes_config.mppy * yres * Micrometer, FALSE); units = gwy_si_unit_new("m"); // values are in um only gwy_data_field_set_si_unit_xy(dfield, units); g_object_unref(units); units = gwy_si_unit_new("m"); gwy_data_field_set_si_unit_z(dfield, units); g_object_unref(units); mfield = gwy_data_field_new_alike(dfield, FALSE); gwy_data_field_fill(mfield, 1.0); data = gwy_data_field_get_data(dfield); mdata = gwy_data_field_get_data(mfield); for (i = 0; i < yres; i++) { for (j = 0; j < xres; j++) { gdouble v = gwy_get_gfloat_le(p); if (v == 1000001.0) mdata[i*xres + j] = 0.0; else data[i*xres + j] = v*Micrometer; } } gwy_debug("Offset: %g %g", data_desc->axes_config.x_0, data_desc->axes_config.y_0); //FIXME: offset later, support of offset determined by version? //gwy_data_field_set_xoffset(d, pow10(power10)*data_desc.axes_config.x_0); //gwy_data_field_set_yoffset(d, pow10(power10)*data_desc.axes_config.y_0); mcount = gwy_app_channel_remove_bad_data(dfield, mfield); if (maskfield && mcount) *maskfield = mfield; else g_object_unref(mfield); return dfield; }
static GwyContainer* ecs_load(const gchar *filename, G_GNUC_UNUSED GwyRunType mode, GError **error) { GwyContainer *meta, *container = NULL; guchar *buffer = NULL; gsize size = 0; GError *err = NULL; GwyDataField *dfield = NULL; gchar *s = NULL, *s2 = NULL; GwySIUnit *siunit; const guchar *p; gdouble *data, *row; guint xres, yres, i, j; gdouble xreal, q; const gint16 *pdata; guchar c; if (!gwy_file_get_contents(filename, &buffer, &size, &err)) { err_GET_FILE_CONTENTS(error, &err); g_clear_error(&err); return NULL; } if (size < HEADER_SIZE + 2) { err_TOO_SHORT(error); goto fail; } p = buffer + ECS_RESOLUTION; xres = gwy_get_guint16_le(&p); yres = gwy_get_guint16_le(&p); gwy_debug("xres: %u, yres: %u", xres, yres); if (size != HEADER_SIZE + 2*xres*yres) { err_SIZE_MISMATCH(error, HEADER_SIZE + 2*xres*yres, size); goto fail; } /* Scan size */ p = buffer + ECS_SCAN_SIZE; s = get_PASCAL_STRING(&p, HEADER_SIZE - ECS_SCAN_SIZE); if (!s) { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA, _("Scan size header field overlaps with data.")); goto fail; } gwy_debug("Scan size str: <%s>", s); if (!g_str_has_prefix(s, "Scan Size: ")) { err_FILE_TYPE(error, "ECS"); goto fail; } if (sscanf(s + strlen("Scan Size: "), "%lf %lf%c", &xreal, &q, &c) != 3) { err_INVALID(error, "Scan Size"); goto fail; } g_free(s); s = NULL; gwy_debug("xreal: %g q: %g unit: %s", xreal, q, c == 0x8f ? "Angstrom" : "Nanometer"); if (c == 0x8f) { xreal *= 1e-10; q *= 1e-10; } else { xreal *= 1e-9; q *= 1e-9; } q /= 65536.0; /* This does not make much sense when xres != yres, but it is what * Snomputz does. */ dfield = gwy_data_field_new(xres, yres, xreal, xreal, FALSE); data = gwy_data_field_get_data(dfield); pdata = (const gint16*)(buffer + HEADER_SIZE); for (i = 0; i < yres; i++) { row = data + (yres-1 - i)*xres; for (j = 0; j < xres; j++) row[j] = GINT16_TO_LE(pdata[i*xres + j])*q; } siunit = gwy_si_unit_new("m"); gwy_data_field_set_si_unit_xy(dfield, siunit); g_object_unref(siunit); siunit = gwy_si_unit_new("m"); gwy_data_field_set_si_unit_z(dfield, siunit); g_object_unref(siunit); container = gwy_container_new(); gwy_container_set_object_by_name(container, "/0/data", dfield); /* Channel title */ p = buffer + ECS_CHANNEL; s = get_PASCAL_STRING(&p, HEADER_SIZE - ECS_CHANNEL); if (!s || !*s) s = g_strdup("Topography"); gwy_container_set_string_by_name(container, "/0/data/title", s); s = NULL; meta = gwy_container_new(); /* Date & time */ p = buffer + ECS_DATE; s = get_PASCAL_STRING(&p, HEADER_SIZE - ECS_DATE); if (s) { p = buffer + ECS_TIME; s2 = get_PASCAL_STRING(&p, HEADER_SIZE - ECS_TIME); if (s2) { gwy_container_set_string_by_name(meta, "Date", g_strconcat(s, " ", s2, NULL)); g_free(s2); s2 = NULL; } g_free(s); s = NULL; } /* Channel title */ p = buffer + ECS_CHANNEL; s = get_PASCAL_STRING(&p, HEADER_SIZE - ECS_CHANNEL); if (s && *s) { gwy_container_set_string_by_name(meta, "Comment", s); s = NULL; } if (gwy_container_get_n_items(meta)) gwy_container_set_object_by_name(container, "/0/meta", meta); g_object_unref(meta); fail: g_free(s); g_free(s2); gwy_object_unref(dfield); gwy_file_abandon_contents(buffer, size, NULL); return container; }
static GwyDataField* unisoku_read_data_field(const guchar *buffer, gsize size, UnisokuFile *ufile, GError **error) { gint i, n, power10; const gchar *unit; GwyDataField *dfield; GwySIUnit *siunit; gdouble q, pmin, pmax, rmin, rmax; gdouble *data; n = ufile->xres * ufile->yres; if (err_SIZE_MISMATCH(error, n*type_sizes[ufile->data_type], size, FALSE)) return NULL; dfield = gwy_data_field_new(ufile->xres, ufile->yres, fabs((ufile->end_x - ufile->start_x)), fabs((ufile->end_y - ufile->start_y)), FALSE); data = gwy_data_field_get_data(dfield); /* FIXME: what to do when ascii_flag is set? */ switch (ufile->data_type) { case UNISOKU_UINT8: for (i = 0; i < n; i++) data[i] = buffer[i]; break; case UNISOKU_SINT8: for (i = 0; i < n; i++) data[i] = (signed char)buffer[i]; break; case UNISOKU_UINT16: { const guint16 *pdata = (const guint16*)buffer; for (i = 0; i < n; i++) data[i] = GUINT16_FROM_LE(pdata[i]); } break; case UNISOKU_SINT16: { const gint16 *pdata = (const gint16*)buffer; for (i = 0; i < n; i++) data[i] = GINT16_FROM_LE(pdata[i]); } break; case UNISOKU_FLOAT: for (i = 0; i < n; i++) data[i] = gwy_get_gfloat_le(&buffer); break; default: g_return_val_if_reached(NULL); break; } unit = ufile->unit_x; if (!*unit) unit = "nm"; siunit = gwy_si_unit_new_parse(unit, &power10); gwy_data_field_set_si_unit_xy(dfield, siunit); q = pow10((gdouble)power10); gwy_data_field_set_xreal(dfield, q*gwy_data_field_get_xreal(dfield)); gwy_data_field_set_yreal(dfield, q*gwy_data_field_get_yreal(dfield)); g_object_unref(siunit); unit = ufile->unit_z; /* XXX: No fallback yet, just make z unitless */ siunit = gwy_si_unit_new_parse(unit, &power10); gwy_data_field_set_si_unit_z(dfield, siunit); q = pow10((gdouble)power10); pmin = q*ufile->min_z; pmax = q*ufile->max_z; rmin = ufile->min_raw_z; rmax = ufile->max_raw_z; gwy_data_field_multiply(dfield, (pmax - pmin)/(rmax - rmin)); gwy_data_field_add(dfield, (pmin*rmax - pmax*rmin)/(rmax - rmin)); g_object_unref(siunit); return dfield; }
static GwyContainer* gxsm_load(const gchar *filename, G_GNUC_UNUSED GwyRunType mode, GError **error) { static const gchar *dimensions[] = { "time", "value", "dimy", "dimx" }; GwyContainer *data = NULL; GwyDataField *dfield; GwySIUnit *siunit; NetCDF cdffile; const NetCDFDim *dim; const NetCDFVar *var; const NetCDFAttr *attr; gdouble real; gint i, power10; if (!cdffile_load(&cdffile, filename, error)) return NULL; if (cdffile.nrecs) { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA, _("NetCDF records are not supported.")); goto gxsm_load_fail; } /* Look for variable "H" or "FloatField". This seems to be how GXSM calls * data. */ if (!(var = cdffile_get_var(&cdffile, "H")) && !(var = cdffile_get_var(&cdffile, "FloatField"))) { err_NO_DATA(error); goto gxsm_load_fail; } /* Check the dimensions. We only know how to handle time=1 and value=1. */ for (i = 0; i < var->ndims; i++) { dim = cdffile.dims + var->dimids[i]; if (!gwy_strequal(dim->name, dimensions[i]) || (i < 2 && dim->length != 1)) { /* XXX */ err_NO_DATA(error); goto gxsm_load_fail; } } if (err_DIMENSION(error, cdffile.dims[var->dimids[3]].length) || err_DIMENSION(error, cdffile.dims[var->dimids[2]].length)) goto gxsm_load_fail; dfield = read_data_field((const guchar*)(cdffile.buffer + var->begin), cdffile.dims[var->dimids[3]].length, cdffile.dims[var->dimids[2]].length, var->type); if ((siunit = read_real_size(&cdffile, "rangex", &real, &power10))) { /* Use negated positive conditions to catch NaNs */ if (!((real = fabs(real)) > 0)) { g_warning("Real x size is 0.0, fixing to 1.0"); real = 1.0; } gwy_data_field_set_xreal(dfield, real*pow10(power10)); gwy_data_field_set_si_unit_xy(dfield, siunit); g_object_unref(siunit); } if ((siunit = read_real_size(&cdffile, "rangey", &real, &power10))) { /* Use negated positive conditions to catch NaNs */ if (!((real = fabs(real)) > 0)) { g_warning("Real y size is 0.0, fixing to 1.0"); real = 1.0; } gwy_data_field_set_yreal(dfield, real*pow10(power10)); /* must be the same gwy_data_field_set_si_unit_xy(dfield, siunit); */ g_object_unref(siunit); } if ((siunit = read_real_size(&cdffile, "rangez", &real, &power10))) { /* rangez seems to be some bogus value, take only units */ gwy_data_field_set_si_unit_z(dfield, siunit); gwy_data_field_multiply(dfield, pow10(power10)); g_object_unref(siunit); } if ((siunit = read_real_size(&cdffile, "dz", &real, &power10))) { /* on the other hand the units seem to be bogus here, take the range */ gwy_data_field_multiply(dfield, real); g_object_unref(siunit); } data = gwy_container_new(); gwy_container_set_object_by_name(data, "/0/data", dfield); g_object_unref(dfield); if ((attr = cdffile_get_attr(var->attrs, var->nattrs, "long_name")) && attr->type == NC_CHAR && attr->nelems) { gwy_container_set_string_by_name(data, "/0/data/title", g_strndup(attr->values, attr->nelems)); } gxsm_load_fail: gwy_file_abandon_contents(cdffile.buffer, cdffile.size, NULL); cdffile_free(&cdffile); return data; }
static GwyDataField* read_datafield(const guchar *buffer, guint size, const StmprgFile *stmprgfile, GError **error) { gint xres, yres, bpp; gdouble xreal, yreal, q; GwyDataField *dfield; gdouble *data; GwySIUnit *unit; bpp = 2; /* words, always */ xres = stmprgfile->mainfield.points; yres = stmprgfile->mainfield.lines; xreal = Angstrom * stmprgfile->mainfield.field_x; yreal = Angstrom * stmprgfile->mainfield.field_y; q = stmprgfile->mainfield.sol_z * 1.0e-5; /* 5 ?? */ /* resolution of z value in angstrom/bit, 1.0e-10 */ if (err_SIZE_MISMATCH(error, bpp*xres*yres, size, FALSE)) return NULL; dfield = gwy_data_field_new(xres, yres, xreal, yreal, FALSE); data = gwy_data_field_get_data(dfield); if (!read_binary_ubedata(xres * yres, data, buffer, bpp)) { err_BPP(error, bpp); g_object_unref(dfield); return NULL; } gwy_data_field_multiply(dfield, q); unit = gwy_si_unit_new("m"); gwy_data_field_set_si_unit_xy(dfield, unit); g_object_unref(unit); /* Assuming we are reading channel1... */ switch (stmprgfile->control.channel1) { case STMPRG_CHANNEL_OFF: g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA, _("First channel is switched off.")); return NULL; case STMPRG_CHANNEL_Z: unit = gwy_si_unit_new("m"); break; case STMPRG_CHANNEL_I: case STMPRG_CHANNEL_I_I0: case STMPRG_CHANNEL_I0: unit = gwy_si_unit_new("A"); break; case STMPRG_CHANNEL_EXT1: case STMPRG_CHANNEL_EXT2: case STMPRG_CHANNEL_U0: unit = gwy_si_unit_new("V"); break; default: g_assert_not_reached(); break; } gwy_data_field_set_si_unit_z(dfield, unit); g_object_unref(unit); return dfield; }
static GwyContainer* lif_load(const gchar *filename, G_GNUC_UNUSED GwyRunType mode, GError **error) { GwyContainer *container = NULL; LIFHeader *header = NULL; LIFMemBlock *memblock = NULL; LIFFile *file = NULL; LIFElement *element = NULL; LIFDimension *dimension = NULL; LIFChannel *channel = NULL; gsize size = 0, memblock_size = 0; gint64 remaining = 0; gchar *buffer; const guchar *p; GError *err = NULL; GwyDataField *dfield = NULL; GwyBrick *brick = NULL; gdouble *data = NULL; gint i, j, channelno = 0, volumeno = 0; gchar *strkey, *lutname; GMarkupParser parser = { header_start_element, header_end_element, header_parse_text, NULL, NULL }; GMarkupParseContext *context; XMLParserData *xmldata; gint x, xres, xstep, y, yres, ystep, z, zres, zstep, offset, res; gdouble xreal, yreal, zreal, xoffset, yoffset, zoffset; gdouble zscale = 1.0, wscale = 1.0; GwySIUnit *siunitxy = NULL, *siunitz = NULL; GwySIUnit *siunitx = NULL, *siunity = NULL, *siunitw = NULL; gint power10xy = 1; gint power10x = 1, power10y = 1, power10z = 1, power10w = 1; if (!g_file_get_contents(filename, &buffer, &size, &err)) { err_GET_FILE_CONTENTS(error, &err); goto fail; } if (size < 13) { /* header too short */ err_TOO_SHORT(error); goto fail; } p = buffer; remaining = size; header = g_new0(LIFHeader, 1); header->magic = gwy_get_gint32_le(&p); gwy_debug("Magic = %d", header->magic); header->size = gwy_get_guint32_le(&p); gwy_debug("Size = %d", header->size); header->testcode = *(p++); gwy_debug("Testcode = 0x%x", header->testcode); if (header->testcode != TESTCODE) { err_FILE_TYPE(error, "Leica LIF"); goto fail; } header->xmllen = gwy_get_guint32_le(&p); gwy_debug("XML length = %d", header->xmllen); if (size < 13 + header->xmllen * 2) { err_TOO_SHORT(error); goto fail; } remaining -= 13; header->xmlheader = g_convert((const gchar*)p, 2 * header->xmllen, "UTF-8", "UTF-16", NULL, NULL, NULL); p += header->xmllen * 2; remaining -= header->xmllen * 2; // gwy_debug("%s", header->xmlheader); /* Parse XML header */ xmldata = g_new0(XMLParserData, 1); xmldata->file = g_new0(LIFFile, 1); xmldata->file->elements = g_array_new(FALSE, TRUE, sizeof(LIFElement)); xmldata->elements = g_ptr_array_new(); context = g_markup_parse_context_new(&parser, G_MARKUP_TREAT_CDATA_AS_TEXT, (gpointer)xmldata, NULL); if (!g_markup_parse_context_parse(context, header->xmlheader, -1, &err) || !g_markup_parse_context_end_parse(context, &err)) { error = &err; g_clear_error(&err); } g_markup_parse_context_free(context); file = xmldata->file; file->header = header; g_ptr_array_free(xmldata->elements, TRUE); g_free(xmldata); /* Reading memblocks */ file->memblocks = g_hash_table_new(g_str_hash, g_str_equal); while (remaining > 0) { memblock = lif_read_memblock(p, &memblock_size, file->version); if (!memblock) { break; } remaining -= memblock_size; if (remaining >= 0) { gwy_debug("remaining = %" G_GUINT64_FORMAT "", remaining); p += memblock_size; g_hash_table_insert(file->memblocks, memblock->memid, memblock); } } container = gwy_container_new(); for (i = 0; i < file->elements->len; i++) { element = &g_array_index(file->elements, LIFElement, i); if ((element->dimensions == NULL) || (element->channels == NULL)) { gwy_debug("Empty element"); continue; } gwy_debug("Dimensions = %d channels=%d", element->dimensions->len, element->channels->len); gwy_debug("memid=%s", element->memid); /* check if we can load this type of data into * Gwyddion structures */ res = 0; if ((element->dimensions->len != 2) && (element->dimensions->len != 3)) { /* check for case ndim == 4 && res == 1 */ for (i = 0; i < element->dimensions->len; i++) { dimension = &g_array_index(element->dimensions, LIFDimension, i); xres = dimension->res; gwy_debug("dim[%d].res=%d", i, xres); if (i == 2) { res = xres; } } if ((element->dimensions->len == 4) && (res == 1)) { gwy_debug("4D volume"); } else { gwy_debug("not loading"); continue; } } memblock = (LIFMemBlock *)g_hash_table_lookup(file->memblocks, element->memid); if (!memblock) { gwy_debug("Failed to locate memblock with key %s", element->memid); continue; } p = memblock->data; if (element->dimensions->len == 2) { /* Image */ for (j = 0; j < element->channels->len; j++) { dimension = &g_array_index(element->dimensions, LIFDimension, 0); xres = dimension->res; xreal = dimension->length; xoffset = dimension->origin; xstep = dimension->bytesinc; siunitxy = gwy_si_unit_new_parse(dimension->unit, &power10xy); dimension = &g_array_index(element->dimensions, LIFDimension, 1); yres = dimension->res; yreal = dimension->length; yoffset = dimension->origin; ystep = dimension->bytesinc; if (xreal <= 0.0) xreal = 1.0; if (yreal <= 0.0) yreal = 1.0; channel = &g_array_index(element->channels, LIFChannel, j); offset = channel->bytesinc; siunitz = gwy_si_unit_new_parse(channel->unit, &power10z); zscale = pow10(power10z); if (offset + (xres - 1) * xstep + (yres - 1)* ystep > memblock->memsize) { gwy_debug("Memblock too small"); gwy_debug("%d %" G_GUINT64_FORMAT "", offset + (xres-1)*xstep + (yres-1)*ystep, memblock->memsize); err_SIZE_MISMATCH(error, memblock->memsize, offset+(xres-1)*xstep +(yres-1)*ystep, FALSE); goto fail; } dfield = gwy_data_field_new(xres, yres, xreal*pow10(power10xy), yreal*pow10(power10xy), TRUE); gwy_data_field_set_xoffset(dfield, xoffset*pow10(power10xy)); gwy_data_field_set_yoffset(dfield, yoffset*pow10(power10xy)); data = gwy_data_field_get_data(dfield); for (y = 0; y < yres; y++) for (x = 0; x < xres; x++) { *(data++) = zscale * (gdouble)*(p + offset + x*xstep + y*ystep); } if (siunitxy) { gwy_data_field_set_si_unit_xy(dfield, siunitxy); g_object_unref(siunitxy); } if (siunitz) { gwy_data_field_set_si_unit_z(dfield, siunitz); g_object_unref(siunitz); } strkey = g_strdup_printf("/%d/data", channelno); gwy_container_set_object_by_name(container, strkey, dfield); g_object_unref(dfield); g_free(strkey); if (element->name) { strkey = g_strdup_printf("/%d/data/title", channelno); gwy_container_set_string_by_name(container, strkey, g_strdup(element->name)); g_free(strkey); } if (element->metadata) { strkey = g_strdup_printf("/%d/meta", channelno); gwy_container_set_object_by_name(container, strkey, element->metadata); g_free(strkey); } if (channel->lut) { lutname = NULL; if (gwy_strequal(channel->lut, "Red")) lutname = g_strdup_printf("RGB-Red"); else if (gwy_strequal(channel->lut, "Green")) lutname = g_strdup_printf("RGB-Green"); else if (gwy_strequal(channel->lut, "Blue")) lutname = g_strdup_printf("RGB-Blue"); else if (gwy_strequal(channel->lut, "Gray")) lutname = g_strdup_printf("Gray"); if (lutname) { strkey = g_strdup_printf("/%u/base/palette", channelno); gwy_container_set_string_by_name(container, strkey, lutname); g_free(strkey); } } gwy_file_channel_import_log_add(container, channelno, NULL, filename); channelno++; } } else if ((element->dimensions->len == 3) || ((element->dimensions->len == 4) && (res == 1))) { /* Volume */ for (j = 0; j < element->channels->len; j++) { dimension = &g_array_index(element->dimensions, LIFDimension, 0); xres = dimension->res; xreal = dimension->length; xoffset = dimension->origin; xstep = dimension->bytesinc; siunitx = gwy_si_unit_new_parse(dimension->unit, &power10x); dimension = &g_array_index(element->dimensions, LIFDimension, 1); yres = dimension->res; yreal = dimension->length; yoffset = dimension->origin; ystep = dimension->bytesinc; siunity = gwy_si_unit_new_parse(dimension->unit, &power10y); if (element->dimensions->len == 3) { dimension = &g_array_index(element->dimensions, LIFDimension, 2); } else { dimension = &g_array_index(element->dimensions, LIFDimension, 3); } zres = dimension->res; zreal = dimension->length; zoffset = dimension->origin; zstep = dimension->bytesinc; siunitz = gwy_si_unit_new_parse(dimension->unit, &power10z); channel = &g_array_index(element->channels, LIFChannel, j); offset = channel->bytesinc; siunitw = gwy_si_unit_new_parse(channel->unit, &power10w); wscale = pow10(power10w); if (offset + (xres-1)*xstep + (yres-1)*ystep + (zres-1)*zstep > memblock->memsize) { gwy_debug("Memblock too small"); gwy_debug("%d %" G_GUINT64_FORMAT "", offset + (xres-1)*xstep + (yres-1)*ystep + (zres-1)*zstep, memblock->memsize); err_SIZE_MISMATCH(error, memblock->memsize, offset + (xres-1)*xstep + (yres-1)*ystep + (zres-1)*zstep, FALSE); goto fail; } brick = gwy_brick_new(xres, yres, zres, xreal*pow10(power10x), yreal*pow10(power10y), zreal*pow10(power10z), TRUE); gwy_brick_set_xoffset(brick, xoffset*pow10(power10x)); gwy_brick_set_yoffset(brick, yoffset*pow10(power10y)); gwy_brick_set_zoffset(brick, zoffset*pow10(power10z)); data = gwy_brick_get_data(brick); for (z = 0; z < zres; z++) for (y = 0; y < yres; y++) for (x = 0; x < xres; x++) { *(data++) = wscale * (gdouble)*(p + offset + x*xstep + y*ystep + z*zstep); } if (siunitx) { gwy_brick_set_si_unit_x(brick, siunitx); g_object_unref(siunitx); } if (siunity) { gwy_brick_set_si_unit_y(brick, siunity); g_object_unref(siunity); } if (siunitz) { gwy_brick_set_si_unit_z(brick, siunitz); g_object_unref(siunitz); } if (siunitw) { gwy_brick_set_si_unit_w(brick, siunitw); g_object_unref(siunitw); } strkey = g_strdup_printf("/brick/%d", volumeno); gwy_container_set_object_by_name(container, strkey, brick); g_free(strkey); if (element->name) { strkey = g_strdup_printf("/brick/%d/title", volumeno); gwy_container_set_string_by_name(container, strkey, g_strdup(element->name)); g_free(strkey); } if (element->metadata) { strkey = g_strdup_printf("/brick/%d/meta", volumeno); gwy_container_set_object_by_name(container, strkey, element->metadata); g_free(strkey); } if (channel->lut) { lutname = NULL; if (gwy_strequal(channel->lut, "Red")) lutname = g_strdup_printf("RGB-Red"); else if (gwy_strequal(channel->lut, "Green")) lutname = g_strdup_printf("RGB-Green"); else if (gwy_strequal(channel->lut, "Blue")) lutname = g_strdup_printf("RGB-Blue"); else if (gwy_strequal(channel->lut, "Gray")) lutname = g_strdup_printf("Gray"); if (lutname) { strkey = g_strdup_printf("/brick/%d/preview/palette", volumeno); gwy_container_set_string_by_name(container, strkey, lutname); g_free(strkey); } } dfield = gwy_data_field_new(xres, yres, xreal, yreal, FALSE); gwy_brick_mean_plane(brick, dfield, 0, 0, 0, xres, yres, -1, FALSE); strkey = g_strdup_printf("/brick/%d/preview", volumeno); gwy_container_set_object_by_name(container, strkey, dfield); g_free(strkey); g_object_unref(brick); g_object_unref(dfield); gwy_file_volume_import_log_add(container, volumeno, NULL, filename); volumeno++; } /* for (channels) */ } /* if (volume) */ } fail: /* freeing all stuff */ if (file) { if (file->memblocks) { g_hash_table_foreach_remove(file->memblocks, lif_remove_memblock, NULL); g_hash_table_unref(file->memblocks); } if (file->elements) { for (i = 0; i < file->elements->len; i++) { element = &g_array_index(file->elements, LIFElement, i); if (element->dimensions) { for (j = 0; j < element->dimensions->len; j++) { dimension = &g_array_index(element->dimensions, LIFDimension, j); if (dimension->unit) g_free(dimension->unit); } g_array_free(element->dimensions, TRUE); } if (element->channels) { for (j = 0; j < element->channels->len; j++) { channel = &g_array_index(element->channels, LIFChannel, j); if (channel->unit) g_free(channel->unit); if (channel->lut) g_free(channel->lut); } g_array_free(element->channels, TRUE); } if (element->name) g_free(element->name); if (element->memid) g_free(element->memid); if (element->metadata) g_object_unref(element->metadata); } g_array_free(file->elements, TRUE); } g_free(file); } if (header->xmlheader) g_free(header->xmlheader); if (header) { g_free(header); } 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 GwyDataField* read_data_field(const guchar *buffer, guint size, guchar version, gchar **title, gint *direction, GError **error) { enum { MIN_REMAINDER = 2620 }; /* information offsets in different versions, in r5+ relative to data * start, in order: * data offset, * pixel dimensions, * physical dimensions, * value multiplier, * unit string, * data type, (if zero, use channel title) * channel title (if zero, use data type) */ const guint offsets34[] = { 0x0104, 0x0196, 0x01a2, 0x01b2, 0x01c2, 0x0400, 0x0000 }; const guint offsets56[] = { 0x0104, 0x025c, 0x0268, 0x0288, 0x02a0, 0x0708, 0x0000 }; const guint offsets7[] = { 0x0104, 0x029c, 0x02a8, 0x02c8, 0x02e0, 0x0000, 0x0b90 }; gint xres, yres, doffset, i, power10, type; gdouble xreal, yreal, q, z0; GwyDataField *dfield; GwySIUnit *unitxy, *unitz; gdouble *data; const guint *offset; const guchar *p, *r, *last; /* get floats in single precision from r4 but double from r5+ */ gdouble (*getflt)(const guchar**); *title = NULL; *direction = -1; if (version == '5' || version == '6' || version == '7') { /* There are more headers in r5, * try to find something that looks like #R5. */ last = r = buffer; while ((p = memchr(r, '#', size - (r - buffer) - MIN_REMAINDER))) { if (p[1] == 'R' && p[2] == version && p[3] == '.') { gwy_debug("pos: %ld", (long)(p - buffer)); last = p; r = p + MIN_REMAINDER-1; } else r = p + 1; } offset = (version == '7') ? &offsets7[0] : &offsets56[0]; buffer = last; getflt = &gwy_get_gdouble_le; } else { offset = &offsets34[0]; getflt = &get_gfloat_le_as_double; } p = buffer + *(offset++); doffset = gwy_get_guint32_le(&p); /* this appears to be the same number as in the ASCII miniheader -- so get it here since it's easier */ gwy_debug("data offset = %u", doffset); p = buffer + *(offset++); xres = gwy_get_guint32_le(&p); yres = gwy_get_guint32_le(&p); if (err_DIMENSION(error, xres) || err_DIMENSION(error, yres)) return NULL; p = buffer + *(offset++); xreal = -getflt(&p); xreal += getflt(&p); yreal = -getflt(&p); yreal += getflt(&p); 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; } p = buffer + *(offset++); q = getflt(&p); z0 = getflt(&p); gwy_debug("xreal.raw = %g, yreal.raw = %g, q.raw = %g, z0.raw = %g", xreal, yreal, q, z0); p = buffer + *(offset++); unitz = gwy_si_unit_new_parse(p, &power10); q *= pow10(power10); z0 *= pow10(power10); unitxy = gwy_si_unit_new_parse(p + 10, &power10); xreal *= pow10(power10); yreal *= pow10(power10); gwy_debug("xres = %d, yres = %d, xreal = %g, yreal = %g, q = %g, z0 = %g", xres, yres, xreal, yreal, q, z0); gwy_debug("unitxy = %s, unitz = %s", p, p + 10); if (offset[1]) { /* We know channel title */ offset++; p = buffer + *(offset++); *title = g_strndup(p, size - (p - buffer)); gwy_debug("title = <%s>", *title); } else { /* We know data type */ p = buffer + *(offset++); type = gwy_get_guint16_le(&p); *direction = gwy_get_guint16_le(&p); gwy_debug("type = %d, dir = %d", type, *direction); offset++; *title = type_to_title(type); } p = buffer + doffset; if (err_SIZE_MISMATCH(error, 2*xres*yres, size - (p - buffer), FALSE)) return NULL; dfield = gwy_data_field_new(xres, yres, xreal, yreal, FALSE); gwy_data_field_set_si_unit_xy(dfield, unitxy); g_object_unref(unitxy); gwy_data_field_set_si_unit_z(dfield, unitz); g_object_unref(unitz); data = gwy_data_field_get_data(dfield); for (i = 0; i < xres*yres; i++) data[i] = (p[2*i] + 256.0*p[2*i + 1])*q + z0; return dfield; }
static GwyContainer* pni_load(const gchar *filename, G_GNUC_UNUSED GwyRunType mode, GError **error) { static const GwyEnum titles[] = { { "Height", DATA_TYPE_HGT, }, { "Sens", DATA_TYPE_SEN, }, { "Dem", DATA_TYPE_DEM, }, { "Error", DATA_TYPE_ERR, }, { "L-R", DATA_TYPE_L_R, }, }; GwyContainer *container = NULL; guchar *buffer = NULL; gsize size = 0; GError *err = NULL; GwyDataField *dfield = NULL; const guchar *p; gint i, xres, yres; PNIDataType data_type; PNIValueType value_type; PNIDirection direction; gdouble xreal, yreal, zscale; gdouble *data; const gint16 *d16; GwySIUnit *siunit; const gchar *title; gchar *s; if (!gwy_file_get_contents(filename, &buffer, &size, &err)) { err_GET_FILE_CONTENTS(error, &err); return NULL; } if (size < DATA_START + 2) { err_TOO_SHORT(error); gwy_file_abandon_contents(buffer, size, NULL); return NULL; } p = buffer + DATA_HEADER_START + RESOLUTION_OFFSET; xres = gwy_get_guint32_le(&p); yres = gwy_get_guint32_le(&p); gwy_debug("%d %d", xres, yres); if (err_DIMENSION(error, xres) || err_DIMENSION(error, yres) || err_SIZE_MISMATCH(error, DATA_START + 2*xres*yres, size, TRUE)) { gwy_file_abandon_contents(buffer, size, NULL); return NULL; } p = buffer + DATA_HEADER_START; data_type = p[DATA_TYPE_OFFSET]; value_type = p[VALUE_TYPE_OFFSET]; direction = p[DIRECTION_OFFSET]; p = buffer + DATA_HEADER_START + REAL_SIZE_OFFSET; xreal = gwy_get_gfloat_le(&p); yreal = gwy_get_gfloat_le(&p); /* 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; } xreal *= Micrometer; yreal *= Micrometer; p = buffer + DATA_HEADER_START + VALUE_SCALE_OFFSET; zscale = gwy_get_gfloat_le(&p); dfield = gwy_data_field_new(xres, yres, xreal, yreal, FALSE); data = gwy_data_field_get_data(dfield); d16 = (const gint16*)(buffer + DATA_START); for (i = 0; i < xres*yres; i++) data[i] = zscale*GINT16_FROM_LE(d16[i])/65536.0; gwy_file_abandon_contents(buffer, size, NULL); siunit = gwy_si_unit_new("m"); gwy_data_field_set_si_unit_xy(dfield, siunit); g_object_unref(siunit); switch (value_type) { case VALUE_TYPE_NM: siunit = gwy_si_unit_new("m"); gwy_data_field_multiply(dfield, Nanometer); break; case VALUE_TYPE_MV: siunit = gwy_si_unit_new("V"); gwy_data_field_multiply(dfield, Milivolt); break; default: g_warning("Value type %d is unknown", value_type); siunit = gwy_si_unit_new(NULL); break; } gwy_data_field_set_si_unit_z(dfield, siunit); g_object_unref(siunit); container = gwy_container_new(); gwy_container_set_object_by_name(container, "/0/data", dfield); g_object_unref(dfield); title = gwy_enum_to_string(data_type, titles, G_N_ELEMENTS(titles)); if (title) { s = g_strdup_printf("%s (%s)", title, direction ? "Forward" : "Backward"); gwy_container_set_string_by_name(container, "/0/data/title", s); } else g_warning("Data type %d is unknown", data_type); gwy_file_channel_import_log_add(container, 0, NULL, filename); return container; }
static GwyDataField* omicron_read_data(OmicronFile *ofile, OmicronTopoChannel *channel, GError **error) { GError *err = NULL; GwyDataField *dfield; GwySIUnit *siunit; gchar *filename; gdouble *data; guchar *buffer; const gint16 *d; gdouble scale; gsize size; guint i, j, n; gint power10 = 0; filename = omicron_fix_file_name(ofile->filename, channel->filename, error); if (!filename) return NULL; gwy_debug("Succeeded with <%s>", filename); if (!gwy_file_get_contents(filename, &buffer, &size, &err)) { g_free(filename); err_GET_FILE_CONTENTS(error, &err); return NULL; } g_free(filename); n = ofile->xres*ofile->yres; if (err_SIZE_MISMATCH(error, 2*n, size, TRUE)) { gwy_file_abandon_contents(buffer, size, NULL); return NULL; } scale = (channel->max_phys - channel->min_phys) /(channel->max_raw - channel->min_raw); dfield = gwy_data_field_new(ofile->xres, ofile->yres, ofile->xreal, ofile->yreal, FALSE); data = gwy_data_field_get_data(dfield); d = (const gint16*)buffer; for (i = 0; i < ofile->yres; i++) { for (j = 0; j < ofile->xres; j++) data[(ofile->yres-1 - i)*ofile->xres + j] = scale*GINT16_FROM_BE(d[i*ofile->xres + j]); } gwy_file_abandon_contents(buffer, size, NULL); siunit = gwy_si_unit_new("m"); gwy_data_field_set_si_unit_xy(dfield, siunit); g_object_unref(siunit); siunit = gwy_si_unit_new_parse(channel->units, &power10); gwy_data_field_set_si_unit_z(dfield, siunit); g_object_unref(siunit); if (power10) gwy_data_field_multiply(dfield, pow10(power10)); return dfield; }
static GwyDataField* read_binary_data(const gchar *buffer, gsize size, GHashTable *hash, GError **error) { ShimadzuDataType data_type; gint xres, yres, i; guint expected; gdouble xreal, yreal, zscale, xoff, yoff, zoff; GwySIUnit *unitxy, *unitz; GwyDataField *dfield = NULL; gdouble *d; const gchar *s; if (!(s = g_hash_table_lookup(hash, "DataType"))) { err_MISSING_FIELD(error, "DataType"); return NULL; } if (g_ascii_strcasecmp(s, "short") == 0) data_type = SHIMADZU_SHORT; else if (g_ascii_strcasecmp(s, "float") == 0) data_type = SHIMADZU_FLOAT; else { err_UNSUPPORTED(error, "DataType"); return NULL; } unitxy = gwy_si_unit_new(NULL); unitz = gwy_si_unit_new(NULL); if (!get_scales(hash, FALSE, &xres, &yres, &xreal, &yreal, &xoff, &yoff, unitxy, &zscale, &zoff, unitz, error)) goto fail; expected = data_type*xres*yres + HEADER_SIZE; if (err_SIZE_MISMATCH(error, expected, size, FALSE)) goto fail; dfield = gwy_data_field_new(xres, yres, xreal, yreal, FALSE); gwy_data_field_set_xoffset(dfield, xoff); gwy_data_field_set_yoffset(dfield, yoff); gwy_data_field_set_si_unit_xy(dfield, unitxy); gwy_data_field_set_si_unit_z(dfield, unitz); d = gwy_data_field_get_data(dfield); if (data_type == SHIMADZU_SHORT) { const gint16 *d16 = (const gint16*)(buffer + HEADER_SIZE); for (i = 0; i < xres*yres; i++) d[i] = zscale*GUINT16_FROM_LE(d16[i]) + zoff; } else if (data_type == SHIMADZU_FLOAT) { const guchar *p = buffer + HEADER_SIZE; for (i = 0; i < xres*yres; i++) d[i] = zscale*gwy_get_gfloat_le(&p) + zoff; } else { g_assert_not_reached(); } gwy_data_field_invert(dfield, TRUE, FALSE, FALSE); fail: g_object_unref(unitxy); g_object_unref(unitz); return dfield; }
static GwyDataField* read_data_field_old(const guchar *buffer, guint size, GError **error) { gint xres, yres, n, i, j, vx, vy; G_GNUC_UNUSED gint vz; gdouble xscale, yscale, zscale, xreal, yreal, q; G_GNUC_UNUSED gdouble xunit, yunit, zunit; GwyDataField *dfield; GwySIUnit *siunit; gdouble *data, *row; const gint16 *pdata; const guchar *p; p = buffer + RES_OFFSET_OLD; xres = gwy_get_guint16_le(&p); yres = gwy_get_guint16_le(&p); gwy_debug("xres: %d, yres: %d", xres, yres); if (err_DIMENSION(error, xres) || err_DIMENSION(error, yres)) return NULL; n = xres*yres; if (err_SIZE_MISMATCH(error, 2*n + HEADER_SIZE_OLD, size, TRUE)) return NULL; p = buffer + SCALE_OFFSET_OLD; xscale = gwy_get_gdouble_le(&p); yscale = gwy_get_gdouble_le(&p); zscale = gwy_get_gdouble_le(&p); p = buffer + UNIT_OFFSET_OLD; xunit = gwy_get_gdouble_le(&p); yunit = gwy_get_gdouble_le(&p); zunit = gwy_get_gdouble_le(&p); p = buffer + SPEED_OFFSET_OLD; vx = gwy_get_guint32_le(&p); vy = gwy_get_guint32_le(&p); vz = gwy_get_guint32_le(&p); xreal = xscale * vx; yreal = yscale * vy; q = zscale; gwy_debug("xreal: %g, yreal: %g, zscale: %g", xreal, yreal, q); /* 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); data = gwy_data_field_get_data(dfield); pdata = (const gint16*)(buffer + HEADER_SIZE_OLD); for (i = 0; i < yres; i++) { row = data + i*xres; for (j = 0; j < xres; j++) row[j] = GUINT16_FROM_LE(pdata[i*xres + j])*q; } siunit = gwy_si_unit_new("m"); gwy_data_field_set_si_unit_xy(dfield, siunit); g_object_unref(siunit); siunit = gwy_si_unit_new("m"); gwy_data_field_set_si_unit_z(dfield, siunit); g_object_unref(siunit); return dfield; }
static GwyContainer* text_dump_import(gchar *buffer, gsize size, const gchar *filename, GError **error) { gchar *val, *key, *pos, *line, *title; GwyContainer *data; GwyDataField *dfield; gdouble xreal, yreal; gint xres, yres, id; GwySIUnit *uxy, *uz; const guchar *s; gdouble *d; gsize n; data = gwy_container_new(); pos = buffer; while ((line = gwy_str_next_line(&pos)) && *line) { val = strchr(line, '='); if (!val || *line != '/') { g_warning("Garbage key: %s", line); continue; } if ((gsize)(val - buffer) + 1 > size) { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA, _("End of file reached when value was expected.")); goto fail; } *val = '\0'; val++; if (!gwy_strequal(val, "[") || !pos || *pos != '[') { gwy_debug("<%s>=<%s>", line, val); if (*val) gwy_container_set_string_by_name(data, line, g_strdup(val)); else gwy_container_remove_by_name(data, line); continue; } g_assert(pos && *pos == '['); pos++; dfield = NULL; gwy_container_gis_object_by_name(data, line, &dfield); id = 0; sscanf(line, "/%d", &id); /* get datafield parameters from already read values, failing back * to values of original data field */ key = g_strconcat(line, "/xres", NULL); if (gwy_container_gis_string_by_name(data, key, &s)) xres = atoi(s); else if (dfield) xres = gwy_data_field_get_xres(dfield); else { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA, _("Missing data field width.")); goto fail; } g_free(key); key = g_strconcat(line, "/yres", NULL); if (gwy_container_gis_string_by_name(data, key, &s)) yres = atoi(s); else if (dfield) yres = gwy_data_field_get_yres(dfield); else { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA, _("Missing data field height.")); goto fail; } g_free(key); key = g_strconcat(line, "/xreal", NULL); if (gwy_container_gis_string_by_name(data, key, &s)) xreal = g_ascii_strtod(s, NULL); else if (dfield) xreal = gwy_data_field_get_xreal(dfield); else { g_warning("Missing real data field width."); xreal = 1.0; /* 0 could cause troubles */ } g_free(key); key = g_strconcat(line, "/yreal", NULL); if (gwy_container_gis_string_by_name(data, key, &s)) yreal = g_ascii_strtod(s, NULL); else if (dfield) yreal = gwy_data_field_get_yreal(dfield); else { g_warning("Missing real data field height."); yreal = 1.0; /* 0 could cause troubles */ } g_free(key); if (!(xres > 0 && yres > 0 && xreal > 0 && yreal > 0)) { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA, _("Data field dimensions are not positive numbers.")); goto fail; } key = g_strconcat(line, "/unit-xy", NULL); if (gwy_container_gis_string_by_name(data, key, &s)) uxy = gwy_si_unit_new((const gchar*)s); else if (dfield) { uxy = gwy_data_field_get_si_unit_xy(dfield); uxy = gwy_si_unit_duplicate(uxy); } else { g_warning("Missing lateral units."); uxy = gwy_si_unit_new("m"); } g_free(key); key = g_strconcat(line, "/unit-z", NULL); if (gwy_container_gis_string_by_name(data, key, &s)) uz = gwy_si_unit_new((const gchar*)s); else if (dfield) { uz = gwy_data_field_get_si_unit_z(dfield); uz = gwy_si_unit_duplicate(uz); } else { g_warning("Missing value units."); uz = gwy_si_unit_new("m"); } g_free(key); key = g_strconcat(line, "/title", NULL); title = NULL; gwy_container_gis_string_by_name(data, key, (const guchar**)&title); /* We got the contained string but that would disappear. */ title = g_strdup(title); g_free(key); n = xres*yres*sizeof(gdouble); if ((gsize)(pos - buffer) + n + 3 > size) { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA, _("End of file reached inside a data field.")); goto fail; } dfield = GWY_DATA_FIELD(gwy_data_field_new(xres, yres, xreal, yreal, FALSE)); gwy_data_field_set_si_unit_xy(dfield, GWY_SI_UNIT(uxy)); gwy_object_unref(uxy); gwy_data_field_set_si_unit_z(dfield, GWY_SI_UNIT(uz)); gwy_object_unref(uz); d = gwy_data_field_get_data(dfield); #if (G_BYTE_ORDER == G_LITTLE_ENDIAN) memcpy(d, pos, n); #else gwy_memcpy_byte_swap(pos, (guint8*)d, sizeof(gdouble), xres*yres, sizeof(gdouble)-1); #endif pos += n; val = gwy_str_next_line(&pos); if (!gwy_strequal(val, "]]")) { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA, _("Missing end of data field marker.")); gwy_object_unref(dfield); goto fail; } gwy_container_remove_by_prefix(data, line); gwy_container_set_object_by_name(data, line, dfield); g_object_unref(dfield); if (title) { key = g_strconcat(line, "/title", NULL); gwy_container_set_string_by_name(data, key, title); g_free(key); } gwy_file_channel_import_log_add(data, id, NULL, filename); } return data; fail: gwy_container_remove_by_prefix(data, NULL); g_object_unref(data); return NULL; }
static gboolean read_aist_raster(const guchar **p, gsize *size, AistContext *context) { AistRaster raster; GwyDataField *dfield, *mfield; GwySIUnit *xyunit, *zunit; gboolean ok = FALSE; guint i, j, n, len; const guchar *data; gchar *s; gchar key[32]; gdouble *d; gdouble qxy, qz; gwy_clear(&raster, 1); gwy_debug("reading common"); if (!read_aist_common(p, size, &raster.common)) goto fail; gwy_debug("reading raster"); if (!read_qt_int(p, size, &raster.xres) || !read_qt_int(p, size, &raster.yres) || !read_qt_double(p, size, &raster.left) || !read_qt_double(p, size, &raster.right) || !read_qt_double(p, size, &raster.top) || !read_qt_double(p, size, &raster.bottom) || !read_qt_string(p, size, &raster.xunits) || !read_qt_string(p, size, &raster.yunits) || !read_qt_string(p, size, &raster.zunits)) goto fail; if (!read_qt_byte_array(p, size, &len, &data)) goto fail; n = raster.xres * raster.yres; if (len != n*sizeof(gdouble)) goto fail; xyunit = extract_units(raster.xunits, &qxy); zunit = extract_units(raster.zunits, &qz); dfield = gwy_data_field_new(raster.xres, raster.yres, qxy*fabs(raster.right - raster.left), qxy*fabs(raster.bottom - raster.top), FALSE); gwy_data_field_set_si_unit_xy(dfield, xyunit); gwy_data_field_set_si_unit_z(dfield, zunit); /* Apparently this is not generally wanted. gwy_data_field_set_xoffset(dfield, qxy*MIN(raster.left, raster.right)); gwy_data_field_set_yoffset(dfield, qxy*MIN(raster.top, raster.bottom)); */ g_object_unref(xyunit); g_object_unref(zunit); d = gwy_data_field_get_data(dfield); for (i = 0; i < raster.yres; i++) { for (j = 0; j < raster.xres; j++) { d[(raster.yres-1 - i)*raster.xres + j] = qz*gwy_get_gdouble_le(&data); } } g_snprintf(key, sizeof(key), "/%d/data", context->channel_id); gwy_container_set_object_by_name(context->container, key, dfield); g_object_unref(dfield); gwy_file_channel_import_log_add(context->container, context->channel_id, NULL, context->filename); if ((s = strchr(raster.common.name, '['))) s = g_strchomp(g_strndup(raster.common.name, s - raster.common.name)); else s = g_strdup(raster.common.name); g_snprintf(key, sizeof(key), "/%d/data/title", context->channel_id); gwy_container_set_string_by_name(context->container, key, s); g_snprintf(key, sizeof(key), "/%d/mask", context->channel_id); context->channel_id++; /* At this moment we consider the loading successful. */ ok = TRUE; /* The mask raster is byte-valued. It contains nonzeroes in points that * were measured (the opposite of how we normally create masks upon * import). */ if (read_qt_byte_array(p, size, &len, &data)) { if (len == raster.xres*raster.yres) { mfield = make_mask_field(dfield, data); if (mfield) { gwy_app_channel_remove_bad_data(dfield, mfield); gwy_container_set_object_by_name(context->container, key, mfield); g_object_unref(mfield); } } /* Here's something called view data. It means the data was processed * (by whatever means) hence we are not interesed in it. */ read_qt_byte_array(p, size, &len, &data); } fail: free_aist_common(&raster.common); g_free(raster.xunits); g_free(raster.yunits); g_free(raster.zunits); return ok; }
static GwyContainer* burleigh_load(const gchar *filename) { GwySIUnit *unit; GwyContainer *container = NULL; guchar *buffer = NULL; const guchar *p; gsize size = 0; GError *err = NULL; IMGFile imgfile; GwyDataField *dfield; gdouble *data; const gint16 *d; gdouble scale; guint i; if (!gwy_file_get_contents(filename, &buffer, &size, &err)) { g_warning("Cannot get file contents"); g_clear_error(&err); return NULL; } if (size < HEADER_SIZE_MIN + 2) { g_warning("File is too short"); gwy_file_abandon_contents(buffer, size, NULL); return NULL; } memset(&imgfile, 0, sizeof(imgfile)); p = buffer; imgfile.version = get_FLOAT(&p); imgfile.version_int = ROUND(10*imgfile.version); if (imgfile.version_int == 21) { d = burleigh_load_v21(&imgfile, buffer, size); if (!d) { gwy_file_abandon_contents(buffer, size, NULL); return NULL; } } else { g_warning("File format version %.f is not supported", imgfile.version); gwy_file_abandon_contents(buffer, size, NULL); return NULL; } dfield = GWY_DATA_FIELD(gwy_data_field_new(imgfile.xres, imgfile.yres, Angstrom*imgfile.xrange, Angstrom*imgfile.yrange, FALSE)); data = gwy_data_field_get_data(dfield); scale = Angstrom * imgfile.z_gain * imgfile.zrange; for (i = 0; i < imgfile.xres*imgfile.yres; i++) data[i] = scale * GINT16_FROM_LE(d[i]); gwy_file_abandon_contents(buffer, size, NULL); unit = GWY_SI_UNIT(gwy_si_unit_new("m")); gwy_data_field_set_si_unit_xy(dfield, unit); g_object_unref(unit); container = GWY_CONTAINER(gwy_container_new()); switch (imgfile.data_type) { case BURLEIGH_CURRENT: unit = GWY_SI_UNIT(gwy_si_unit_new("A")); gwy_container_set_string_by_name(container, "/filename/title", g_strdup("Current")); break; case BURLEIGH_TOPOGRAPHY: unit = GWY_SI_UNIT(gwy_si_unit_new("m")); gwy_container_set_string_by_name(container, "/filename/title", g_strdup("Topography")); break; default: unit = GWY_SI_UNIT(gwy_si_unit_new("m")); break; } gwy_data_field_set_si_unit_z(dfield, unit); g_object_unref(unit); gwy_container_set_object_by_name(container, "/0/data", (GObject*)dfield); g_object_unref(dfield); return container; }
/* FIXME: this function could use some sort of failure indication, if the * file is damaged and no data field can be loaded, suspicionless caller can * return empty Container */ static void tiff_load_channel(TIFF *tiff, GwyContainer *container, GwyContainer *meta, gint idx, gint ilen, gint jlen, gdouble ulen, gdouble vlen) { GwyDataField *dfield; GwySIUnit *siunit; GString *key; gdouble *data; guchar *buffer; gchar *channel; const gchar *name = NULL; const gchar *slot = NULL; const gchar *unit = NULL; gboolean retrace = FALSE; gboolean reflect = FALSE; gdouble mult = 0.0; gdouble offset = 0.0; gint num_slots = 0; gint i, j; tiff_get_custom_string(tiff, JPK_TIFFTAG_ChannelFancyName, &name); if (!name) tiff_get_custom_string(tiff, JPK_TIFFTAG_Channel, &name); g_return_if_fail(name != NULL); tiff_get_custom_boolean(tiff, JPK_TIFFTAG_Channel_retrace, &retrace); channel = g_strdup_printf("%s%s", name, retrace ? " (retrace)" : ""); gwy_debug("channel: %s", channel); tiff_get_custom_integer(tiff, JPK_TIFFTAG_NrOfSlots, &num_slots); g_return_if_fail(num_slots > 0); gwy_debug("num_slots: %d", num_slots); /* Locate the default slot */ tiff_get_custom_string(tiff, JPK_TIFFTAG_DefaultSlot, &slot); g_return_if_fail(slot != NULL); gwy_debug("num_slots: %d, default slot: %s", num_slots, slot); for (i = 0; i < num_slots; i++) { const gchar *string; if (tiff_get_custom_string(tiff, JPK_TIFFTAG_Slot_Name(i), &string) && string && gwy_strequal(string, slot)) { tiff_get_custom_string(tiff, JPK_TIFFTAG_Scaling_Type(i), &string); g_return_if_fail(gwy_strequal(string, "LinearScaling")); tiff_get_custom_double(tiff, JPK_TIFFTAG_Scaling_Multiply(i), &mult); tiff_get_custom_double(tiff, JPK_TIFFTAG_Scaling_Offset(i), &offset); gwy_debug("multipler: %g offset: %g", mult, offset); tiff_get_custom_string(tiff, JPK_TIFFTAG_Encoder_Unit(i), &unit); break; } } /* Create a new data field */ dfield = gwy_data_field_new(ilen, jlen, ulen, vlen, FALSE); siunit = gwy_si_unit_new("m"); gwy_data_field_set_si_unit_xy(dfield, siunit); g_object_unref(siunit); if (unit) { siunit = gwy_si_unit_new(unit); gwy_data_field_set_si_unit_z(dfield, siunit); g_object_unref(siunit); } /* Read the scan data */ data = gwy_data_field_get_data(dfield); buffer = g_new(guchar, TIFFScanlineSize(tiff)); tiff_get_custom_boolean(tiff, JPK_TIFFTAG_Grid_Reflect, &reflect); if (!reflect) data += (jlen - 1) * ilen; for (j = 0; j < jlen; j++) { const guint16 *src = (const guint16 *)buffer; gdouble *dest = data; TIFFReadScanline(tiff, buffer, j, 0); for (i = 0; i < ilen; i++) { guint16 s = *src++; *dest++ = offset + mult * (gdouble)s; } if (reflect) data += ilen; else data -= ilen; } /* Add the GwyDataField to the container */ key = g_string_new(""); g_string_printf(key, "/%d/data", idx); gwy_container_set_object_by_name(container, key->str, dfield); g_object_unref(dfield); g_string_append(key, "/title"); gwy_container_set_string_by_name(container, key->str, channel); if (gwy_container_get_n_items(meta)) { GwyContainer *tmp; tmp = gwy_container_duplicate(meta); g_string_printf(key, "/%d/meta", idx); gwy_container_set_object_by_name(container, key->str, tmp); g_object_unref(tmp); } g_string_free(key, TRUE); }
static GwyContainer* burleigh_load(const gchar *filename, G_GNUC_UNUSED GwyRunType mode, GError **error) { GwySIUnit *unit; GwyContainer *container = NULL; guchar *buffer = NULL; const guchar *p; gsize size = 0; GError *err = NULL; IMGFile imgfile; GwyDataField *dfield; gdouble *data; const gint16 *d; gdouble zoom; guint i; if (!gwy_file_get_contents(filename, &buffer, &size, &err)) { err_GET_FILE_CONTENTS(error, &err); return NULL; } if (size < HEADER_SIZE_MIN + 2) { err_TOO_SHORT(error); gwy_file_abandon_contents(buffer, size, NULL); return NULL; } gwy_clear(&imgfile, 1); p = buffer; imgfile.version = gwy_get_gfloat_le(&p); imgfile.version_int = GWY_ROUND(10*imgfile.version); if (imgfile.version_int == 21) { d = burleigh_load_v21(&imgfile, buffer, size, error); if (!d) { gwy_file_abandon_contents(buffer, size, NULL); return NULL; } } else { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA, _("File format version %.1f is not supported."), imgfile.version); gwy_file_abandon_contents(buffer, size, NULL); return NULL; } zoom = burleigh_get_zoom_v21(&imgfile); if (err_DIMENSION(error, imgfile.xres) || err_DIMENSION(error, imgfile.yres)) { gwy_file_abandon_contents(buffer, size, NULL); return NULL; } dfield = gwy_data_field_new(imgfile.xres, imgfile.yres, Angstrom*imgfile.xrange/zoom, Angstrom*imgfile.yrange/zoom, FALSE); data = gwy_data_field_get_data(dfield); for (i = 0; i < imgfile.xres*imgfile.yres; i++) data[i] = GINT16_FROM_LE(d[i])*imgfile.zrange/4095.0; gwy_file_abandon_contents(buffer, size, NULL); unit = gwy_si_unit_new("m"); gwy_data_field_set_si_unit_xy(dfield, unit); g_object_unref(unit); container = gwy_container_new(); switch (imgfile.data_type) { case BURLEIGH_CURRENT: unit = gwy_si_unit_new("A"); gwy_container_set_string_by_name(container, "/0/data/title", g_strdup("Current")); gwy_data_field_multiply(dfield, Picoampere); break; case BURLEIGH_TOPOGRAPHY: unit = gwy_si_unit_new("m"); gwy_container_set_string_by_name(container, "/0/data/title", g_strdup("Topography")); gwy_data_field_multiply(dfield, Angstrom); break; default: unit = gwy_si_unit_new("m"); break; } gwy_data_field_set_si_unit_z(dfield, unit); g_object_unref(unit); gwy_container_set_object_by_name(container, "/0/data", dfield); g_object_unref(dfield); gwy_file_channel_import_log_add(container, 0, NULL, filename); return container; }
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 void gwy_data_field_facet_distribution(GwyDataField *dfield, gint kernel_size, GwyContainer *container) { GwyDataField *dtheta, *dphi, *dist; GwySIUnit *siunit; gdouble *xd, *yd, *data; const gdouble *xdc, *ydc; gdouble q, max; gint res, hres, i, j, mi, mj, xres, yres; if (gwy_container_gis_object_by_name(container, "/theta", &dtheta)) g_object_ref(dtheta); else dtheta = gwy_data_field_new_alike(dfield, FALSE); if (gwy_container_gis_object_by_name(container, "/phi", &dphi)) g_object_ref(dphi); else dphi = gwy_data_field_new_alike(dfield, FALSE); compute_slopes(dfield, kernel_size, dtheta, dphi); xres = gwy_data_field_get_xres(dfield); yres = gwy_data_field_get_yres(dfield); xd = gwy_data_field_get_data(dtheta); yd = gwy_data_field_get_data(dphi); for (i = xres*yres; i; i--, xd++, yd++) { gdouble theta, phi; slopes_to_angles(*xd, *yd, &theta, &phi); *xd = theta; *yd = phi; } q = gwy_data_field_get_max(dtheta); q = MIN(q*1.05, G_PI/2.0); q = G_SQRT2/(2.0*sin(q/2.0)); if (gwy_container_gis_object_by_name(container, "/0/data", &dist)) { g_object_ref(dist); gwy_data_field_clear(dist); gwy_data_field_set_xreal(dist, 2.0*G_SQRT2/q); gwy_data_field_set_yreal(dist, 2.0*G_SQRT2/q); } else { dist = gwy_data_field_new(FDATA_RES, FDATA_RES, 2.0*G_SQRT2/q, 2.0*G_SQRT2/q, TRUE); siunit = gwy_si_unit_new(""); gwy_data_field_set_si_unit_z(dist, siunit); g_object_unref(siunit); /* FIXME */ siunit = gwy_si_unit_new(""); gwy_data_field_set_si_unit_xy(dist, siunit); g_object_unref(siunit); } res = FDATA_RES; hres = (res - 1)/2; data = gwy_data_field_get_data(dist); xdc = gwy_data_field_get_data_const(dtheta); ydc = gwy_data_field_get_data_const(dphi); for (i = xres*yres; i; i--, xdc++, ydc++) { gdouble x, y; gint xx, yy; angles_to_xy(*xdc, *ydc, &x, &y); xx = GWY_ROUND(q*x/G_SQRT2*hres) + hres; yy = GWY_ROUND(q*y/G_SQRT2*hres) + hres; data[yy*res + xx] += 1.0; } /* Find maxima */ mi = mj = hres; max = 0; for (i = 1; i+1 < res; i++) { for (j = 1; j+1 < res; j++) { gdouble z; z = data[i*res + j] + 0.3*(data[i*res + j - 1] + data[i*res + j + 1] + data[i*res - res + j] + data[i*res + res + j]) + 0.1*(data[i*res - res + j - 1] + data[i*res - res + j + 1] + data[i*res + res + j - 1] + data[i*res + res + j + 1]); if (G_UNLIKELY(z > max)) { max = z; mi = i; mj = j; } } } for (i = res*res; i; i--, data++) *data = pow(*data, 0.35); gwy_container_set_double_by_name(container, "/q", q); { gdouble x, y, theta, phi; x = (mj - hres)*G_SQRT2/(q*hres); y = (mi - hres)*G_SQRT2/(q*hres); xy_to_angles(x, y, &theta, &phi); gwy_container_set_double_by_name(container, "/theta0", theta); gwy_container_set_double_by_name(container, "/phi0", phi); } gwy_container_set_object_by_name(container, "/0/data", dist); g_object_unref(dist); gwy_container_set_object_by_name(container, "/theta", dtheta); g_object_unref(dtheta); gwy_container_set_object_by_name(container, "/phi", dphi); g_object_unref(dphi); gwy_container_set_string_by_name(container, "/0/base/palette", g_strdup(FVIEW_GRADIENT)); gwy_data_field_data_changed(dist); }
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; }