Exemplo n.º 1
0
static GwyContainer*
get_meta(const X3PFile *x3pfile)
{
    GwyContainer *meta = gwy_container_new();

    g_hash_table_foreach(x3pfile->hash, add_meta_record, meta);
    if (gwy_container_get_n_items(meta))
        return meta;

    g_object_unref(meta);
    return NULL;
}
Exemplo n.º 2
0
static GwyContainer*
omicron_make_meta(OmicronFile *ofile)
{
    GwyContainer *meta = gwy_container_new();

    g_hash_table_foreach(ofile->meta, add_meta, meta);
    if (gwy_container_get_n_items(meta))
        return meta;
    g_object_unref(meta);

    return NULL;
}
Exemplo n.º 3
0
static void
clone_meta(GwyContainer *container, GwyContainer *meta, guint nchannels)
{
    guint i;
    gchar s[32];

    if (!gwy_container_get_n_items(meta))
        return;

    /* Simply store identical metadata for each channel */
    for (i = 0; i < nchannels; i++) {
        GwyContainer *m = gwy_container_duplicate(meta);
        g_snprintf(s, sizeof(s), "/%u/meta", i);
        gwy_container_set_object_by_name(container, s, m);
        g_object_unref(m);
    }
}
Exemplo n.º 4
0
/**
 * gwyfile_pack_metadata:
 * @data: A data container.
 *
 * Pack scattered metadata under "/meta" to a container at "/0/meta" and
 * metadata scattered under "/0/data/meta" to a container at "/0/meta".
 **/
static void
gwyfile_pack_metadata(GwyContainer *data)
{
    GwyContainer *meta;

    meta = gwy_container_new();

    /* Mindlessly run one packing after another.  Losing some metadata is not
     * a tragedy and the file has to be borken in the first place to have
     * metadata conflicts. */
    gwy_container_foreach(data, "/meta", &gwyfile_gather_meta, meta);
    gwy_container_foreach(data, "/0/data/meta", &gwyfile_gather_0_data_meta,
                          meta);
    if (gwy_container_get_n_items(meta)) {
        gwy_container_remove_by_prefix(data, "/meta");
        gwy_container_remove_by_prefix(data, "/0/data/meta");
        gwy_container_set_object_by_name(data, "/0/meta", meta);
    }

    g_object_unref(meta);
}
Exemplo n.º 5
0
static GwyContainer*
ezdfile_get_metadata(GPtrArray *ezdfile,
                     G_GNUC_UNUSED gint idx)
{
    EZDSection *section;
    GwyContainer *meta;
    guint i;

    meta = gwy_container_new();

    for (i = 0; i < ezdfile->len; i++) {
        section = (EZDSection*)g_ptr_array_index(ezdfile, i);
        if (gwy_strequal(section->name, "DataSet-Info"))
            g_hash_table_foreach(section->meta, store_meta, meta);
    }

    if (!gwy_container_get_n_items(meta)) {
        g_object_unref(meta);
        meta = NULL;
    }

    return meta;
}
Exemplo n.º 6
0
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;
}
Exemplo n.º 7
0
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;
}
Exemplo n.º 8
0
/* 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);
}
Exemplo n.º 9
0
static GwyContainer*
gsf_load(const gchar *filename,
         G_GNUC_UNUSED GwyRunType mode,
         GError **error)
{
    GwyContainer *container = NULL, *meta = NULL;
    GwyDataField *dfield = NULL;
    GwyTextHeaderParser parser;
    GwySIUnit *unit;
    guchar *p, *value, *buffer = NULL, *header = NULL;
    const guchar *datap;
    GHashTable *hash = NULL;
    gsize size, expected_size;
    GError *err = NULL;
    gdouble xreal, yreal, xoff, yoff;
    guint i, xres, yres;
    gdouble *d;

    if (!gwy_file_get_contents(filename, &buffer, &size, &err)) {
        err_GET_FILE_CONTENTS(error, &err);
        return NULL;
    }

    if (size < MAGIC_SIZE || memcmp(buffer, MAGIC, MAGIC_SIZE) != 0) {
        err_FILE_TYPE(error, "Gwyddion Simple Field");
        goto fail;
    }

    p = buffer + MAGIC_SIZE;
    datap = memchr(p, '\0', size - (p - buffer));
    if (!datap) {
        g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA,
                    _("File header is truncated."));
        goto fail;
    }
    header = g_strdup(p);
    datap += 4 - ((datap - buffer) % 4);

    gwy_clear(&parser, 1);
    parser.key_value_separator = "=";
    if (!(hash = gwy_text_header_parse(header, &parser, NULL, NULL))) {
        g_propagate_error(error, err);
        goto fail;
    }

    xres = read_pixel_size(hash, "XRes", error);
    yres = read_pixel_size(hash, "YRes", error);
    if (!xres || !yres)
        goto fail;

    expected_size = (datap - buffer) + sizeof(gfloat)*xres*yres;
    if (err_SIZE_MISMATCH(error, expected_size, size, TRUE))
        goto fail;

    xreal = read_real_size(hash, "XReal");
    yreal = read_real_size(hash, "YReal");
    dfield = gwy_data_field_new(xres, yres, xreal, yreal, FALSE);

    xoff = read_real_offset(hash, "XOffset");
    yoff = read_real_offset(hash, "YOffset");
    gwy_data_field_set_xoffset(dfield, xoff);
    gwy_data_field_set_yoffset(dfield, yoff);

    value = g_hash_table_lookup(hash, "XYUnits");
    unit = gwy_si_unit_new(value);
    gwy_data_field_set_si_unit_xy(dfield, unit);
    g_object_unref(unit);

    value = g_hash_table_lookup(hash, "ZUnits");
    unit = gwy_si_unit_new(value);
    gwy_data_field_set_si_unit_z(dfield, unit);
    g_object_unref(unit);

    d = gwy_data_field_get_data(dfield);
    for (i = xres*yres; i; i--)
        *(d++) = gwy_get_gfloat_le(&datap);

    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, "Title"))) {
        /* FIXME: Ensure valid UTF-8 */
        gwy_container_set_string_by_name(container, "/0/data/title",
                                         g_strdup(value));
    }
    else
        gwy_app_channel_title_fall_back(container, 0);

    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);

    gwy_file_channel_import_log_add(container, 0, NULL, filename);

fail:
    gwy_file_abandon_contents(buffer, size, NULL);
    if (header)
        g_free(header);
    if (hash)
        g_hash_table_destroy(hash);

    return container;
}