示例#1
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;
}
示例#2
0
static gboolean
x3p_file_get_data_type(const gchar *type,
                       GwyRawDataType *rawtype,
                       GError **error)
{
    if (gwy_strequal(type, "I")) {
        *rawtype = GWY_RAW_DATA_SINT16;
        return TRUE;
    }
    if (gwy_strequal(type, "L")) {
        *rawtype = GWY_RAW_DATA_SINT32;
        return TRUE;
    }
    if (gwy_strequal(type, "F")) {
        *rawtype = GWY_RAW_DATA_FLOAT;
        return TRUE;
    }
    if (gwy_strequal(type, "D")) {
        *rawtype = GWY_RAW_DATA_DOUBLE;
        return TRUE;
    }

    err_UNSUPPORTED(error, AXES_PREFIX "/CZ/DataType");
    return FALSE;
}
示例#3
0
static GwyDataField*
read_binary_data(const gchar *buffer,
                 gsize size,
                 GHashTable *hash,
                 GError **error)
{
    ShimadzuDataType data_type;
    gint xres, yres, i;
    guint expected;
    gdouble xreal, yreal, zscale, xoff, yoff, zoff;
    GwySIUnit *unitxy, *unitz;
    GwyDataField *dfield = NULL;
    gdouble *d;
    const gchar *s;

    if (!(s = g_hash_table_lookup(hash, "DataType"))) {
        err_MISSING_FIELD(error, "DataType");
        return NULL;
    }

    if (g_ascii_strcasecmp(s, "short") == 0)
        data_type = SHIMADZU_SHORT;
    else if (g_ascii_strcasecmp(s, "float") == 0)
        data_type = SHIMADZU_FLOAT;
    else {
        err_UNSUPPORTED(error, "DataType");
        return NULL;
    }

    unitxy = gwy_si_unit_new(NULL);
    unitz = gwy_si_unit_new(NULL);

    if (!get_scales(hash, FALSE,
                    &xres, &yres, &xreal, &yreal, &xoff, &yoff, unitxy,
                    &zscale, &zoff, unitz, error))
        goto fail;

    expected = data_type*xres*yres + HEADER_SIZE;
    if (err_SIZE_MISMATCH(error, expected, size, FALSE))
        goto fail;

    dfield = gwy_data_field_new(xres, yres, xreal, yreal, FALSE);
    gwy_data_field_set_xoffset(dfield, xoff);
    gwy_data_field_set_yoffset(dfield, yoff);
    gwy_data_field_set_si_unit_xy(dfield, unitxy);
    gwy_data_field_set_si_unit_z(dfield, unitz);
    d = gwy_data_field_get_data(dfield);

    if (data_type == SHIMADZU_SHORT) {
        const gint16 *d16 = (const gint16*)(buffer + HEADER_SIZE);

        for (i = 0; i < xres*yres; i++)
            d[i] = zscale*GUINT16_FROM_LE(d16[i]) + zoff;
    }
    else if (data_type == SHIMADZU_FLOAT) {
        const guchar *p = buffer + HEADER_SIZE;

        for (i = 0; i < xres*yres; i++)
            d[i] = zscale*gwy_get_gfloat_le(&p) + zoff;
    }
    else {
        g_assert_not_reached();
    }

    gwy_data_field_invert(dfield, TRUE, FALSE, FALSE);

fail:
    g_object_unref(unitxy);
    g_object_unref(unitz);
    return dfield;
}
示例#4
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;
}
示例#5
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;
}
示例#6
0
static gboolean
mprofile_read_header(const guchar *buffer,
                     gsize size,
                     MProFile *mprofile,
                     GError **error)
{
    const guchar *p;
    guint i;

    p = buffer;
    if (size < HEADER_SIZE + 2) {
        err_TOO_SHORT(error);
        return FALSE;
    }
    get_CHARARRAY(mprofile->magic, &p);
    if (memcmp(mprofile->magic, MAGIC, MAGIC_SIZE) != 0) {
        err_FILE_TYPE(error, "MetroPro");
        return FALSE;
    }

    mprofile->header_format = gwy_get_guint16_be(&p);
    if (mprofile->header_format != 1) {
        err_UNSUPPORTED(error, "FormatVersion");
        return FALSE;
    }
    mprofile->header_size = gwy_get_guint32_be(&p);
    gwy_debug("header_format: %d, header_size: %d",
              mprofile->header_format, mprofile->header_size);
    if (mprofile->header_size < 570) {
        g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA,
                    _("File header is too short."));
        return FALSE;
    }
    if (mprofile->header_size > size) {
        g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA,
                    _("File header is larger than file."));
        return FALSE;
    }
    mprofile->software_type = gwy_get_guint16_be(&p);
    get_CHARARRAY0(mprofile->software_date, &p);
    gwy_debug("software_type: %d, software_date: %s",
              mprofile->software_type, mprofile->software_date);

    mprofile->version_major = gwy_get_guint16_be(&p);
    mprofile->version_minor = gwy_get_guint16_be(&p);
    mprofile->version_micro = gwy_get_guint16_be(&p);
    gwy_debug("version: %d.%d.%d",
              mprofile->version_major,
              mprofile->version_minor,
              mprofile->version_micro);

    mprofile->intens_xoff = gwy_get_guint16_be(&p);
    mprofile->intens_yoff = gwy_get_guint16_be(&p);
    mprofile->intens_xres = gwy_get_guint16_be(&p);
    mprofile->intens_yres = gwy_get_guint16_be(&p);
    gwy_debug("INTENS xres: %d, yres: %d, xoff: %d, yoff: %d",
              mprofile->intens_xres, mprofile->intens_yres,
              mprofile->intens_xoff, mprofile->intens_yoff);
    mprofile->nbuckets = gwy_get_guint16_be(&p);
    mprofile->intens_range = gwy_get_guint16_be(&p);
    mprofile->intens_nbytes = gwy_get_guint32_be(&p);
    gwy_debug("intens_nbytes: %d, expecting: %d",
              mprofile->intens_nbytes,
              2*mprofile->intens_xres*mprofile->intens_yres*mprofile->nbuckets);

    mprofile->phase_xoff = gwy_get_guint16_be(&p);
    mprofile->phase_yoff = gwy_get_guint16_be(&p);
    mprofile->phase_xres = gwy_get_guint16_be(&p);
    mprofile->phase_yres = gwy_get_guint16_be(&p);
    gwy_debug("PHASE xres: %d, yres: %d, xoff: %d, yoff: %d",
              mprofile->phase_xres, mprofile->phase_yres,
              mprofile->phase_xoff, mprofile->phase_yoff);
    mprofile->phase_nbytes = gwy_get_guint32_be(&p);
    gwy_debug("phase_nbytes: %d, expecting: %d",
              mprofile->phase_nbytes,
              4*mprofile->phase_xres*mprofile->phase_yres);

    mprofile->timestamp = gwy_get_guint32_be(&p);
    get_CHARARRAY0(mprofile->comment, &p);
    gwy_debug("comment: %s", mprofile->comment);
    mprofile->source = gwy_get_guint16_be(&p);

    mprofile->scale_factor = gwy_get_gfloat_be(&p);
    mprofile->wavelength_in = gwy_get_gfloat_be(&p);
    mprofile->numeric_aperture = gwy_get_gfloat_be(&p);
    mprofile->obliquity_factor = gwy_get_gfloat_be(&p);
    mprofile->magnification = gwy_get_gfloat_be(&p);
    mprofile->camera_res = gwy_get_gfloat_be(&p);

    mprofile->acquire_mode = gwy_get_guint16_be(&p);
    gwy_debug("acquire_mode: %d", mprofile->acquire_mode);
    mprofile->intens_avgs = gwy_get_guint16_be(&p);
    if (!mprofile->intens_avgs)
        mprofile->intens_avgs = 1;
    mprofile->pzt_cal = gwy_get_guint16_be(&p);
    mprofile->pzt_gain_tolerance = gwy_get_guint16_be(&p);
    mprofile->pzt_gain = gwy_get_guint16_be(&p);
    mprofile->part_thickness = gwy_get_gfloat_be(&p);
    mprofile->agc = gwy_get_guint16_be(&p);
    mprofile->target_range = gwy_get_gfloat_be(&p);

    p += 2;
    mprofile->min_mod = gwy_get_guint32_be(&p);
    mprofile->min_mod_pts = gwy_get_guint32_be(&p);
    mprofile->phase_res = gwy_get_guint16_be(&p);
    mprofile->min_area_size = gwy_get_guint32_be(&p);
    mprofile->discont_action = gwy_get_guint16_be(&p);
    mprofile->discont_filter = gwy_get_gfloat_be(&p);
    mprofile->connection_order = gwy_get_guint16_be(&p);
    mprofile->data_inverted = gwy_get_guint16_be(&p);
    mprofile->camera_width = gwy_get_guint16_be(&p);
    mprofile->camera_height = gwy_get_guint16_be(&p);
    mprofile->system_type = gwy_get_guint16_be(&p);
    mprofile->system_board = gwy_get_guint16_be(&p);
    mprofile->system_serial = gwy_get_guint16_be(&p);
    mprofile->instrument_id = gwy_get_guint16_be(&p);
    get_CHARARRAY0(mprofile->objective_name, &p);
    get_CHARARRAY0(mprofile->part_num, &p);
    gwy_debug("part_num: %s", mprofile->part_num);
    mprofile->code_vtype = gwy_get_guint16_be(&p);
    mprofile->phase_avgs = gwy_get_guint16_be(&p);
    mprofile->subtract_sys_err = gwy_get_guint16_be(&p);
    p += 16;
    get_CHARARRAY0(mprofile->part_ser_num, &p);
    mprofile->refactive_index = gwy_get_gfloat_be(&p);
    mprofile->remove_tilt_bias = gwy_get_guint16_be(&p);
    mprofile->remove_fringes = gwy_get_guint16_be(&p);
    mprofile->max_area_size = gwy_get_guint32_be(&p);
    mprofile->setup_type = gwy_get_guint16_be(&p);
    p += 2;
    mprofile->pre_connect_filter = gwy_get_gfloat_be(&p);

    mprofile->wavelength2 = gwy_get_gfloat_be(&p);
    mprofile->wavelength_fold = gwy_get_guint16_be(&p);
    mprofile->wavelength1 = gwy_get_gfloat_be(&p);
    mprofile->wavelength3 = gwy_get_gfloat_be(&p);
    mprofile->wavelength4 = gwy_get_gfloat_be(&p);
    get_CHARARRAY0(mprofile->wavelength_select, &p);
    mprofile->fda_res = gwy_get_guint16_be(&p);
    get_CHARARRAY0(mprofile->scan_description, &p);
    gwy_debug("scan_description: %s", mprofile->scan_description);

    mprofile->nfiducials = gwy_get_guint16_be(&p);
    for (i = 0; i < G_N_ELEMENTS(mprofile->fiducials); i++)
        mprofile->fiducials[i] = gwy_get_gfloat_be(&p);

    mprofile->pixel_width = gwy_get_gfloat_be(&p);
    mprofile->pixel_height = gwy_get_gfloat_be(&p);
    mprofile->exit_pupil_diam = gwy_get_gfloat_be(&p);
    mprofile->light_level_pct = gwy_get_gfloat_be(&p);
    mprofile->coords_state = gwy_get_guint32_be(&p);
    mprofile->xpos = gwy_get_gfloat_be(&p);
    mprofile->ypos = gwy_get_gfloat_be(&p);
    mprofile->zpos = gwy_get_gfloat_be(&p);
    mprofile->xrot = gwy_get_gfloat_be(&p);
    mprofile->yrot = gwy_get_gfloat_be(&p);
    mprofile->zrot = gwy_get_gfloat_be(&p);
    mprofile->coherence_mode = gwy_get_guint16_be(&p);
    mprofile->surface_filter = gwy_get_guint16_be(&p);
    get_CHARARRAY0(mprofile->sys_err_file, &p);
    get_CHARARRAY0(mprofile->zoom_desc, &p);

    return TRUE;
}
示例#7
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;
}