示例#1
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;
}
示例#2
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;
}
示例#3
0
static gboolean
parse_scale(gchar **p,
            const gchar *name,
            double *value,
            GwySIUnit **units,
            GError **error)
{
    gint power10;
    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 = g_ascii_strtod(vp, &vp);
    *units = gwy_si_unit_new_parse(vp, &power10);
    *value *= pow10(power10);

    if (!*value) {
        g_warning("%s is 0.0, fixing to 1.0", name);
        *value = 1.0;
    }

    return TRUE;
}
示例#4
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;
}
示例#5
0
static gboolean
require_keys(GHashTable *hash,
             GError **error,
             ...)
{
    va_list ap;
    const gchar *key;

    va_start(ap, error);
    while ((key = va_arg(ap, const gchar *))) {
        if (!g_hash_table_lookup(hash, key)) {
            err_MISSING_FIELD(error, key);
            va_end(ap);
            return FALSE;
        }
    }
    va_end(ap);

    return TRUE;
}
示例#6
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;
}
示例#7
0
static GwyContainer*
zeiss_load_tiff(const GwyTIFF *tiff, GError **error)
{
    GwyContainer *container = NULL, *meta = NULL;
    GwyDataField *dfield;
    GwySIUnit *siunit;
    GwyTIFFImageReader *reader = NULL;
    GHashTable *hash = NULL;
    gint i, power10;
    gchar *value, *end, *comment = NULL;
    gdouble *data;
    gboolean new_file;
    double factor, dx;

    /* Comment with parameters is common for all data fields */
    if (!gwy_tiff_get_string0(tiff, ZEISS_HEADER_TAG, &comment)) {
        err_FILE_TYPE(error, "Carl Zeiss SEM");
        goto fail;
    }

    if (strstr(comment, MAGIC_COMMENT))
        new_file = TRUE;
    else if (g_str_has_prefix(comment, SOMEWHAT_LESS_MAGIC_COMMENT))
        new_file = FALSE;
    else {
        err_FILE_TYPE(error, "Carl Zeiss SEM");
        goto fail;
    }

    /* Read the comment header. */
    if (new_file) {
        hash = parse_comment(comment);
        if ((value = g_hash_table_lookup(hash, "Image Pixel Size"))) {
            gwy_debug("Using dx from Image Pixel Size: %s", value);
        }
        else if ((value = g_hash_table_lookup(hash, "Pixel Size"))) {
            gwy_debug("Using dx from Pixel Size: %s", value);
        }
        else {
            err_MISSING_FIELD(error, "Pixel Size");
            goto fail;
        }
    }
    else {
        /* The first thing is the pixel size, apparently. */
        value = comment + strlen(SOMEWHAT_LESS_MAGIC_COMMENT);
        gwy_debug("Using dx from old-style comment: %s", value);
    }

    dx = g_ascii_strtod(value, &end);
    /* Use negated positive conditions to catch NaNs */
    if (!((dx = fabs(dx)) > 0)) {
        g_warning("Real pixel size is 0.0, fixing to 1.0");
        dx = 1.0;
    }
    if (!new_file)
        end = "m";

    /* Request a reader, this ensures dimensions and stuff are defined.
     * NB: Newer versions store the image as RGB.  Not useful here; just
     * average the channels.  */
    if (!(reader = gwy_tiff_get_image_reader(tiff, 0, 3, error)))
        goto fail;

    siunit = gwy_si_unit_new_parse(end, &power10);
    factor = pow10(power10);
    dfield = gwy_data_field_new(reader->width, reader->height,
                                reader->width * factor * dx,
                                reader->height * factor * dx,
                                FALSE);
    gwy_data_field_set_si_unit_xy(dfield, siunit);
    g_object_unref(siunit);

    data = gwy_data_field_get_data(dfield);
    if (reader->samples_per_pixel > 1) {
        gdouble *datarow = g_new(gdouble, reader->width);
        gint ch, j, spp = reader->samples_per_pixel;

        gwy_data_field_clear(dfield);
        for (i = 0; i < reader->height; i++) {
            for (ch = 0; ch < spp; ch++) {
                gwy_tiff_read_image_row(tiff, reader, 0, i, 1.0, 0.0, datarow);
                for (j = 0; j < reader->width; j++)
                    data[i*reader->width + j] += datarow[j];
            }
        }
        g_free(datarow);
        gwy_data_field_multiply(dfield, 1.0/spp);
        gwy_data_field_invalidate(dfield);
    }
    else {
        for (i = 0; i < reader->height; i++)
            gwy_tiff_read_image_row(tiff, reader, 0, i, 1.0, 0.0,
                                    data + i*reader->width);
    }

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

    if (new_file) {
        meta = gwy_container_new();
        g_hash_table_foreach(hash, add_meta, meta);
        if (gwy_container_get_n_items(meta))
            gwy_container_set_object_by_name(container, "/0/meta", meta);
        g_object_unref(meta);
    }

fail:
    if (hash)
        g_hash_table_destroy(hash);
    g_free(comment);

    return container;
}
示例#8
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;
}
示例#9
0
static gboolean
read_binary_data(X3PFile *x3pfile, unzFile *zipfile, GError **error)
{
    GwyRawDataType rawtype;
    gsize size;
    guchar *bindata;
    gchar *s;
    guint i;

    s = g_hash_table_lookup(x3pfile->hash, DATA_LINK_PREFIX "/PointDataLink");
    if (!s) {
        err_NO_DATA(error);
        return FALSE;
    }
    gwy_debug("binary data file %s", s);

    if (unzLocateFile(zipfile, s, 1) != UNZ_OK) {
        g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_IO,
                    _("File %s is missing in the zip file."), s);
        return FALSE;
    }

    s = g_hash_table_lookup(x3pfile->hash, AXES_PREFIX "/CZ/DataType");
    if (!s) {
        err_MISSING_FIELD(error, AXES_PREFIX "CZ/DataType");
        return FALSE;
    }

    if (!x3p_file_get_data_type(s, &rawtype, error))
        return FALSE;

    if (!(bindata = x3p_get_file_content(zipfile, &size, error)))
        return FALSE;

    if (err_SIZE_MISMATCH(error, x3pfile->ndata * gwy_raw_data_size(rawtype),
                          size, TRUE)) {
        g_free(bindata);
        return FALSE;
    }

    gwy_convert_raw_data(bindata, x3pfile->ndata, 1,
                         rawtype, GWY_BYTE_ORDER_LITTLE_ENDIAN,
                         x3pfile->values, x3pfile->dz, x3pfile->zoff);
    g_free(bindata);

    for (i = 0; i < x3pfile->ndata; i++)
        x3pfile->valid[i] = TRUE;

    s = g_hash_table_lookup(x3pfile->hash, DATA_LINK_PREFIX "/ValidPointsLink");
    if (!s)
        return TRUE;

    if (unzLocateFile(zipfile, s, 1) != UNZ_OK) {
        g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_IO,
                    _("File %s is missing in the zip file."), s);
        return FALSE;
    }

    if (!(bindata = x3p_get_file_content(zipfile, &size, error)))
        return FALSE;

    if (err_SIZE_MISMATCH(error, (x3pfile->ndata + 7)/8, size, TRUE)) {
        g_free(bindata);
        return FALSE;
    }

    for (i = 0; i < x3pfile->ndata; i++)
        x3pfile->valid[i] = bindata[i/8] & (1 << (i % 8));

    g_free(bindata);

    return TRUE;
}
示例#10
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;
}
示例#11
0
static GwySIUnit*
get_physical_scale(GHashTable *hash,
                   GHashTable *scannerlist,
                   GHashTable *scanlist,
                   gboolean has_version,
                   gdouble *scale,
                   GError **error)
{
    GwySIUnit *siunit, *siunit2;
    NanoscopeValue *val, *sval;
    gchar *key;
    gint q;

    /* Very old style scales (files with Version field) */
    if (!has_version) {
        if (!(val = g_hash_table_lookup(hash, "Z magnify image"))) {
            err_MISSING_FIELD(error, "Z magnify image");
            return NULL;
        }

        /* TODO: Luminescence */
        siunit = gwy_si_unit_new("m");
        /* According to Markus, the units are 1/100 nm, but his scale
         * calculation is raw/655.36 [nm].  We have the factor 1/65536 applied
         * automatically, that gives 1e-7 [m].  Whatever. */
        *scale = 1e-7 * val->hard_value;
        return siunit;
    }

    /* XXX: This is a damned heuristics.  For some value types we try to guess
     * a different quantity scale to look up. */
    if (!(val = g_hash_table_lookup(hash, "@2:Z scale"))) {
        if (!(val = g_hash_table_lookup(hash, "Z scale"))) {
            err_MISSING_FIELD(error, "Z scale");
            return NULL;
        }

        /* Old style scales */
        siunit = gwy_si_unit_new_parse(val->hard_value_units, &q);
        *scale = val->hard_value * pow10(q);
        if (val->hard_scale)
            *scale *= 65536.0/val->hard_scale;
        return siunit;
    }

    key = g_strdup_printf("@%s", val->soft_scale);

    if (!(sval = g_hash_table_lookup(scannerlist, key))
        && (!scanlist || !(sval = g_hash_table_lookup(scanlist, key)))) {
        g_warning("`%s' not found", key);
        g_free(key);
        /* XXX */
        *scale = val->hard_value;
        return gwy_si_unit_new("");
    }

    *scale = val->hard_value*sval->hard_value;

    if (!sval->hard_value_units || !*sval->hard_value_units) {
        if (gwy_strequal(val->soft_scale, "Sens. Phase"))
            siunit = gwy_si_unit_new("deg");
        else
            siunit = gwy_si_unit_new("V");
    }
    else {
        siunit = gwy_si_unit_new_parse(sval->hard_value_units, &q);
        siunit2 = gwy_si_unit_new("V");
        gwy_si_unit_multiply(siunit, siunit2, siunit);
        gwy_debug("Scale1 = %g V/LSB", val->hard_value);
        gwy_debug("Scale2 = %g %s", sval->hard_value, sval->hard_value_units);
        *scale *= pow10(q);
        gwy_debug("Total scale = %g %s/LSB",
                  *scale, gwy_si_unit_get_string(siunit,
                                                 GWY_SI_UNIT_FORMAT_PLAIN));
        g_object_unref(siunit2);
    }
    g_free(key);

    return siunit;
}
示例#12
0
static GwyContainer*
micromap_load(const gchar *filename,
              G_GNUC_UNUSED GwyRunType mode,
              GError **error)
{
    SDFile sdfile;
    GwyContainer *container = NULL;
    gchar *p, *buffer = NULL;
    gsize len, size = 0;
    GError *err = NULL;
    GwyDataField *dfield = NULL;
    gdouble objectivemag, tubemag, cameraxpixel, cameraypixel;

    if (!g_file_get_contents(filename, &buffer, &size, &err)) {
        err_GET_FILE_CONTENTS(error, &err);
        return NULL;
    }
    len = size;
    p = buffer;
    if (sdfile_read_header_text(&p, &len, &sdfile, error)) {
        if (check_params(&sdfile, len, error))
            dfield = sdfile_read_data_text(&sdfile, error);
    }
    if (!dfield) {
        g_free(buffer);
        return NULL;
    }

    if (!sdfile.extras) {
        err_MISSING_FIELD(error, "OBJECTIVEMAG");
        goto fail;
    }

    if (!require_keys(sdfile.extras, error,
                      "OBJECTIVEMAG", "TUBEMAG", "CAMERAXPIXEL", "CAMERAYPIXEL",
                      NULL))
        goto fail;

    objectivemag = g_ascii_strtod(g_hash_table_lookup(sdfile.extras,
                                                      "OBJECTIVEMAG"), NULL);
    tubemag = g_ascii_strtod(g_hash_table_lookup(sdfile.extras,
                                                 "TUBEMAG"), NULL);
    cameraxpixel = g_ascii_strtod(g_hash_table_lookup(sdfile.extras,
                                                      "CAMERAXPIXEL"), NULL);
    cameraypixel = g_ascii_strtod(g_hash_table_lookup(sdfile.extras,
                                                      "CAMERAYPIXEL"), NULL);

    sdfile_set_units(&sdfile, dfield);
    gwy_data_field_set_xreal(dfield,
                             Micrometer * sdfile.xres * objectivemag
                             * tubemag * cameraxpixel);
    gwy_data_field_set_yreal(dfield,
                             Micrometer * sdfile.yres * objectivemag
                             * tubemag * cameraypixel);

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

fail:
    g_object_unref(dfield);
    g_free(buffer);
    if (sdfile.extras)
        g_hash_table_destroy(sdfile.extras);

    return container;
}