Пример #1
0
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;
}
Пример #2
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;
}