Пример #1
0
static gboolean
read_dimensions(GHashTable *hash,
                gint *ndata,
                Dimensions *dimensions,
                GError **error)
{
    const gchar *value;

    /* Number of fields */
    if (!(value = g_hash_table_lookup(hash, "Channels"))) {
        err_MISSING_FIELD(error, "Channels");
        return FALSE;
    }
    *ndata = atoi(value);
    if (*ndata <= 0 || *ndata > 1024) {
        err_INVALID(error, "Channels");
        return FALSE;
    }

    /* Pixel sizes */
    if (!(value = g_hash_table_lookup(hash, "Lines"))) {
        err_MISSING_FIELD(error, "Lines");
        return FALSE;
    }
    dimensions->yres = atoi(value);
    if (err_DIMENSION(error, dimensions->yres))
        return FALSE;

    if (!(value = g_hash_table_lookup(hash, "Rows"))) {
        err_MISSING_FIELD(error, "Rows");
        return FALSE;
    }
    /* XXX: When the file says Rows, it actually means Columns-1.  Bite me. */
    dimensions->xres = atoi(value) + 1;
    if (err_DIMENSION(error, dimensions->xres))
        return FALSE;

    /* Real sizes */
    if (!(value = g_hash_table_lookup(hash, "X-Length"))) {
        err_MISSING_FIELD(error, "X-Length");
        return FALSE;
    }
    dimensions->xreal = Micrometer * g_ascii_strtod(value, NULL);
    if (!((dimensions->xreal = fabs(dimensions->xreal)) > 0)) {
        g_warning("Real x size is 0.0, fixing to 1.0");
        dimensions->xreal = 1.0;
    }

    if (!(value = g_hash_table_lookup(hash, "Y-Length"))) {
        err_MISSING_FIELD(error, "Y-Length");
        return FALSE;
    }
    dimensions->yreal = Micrometer * g_ascii_strtod(value, NULL);
    if (!((dimensions->yreal = fabs(dimensions->yreal)) > 0)) {
        g_warning("Real y size is 0.0, fixing to 1.0");
        dimensions->yreal = 1.0;
    }

    return TRUE;
}
Пример #2
0
static gboolean
check_params(const SDFile *sdfile,
             guint len,
             GError **error)
{
    if (sdfile->data_type >= SDF_NTYPES) {
        err_DATA_TYPE(error, sdfile->data_type);
        return FALSE;
    }
    if (err_DIMENSION(error, sdfile->xres)
        || err_DIMENSION(error, sdfile->yres))
        return FALSE;
    if (err_SIZE_MISMATCH(error, sdfile->expected_size, len, FALSE))
        return FALSE;
    if (sdfile->compression) {
        err_UNSUPPORTED(error, "Compression");
        return FALSE;
    }
    if (sdfile->check_type) {
        err_UNSUPPORTED(error, "CheckType");
        return FALSE;
    }

    return TRUE;
}
Пример #3
0
static GwyDataField*
mif_read_data_field(const MIFImageHeader *image_header,
                    const MIFBlock *block,
                    const guchar *buffer,
                    gsize size,
                    GError **error)
{
    gint xres = image_header->setup.xres;
    gint yres = image_header->setup.yres;
    gdouble xreal = image_header->setup.xreal;
    gdouble yreal = image_header->setup.yreal;
    gdouble xoff = image_header->setup.xoff;
    gdouble yoff = image_header->setup.yoff;
    gdouble q = image_header->configuration.scan_int_to_meter;
    GwyDataField *dfield;
    gdouble *data;
    const gint16 *d16;
    gint i, j;

    if (err_DIMENSION(error, xres) || err_DIMENSION(error, yres))
        return NULL;

    if (!block->size || block->offset > size || block->size > size
        || block->offset + block->size > size) {
        g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA,
                    _("Image data are outside the file."));
        return NULL;
    }

    if (err_SIZE_MISMATCH(error, xres*yres*sizeof(gint16), block->size, FALSE))
        return NULL;

    dfield = gwy_data_field_new(xres, yres, xreal, yreal, FALSE);
    gwy_data_field_set_xoffset(dfield, xoff);
    gwy_data_field_set_yoffset(dfield, yoff);
    data = gwy_data_field_get_data(dfield);
    d16 = (const gint16*)(buffer + block->offset);

    gwy_si_unit_set_from_string(gwy_data_field_get_si_unit_xy(dfield), "m");
    gwy_si_unit_set_from_string(gwy_data_field_get_si_unit_z(dfield), "m");

    // FIXME: Don't know why this factor.  It seems to match what MIF spmview
    // profile reader shows though.
    q *= 1.0e4;
    for (i = 0; i < yres; i++) {
        for (j = 0; j < yres; j++) {
            data[(yres-1 - i)*xres + j] = q*GINT16_FROM_LE(d16[i*xres + j]);
        }
    }

    return dfield;
}
Пример #4
0
static gboolean
parse_dim(gchar **p,
          const gchar *name,
          gint *value,
          GError **error)
{
    gchar *vp, *line;

    line = gwy_str_next_line(p);
    if (!line) {
        err_MISSING_FIELD(error, name);
        return FALSE;
    }

    vp = strchr(line, ':');
    if (!vp) {
        g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA,
                    _("Missing colon in header line."));
        return FALSE;
    }
    *vp = '\0';
    vp++;

    gwy_debug("<%s> = <%s>", name, vp);
    if (!gwy_strequal(line, name)) {
        err_MISSING_FIELD(error, name);
        return FALSE;
    }

    *value = strtol(vp, NULL, 10);
    if (err_DIMENSION(error, *value))
        return FALSE;

    return TRUE;
}
Пример #5
0
static guint
read_pixel_size(GHashTable *hash,
                const gchar *key,
                GError **error)
{
    gchar *value;
    guint size;

    if (!(value = g_hash_table_lookup(hash, key))) {
        err_MISSING_FIELD(error, key);
        return 0;
    }
    size = atoi(g_hash_table_lookup(hash, key));
    if (err_DIMENSION(error, size))
       return 0;

    return size;
}
Пример #6
0
/* This is the main verification function that checks we have everything we
 * need and the data are of a supported type. */
static gboolean
data_start(X3PFile *x3pfile, GError **error)
{
    static const GwyEnum features[] = {
        { "SUR", X3P_FEATURE_SUR, },
        { "PRF", X3P_FEATURE_PRF, },
        { "PCL", X3P_FEATURE_PCL, },
    };

    gchar *s;

    if (x3pfile->values) {
        g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA,
                    _("File main.xml contains multiple data elements."));
        return FALSE;
    }

    /* First check axes to get meaningful error messages if their types are
     * not as expected. */
    if (!require_keys(x3pfile->hash, error,
                      "/ISO5436_2/Record1/FeatureType",
                      AXES_PREFIX "/CX/AxisType",
                      AXES_PREFIX "/CY/AxisType",
                      AXES_PREFIX "/CZ/AxisType",
                      NULL))
        return FALSE;

    s = (gchar*)g_hash_table_lookup(x3pfile->hash,
                                    "/ISO5436_2/Record1/FeatureType");
    if ((x3pfile->feature_type
         = gwy_string_to_enum(s, features, G_N_ELEMENTS(features))) == -1) {
        err_UNSUPPORTED(error, "/ISO5436_2/Record1/FeatureType");
        return FALSE;
    }

    if (x3pfile->feature_type != X3P_FEATURE_SUR
        && x3pfile->feature_type != X3P_FEATURE_PRF) {
        err_UNSUPPORTED(error, "/ISO5436_2/Record1/FeatureType");
        return FALSE;
    }

    s = (gchar*)g_hash_table_lookup(x3pfile->hash, AXES_PREFIX "/CX/AxisType");
    if (!gwy_strequal(s, "I")) {
        g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA,
                    /* TRANSLATORS: type and axis are symbols such as I, CX, ...*/
                    _("Only type %s is supported for axis %s."),
                    "I", "CX");
        return FALSE;
    }

    s = (gchar*)g_hash_table_lookup(x3pfile->hash, AXES_PREFIX "/CY/AxisType");
    if (x3pfile->feature_type != X3P_FEATURE_PRF && !gwy_strequal(s, "I")) {
        g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA,
                    _("Only type %s is supported for axis %s."),
                    "I", "CY");
        return FALSE;
    }

    s = (gchar*)g_hash_table_lookup(x3pfile->hash, AXES_PREFIX "/CZ/AxisType");
    if (!gwy_strequal(s, "A")) {
        g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA,
                    _("Only type %s is supported for axis %s."),
                    "A", "CZ");
        return FALSE;
    }

    /* Then check sizes, offsets and steps when we know the grid is regular. */
    if (!require_keys(x3pfile->hash, error,
                      AXES_PREFIX "/CX/Increment",
                      AXES_PREFIX "/CY/Increment",
                      AXES_PREFIX "/CX/Offset",
                      AXES_PREFIX "/CY/Offset",
                      MAT_DIM_PREFIX "/SizeX",
                      MAT_DIM_PREFIX "/SizeY",
                      MAT_DIM_PREFIX "/SizeZ",
                      NULL))
        return FALSE;

    s = (gchar*)g_hash_table_lookup(x3pfile->hash, MAT_DIM_PREFIX "/SizeX");
    x3pfile->xres = atoi(s);

    s = (gchar*)g_hash_table_lookup(x3pfile->hash, MAT_DIM_PREFIX "/SizeY");
    x3pfile->yres = atoi(s);

    s = (gchar*)g_hash_table_lookup(x3pfile->hash, MAT_DIM_PREFIX "/SizeZ");
    x3pfile->zres = atoi(s);

    gwy_debug("xres=%u, yres=%u, zres=%u",
              x3pfile->xres, x3pfile->yres, x3pfile->zres);

    if (err_DIMENSION(error, x3pfile->xres)
        || err_DIMENSION(error, x3pfile->yres)
        || err_DIMENSION(error, x3pfile->zres))
        return FALSE;

    /* PRF feature types are sets of profiles N×1×M. */
    if (x3pfile->feature_type == X3P_FEATURE_PRF && x3pfile->yres != 1) {
        err_UNSUPPORTED(error, MAT_DIM_PREFIX "/SizeY");
        return FALSE;
    }

    s = (gchar*)g_hash_table_lookup(x3pfile->hash, AXES_PREFIX "/CX/Increment");
    x3pfile->dx = g_ascii_strtod(s, NULL);
    if (!((x3pfile->dx = fabs(x3pfile->dx)) > 0)) {
        g_warning("Real x step is 0.0, fixing to 1.0");
        x3pfile->dx = 1.0;
    }

    s = (gchar*)g_hash_table_lookup(x3pfile->hash, AXES_PREFIX "/CY/Increment");
    x3pfile->dy = g_ascii_strtod(s, NULL);
    if (!((x3pfile->dy = fabs(x3pfile->dy)) > 0)) {
        g_warning("Real x step is 0.0, fixing to 1.0");
        x3pfile->dy = 1.0;
    }

    s = (gchar*)g_hash_table_lookup(x3pfile->hash, AXES_PREFIX "/CX/Offset");
    x3pfile->xoff = g_ascii_strtod(s, NULL);

    s = (gchar*)g_hash_table_lookup(x3pfile->hash, AXES_PREFIX "/CY/Offset");
    x3pfile->yoff = g_ascii_strtod(s, NULL);

    /* Defaults that are good for floating point data conversion.  If a file
     * with floating point data specifies Increment and Offset, we apply them
     * without hesitation.  The behaviour is probably undefined.  */
    x3pfile->dz = 1.0;
    x3pfile->zoff = 0.0;

    s = (gchar*)g_hash_table_lookup(x3pfile->hash, AXES_PREFIX "/CZ/Increment");
    if (s)
        x3pfile->dz = g_ascii_strtod(s, NULL);

    s = (gchar*)g_hash_table_lookup(x3pfile->hash, AXES_PREFIX "/CZ/Offset");
    if (s)
        x3pfile->zoff = g_ascii_strtod(s, NULL);

    gwy_debug("dz=%g, zoff=%g", x3pfile->dz, x3pfile->zoff);

    x3pfile->ndata = x3pfile->xres*x3pfile->yres*x3pfile->zres;
    x3pfile->values = g_new(gdouble, x3pfile->ndata);
    x3pfile->valid = g_new(gboolean, x3pfile->ndata);
    x3pfile->datapos = 0;

    return TRUE;
}
Пример #7
0
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;
}
Пример #8
0
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;
}
Пример #9
0
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;
}
Пример #10
0
static GwyContainer*
hitachi_load(const gchar *filename,
             G_GNUC_UNUSED GwyRunType mode,
             GError **error)
{
    GwyContainer *container = NULL, *meta;
    GdkPixbuf *pixbuf = NULL;
    GwyDataField *dfield = NULL;
    gchar *value, *imagename = NULL, *header = NULL;
    guchar *pixels;
    GHashTable *hash = NULL;
    GError *err = NULL;
    gdouble dx;
    gint pxres, pyres, hxres, hyres, rowstride, nchannels, i, j;
    gdouble *data;

    if (!(hash = hitachi_load_header(filename, &header, error)))
        return NULL;

    if (!require_keys(hash, error,
                      "ImageName", "DataSize", "PixelSize",
                      NULL))
        goto fail;
    value = g_hash_table_lookup(hash, "ImageName");

    if (!(imagename = hitachi_find_data_name(filename, value))) {
        g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA,
                    _("No corresponding data file was found for header file."));
        goto fail;
    }

    if (!(pixbuf = gdk_pixbuf_new_from_file(imagename, &err))) {
        g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_IO,
                    _("Cannot load image: %s"), err->message);
        g_clear_error(&err);
        goto fail;
    }

    /* We know the image dimensions so check them. */
    pxres = gdk_pixbuf_get_width(pixbuf);
    pyres = gdk_pixbuf_get_height(pixbuf);

    value = g_hash_table_lookup(hash, "DataSize");
    if (sscanf(value, "%ux%u", &hxres, &hyres) != 2) {
        err_INVALID(error, "DataSize");
        goto fail;
    }
    if (hxres != pxres || hyres != pyres) {
        g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA,
                    _("Field DataSize %ux%u does not match image dimensions "
                      "%ux%u."),
                    hxres, hyres, pxres, pyres);
        goto fail;
    }
    if (err_DIMENSION(error, hxres) || err_DIMENSION(error, hyres))
        goto fail;

    dx = g_ascii_strtod(g_hash_table_lookup(hash, "PixelSize"), NULL);
    /* Use negated positive conditions to catch NaNs */
    if (!((dx = fabs(dx)) > 0)) {
        g_warning("Pixel size is 0.0, fixing to 1.0");
        dx = 1.0;
    }
    dx *= Nanometre;

    dfield = gwy_data_field_new(hxres, hyres, hxres*dx, hyres*dx, FALSE);
    gwy_si_unit_set_from_string(gwy_data_field_get_si_unit_xy(dfield), "m");

    data = gwy_data_field_get_data(dfield);
    pixels = gdk_pixbuf_get_pixels(pixbuf);
    rowstride = gdk_pixbuf_get_rowstride(pixbuf);
    nchannels = gdk_pixbuf_get_n_channels(pixbuf);
    for (i = 0; i < hyres; i++) {
        gdouble *drow = data + i*hxres;
        guchar *p = pixels + i*rowstride;

        for (j = 0; j < hxres; j++, p += nchannels)
            drow[j] = (p[0] + p[1] + p[2])/765.0;
    }

    container = gwy_container_new();
    gwy_container_set_object(container, gwy_app_get_data_key_for_id(0), dfield);
    g_object_unref(dfield);

    if ((value = g_hash_table_lookup(hash, "SampleName"))
        && *value)
        gwy_container_set_string_by_name(container, "/0/data/title",
                                         g_strdup(value));
    else
        gwy_container_set_string_by_name(container, "/0/data/title",
                                         g_strdup("SEM"));

    meta = gwy_container_new();
    g_hash_table_foreach(hash, store_meta, meta);
    gwy_container_set_object_by_name(container, "/0/meta", meta);
    g_object_unref(meta);

    gwy_file_channel_import_log_add(container, 0, NULL, filename);

fail:
    gwy_object_unref(pixbuf);
    g_free(imagename);
    g_free(header);
    g_hash_table_destroy(hash);

    return container;
}
Пример #11
0
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;
}
Пример #12
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;
}
Пример #13
0
static GwyDataField*
mif_read_data_field(const MIFImageHeader *image_header,
                    const MIFBlock *block,
                    const guchar *buffer,
                    gsize size,
                    GError **error)
{
    const MIFScanSetup *setup = &image_header->setup;
    const MIFImageConfiguration *configuration = &image_header->configuration;
    gint xres = setup->xres;
    gint yres = setup->yres;
    gdouble xreal = setup->xreal * image_header->configuration.xcal;
    gdouble yreal = setup->yreal * image_header->configuration.ycal;
    gdouble xoff = setup->xoff;
    gdouble yoff = setup->yoff;
    gdouble q = configuration->zcal/65536.0;
    GwyDataField *dfield;
    gdouble *data, *linecorrdata = NULL;
    gsize datasize;
    const gint16 *d16;
    gint i, j;

    if (err_DIMENSION(error, xres) || err_DIMENSION(error, yres))
        return NULL;

    if (!block->size || block->offset > size || block->size > size
        || block->offset + block->size > size) {
        g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA,
                    _("Image data are outside the file."));
        return NULL;
    }

    datasize = xres*yres*sizeof(gint16);
    if (err_SIZE_MISMATCH(error, datasize, block->size, FALSE))
        return NULL;

    if (datasize + yres*sizeof(gint16) <= block->size) {
        gwy_debug("There may be %u correction data after the image.", yres);
        linecorrdata = g_new(gdouble, yres);
        d16 = (const gint16*)(buffer + block->offset + datasize);
        for (i = 0; i < yres; i++) {
            linecorrdata[i] = pow(2.0, d16[i] - 13);
            gwy_debug("corr[%u] %g", i, linecorrdata[i]);
        }
    }

    dfield = gwy_data_field_new(xres, yres, xreal, yreal, FALSE);
    gwy_data_field_set_xoffset(dfield, xoff);
    gwy_data_field_set_yoffset(dfield, yoff);
    data = gwy_data_field_get_data(dfield);
    d16 = (const gint16*)(buffer + block->offset);

    gwy_si_unit_set_from_string(gwy_data_field_get_si_unit_xy(dfield), "m");
    gwy_si_unit_set_from_string(gwy_data_field_get_si_unit_z(dfield), "m");

    // XXX: Don't know why this range.  A user got it from DME.  Have no idea
    // why scan_int_to_meter does not appear here.
    if (!configuration->z_linearized)
        q *= 15e-6;
    else
        q *= 20e-6;

    for (i = 0; i < yres; i++) {
        gdouble qi = linecorrdata ? q*linecorrdata[i] : q;
        for (j = 0; j < yres; j++) {
            data[(yres-1 - i)*xres + j] = qi*GINT16_FROM_LE(d16[i*xres + j]);
        }
    }

    g_free(linecorrdata);

    return dfield;
}
Пример #14
0
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;
}
Пример #15
0
static GwyGraphModel*
sensofar_read_profile(SensofarDataDesc *data_desc,
                      const guchar **p,
                      gsize size,
                      GError **error)
{
    GwyGraphModel *gmodel;
    GwyGraphCurveModel *gcmodel;
    guint xres, yres, j, n;
    GwySIUnit *units = NULL;
    gdouble *xdata, *ydata;
    gdouble dx;

    yres = gwy_get_guint32_le(p);
    if (yres != 1)
        g_warning("ysize is not 1 for profile");
    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;
    }

    xdata = g_new(gdouble, xres);
    ydata = g_new(gdouble, xres);
    dx = data_desc->axes_config.mppx * Micrometer;

    for (j = n = 0; j < xres; j++) {
        gdouble v = gwy_get_gfloat_le(p);
        if (v != 1000001.0) {
            xdata[n] = dx*j;
            ydata[n] = v*Micrometer;
            n++;
        }
    }

    if (!n) {
        g_free(xdata);
        g_free(ydata);
        err_NO_DATA(error);
        return NULL;
    }

    gmodel = gwy_graph_model_new();
    g_object_set(gmodel, "title", _("Profile"), NULL);

    units = gwy_si_unit_new("m"); // values are in um only
    g_object_set(gmodel, "si-unit-x", units, NULL);
    g_object_unref(units);

    units = gwy_si_unit_new("m"); // values are in um only
    g_object_set(gmodel, "si-unit-y", units, NULL);
    g_object_unref(units);

    gcmodel = gwy_graph_curve_model_new();
    gwy_graph_curve_model_set_data(gcmodel, xdata, ydata, n);
    g_object_set(gcmodel,
                 "mode", GWY_GRAPH_CURVE_LINE,
                 "description", _("Profile"),
                 NULL);
    gwy_graph_model_add_curve(gmodel, gcmodel);
    g_object_unref(gcmodel);

    return gmodel;
}
Пример #16
0
static GwyContainer*
csmfile_load(const gchar *filename,
             G_GNUC_UNUSED GwyRunType mode,
             GError **error)
{
    GwyContainer *meta, *container = NULL;
    GHashTable *hash = NULL;
    guchar *d24, *buffer = NULL;
    gsize size = 0;
    GError *err = NULL;
    GwyDataField *dfield = NULL;
    guint xres, yres, bmpsize, header_size, maxval, i, j;
    gdouble real, zmin, zmax, q, z0;
    GwyTextHeaderParser parser;
    GwySIUnit *unit = NULL;
    gchar *value, *end, *header = NULL;
    gdouble *data;
    gint power10;

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

    if (size < BMP_HEADER_SIZE) {
        err_TOO_SHORT(error);
        goto fail;
    }
    if (!read_bmp_header(buffer, &xres, &yres, &bmpsize)
        || size <= bmpsize) {
        err_FILE_TYPE(error, "CSM");
        goto fail;
    }

    header_size = size - bmpsize;
    header = g_new(gchar, header_size + 1);
    memcpy(header, buffer + bmpsize, header_size);
    header[header_size] = '\0';

    gwy_clear(&parser, 1);
    parser.key_value_separator = "=";
    hash = gwy_text_header_parse(header, &parser, NULL, NULL);

    /* Do NOT use the fields Image width, Image height from the added footer.
     * Even though it is specifically added by Benyuan it can disagree with the
     * BMP diemsions and when they disagree the BMP diemsions are apparently
     * right. */
    if (err_DIMENSION(error, xres))
        goto fail;
    if (err_DIMENSION(error, yres))
        goto fail;

    if (!(value = g_hash_table_lookup(hash, "ScanSize"))) {
        err_MISSING_FIELD(error, "ScanSize");
        goto fail;
    }
    real = g_ascii_strtod(value, NULL);
    /* Use negated positive conditions to catch NaNs */
    if (!((real = fabs(real)) > 0)) {
        g_warning("Real size is 0.0, fixing to 1.0");
        real = 1.0;
    }

    if (!(value = g_hash_table_lookup(hash, "HeightScale"))) {
        err_MISSING_FIELD(error, "HeightScale");
        goto fail;
    }
    zmax = g_ascii_strtod(value, &end);
    unit = gwy_si_unit_new_parse(end, &power10);

    /* Optional stuff for which we try to fall back. */
    if (!(value = g_hash_table_lookup(hash, "StartHeightScale")))
        zmin = 0.0;
    else
        zmin = g_ascii_strtod(value, NULL);

    if (!(value = g_hash_table_lookup(hash, "MaxValue")))
        maxval = 0xffff;
    else
        maxval = MAX(atoi(value), 1);


    dfield = gwy_data_field_new(xres, yres, real*Nanometre, real*Nanometre,
                                FALSE);
    data = gwy_data_field_get_data(dfield);

    d24 = buffer + BMP_HEADER_SIZE;
    q = pow10(power10)*(zmax - zmin)/maxval;
    z0 = pow10(power10)*zmin;
    for (i = 0; i < yres; i++) {
        gdouble *row = data + (yres-1 - i)*xres;
        for (j = 0; j < xres; j++, row++, d24 += 3)
            *row = (d24[0] + 256.0*d24[1])*q + z0;
    }

    gwy_si_unit_set_from_string(gwy_data_field_get_si_unit_xy(dfield), "m");
    gwy_data_field_set_si_unit_z(dfield, unit);

    container = gwy_container_new();
    gwy_container_set_object_by_name(container, "/0/data", dfield);
    g_object_unref(dfield);

    meta = gwy_container_new();
    g_hash_table_foreach(hash, store_meta, meta);
    gwy_container_set_object_by_name(container, "/0/meta", meta);
    g_object_unref(meta);

    if ((value = g_hash_table_lookup(hash, "sTitle"))
        && g_utf8_validate(value, -1, NULL)) {
        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:
    gwy_file_abandon_contents(buffer, size, NULL);
    GWY_OBJECT_UNREF(unit);
    if (header)
        g_free(header);
    if (hash)
        g_hash_table_destroy(hash);

    return container;
}
Пример #17
0
static GwyContainer*
apefile_load(const gchar *filename,
             G_GNUC_UNUSED GwyRunType mode,
             GError **error)
{
    APEFile apefile;
    GwyContainer *meta, *container = NULL;
    guchar *buffer = NULL;
    const guchar *p;
    gsize size = 0;
    GError *err = NULL;
    GwyDataField *dfield = NULL;
    guint b, i, n;

    if (!gwy_file_get_contents(filename, &buffer, &size, &err)) {
        err_GET_FILE_CONTENTS(error, &err);
        return NULL;
    }
    p = buffer;
    apefile.version = *(p++);
    if (size < 1294) {
        err_TOO_SHORT(error);
        gwy_file_abandon_contents(buffer, size, NULL);
        return NULL;
    }

    apefile.spm_mode = *(p++);
    p += 2;   /* Skip VisualBasic VARIANT type type */
    apefile.scan_date = gwy_get_gdouble_le(&p);
    apefile.maxr_x = gwy_get_gfloat_le(&p);
    apefile.maxr_y = gwy_get_gfloat_le(&p);
    apefile.x_offset = gwy_get_guint32_le(&p);
    apefile.y_offset = gwy_get_guint32_le(&p);
    apefile.size_flag = gwy_get_guint16_le(&p);
    apefile.res = 16 << apefile.size_flag;
    if (err_DIMENSION(error, apefile.res)) {
        gwy_file_abandon_contents(buffer, size, NULL);
        return NULL;
    }
    apefile.acquire_delay = gwy_get_gfloat_le(&p);
    apefile.raster_delay = gwy_get_gfloat_le(&p);
    apefile.tip_dist = gwy_get_gfloat_le(&p);
    apefile.v_ref = gwy_get_gfloat_le(&p);
    if (apefile.version == 1) {
        apefile.vpmt1 = gwy_get_guint16_le(&p);
        apefile.vpmt2 = gwy_get_guint16_le(&p);
    }
    else {
        apefile.vpmt1 = gwy_get_gfloat_le(&p);
        apefile.vpmt2 = gwy_get_gfloat_le(&p);
    }
    apefile.remark = g_strndup(p, 120);
    p += 120;
    apefile.x_piezo_factor = gwy_get_guint32_le(&p);
    apefile.y_piezo_factor = gwy_get_guint32_le(&p);
    apefile.z_piezo_factor = gwy_get_guint32_le(&p);
    apefile.hv_gain = gwy_get_gfloat_le(&p);
    apefile.freq_osc_tip = gwy_get_gdouble_le(&p);
    apefile.rotate = gwy_get_gfloat_le(&p);
    apefile.slope_x = gwy_get_gfloat_le(&p);
    apefile.slope_y = gwy_get_gfloat_le(&p);
    apefile.topo_means = gwy_get_guint16_le(&p);
    apefile.optical_means = gwy_get_guint16_le(&p);
    apefile.error_means = gwy_get_guint16_le(&p);
    /*
    g_printerr("%04x %04x %04x\n",
               apefile.topo_means, apefile.optical_means, apefile.error_means);
               */
    apefile.channels = gwy_get_guint32_le(&p);
    apefile.ndata = 0;
    for (b = apefile.channels; b; b = b >> 1)
        apefile.ndata += (b & 1);
    apefile.range_x = gwy_get_gfloat_le(&p);
    apefile.range_y = gwy_get_gfloat_le(&p);
    apefile.subversion = gwy_get_guint16_le(&p);
    /* Read everything since the header is long enough, check the version
     * later when we decide whether to use these values or not. */
    /* Since 2.1 */
    apefile.hv_gain_z = gwy_get_gfloat_le(&p);
    /* Since 2.2 */
    apefile.fast2_0 = gwy_get_gdouble_le(&p);
    apefile.fast2_1 = gwy_get_gdouble_le(&p);
    apefile.fast2_2 = gwy_get_gdouble_le(&p);
    apefile.fast2_3 = gwy_get_gdouble_le(&p);
    /* Since 2.3 */
    apefile.pg850_image = !!gwy_get_guint16_le(&p);
    /* Since 2.4 */
    apefile.xy_hv_status = gwy_get_gint16_le(&p);
    apefile.z_hv_status = gwy_get_gint16_le(&p);
    /* reserved */
    p += 2;

    apefile.xreal = apefile.maxr_x * apefile.x_piezo_factor * apefile.range_x
                    * apefile.hv_gain/65535.0 * 1e-9;
    apefile.yreal = apefile.maxr_y * apefile.y_piezo_factor * apefile.range_y
                    * apefile.hv_gain/65535.0 * 1e-9;
    /* Use negated positive conditions to catch NaNs */
    if (!((apefile.xreal = fabs(apefile.xreal)) > 0)) {
        g_warning("Real x size is 0.0, fixing to 1.0");
        apefile.xreal = 1.0;
    }
    if (!((apefile.yreal = fabs(apefile.yreal)) > 0)) {
        g_warning("Real y size is 0.0, fixing to 1.0");
        apefile.yreal = 1.0;
    }

    gwy_debug("version = %u.%u, spm_mode = %u",
              apefile.version, apefile.subversion, apefile.spm_mode);
    gwy_debug("scan_date = %f", apefile.scan_date);
    gwy_debug("maxr_x = %g, maxr_y = %g", apefile.maxr_x, apefile.maxr_y);
    gwy_debug("x_offset = %u, y_offset = %u",
              apefile.x_offset, apefile.y_offset);
    gwy_debug("size_flag = %u", apefile.size_flag);
    gwy_debug("acquire_delay = %g, raster_delay = %g, tip_dist = %g",
              apefile.acquire_delay, apefile.raster_delay, apefile.tip_dist);
    gwy_debug("v_ref = %g, vpmt1 = %g, vpmt2 = %g",
              apefile.v_ref, apefile.vpmt1, apefile.vpmt2);
    gwy_debug("x_piezo_factor = %u, y_piezo_factor = %u, z_piezo_factor = %u",
              apefile.x_piezo_factor, apefile.y_piezo_factor,
              apefile.z_piezo_factor);
    gwy_debug("hv_gain = %g, freq_osc_tip = %g, rotate = %g",
              apefile.hv_gain, apefile.freq_osc_tip, apefile.rotate);
    gwy_debug("slope_x = %g, slope_y = %g",
              apefile.slope_x, apefile.slope_y);
    gwy_debug("topo_means = %u, optical_means = %u, error_means = %u",
              apefile.topo_means, apefile.optical_means, apefile.error_means);
    gwy_debug("channel bitmask = %03x, ndata = %u",
              apefile.channels, apefile.ndata);
    gwy_debug("range_x = %g, range_y = %g",
              apefile.range_x, apefile.range_y);

    n = (apefile.res + 1)*(apefile.res + 1)*sizeof(float);
    if (size - (p - buffer) != n*apefile.ndata) {
        g_warning("Expected data size %u, but it's %u.",
                  n*apefile.ndata, (guint)(size - (p - buffer)));
        apefile.ndata = MIN(apefile.ndata, (size - (p - buffer))/n);
    }
    if (!apefile.ndata) {
        err_NO_DATA(error);
        gwy_file_abandon_contents(buffer, size, NULL);
        return NULL;
    }
    fill_data_fields(&apefile, p);
    gwy_file_abandon_contents(buffer, size, NULL);

    container = gwy_container_new();
    /* All metadata seems to be per-file (global) */
    meta = apefile_get_metadata(&apefile);
    for (b = apefile.channels, n = 0, i = 0; b; b = b >> 1, i++) {
        GwyContainer *tmp;
        gchar *title;
        gchar key[32];

        if (!(b & 1))
            continue;

        g_snprintf(key, sizeof(key), "/%d/data", n);
        dfield = apefile.data[n];
        gwy_container_set_object_by_name(container, key, dfield);
        g_object_unref(apefile.data[n]);

        g_snprintf(key, sizeof(key), "/%d/data/title", n);

        /*
         * Channel labelling based on SPM Mode
         */
        switch (apefile.spm_mode) {
            case SPM_MODE_SNOM:
            title = gwy_enuml_to_string(i,
                                        "Height",   APE_HEIGHT,
                                        "Height-R", APE_HEIGHT_R,
                                        "NSOM",     APE_NSOM,
                                        "NSOM-R",   APE_NSOM_R,
                                        "Error",    APE_ERROR,
                                        "Error-R",  APE_ERROR_R,
                                        "NSOM2",    APE_NSOM2,
                                        "NSOM2-R",  APE_NSOM2_R,
                                        "Lateral",     APE_AUX1,
                                        "Z-Z0",     APE_AUX2,
                                        "Lateral-R",   APE_AUX1_R,
                                        "Z-Z0-R",   APE_AUX2_R,
                                        NULL);
            break;

            case SPM_MODE_AFM_NONCONTACT:
            case SPM_MODE_AFM_CONTACT:
            case SPM_MODE_PHASE_DETECT_AFM:
            title = gwy_enuml_to_string(i,
                                        "Height",   APE_HEIGHT,
                                        "Height-R", APE_HEIGHT_R,
                                        "IN1",     APE_NSOM,
                                        "IN1-R",   APE_NSOM_R,
                                        "Error",    APE_ERROR,
                                        "Error-R",  APE_ERROR_R,
                                        "IN2",    APE_NSOM2,
                                        "IN2-R",  APE_NSOM2_R,
                                        "Lateral",     APE_AUX1,
                                        "Z-Z0",     APE_AUX2,
                                        "Lateral-R",   APE_AUX1_R,
                                        "Z-Z0-R",   APE_AUX2_R,
                                        NULL);
            break;

            default:
            title = gwy_enuml_to_string(i,
                                        "Height",   APE_HEIGHT,
                                        "Height-R", APE_HEIGHT_R,
                                        "IN1",     APE_NSOM,
                                        "IN1-R",   APE_NSOM_R,
                                        "Error",    APE_ERROR,
                                        "Error-R",  APE_ERROR_R,
                                        "IN2",    APE_NSOM2,
                                        "IN2-R",  APE_NSOM2_R,
                                        "Aux1",     APE_AUX1,
                                        "Z-Z0",     APE_AUX2,
                                        "Aux1-R",   APE_AUX1_R,
                                        "Z-Z0-R",   APE_AUX2_R,
                                        NULL);
            break;
        }
        if (title && *title)
            gwy_container_set_string_by_name(container, key, g_strdup(title));

        tmp = gwy_container_duplicate(meta);
        g_snprintf(key, sizeof(key), "/%d/meta", n);
        gwy_container_set_object_by_name(container, key, tmp);
        g_object_unref(tmp);

        gwy_file_channel_import_log_add(container, n, NULL, filename);

        n++;
    }

    g_object_unref(meta);
    g_free(apefile.remark);

    return container;
}
Пример #18
0
static GwyContainer*
jeol_load(const gchar *filename,
          G_GNUC_UNUSED GwyRunType mode,
          GError **error)
{
    JEOLImageHeader image_header;
    GwyContainer *meta, *container = NULL;
    guchar *buffer = NULL;
    gsize expected_size, size = 0;
    GError *err = NULL;
    GwyDataField *dfield = NULL;
    const gchar *title;
    gchar *s;

    if (!gwy_file_get_contents(filename, &buffer, &size, &err)) {
        err_GET_FILE_CONTENTS(error, &err);
        return NULL;
    }
    if (size < JEOL_DATA_START) {
        err_TOO_SHORT(error);
        goto fail;
    }
    if (memcmp(buffer, MAGIC, MAGIC_SIZE) != 0) {
        err_FILE_TYPE(error, "JEOL");
        goto fail;
    }

    jeol_read_image_header(buffer, &image_header);
    /* Elementrary sanity */
    if (image_header.bpp != 16) {
        err_BPP(error, image_header.bpp);
        goto fail;
    }

    if (err_DIMENSION(error, image_header.xres)
        || err_DIMENSION(error, image_header.yres))
        goto fail;

    expected_size = image_header.bpp/8 * image_header.xres*image_header.yres;
    if (err_SIZE_MISMATCH(error, JEOL_DATA_START + expected_size, size, FALSE))
        goto fail;

    if (image_header.image_type != JEOL_IMAGE || image_header.compressed) {
        err_NO_DATA(error);
        goto fail;
    }

    /* Use negated positive conditions to catch NaNs */
    if (!((image_header.xreal = fabs(image_header.xreal)) > 0)) {
        g_warning("Real x size is 0.0, fixing to 1.0");
        image_header.xreal = 1.0;
    }
    if (!((image_header.yreal = fabs(image_header.yreal)) > 0)) {
        g_warning("Real y size is 0.0, fixing to 1.0");
        image_header.yreal = 1.0;
    }

    dfield = jeol_read_data_field(buffer + JEOL_DATA_START, &image_header);
    if (!dfield) {
        g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA,
                    _("The type of data is unknown.  "
                      "Please report it to the developers."));
        goto fail;
    }

    container = gwy_container_new();
    gwy_container_set_object_by_name(container, "/0/data", dfield);
    g_object_unref(dfield);

    /* Title */
    s = g_convert(image_header.internal_filename, -1,
                  "iso-8859-1", "utf-8", NULL, NULL, NULL);
    if (s)
        g_strstrip(s);
    if (s && *s)
        gwy_container_set_string_by_name(container, "/0/data/title", s);
    else {
        title = gwy_flat_enum_to_string(image_header.data_source,
                                        G_N_ELEMENTS(data_sources),
                                        data_sources, data_sources_name);
        if (title)
            gwy_container_set_string_by_name(container, "/0/data/title",
                                             g_strdup(title));
    }

    /* Meta */
    meta = jeol_get_metadata(&image_header);
    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);
    return container;
}
Пример #19
0
static gboolean
rhkspm32_read_header(RHKPage *rhkpage,
                     GError **error)
{
    const gchar *buffer;
    gchar *end;
    guint pos;

    buffer = rhkpage->buffer;

    rhkpage->date = g_strstrip(g_strndup(buffer + MAGIC_SIZE,
                                         0x20 - MAGIC_SIZE));
    if (sscanf(buffer + 0x20, "%d %d %d %d %d %d %d",
               (gint*)&rhkpage->type, (gint*)&rhkpage->data_type,
               &rhkpage->line_type,
               &rhkpage->xres, &rhkpage->yres, &rhkpage->size,
               (gint*)&rhkpage->page_type) != 7) {
        g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA,
                    _("Invalid file header."));
        return FALSE;
    }
    gwy_debug("type = %u, data = %u, line = %u, image = %u",
              rhkpage->type, rhkpage->data_type, rhkpage->line_type,
              rhkpage->page_type);
    gwy_debug("xres = %d, yres = %d", rhkpage->xres, rhkpage->yres);
    if (err_DIMENSION(error, rhkpage->xres)
        || err_DIMENSION(error, rhkpage->yres))
        return FALSE;
    if (!((rhkpage->type == RHK_TYPE_IMAGE)
          || (rhkpage->type == RHK_TYPE_LINE))) {
        g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA,
                    _("Only image and line files are supported."));
        return FALSE;
    }
    if ((rhkpage->type == RHK_TYPE_IMAGE)
        && (rhkpage->data_type != RHK_DATA_INT16)) {
        g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA,
                    _("Invalid data type %d for image data."),
                    rhkpage->data_type);
        return FALSE;
    }
    if ((rhkpage->type == RHK_TYPE_LINE)
        && !((rhkpage->data_type == RHK_DATA_INT16)
             || (rhkpage->data_type == RHK_DATA_SINGLE))) {
        g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA,
                    _("Invalid data type %d for line data."),
                    rhkpage->data_type);
        return FALSE;
    }

    if ((rhkpage->data_type) == RHK_DATA_INT8)
        rhkpage->item_size = 1;
    else if ((rhkpage->data_type) == RHK_DATA_INT16)
        rhkpage->item_size = 2;
    else if ((rhkpage->data_type) == RHK_DATA_INT32)
        rhkpage->item_size = 4;
    else if ((rhkpage->data_type) == RHK_DATA_SINGLE)
        rhkpage->item_size = 4;

    //rhkpage->item_size = rhkpage->data_type; // niv

    if (!rhkspm32_read_range(buffer + 0x40, "X", &rhkpage->x)
        || !rhkspm32_read_range(buffer + 0x60, "Y", &rhkpage->y)
        || !rhkspm32_read_range(buffer + 0x80, "Z", &rhkpage->z)) {
        err_INVALID(error, _("data ranges"));
        return FALSE;
    }

    /* Use negated positive conditions to catch NaNs */
    // niv - modifying this - otherwise it messes with the spectra
    // (but i don;t really understand it)
    if (!((fabs(rhkpage->x.scale)) > 0)) {
        g_warning("Real x scale is 0.0, fixing to 1.0");
        rhkpage->x.scale = 1.0;
    }
    if (!((fabs(rhkpage->y.scale)) > 0)) {
        /* The y scale seem unused for non-image data */
        if (rhkpage->type == RHK_TYPE_IMAGE)
            g_warning("Real y scale is 0.0, fixing to 1.0");
        rhkpage->y.scale = 1.0;
    }

    if (!g_str_has_prefix(buffer + 0xa0, "XY ")) {
        err_MISSING_FIELD(error, "XY");
        return FALSE;
    }
    pos = 0xa0 + sizeof("XY");
    rhkpage->xyskew = g_ascii_strtod(buffer + pos, &end);
    if (end == buffer + pos) {
        err_INVALID(error, "XY");
        return FALSE;
    }
    pos = (end - buffer) + 2;
    /* Don't check failure, it seems the value is optional */
    rhkpage->alpha = g_ascii_strtod(buffer + pos, &end);
    // not failing, but setting an existance flag, this happens for spectra,
    // but otherwise i want to add this to the metadata
    if (end == buffer + pos)
        rhkpage->e_alpha = FALSE;
    else
        rhkpage->e_alpha = TRUE;

    if (!rhkspm32_read_range(buffer + 0xc0, "IV", &rhkpage->iv)) {
        err_INVALID(error, "IV");
        return FALSE;
    }

    if (g_str_has_prefix(buffer + 0xe0, "scan "))
        pos = 0xe0 + sizeof("scan");
    rhkpage->scan = strtol(buffer + pos, &end, 10);
    if (end == buffer + pos) {
        err_INVALID(error, "scan");
        return FALSE;
    }
    pos = (end - buffer);
    rhkpage->period = g_ascii_strtod(buffer + pos, &end);
    if (end == buffer + pos) {
        err_INVALID(error, "period");
        return FALSE;
    }

    if (sscanf(buffer + 0x100, "id %u %u",
               &rhkpage->id, &rhkpage->data_offset) != 2) {
        /* XXX: Some braindamaged files encountered in practice do not contain
         * the data offset.  Cross fingers and substitute HEADER_SIZE.  */
        g_warning("Data offset is missing, just guessing from now...");
        rhkpage->id = 0;
        rhkpage->data_offset = HEADER_SIZE;
    }
    gwy_debug("data_offset = %u", rhkpage->data_offset);
    if (rhkpage->data_offset < HEADER_SIZE) {
        err_INVALID(error, _("data offset"));
        return FALSE;
    }

    /* XXX: The same braindamaged files overwrite the label and comment part
     * with some XML mumbo jumbo.  Sigh and ignore it.  */
    if (strncmp(buffer + 0x140, "\x0d\x0a<?", 4) != 0) {
        rhkpage->label = g_strstrip(g_strndup(buffer + 0x140, 0x20));
        rhkpage->comment = g_strstrip(g_strndup(buffer + 0x160,
                                                HEADER_SIZE - 0x160));
    }

    return TRUE;
}
Пример #20
0
static gboolean
get_scales(GHashTable *hash,
           gboolean is_text,
           gint *xres, gint *yres,
           gdouble *xreal, gdouble *yreal,
           gdouble *xoff, gdouble *yoff,
           GwySIUnit *si_unit_xy,
           gdouble *zscale,
           gdouble *zoff,
           GwySIUnit *si_unit_z,
           GError **error)
{
    GwySIUnit *unit;
    gint power10, zp;
    gchar *p;
    gboolean has_unit = FALSE;

    /* Dimensions are mandatory. */
    if (!require_keys(hash, error,
                      "SCANNING PARAMS::PixelsX",
                      "SCANNING PARAMS::PixelsY",
                      "SCANNING PARAMS::PixelsZ",
                      "SCANNING PARAMS::SizeX",
                      "SCANNING PARAMS::SizeY",
                      "SCANNING PARAMS::SizeZ",
                      NULL))
        return FALSE;

    *xres = atoi(g_hash_table_lookup(hash, "SCANNING PARAMS::PixelsX"));
    if (err_DIMENSION(error, *xres))
        return FALSE;
    *yres = atoi(g_hash_table_lookup(hash, "SCANNING PARAMS::PixelsY"));
    if (err_DIMENSION(error, *yres))
        return FALSE;

    unit = gwy_si_unit_new(NULL);

    p = g_hash_table_lookup(hash, "SCANNING PARAMS::SizeX");
    *xreal = fabs(g_ascii_strtod(p, &p));
    if (!*xreal) {
        g_warning("Real x size is 0.0, fixing to 1.0");
        *xreal = 1.0;
    }
    gwy_si_unit_set_from_string_parse(si_unit_xy, p, &power10);
    *xreal *= pow10(power10);

    p = g_hash_table_lookup(hash, "SCANNING PARAMS::SizeY");
    *yreal = fabs(g_ascii_strtod(p, &p));
    if (!*yreal) {
        g_warning("Real y size is 0.0, fixing to 1.0");
        *yreal = 1.0;
    }
    gwy_si_unit_set_from_string_parse(unit, p, &power10);
    *yreal *= pow10(power10);
    if (!gwy_si_unit_equal(unit, si_unit_xy)) {
        g_warning("X and Y units differ, using X");
    }

    zp = atoi(g_hash_table_lookup(hash, "SCANNING PARAMS::PixelsZ"));
    if (!zp) {
        g_warning("Z pixels is 0, fixing to 1");
        zp = 1;
    }
    p = g_hash_table_lookup(hash, "SCANNING PARAMS::SizeZ");
    *zscale = g_ascii_strtod(p, &p);
    *zoff = 0.0;
    gwy_si_unit_set_from_string_parse(si_unit_z, p, &power10);
    *zscale *= pow10(power10)/zp;
    /* XXX: Version 4 can have UNIT section that takes precedence.  The Conv
     * factor may not be enough.  Apparently, binary phase data need
     * subtracting 180 deg because data are unsinged.  Bite me. */
    if ((p = g_hash_table_lookup(hash, "UNIT::Unit"))) {
        const gchar *s = g_hash_table_lookup(hash, "UNIT::Name");
        has_unit = TRUE;
        gwy_si_unit_set_from_string_parse(si_unit_z, p, &power10);
        *zscale *= pow10(power10);
        if ((p = g_hash_table_lookup(hash, "UNIT::Conv")))
            *zscale *= g_ascii_strtod(p, NULL);

        if (!is_text && gwy_strequal(s, "Phase"))
            *zoff = -180.0;
    }

    /* Offsets are optional. */
    *xoff = 0.0;
    if ((p = g_hash_table_lookup(hash, "SCANNING PARAMS::OffsetX"))) {
        *xoff = g_ascii_strtod(p, &p);
        gwy_si_unit_set_from_string_parse(unit, p, &power10);
        if (gwy_si_unit_equal(unit, si_unit_xy))
            *xoff *= pow10(power10);
        else {
            g_warning("X offset units differ from X size units, ignoring.");
            *xoff = 0.0;
        }
    }

    *yoff = 0.0;
    if ((p = g_hash_table_lookup(hash, "SCANNING PARAMS::OffsetY"))) {
        *yoff = g_ascii_strtod(p, &p);
        gwy_si_unit_set_from_string_parse(unit, p, &power10);
        if (gwy_si_unit_equal(unit, si_unit_xy))
            *yoff *= pow10(power10);
        else {
            g_warning("Y offset units differ from Y size units, ignoring.");
            *yoff = 0.0;
        }
    }

    // Don't know what to do with the offset when UNIT section is present.
    // It seems to be always 0 in wrong units, so skip it.
    if (!has_unit) {
        if ((p = g_hash_table_lookup(hash, "SCANNING PARAMS::OffsetZ"))) {
            *zoff = g_ascii_strtod(p, &p);
            gwy_si_unit_set_from_string_parse(unit, p, &power10);
            if (gwy_si_unit_equal(unit, si_unit_z))
                *zoff *= pow10(power10);
            else {
                g_warning("Z offset units differ from Z size units, ignoring.");
                *zoff = 0.0;
            }
        }
    }

    g_object_unref(unit);

    return TRUE;
}
Пример #21
0
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;
}
Пример #22
0
static gboolean
read_parameters(const guchar *buffer,
                guint size,
                StmprgFile *stmprgfile,
                GError **error)
{
    const guchar *p = buffer + MAGIC_SIZE;
    StmprgMainfield *mainfield;
    StmprgControl *control;
    StmprgOtherControl *other_control;

    gwy_debug("tp file size is %u, expecting %u", size, PARAM_SIZE);
    if (size < PARAM_SIZE) {
        g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA,
                    _("Parameter file is too short."));
        return FALSE;
    }

    /* mainfield */
    mainfield = &stmprgfile->mainfield;
    mainfield->start_x = gwy_get_gfloat_be(&p);
    mainfield->start_y = gwy_get_gfloat_be(&p);
    mainfield->field_x = gwy_get_gfloat_be(&p);
    mainfield->field_y = gwy_get_gfloat_be(&p);
    mainfield->inc_x = gwy_get_gfloat_be(&p);
    mainfield->inc_y = gwy_get_gfloat_be(&p);
    mainfield->points = gwy_get_gint32_be(&p);
    mainfield->lines = gwy_get_gint32_be(&p);
    mainfield->angle = gwy_get_gfloat_be(&p);
    mainfield->sol_x = gwy_get_gfloat_be(&p);
    mainfield->sol_y = gwy_get_gfloat_be(&p);
    mainfield->sol_z = gwy_get_gfloat_be(&p);
    mainfield->sol_ext1 = gwy_get_gfloat_be(&p);
    mainfield->sol_ext2 = gwy_get_gfloat_be(&p);
    mainfield->sol_h = gwy_get_gfloat_be(&p);
    g_assert(p - buffer == MAGIC_SIZE + MAINFIELD_SIZE);
    gwy_debug("start_x = %g", mainfield->start_x);
    gwy_debug("start_y = %g", mainfield->start_y);
    gwy_debug("field_x = %g", mainfield->field_x);
    gwy_debug("field_y = %g", mainfield->field_y);
    gwy_debug("inc_x = %g", mainfield->inc_x);
    gwy_debug("inc_y = %g", mainfield->inc_y);
    gwy_debug("points = %d", mainfield->points);
    gwy_debug("lines = %d", mainfield->lines);
    gwy_debug("angle = %g", mainfield->angle);
    gwy_debug("sol_x = %g", mainfield->sol_x);
    gwy_debug("sol_y = %g", mainfield->sol_y);
    gwy_debug("sol_z = %g", mainfield->sol_z);
    gwy_debug("sol_ext1 = %g", mainfield->sol_ext1);
    gwy_debug("sol_ext2 = %g", mainfield->sol_ext2);
    gwy_debug("sol_h = %g", mainfield->sol_h);

    if (err_DIMENSION(error, mainfield->points)
        || err_DIMENSION(error, mainfield->lines))
        return FALSE;

    /* control */
    control = &stmprgfile->control;
    control->mode = *(p++);
    control->channel1 = *(p++);
    control->channel2 = *(p++);
    control->channel3 = *(p++);
    control->spectr = *(p++);
    control->cfree = *(p++);
    control->type = gwy_get_gint16_be(&p);
    control->steps_x = gwy_get_gint32_be(&p);
    control->steps_y = gwy_get_gint32_be(&p);
    control->dac_speed = gwy_get_gint32_be(&p);
    control->poi_inc = gwy_get_gfloat_be(&p);
    control->lin_inc = gwy_get_gfloat_be(&p);
    control->ad1_reads = gwy_get_gint32_be(&p);
    control->ad2_reads = gwy_get_gint32_be(&p);
    control->ad3_reads = gwy_get_gint32_be(&p);
    control->analog_ave = gwy_get_gint32_be(&p);
    control->speed = gwy_get_gint32_be(&p);
    control->voltage = gwy_get_gfloat_be(&p);
    control->voltage_l = gwy_get_gfloat_be(&p);
    control->voltage_r = gwy_get_gfloat_be(&p);
    control->volt_flag = gwy_get_gint32_be(&p);
    control->volt_region = gwy_get_gint32_be(&p);
    control->current = gwy_get_gfloat_be(&p);
    control->current_l = gwy_get_gfloat_be(&p);
    control->current_r = gwy_get_gfloat_be(&p);
    control->curr_flag = gwy_get_gint32_be(&p);
    control->curr_region = gwy_get_gint32_be(&p);
    control->spec_lstart = gwy_get_gfloat_be(&p);
    control->spec_lend = gwy_get_gfloat_be(&p);
    control->spec_linc = gwy_get_gfloat_be(&p);
    control->spec_lsteps = gwy_get_guint32_be(&p);
    control->spec_rstart = gwy_get_gfloat_be(&p);
    control->spec_rend = gwy_get_gfloat_be(&p);
    control->spec_rinc = gwy_get_gfloat_be(&p);
    control->spec_rsteps = gwy_get_guint32_be(&p);
    control->version = gwy_get_gfloat_be(&p);
    control->free_lend = gwy_get_gfloat_be(&p);
    control->free_linc = gwy_get_gfloat_be(&p);
    control->free_lsteps = gwy_get_guint32_be(&p);
    control->free_rstart = gwy_get_gfloat_be(&p);
    control->free_rend = gwy_get_gfloat_be(&p);
    control->free_rinc = gwy_get_gfloat_be(&p);
    control->free_rsteps = gwy_get_guint32_be(&p);
    control->timer1 = gwy_get_guint32_be(&p);
    control->timer2 = gwy_get_guint32_be(&p);
    control->timer3 = gwy_get_guint32_be(&p);
    control->timer4 = gwy_get_guint32_be(&p);
    control->m_time = gwy_get_guint32_be(&p);
    control->u_divider = gwy_get_gfloat_be(&p);
    control->fb_control = gwy_get_gint32_be(&p);
    control->fb_delay = gwy_get_gint32_be(&p);
    control->point_time = gwy_get_gint32_be(&p);
    control->spec_time = gwy_get_gint32_be(&p);
    control->spec_delay = gwy_get_gint32_be(&p);
    control->fm = gwy_get_gint16_be(&p);
    control->fm_prgmode = gwy_get_gint16_be(&p);
    control->fm_channel1 = gwy_get_gint32_be(&p);
    control->fm_channel2 = gwy_get_gint32_be(&p);
    control->fm_wait = gwy_get_gint32_be(&p);
    control->fm_frames = gwy_get_gint32_be(&p);
    control->fm_delay = gwy_get_gint16_be(&p);
    control->spectr_edit = gwy_get_gint16_be(&p);
    control->fm_speed = gwy_get_gint16_be(&p);
    control->fm_reads = gwy_get_gint16_be(&p);
    g_assert(p - buffer == MAGIC_SIZE + MAINFIELD_SIZE + CONTROL_SIZE);
    gwy_debug("type = %d", control->type);
    gwy_debug("steps_x = %d", control->steps_x);
    gwy_debug("steps_y = %d", control->steps_y);
    gwy_debug("dac_speed = %d", control->dac_speed);
    gwy_debug("poi_inc = %g", control->poi_inc);
    gwy_debug("lin_inc = %g", control->lin_inc);
    gwy_debug("ad1_reads = %d", control->ad1_reads);
    gwy_debug("ad2_reads = %d", control->ad2_reads);
    gwy_debug("ad3_reads = %d", control->ad3_reads);
    gwy_debug("analog_ave = %d", control->analog_ave);
    gwy_debug("speed = %d", control->speed);
    gwy_debug("voltage = %g", control->voltage);
    gwy_debug("voltage_l = %g", control->voltage_l);
    gwy_debug("voltage_r = %g", control->voltage_r);
    gwy_debug("volt_flag = %d", control->volt_flag);
    gwy_debug("volt_region = %d", control->volt_region);
    gwy_debug("current = %g", control->current);
    gwy_debug("current_l = %g", control->current_l);
    gwy_debug("current_r = %g", control->current_r);
    gwy_debug("curr_flag = %d", control->curr_flag);
    gwy_debug("curr_region = %d", control->curr_region);
    gwy_debug("spec_lstart = %g", control->spec_lstart);
    gwy_debug("spec_lend = %g", control->spec_lend);
    gwy_debug("spec_linc = %g", control->spec_linc);
    gwy_debug("spec_lsteps = %u", control->spec_lsteps);
    gwy_debug("spec_rstart = %g", control->spec_rstart);
    gwy_debug("spec_rend = %g", control->spec_rend);
    gwy_debug("spec_rinc = %g", control->spec_rinc);
    gwy_debug("spec_rsteps = %u", control->spec_rsteps);
    gwy_debug("version = %g", control->version);
    gwy_debug("free_lend = %g", control->free_lend);
    gwy_debug("free_linc = %g", control->free_linc);
    gwy_debug("free_lsteps = %u", control->free_lsteps);
    gwy_debug("free_rstart = %g", control->free_rstart);
    gwy_debug("free_rend = %g", control->free_rend);
    gwy_debug("free_rinc = %g", control->free_rinc);
    gwy_debug("free_rsteps = %u", control->free_rsteps);
    gwy_debug("timer1 = %u", control->timer1);
    gwy_debug("timer2 = %u", control->timer2);
    gwy_debug("timer3 = %u", control->timer3);
    gwy_debug("timer4 = %u", control->timer4);
    gwy_debug("m_time = %u", control->m_time);
    gwy_debug("u_divider = %g", control->u_divider);
    gwy_debug("fb_control = %d", control->fb_control);
    gwy_debug("fb_delay = %d", control->fb_delay);
    gwy_debug("point_time = %d", control->point_time);
    gwy_debug("spec_time = %d", control->spec_time);
    gwy_debug("spec_delay = %d", control->spec_delay);
    gwy_debug("fm = %d", control->fm);
    gwy_debug("fm_prgmode = %d", control->fm_prgmode);
    gwy_debug("fm_channel1 = %d", control->fm_channel1);
    gwy_debug("fm_channel2 = %d", control->fm_channel2);
    gwy_debug("fm_wait = %d", control->fm_wait);
    gwy_debug("fm_frames = %d", control->fm_frames);
    gwy_debug("fm_delay = %d", control->fm_delay);
    gwy_debug("spectr_edit = %d", control->spectr_edit);
    gwy_debug("fm_speed = %d", control->fm_speed);
    gwy_debug("fm_reads = %d", control->fm_reads);

    /* other_control */
    other_control = &stmprgfile->other_control;
    other_control->version = gwy_get_gfloat_be(&p);
    other_control->adc_data_l = gwy_get_gint32_be(&p);
    other_control->adc_data_r = gwy_get_gint32_be(&p);
    other_control->first_zp = gwy_get_gint16_be(&p);
    other_control->last_zp = gwy_get_gint16_be(&p);
    other_control->zdrift = gwy_get_gfloat_be(&p);
    other_control->savememory = gwy_get_gint32_be(&p);
    get_CHARARRAY0(other_control->date, &p);
    get_CHARARRAY0(other_control->comment, &p);
    get_CHARARRAY0(other_control->username, &p);
    get_CHARARRAY0(other_control->macro_file, &p);
    get_CHARARRAY0(other_control->cext_a, &p);
    get_CHARARRAY0(other_control->cext_b, &p);
    other_control->contscan = gwy_get_gint32_be(&p);
    other_control->spec_loop = gwy_get_gint32_be(&p);
    other_control->ext_c = gwy_get_gint32_be(&p);
    other_control->fm_zlift = gwy_get_gfloat_be(&p);
    other_control->ext_a = gwy_get_gint32_be(&p);
    other_control->vme_release = gwy_get_gfloat_be(&p);
    g_assert(p - buffer == PARAM_SIZE);
    gwy_debug("version = %g", other_control->version);
    gwy_debug("adc_data_l = %d", other_control->adc_data_l);
    gwy_debug("adc_data_r = %d", other_control->adc_data_r);
    gwy_debug("first_zp = %d", other_control->first_zp);
    gwy_debug("last_zp = %d", other_control->last_zp);
    gwy_debug("zdrift = %g", other_control->zdrift);
    gwy_debug("savememory = %d", other_control->savememory);
    gwy_debug("date = %s", other_control->date);
    gwy_debug("comment = %s", other_control->comment);
    gwy_debug("username = %s", other_control->username);
    gwy_debug("macro_file = %s", other_control->macro_file);
    gwy_debug("cext_a = %s", other_control->cext_a);
    gwy_debug("cext_b = %s", other_control->cext_b);
    gwy_debug("contscan = %d", other_control->contscan);
    gwy_debug("spec_loop = %d", other_control->spec_loop);
    gwy_debug("ext_c = %d", other_control->ext_c);
    gwy_debug("fm_zlift = %g", other_control->fm_zlift);
    gwy_debug("ext_a = %d", other_control->ext_a);
    gwy_debug("vme_release = %g", other_control->vme_release);

    return TRUE;
}
Пример #23
0
static GwyDataField*
apedax_get_data_field(unzFile uFile,
                      const gchar *chFileName,
                      const APEScanSize *scanSize,
                      gchar *zUnit,
                      gdouble scale,
                      GError **error)
{
    GwyDataField *dfield = NULL;
    GwySIUnit *xyUnit;
    GwySIUnit *zSIUnit;
    gdouble *data;
    guchar *buffer;
    gsize size, expectedSize;
    unz_file_info uFileInfo;

    /*Checking the dimensions*/
    if (err_DIMENSION(error, scanSize->XRes)) {
        return NULL;
    }

    if (err_DIMENSION(error, scanSize->YRes)) {
        return NULL;
    }

    /*If XReal it's not greater than 0 or XReal is NaN*/
    if (!(fabs(scanSize->XReal) > 0)) {
        err_UNSUPPORTED(error, "X scan size");
        return NULL;
    }

    /*Same for YReal*/
    if (!(fabs(scanSize->YReal) > 0)) {
        err_UNSUPPORTED(error, "Y scan size");
        return NULL;
    }

    expectedSize = scanSize->XRes * scanSize->YRes * sizeof(gdouble);

    unzGoToFirstFile(uFile);

    if (unzLocateFile(uFile, chFileName, 0) != UNZ_OK) {
        gwy_debug("Binary file not found");
        err_NO_DATA(error);
        return NULL;
    }

    if (unzGetCurrentFileInfo(uFile,
                              &uFileInfo,
                              NULL,
                              0L,
                              NULL,
                              0L,
                              NULL,
                              0L) != UNZ_OK) {
        err_NO_DATA(error);
        return NULL;
    }

    buffer = apedax_get_file_content(uFile, &uFileInfo, &size, error);

    if (buffer == NULL) {
        err_NO_DATA(error);
        return NULL;
    }

    if (err_SIZE_MISMATCH(error, expectedSize, size, FALSE)) {
       return NULL;
    }

    dfield = gwy_data_field_new(scanSize->XRes, scanSize->YRes,
                                scanSize->XReal, scanSize->YReal,
                                FALSE);

    data = gwy_data_field_get_data(dfield);

    xyUnit = gwy_data_field_get_si_unit_xy(dfield);
    gwy_si_unit_set_from_string(xyUnit, "m");

    zSIUnit = gwy_data_field_get_si_unit_z(dfield);
    gwy_si_unit_set_from_string(zSIUnit, zUnit);

    gwy_debug("Reading RAW data");

    gwy_convert_raw_data(buffer,
                         scanSize->XRes * scanSize->YRes,
                         1,
                         GWY_RAW_DATA_DOUBLE,
                         GWY_BYTE_ORDER_LITTLE_ENDIAN,
                         data,
                         scale,
                         0.0);

    return dfield;
}
Пример #24
0
static gboolean
unisoku_read_header(gchar *buffer,
                    UnisokuFile *ufile,
                    GError **error)
{
    gchar *line;
    gint type1, type2;

    line = gwy_str_next_line(&buffer);
    if (!line)
        return FALSE;

    NEXT(buffer, line, error);
    /* garbage */

    NEXT(buffer, line, error);
    if (unisoku_sscanf(line, "i", &ufile->format_version) != 1) {
        err_UNSUPPORTED(error, _("format version"));
        return FALSE;
    }

    NEXT(buffer, line, error);
    ufile->date = g_strdup(line);
    NEXT(buffer, line, error);
    ufile->time = g_strdup(line);
    NEXT(buffer, line, error);
    ufile->sample_name = g_strdup(line);
    NEXT(buffer, line, error);
    ufile->remark = g_strdup(line);

    NEXT(buffer, line, error);
    if (unisoku_sscanf(line, "ii", &ufile->ascii_flag, &type1) != 2) {
        err_INVALID(error, _("format flags"));
        return FALSE;
    }
    ufile->data_type = type1;

    NEXT(buffer, line, error);
    if (unisoku_sscanf(line, "ii", &ufile->xres, &ufile->yres) != 2) {
        err_INVALID(error, _("resolution"));
        return FALSE;
    }

    if (err_DIMENSION(error, ufile->xres) || err_DIMENSION(error, ufile->yres))
        return FALSE;

    NEXT(buffer, line, error);
    if (unisoku_sscanf(line, "ii", &type1, &type2) != 2) {
        /* FIXME */
        g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA,
                    _("Missing or invalid some integers heaven knows what "
                      "they mean but that should be here."));
        return FALSE;
    }
    ufile->dim_x = type1;
    ufile->dim_y = type2;

    NEXT(buffer, line, error);
    ufile->unit_x = g_strdup(line);

    NEXT(buffer, line, error);
    if (unisoku_sscanf(line, "ddi",
                       &ufile->start_x, &ufile->end_x,
                       &ufile->log_flag_x) != 3) {
        err_INVALID(error, _("x scale parameters"));
        return FALSE;
    }

    NEXT(buffer, line, error);
    ufile->unit_y = g_strdup(line);

    NEXT(buffer, line, error);
    if (unisoku_sscanf(line, "ddii",
                       &ufile->start_y, &ufile->end_y,
                       &ufile->ineq_flag, &ufile->log_flag_y) != 4) {
        err_INVALID(error, _("y scale parameters"));
        return FALSE;
    }

    /* Use negated positive conditions to catch NaNs */
    if (!(ufile->end_x - ufile->start_x > 0)) {
        g_warning("Real x size is 0.0, fixing to 1.0");
        ufile->start_x = 0.0;
        ufile->end_x = 1.0;
    }
    if (!(ufile->end_y - ufile->start_y > 0)) {
        g_warning("Real y size is 0.0, fixing to 1.0");
        ufile->start_y = 0.0;
        ufile->end_y = 1.0;
    }

    NEXT(buffer, line, error);
    ufile->unit_z = g_strdup(line);

    NEXT(buffer, line, error);
    if (unisoku_sscanf(line, "ddddi",
                       &ufile->max_raw_z, &ufile->min_raw_z,
                       &ufile->max_z, &ufile->min_z,
                       &ufile->log_flag_z) != 5) {
        err_INVALID(error, _("z scale parameters"));
        return FALSE;
    }

    NEXT(buffer, line, error);
    if (unisoku_sscanf(line, "dddi",
                       &ufile->stm_voltage, &ufile->stm_current,
                       &ufile->scan_time, &ufile->accum) != 4) {
        err_INVALID(error, _("data type parameters"));
        return FALSE;
    }

    NEXT(buffer, line, error);
    /* reserved */

    NEXT(buffer, line, error);
    ufile->stm_voltage_unit = g_strdup(line);

    NEXT(buffer, line, error);
    ufile->stm_current_unit = g_strdup(line);

    NEXT(buffer, line, error);
    ufile->ad_name = g_strdup(line);

    /* There is more stuff after that, but heaven knows what it means... */

    return TRUE;
}
Пример #25
0
static gboolean
rhk_sm4_read_page_header(RHKPage *page,
                         const RHKObject *obj,
                         const guchar *buffer,
                         gsize size,
                         GError **error)
{
    const guchar *p;
    guint i;

    if (obj->size < PAGE_HEADER_SIZE) {
        err_OBJECT_TRUNCATED(error, RHK_OBJECT_PAGE_HEADER);
        return FALSE;
    }

    p = buffer + obj->offset;
    page->field_size = gwy_get_guint16_le(&p);
    if (obj->size < page->field_size) {
        err_OBJECT_TRUNCATED(error, RHK_OBJECT_PAGE_HEADER);
        return FALSE;
    }

    page->string_count = gwy_get_guint16_le(&p);
    gwy_debug("string_count = %u", page->string_count);
    page->page_type = gwy_get_guint32_le(&p);
    gwy_debug("page_type = %u", page->page_type);
    page->data_sub_source = gwy_get_guint32_le(&p);
    page->line_type = gwy_get_guint32_le(&p);
    page->x_coord = gwy_get_gint32_le(&p);
    page->y_coord = gwy_get_gint32_le(&p);
    gwy_debug("x_coord = %u, y_coord = %u", page->x_coord, page->y_coord);
    page->x_size = gwy_get_guint32_le(&p);
    page->y_size = gwy_get_guint32_le(&p);
    gwy_debug("x_size = %u, y_size = %u", page->x_size, page->y_size);
    if (err_DIMENSION(error, page->x_size)
        || err_DIMENSION(error, page->y_size))
        return FALSE;

    page->image_type = gwy_get_guint32_le(&p);
    gwy_debug("image_type = %u", page->image_type);
    page->scan_dir = gwy_get_guint32_le(&p);
    gwy_debug("scan_dir = %u", page->scan_dir);
    page->group_id = gwy_get_guint32_le(&p);
    gwy_debug("group_id = 0x%08x", page->group_id);
    page->data_size = gwy_get_guint32_le(&p);
    gwy_debug("data_size = %u", page->data_size);
    page->min_z_value = gwy_get_gint32_le(&p);
    page->max_z_value = gwy_get_gint32_le(&p);
    gwy_debug("min,max_z_value = %d %d", page->min_z_value, page->max_z_value);
    page->x_scale = gwy_get_gfloat_le(&p);
    page->y_scale = gwy_get_gfloat_le(&p);
    page->z_scale = gwy_get_gfloat_le(&p);
    gwy_debug("x,y,z_scale = %g %g %g",
              page->x_scale, page->y_scale, page->z_scale);
    /* Use negated positive conditions to catch NaNs */
    /* Must not take the absolute value here, spectra may have valid negative
     * scales. */
    if (!(page->x_scale != 0)) {
        g_warning("Real x scale is 0.0, fixing to 1.0");
        page->x_scale = 1.0;
    }
    if (!(page->y_scale != 0)) {
        g_warning("Real y scale is 0.0, fixing to 1.0");
        page->y_scale = 1.0;
    }
    page->xy_scale = gwy_get_gfloat_le(&p);
    page->x_offset = gwy_get_gfloat_le(&p);
    page->y_offset = gwy_get_gfloat_le(&p);
    page->z_offset = gwy_get_gfloat_le(&p);
    gwy_debug("x,y,z_offset = %g %g %g",
              page->x_offset, page->y_offset, page->z_offset);
    page->period = gwy_get_gfloat_le(&p);
    page->bias = gwy_get_gfloat_le(&p);
    page->current = gwy_get_gfloat_le(&p);
    page->angle = gwy_get_gfloat_le(&p);
    gwy_debug("period = %g, bias = %g, current = %g, angle = %g",
              page->period, page->bias, page->current, page->angle);
    page->color_info_count = gwy_get_guint32_le(&p);
    gwy_debug("color_info_count = %u", page->color_info_count);
    page->grid_x_size = gwy_get_guint32_le(&p);
    page->grid_y_size = gwy_get_guint32_le(&p);
    gwy_debug("gird_x,y = %u %u", page->grid_x_size, page->grid_y_size);
    page->object_count = gwy_get_guint32_le(&p);
    for (i = 0; i < G_N_ELEMENTS(page->reserved); i++)
        page->reserved[i] = gwy_get_guint32_le(&p);

    if (!(page->objects = rhk_sm4_read_objects(buffer, p, size,
                                               page->object_count,
                                               RHK_OBJECT_PAGE_HEADER,
                                               error)))
        return FALSE;

    return TRUE;
}
Пример #26
0
static gboolean
omicron_read_header(gchar *buffer,
                    OmicronFile *ofile,
                    GError **error)
{
    gchar *line, *val, *comment;

    ofile->meta = g_hash_table_new(g_str_hash, g_str_equal);

    while ((line = gwy_str_next_line(&buffer))) {
        /* FIXME: This strips 2nd and following lines from possibly multiline
         * fields like Comment. */
        if (!line[0] || line[0] == ';' || g_ascii_isspace(line[0]))
            continue;

        val = strchr(line, ':');
        if (!val) {
            g_set_error(error, GWY_MODULE_FILE_ERROR,
                        GWY_MODULE_FILE_ERROR_DATA,
                        _("Missing colon in header line."));
            return FALSE;
        }
        if (val == line) {
            g_set_error(error, GWY_MODULE_FILE_ERROR,
                        GWY_MODULE_FILE_ERROR_DATA,
                        _("Header line starts with a colon."));
            return FALSE;
        }
        *val = '\0';
        val++;
        g_strstrip(line);
        comment = strchr(val, ';');
        if (comment) {
            /* If the coment has the form ;[units], move the [units] part after
             * the number. */
            if (comment[1] == '[' && (g_ascii_isalpha(comment[2])
                                      || comment[2] == '%')) {
                gchar *c, *s = comment-1;

                while (g_ascii_isspace(*s))
                    s--;
                s++;

                c = comment + 1;
                *c = ' ';
                while (*c && *c != ']')
                    *(s++) = *(c++);
                *s = '\0';
            }
            else
                *comment = '\0';
            comment++;
            g_strstrip(comment);
        }
        g_strstrip(val);

        if (gwy_strequal(line, "Topographic Channel")) {
            OmicronTopoChannel *channel;

            gwy_debug("Topographic Channel found (type %c)", val[0]);
            channel = g_new0(OmicronTopoChannel, 1);
            channel->type = val[0];
            if (!omicron_read_topo_header(&buffer, channel, error)) {
                g_free(channel);
                return FALSE;
            }
            if (!ofile->topo_channels)
                ofile->topo_channels = g_ptr_array_new();
            g_ptr_array_add(ofile->topo_channels, channel);
        }
        else if (gwy_strequal(line, "Spectroscopy Channel")) {
            OmicronSpectroChannel *channel;

            gwy_debug("Spectroscopic Channel found (chan %s)", val);

            channel = g_new0(OmicronSpectroChannel, 1);
            channel->chan = val;
            if (!omicron_read_spectro_header(&buffer, channel, error)) {
                g_free(channel);
                return FALSE;
            }
            if (!ofile->spectro_channels)
                ofile->spectro_channels = g_ptr_array_new();
            g_ptr_array_add(ofile->spectro_channels, channel);

        }
        else {
            gwy_debug("<%s> = <%s>", line, val);
            g_hash_table_insert(ofile->meta, line, val);
        }
    }

    GET_FIELD(ofile->meta, val, "Image Size in X", error);
    ofile->xres = abs(atoi(val));
    GET_FIELD(ofile->meta, val, "Image Size in Y", error);
    ofile->yres = abs(atoi(val));
    if (err_DIMENSION(error, ofile->xres)
        || err_DIMENSION(error, ofile->yres))
        return FALSE;

    GET_FIELD(ofile->meta, val, "Field X Size in nm", error);
    ofile->xreal = g_ascii_strtod(val, NULL);
    GET_FIELD(ofile->meta, val, "Field Y Size in nm", error);
    ofile->yreal = g_ascii_strtod(val, NULL);
    /* Use negated positive conditions to catch NaNs */
    if (!((ofile->xreal = fabs(ofile->xreal)) > 0)) {
        g_warning("Real x size is 0.0, fixing to 1.0");
        ofile->xreal = 1.0;
    }
    if (!((ofile->yreal = fabs(ofile->yreal)) > 0)) {
        g_warning("Real y size is 0.0, fixing to 1.0");
        ofile->yreal = 1.0;
    }
    ofile->xreal *= Nanometer;
    ofile->yreal *= Nanometer;

    return TRUE;
}
Пример #27
0
static gsize
pt3file_read_header(const guchar *buffer,
                    gsize size,
                    PicoHarpFile *pt3file,
                    GError **error)
{
    const guchar* (*read_imaging_header)(PicoHarpImagingHeader *header,
                                         const guchar *p);
    PicoHarpInstrument instr;
    const guchar *p;
    guint i, expected_size;

    p = buffer;
    if (size < HEADER_MIN_SIZE + 2) {
        err_TOO_SHORT(error);
        return 0;
    }

    get_CHARARRAY(pt3file->ident, &p);
    get_CHARARRAY(pt3file->format_version, &p);
    get_CHARARRAY(pt3file->creator_name, &p);
    get_CHARARRAY(pt3file->creator_version, &p);
    gwy_debug("<%.*s> <%.*s> <%.*s> <%.*s>",
              (gint)sizeof(pt3file->ident), pt3file->ident,
              (gint)sizeof(pt3file->format_version), pt3file->format_version,
              (gint)sizeof(pt3file->creator_name), pt3file->creator_name,
              (gint)sizeof(pt3file->creator_version), pt3file->creator_version);
    get_CHARARRAY(pt3file->file_time, &p);
    get_CHARARRAY(pt3file->crlf, &p);
    get_CHARARRAY(pt3file->comment, &p);
    if (memcmp(pt3file->ident, MAGIC, MAGIC_SIZE) != 0
        || pt3file->crlf[0] != '\r'
        || pt3file->crlf[1] != '\n') {
        err_FILE_TYPE(error, "PicoHarp");
        return 0;
    }

    pt3file->number_of_curves = gwy_get_guint32_le(&p);
    gwy_debug("number_of_curves: %u", pt3file->number_of_curves);
    pt3file->bits_per_record = gwy_get_guint32_le(&p);
    gwy_debug("bits_per_record: %u", pt3file->bits_per_record);
    pt3file->routing_channels = gwy_get_guint32_le(&p);
    gwy_debug("routing_channels: %u", pt3file->routing_channels);
    pt3file->number_of_boards = gwy_get_guint32_le(&p);
    gwy_debug("number_of_boards: %u", pt3file->number_of_boards);
    if (pt3file->number_of_boards != 1) {
        g_warning("Number of boards is %u instead of 1.  Reading one.",
                  pt3file->number_of_boards);

        pt3file->number_of_boards = MAX(pt3file->number_of_boards, 1);
        if (size < HEADER_MIN_SIZE + BOARD_SIZE*pt3file->number_of_boards) {
            g_set_error(error, GWY_MODULE_FILE_ERROR,
                        GWY_MODULE_FILE_ERROR_DATA,
                        _("File header is truncated."));
            return 0;
        }
    }
    pt3file->active_curve = gwy_get_guint32_le(&p);
    pt3file->measurement_mode = gwy_get_guint32_le(&p);
    gwy_debug("measurement_mode: %u", pt3file->measurement_mode);
    pt3file->sub_mode = gwy_get_guint32_le(&p);
    gwy_debug("sub_mode: %u", pt3file->sub_mode);
    pt3file->range_no = gwy_get_guint32_le(&p);
    pt3file->offset = gwy_get_gint32_le(&p);
    pt3file->acquisition_time = gwy_get_guint32_le(&p);
    pt3file->stop_at = gwy_get_guint32_le(&p);
    pt3file->stop_on_ovfl = gwy_get_guint32_le(&p);
    pt3file->restart = gwy_get_guint32_le(&p);
    pt3file->display_lin_log = !!gwy_get_guint32_le(&p);
    pt3file->display_time_axis_from = gwy_get_guint32_le(&p);
    pt3file->display_time_axis_to = gwy_get_guint32_le(&p);
    pt3file->display_counts_axis_from = gwy_get_guint32_le(&p);
    pt3file->display_counts_axis_to = gwy_get_guint32_le(&p);
    for (i = 0; i < G_N_ELEMENTS(pt3file->display_curve); i++) {
        pt3file->display_curve[i].map_to = gwy_get_guint32_le(&p);
        pt3file->display_curve[i].show = gwy_get_guint32_le(&p);
    }
    for (i = 0; i < G_N_ELEMENTS(pt3file->auto_param); i++) {
        pt3file->auto_param[i].start = gwy_get_gfloat_le(&p);
        pt3file->auto_param[i].step = gwy_get_gfloat_le(&p);
        pt3file->auto_param[i].end = gwy_get_gfloat_le(&p);
    }
    pt3file->repeat_mode = gwy_get_guint32_le(&p);
    pt3file->repeats_per_curve = gwy_get_guint32_le(&p);
    pt3file->repeat_time = gwy_get_guint32_le(&p);
    pt3file->repeat_wait_time = gwy_get_guint32_le(&p);
    get_CHARARRAY(pt3file->script_name, &p);
    p = pt3file_read_board(&pt3file->board, p);
    p += BOARD_SIZE*(pt3file->number_of_boards - 1);
    pt3file->ext_devices = gwy_get_guint32_le(&p);
    pt3file->reserved1 = gwy_get_guint32_le(&p);
    pt3file->reserved2 = gwy_get_guint32_le(&p);
    pt3file->input0_rate = gwy_get_guint32_le(&p);
    pt3file->input1_rate = gwy_get_guint32_le(&p);
    pt3file->stop_after = gwy_get_guint32_le(&p);
    pt3file->stop_reason = gwy_get_guint32_le(&p);
    pt3file->number_of_records = gwy_get_guint32_le(&p);
    gwy_debug("number_of_records: %u", pt3file->number_of_records);
    pt3file->spec_header_length = 4*gwy_get_guint32_le(&p);
    gwy_debug("spec_header_length: %u", pt3file->spec_header_length);
    gwy_debug("now at pos 0x%0lx", (gulong)(p - buffer));

    if (pt3file->measurement_mode != 2
        && pt3file->measurement_mode != 3) {
        g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA,
                    _("Measurement mode must be 2 or 3; %u is invalid."),
                    pt3file->measurement_mode);
        return 0;
    }
    if (pt3file->sub_mode != PICO_HARP_IMAGE) {
        g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA,
                    _("Only area imaging files are supported."));
        return 0;
    }
    if (pt3file->bits_per_record != 32) {
        err_BPP(error, pt3file->bits_per_record);
        return 0;
    }

    pt3file->imaging.common.dimensions = gwy_get_guint32_le(&p);
    gwy_debug("imaging dimensions: %u", pt3file->imaging.common.dimensions);
    if (pt3file->imaging.common.dimensions != 3) {
        g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA,
                    _("Only area imaging files are supported."));
        return 0;
    }
    pt3file->imaging.common.instrument = instr = gwy_get_guint32_le(&p);
    gwy_debug("imaging instrument: %u", pt3file->imaging.common.instrument);
    if (instr == PICO_HARP_PIE710) {
        expected_size = IMAGING_PIE710_SIZE;
        read_imaging_header = &read_pie710_imaging_header;
    }
    else if (instr == PICO_HARP_KDT180) {
        expected_size = IMAGING_KDT180_SIZE;
        read_imaging_header = &read_kdt180_imaging_header;
    }
    else if (instr == PICO_HARP_LSM) {
        expected_size = IMAGING_LSM_SIZE;
        read_imaging_header = &read_lsm_imaging_header;
    }
    else {
        g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA,
                    _("Unknown instrument number %u."),
                    instr);
        return 0;
    }

    if (pt3file->spec_header_length != expected_size) {
        g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA,
                    _("Wrong imaging header size: %u instead of %u."),
                    pt3file->spec_header_length, expected_size);
        return 0;
    }
    if ((p - buffer) + expected_size > size) {
        g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA,
                    _("File header is truncated."));
        return 0;
    }

    p = read_imaging_header(&pt3file->imaging, p);
    gwy_debug("xres: %u", pt3file->imaging.common.xres);
    gwy_debug("yres: %u", pt3file->imaging.common.yres);

    if (err_DIMENSION(error, pt3file->imaging.common.xres)
        || err_DIMENSION(error, pt3file->imaging.common.xres))
        return 0;

    return (gsize)(p - buffer);
}
Пример #28
0
static GwyContainer*
int_load(const gchar *filename,
         G_GNUC_UNUSED GwyRunType mode,
         GError **error)
{
    GwyContainer *container = NULL, *meta;
    GwyDataField *dfield = NULL, *mfield = NULL;
    CodeVGridDataType type;
    gchar *line, *p, *comment, *end, *buffer = NULL;
    const gchar *unit, *title;
    gchar **fields = NULL;
    gsize size;
    GError *err = NULL;
    gdouble xreal, yreal;
    gint i, xres, yres, no_data_value = 32767;
    guint fi;
    gdouble scale_size, wavelength, q = 1.0, x_scale = 1.0;
    gboolean nearest_neighbour = FALSE;
    gdouble *data, *mdata;

    if (!g_file_get_contents(filename, &buffer, &size, &err)) {
        err_GET_FILE_CONTENTS(error, &err);
        goto fail;
    }

    /* Skip comments. */
    p = buffer;
    for (line = gwy_str_next_line(&p);
         line && line[0] == '!';
         line = gwy_str_next_line(&p)) {
        gwy_debug("comment <%s>", line);
    }
    if (!line) {
        err_FILE_TYPE(error, "Code V INT");
        goto fail;
    }

    /* The title. */
    comment = line;
    if (!(line = gwy_str_next_line(&p))) {
        err_FILE_TYPE(error, "Code V INT");
        goto fail;
    }
    gwy_debug("comment <%s>", comment);

    fields = split_line_in_place(line);
    if (!fields
        || g_strv_length(fields) < 8
        || !gwy_strequal(fields[0], "GRD")
        || !(xres = atoi(fields[1]))
        || !(yres = atoi(fields[2]))
        || !(type = gwy_stramong(fields[3],
                                 "SUR", "WFR", "FIL", "THV", "BIR", "CAO",
                                 NULL))
        || !gwy_strequal(fields[4], "WVL")
        || (!(wavelength = g_ascii_strtod(fields[5], &end))
              && end == fields[5])) {
        err_FILE_TYPE(error, "Code V INT");
        goto fail;
    }
    gwy_debug("type %u (%s)", type, fields[3]);
    gwy_debug("xres %d, yres %d", xres, yres);
    gwy_debug("wavelength %g", wavelength);
    fi = 6;
    if (gwy_strequal(fields[fi], "NNB")) {
        nearest_neighbour = TRUE;
        fi++;
    }
    gwy_debug("nearest_neighbour %d", nearest_neighbour);

    if (!fields[fi] || !gwy_strequal(fields[fi], "SSZ")) {
        err_FILE_TYPE(error, "Code V INT");
        goto fail;
    }
    fi++;
    if (!(scale_size = g_ascii_strtod(fields[fi], &end)) && end == fields[fi]) {
        err_FILE_TYPE(error, "Code V INT");
        goto fail;
    }
    gwy_debug("scale_size %g", scale_size);
    if (!scale_size) {
        g_warning("Zero SSZ, fixing to 1.0");
        scale_size = 1.0;
    }
    fi++;

    if (fields[fi] && gwy_strequal(fields[fi], "NDA")) {
        fi++;
        if (!fields[fi]) {
            err_FILE_TYPE(error, "Code V INT");
            goto fail;
        }
        no_data_value = atoi(fields[fi]);
        fi++;
    }
    gwy_debug("no_data_value %d", no_data_value);

    if (fields[fi] && gwy_strequal(fields[fi], "XSC")) {
        fi++;
        if (!fields[fi]) {
            err_FILE_TYPE(error, "Code V INT");
            goto fail;
        }
        if (!(x_scale = g_ascii_strtod(fields[fi], &end))
            && end == fields[fi]) {
            err_FILE_TYPE(error, "Code V INT");
            goto fail;
        }
        fi++;
    }
    gwy_debug("x_scale %g", x_scale);
    if (!x_scale) {
        g_warning("Zero XSC, fixing to 1.0");
        x_scale = 1.0;
    }

    /* There may be more stuff but we do not know anything about it. */

    if (err_DIMENSION(error, xres) || err_DIMENSION(error, yres))
        goto fail;

    yreal = 1.0;
    xreal = x_scale*yreal;
    dfield = gwy_data_field_new(xres, yres, xreal, yreal, TRUE);

    if (type == CODEV_INT_SURFACE_DEFORMATION) {
        q = 1e-6*wavelength/scale_size;
        unit = "m";
        title = "Surface";
    }
    else if (type == CODEV_INT_WAVEFRONT_DEFORMATION) {
        q = 1e-6*wavelength/scale_size;
        unit = "m";
        title = "Wavefront";
    }
    else {
        g_warning("Don't know how to convert this grid data type to physical "
                  "units.");
        title = fields[3];
    }

    gwy_si_unit_set_from_string(gwy_data_field_get_si_unit_z(dfield), unit);

    mfield = gwy_data_field_new_alike(dfield, TRUE);
    data = gwy_data_field_get_data(dfield);
    mdata = gwy_data_field_get_data(mfield);

    for (i = 0; i < xres*yres; i++, p = end) {
        gint value = strtol(p, &end, 10);

        if (value != no_data_value && (type != CODEV_INT_INTENSITY_FILTER
                                       || value >= 0)) {
            mdata[i] = 1.0;
            data[i] = q*value;
        }
    }

    if (!gwy_app_channel_remove_bad_data(dfield, mfield))
        gwy_object_unref(mfield);

    container = gwy_container_new();

    /*
    gwy_data_field_invert(dfield, TRUE, FALSE, FALSE);
    from F. Riguet : apparently no flip is needed (the raw data import module
    gives the correct orientation without further flipping)
    */
    gwy_container_set_object(container, gwy_app_get_data_key_for_id(0), dfield);
    g_object_unref(dfield);
    gwy_app_channel_check_nonsquare(container, 0);

    gwy_container_set_string_by_name(container, "/0/data/title",
                                     g_strdup(title));

    if (mfield) {
        /*
        gwy_data_field_invert(mfield, FALSE, TRUE, FALSE);
        */
        gwy_container_set_object(container, gwy_app_get_mask_key_for_id(0),
                                 mfield);
        g_object_unref(mfield);
    }

    meta = gwy_container_new();

    gwy_container_set_string_by_name(meta, "Comment", g_strdup(comment));
    gwy_container_set_string_by_name(meta, "Interpolation",
                                     g_strdup(nearest_neighbour
                                              ? "NNB" : "Linear"));
    gwy_container_set_string_by_name(meta, "Wavelength",
                                     g_strdup_printf("%g μm", wavelength));

    gwy_container_set_object_by_name(container, "/0/meta", meta);
    g_object_unref(meta);

    gwy_file_channel_import_log_add(container, 0, NULL, filename);

fail:
    g_free(fields);
    g_free(buffer);

    return container;
}
Пример #29
0
static GwyContainer*
amb_load(const gchar *filename,
         G_GNUC_UNUSED GwyRunType mode,
         GError **error)
{
    GwyContainer *container = NULL;
    guchar *buffer = NULL;
    const guchar *p;
    gdouble *data;
    guint i, j;
    gsize size = 0;
    GError *err = NULL;
    guint xres, yres;
    GwyDataField *dfield;

    if (!gwy_file_get_contents(filename, &buffer, &size, &err)) {
        err_GET_FILE_CONTENTS(error, &err);
        return NULL;
    }
    if (size <= HEADER_SIZE) {
        err_TOO_SHORT(error);
        goto fail;
    }

    /* The two bytes before are usually zeroes */
    p = buffer + XRES_OFFSET;
    xres = gwy_get_guint32_le(&p);
    p = buffer + YRES_OFFSET;
    yres = gwy_get_guint32_le(&p);
    gwy_debug("xres: %u yres: %u", xres, yres);
    /* The four bytes after might be a float, then there are four more bytes. */
    if (err_DIMENSION(error, xres) || err_DIMENSION(error, yres))
        goto fail;
    if (err_SIZE_MISMATCH(error, 4*xres*yres + HEADER_SIZE, size, TRUE))
        goto fail;

    dfield = gwy_data_field_new(xres, yres, 1.0, 1.0*yres/xres,
                                FALSE);
    data = gwy_data_field_get_data(dfield);
    p = buffer + HEADER_SIZE;
    for (i = 0; i < yres; i++) {
        for (j = 0; j < xres; j++)
            data[i*xres + j] = gwy_get_gfloat_le(&p);
    }

    gwy_si_unit_set_from_string(gwy_data_field_get_si_unit_xy(dfield), "m");
    gwy_si_unit_set_from_string(gwy_data_field_get_si_unit_z(dfield), "m");

    container = gwy_container_new();
    gwy_container_set_object_by_name(container, "/0/data", dfield);
    gwy_container_set_string_by_name(container, "/0/data/title",
                                     g_strdup("Topography"));
    g_object_unref(dfield);

    gwy_file_channel_import_log_add(container, 0, NULL, filename);

fail:
    gwy_file_abandon_contents(buffer, size, NULL);

    return container;
}
Пример #30
0
static GwyContainer*
surffile_load(const gchar *filename,
             G_GNUC_UNUSED GwyRunType mode,
             GError **error)
{
    SurfFile surffile;
    gint coef = 0;
    GwyContainer *meta, *container = NULL;
    guchar *buffer = NULL;
    const guchar *p;
    gsize expected_size, size = 0;
    GError *err = NULL;
    gchar signature[12];

    gint add = 0;

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

    if (size < SURF_HEADER_SIZE + 2) {
        err_TOO_SHORT(error);
        gwy_file_abandon_contents(buffer, size, NULL);
        return NULL;
    }

    p = buffer;

    get_CHARARRAY(signature, &p);
    if (strncmp(signature, "DIGITAL SURF", 12) != 0) {
        err_FILE_TYPE(error, "Surf");
        gwy_file_abandon_contents(buffer, size, NULL);
        return NULL;
    }

    surffile.format = gwy_get_guint16_le(&p);
    surffile.nobjects = gwy_get_guint16_le(&p);
    surffile.version = gwy_get_guint16_le(&p);
    surffile.type = gwy_get_guint16_le(&p);
    get_CHARS0(surffile.object_name, &p, 30);
    get_CHARS0(surffile.operator_name, &p, 30);
    surffile.material_code = gwy_get_guint16_le(&p);
    surffile.acquisition = gwy_get_guint16_le(&p);
    surffile.range = gwy_get_guint16_le(&p);
    surffile.special_points = gwy_get_guint16_le(&p);
    surffile.absolute = gwy_get_guint16_le(&p);
    /*reserved*/
    p += 8;
    surffile.pointsize = gwy_get_guint16_le(&p);
    surffile.zmin = gwy_get_gint32_le(&p);
    surffile.zmax = gwy_get_gint32_le(&p);
    surffile.xres = gwy_get_gint32_le(&p);
    surffile.yres = gwy_get_gint32_le(&p);
    surffile.nofpoints = gwy_get_guint32_le(&p);

    surffile.dx = gwy_get_gfloat_le(&p);
    surffile.dy = gwy_get_gfloat_le(&p);
    surffile.dz = gwy_get_gfloat_le(&p);
    get_CHARS0(surffile.xaxis, &p, 16);
    get_CHARS0(surffile.yaxis, &p, 16);
    get_CHARS0(surffile.zaxis, &p, 16);
    get_CHARS0(surffile.dx_unit, &p, 16);
    get_CHARS0(surffile.dy_unit, &p, 16);
    get_CHARS0(surffile.dz_unit, &p, 16);
    get_CHARS0(surffile.xlength_unit, &p, 16);
    get_CHARS0(surffile.ylength_unit, &p, 16);
    get_CHARS0(surffile.zlength_unit, &p, 16);

    surffile.xunit_ratio = gwy_get_gfloat_le(&p);
    surffile.yunit_ratio = gwy_get_gfloat_le(&p);
    surffile.zunit_ratio = gwy_get_gfloat_le(&p);
    surffile.imprint = gwy_get_guint16_le(&p);
    surffile.inversion = gwy_get_guint16_le(&p);
    surffile.leveling = gwy_get_guint16_le(&p);

    p += 12;

    surffile.seconds = gwy_get_guint16_le(&p);
    surffile.minutes = gwy_get_guint16_le(&p);
    surffile.hours = gwy_get_guint16_le(&p);
    surffile.day = gwy_get_guint16_le(&p);
    surffile.month = gwy_get_guint16_le(&p);
    surffile.year = gwy_get_guint16_le(&p);
    surffile.dayof = gwy_get_guint16_le(&p);
    surffile.measurement_duration = gwy_get_gfloat_le(&p);
    p += 10;

    surffile.comment_size = gwy_get_guint16_le(&p);
    surffile.private_size = gwy_get_guint16_le(&p);

    get_CHARARRAY(surffile.client_zone, &p);
    surffile.XOffset = gwy_get_gfloat_le(&p);
    surffile.YOffset = gwy_get_gfloat_le(&p);
    surffile.ZOffset = gwy_get_gfloat_le(&p);


    gwy_debug("fileformat: %d,  n_of_objects: %d, "
              "version: %d, object_type: %d",
              surffile.format, surffile.nobjects,
              surffile.version, surffile.type);
    gwy_debug("object name: <%s>", surffile.object_name);
    gwy_debug("operator name: <%s>", surffile.operator_name);

    gwy_debug("material code: %d, acquisition type: %d",
              surffile.material_code, surffile.acquisition);
    gwy_debug("range type: %d, special points: %d, absolute: %d",
              surffile.range,
              surffile.special_points, (gint)surffile.absolute);
    gwy_debug("data point size: %d", surffile.pointsize);
    gwy_debug("zmin: %d, zmax: %d", surffile.zmin, surffile.zmax);
    gwy_debug("xres: %d, yres: %d (xres*yres = %d)",
              surffile.xres, surffile.yres, (surffile.xres*surffile.yres));
    gwy_debug("total number of points: %d", surffile.nofpoints);
    gwy_debug("dx: %g, dy: %g, dz: %g",
              surffile.dx, surffile.dy, surffile.dz);
    gwy_debug("X axis name: %16s", surffile.xaxis);
    gwy_debug("Y axis name: %16s", surffile.yaxis);
    gwy_debug("Z axis name: %16s", surffile.zaxis);
    gwy_debug("dx unit: %16s", surffile.dx_unit);
    gwy_debug("dy unit: %16s", surffile.dy_unit);
    gwy_debug("dz unit: %16s", surffile.dz_unit);
    gwy_debug("X axis unit: %16s", surffile.xlength_unit);
    gwy_debug("Y axis unit: %16s", surffile.ylength_unit);
    gwy_debug("Z axis unit: %16s", surffile.zlength_unit);
    gwy_debug("xunit_ratio: %g, yunit_ratio: %g, zunit_ratio: %g",
              surffile.xunit_ratio, surffile.yunit_ratio, surffile.zunit_ratio);
    gwy_debug("imprint: %d, inversion: %d, leveling: %d",
              surffile.imprint, surffile.inversion, surffile.leveling);
    gwy_debug("Time: %d:%d:%d, Date: %d.%d.%d",
              surffile.hours, surffile.minutes, surffile.seconds,
              surffile.day, surffile.month, surffile.year);
    gwy_debug("private zone size: %d, comment size %d",
              surffile.private_size, surffile.comment_size);

    if (err_DIMENSION(error, surffile.xres)
        || err_DIMENSION(error, surffile.yres)) {
        gwy_file_abandon_contents(buffer, size, NULL);
        return NULL;
    }

    expected_size = (SURF_HEADER_SIZE
                     + surffile.pointsize/8*surffile.xres*surffile.yres);
    if (expected_size != size) {
        gwy_debug("Size mismatch!");
        if (size > expected_size)
            add = size - expected_size; /*TODO  correct this !*/
        else {
            err_SIZE_MISMATCH(error, expected_size, size, TRUE);
            gwy_file_abandon_contents(buffer, size, NULL);
          return NULL;
        }
    }

    /* Use negated positive conditions to catch NaNs */
    if (!((surffile.dx = fabs(surffile.dx)) > 0)) {
        g_warning("Real x step is 0.0, fixing to 1.0");
        surffile.dx = 1.0;
    }
    if (!((surffile.dy = fabs(surffile.dy)) > 0)) {
        g_warning("Real y step is 0.0, fixing to 1.0");
        surffile.dy = 1.0;
    }

    p = buffer + SURF_HEADER_SIZE + add;

    /*units*/
    coef = 0;
    surffile.xyunit = gwy_si_unit_new_parse(surffile.dx_unit, &coef);
    surffile.dx *= pow10(coef);
    coef = 0;
    surffile.xyunit = gwy_si_unit_new_parse(surffile.dy_unit, &coef);
    surffile.dy *= pow10(coef);

    coef = 0;
    surffile.zunit = gwy_si_unit_new_parse (surffile.dz_unit, &coef);
    if (!fill_data_fields(&surffile, p, error)) {
        gwy_file_abandon_contents(buffer, size, NULL);
        return NULL;
    }

    switch (surffile.inversion) {
        case SURF_INV_Z:
        gwy_data_field_invert(surffile.dfield, FALSE, FALSE, TRUE);
        break;

        case SURF_FLIP_Z:
        gwy_data_field_invert(surffile.dfield, FALSE, TRUE, TRUE);
        break;

        case SURF_FLOP_Z:
        gwy_data_field_invert(surffile.dfield, TRUE, FALSE, TRUE);
        break;

        default:
        break;
    }

    gwy_data_field_multiply(surffile.dfield, pow10(coef));
    surffile.ZOffset *=  pow10(coef);
    gwy_data_field_add(surffile.dfield, surffile.ZOffset);

    container = gwy_container_new();
    gwy_container_set_object_by_name(container, "/0/data", surffile.dfield);
    g_object_unref(surffile.dfield);

    meta = surffile_get_metadata(&surffile);
    gwy_container_set_object_by_name(container, "/0/meta", meta);
    g_object_unref(meta);

    gwy_app_channel_check_nonsquare(container, 0);
    gwy_file_channel_import_log_add(container, 0, NULL, filename);

    return container;
}