Example #1
0
static GwyContainer*
hitachi_load(const gchar *filename,
             G_GNUC_UNUSED GwyRunType mode,
             GError **error,
             const gchar *name)
{
    GwyContainer *container = NULL;
    guchar *buffer = NULL;
    gsize size = 0;
    GError *err = NULL;
    GwyDataField *dfield = NULL;
    GwyDataField *(*do_load)(const guchar*, guint, GError**);
    guint header_size;

    if (gwy_strequal(name, "hitachi-afm")) {
        do_load = &read_data_field;
        header_size = HEADER_SIZE;
    }
    else if (gwy_strequal(name, "hitachi-afm-old")) {
        do_load = &read_data_field_old;
        header_size = HEADER_SIZE_OLD;
    }
    else {
        g_set_error(error, GWY_MODULE_FILE_ERROR,
                    GWY_MODULE_FILE_ERROR_UNIMPLEMENTED,
                    _("Hitachi-AFM has not registered file type `%s'."), name);
        return NULL;
    }

    if (!gwy_file_get_contents(filename, &buffer, &size, &err)) {
        err_GET_FILE_CONTENTS(error, &err);
        return NULL;
    }
    if (size < header_size + 2) {
        err_TOO_SHORT(error);
        gwy_file_abandon_contents(buffer, size, NULL);
        return NULL;
    }

    dfield = do_load(buffer, size, error);
    gwy_file_abandon_contents(buffer, size, NULL);
    if (!dfield)
        return NULL;

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

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

    return container;
}
Example #2
0
static GwyContainer*
zeiss_load(const gchar *filename,
           G_GNUC_UNUSED GwyRunType mode,
           GError **error)
{
    GwyTIFF *tiff;
    GwyContainer *container = NULL;

    tiff = gwy_tiff_load(filename, error);
    if (!tiff)
        return NULL;

    container = zeiss_load_tiff(tiff, error);
    if (container)
        gwy_file_channel_import_log_add(container, 0, NULL, filename);

    gwy_tiff_free(tiff);

    return container;
}
Example #3
0
static GwyContainer*
aafm_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;
    AFMFile afmfile;
    GwyDataField *dfield;
    gdouble min, max;

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

    p = buffer;
    afmfile.res = gwy_get_guint16_le(&p);
    if (err_DIMENSION(error, afmfile.res)) {
        gwy_file_abandon_contents(buffer, size, NULL);
        return NULL;
    }
    if (err_SIZE_MISMATCH(error, afmfile.res * afmfile.res + 10, size, FALSE)) {
        gwy_file_abandon_contents(buffer, size, NULL);
        return NULL;
    }

    afmfile.real = Angstrom*gwy_get_gfloat_le(&p);
    if (!(afmfile.real = fabs(afmfile.real))) {
        g_warning("Real size is 0.0, fixing to 1.0");
        afmfile.real = 1.0;
    }

    dfield = gwy_data_field_new(afmfile.res, afmfile.res,
                                afmfile.real, afmfile.real,
                                FALSE);
    read_binary_data(afmfile.res, gwy_data_field_get_data(dfield), p);
    p += 2*afmfile.res*afmfile.res;
    afmfile.range = gwy_get_gfloat_le(&p);
    gwy_data_field_get_min_max(dfield, &min, &max);
    if (min == max)
        gwy_data_field_clear(dfield);
    else
        gwy_data_field_multiply(dfield, afmfile.range/(max - min)*Angstrom);

    unit = gwy_si_unit_new("m");
    gwy_data_field_set_si_unit_xy(dfield, unit);
    g_object_unref(unit);

    unit = gwy_si_unit_new("m");
    gwy_data_field_set_si_unit_z(dfield, unit);
    g_object_unref(unit);

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

    gwy_file_abandon_contents(buffer, size, NULL);

    return container;
}
Example #4
0
static GwyContainer*
lif_load(const gchar *filename,
             G_GNUC_UNUSED GwyRunType mode,
             GError **error)
{
    GwyContainer *container = NULL;
    LIFHeader *header = NULL;
    LIFMemBlock *memblock = NULL;
    LIFFile *file = NULL;
    LIFElement *element = NULL;
    LIFDimension *dimension = NULL;
    LIFChannel *channel = NULL;
    gsize size = 0, memblock_size = 0;
    gint64 remaining = 0;
    gchar *buffer;
    const guchar *p;
    GError *err = NULL;
    GwyDataField *dfield = NULL;
    GwyBrick *brick = NULL;
    gdouble *data = NULL;
    gint i, j, channelno = 0, volumeno = 0;
    gchar *strkey, *lutname;
    GMarkupParser parser = {
        header_start_element,
        header_end_element,
        header_parse_text, NULL, NULL
    };
    GMarkupParseContext *context;
    XMLParserData *xmldata;
    gint x, xres, xstep, y, yres, ystep, z, zres, zstep, offset, res;
    gdouble xreal, yreal, zreal, xoffset, yoffset, zoffset;
    gdouble zscale = 1.0, wscale = 1.0;
    GwySIUnit *siunitxy = NULL, *siunitz = NULL;
    GwySIUnit *siunitx = NULL, *siunity = NULL, *siunitw = NULL;
    gint power10xy = 1;
    gint power10x = 1, power10y = 1, power10z = 1, power10w = 1;

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

    if (size < 13) { /* header too short */
        err_TOO_SHORT(error);
        goto fail;
    }

    p = buffer;
    remaining = size;
    header = g_new0(LIFHeader, 1);
    header->magic = gwy_get_gint32_le(&p);
    gwy_debug("Magic = %d", header->magic);
    header->size = gwy_get_guint32_le(&p);
    gwy_debug("Size = %d", header->size);
    header->testcode = *(p++);
    gwy_debug("Testcode = 0x%x", header->testcode);
    if (header->testcode != TESTCODE) {
        err_FILE_TYPE(error, "Leica LIF");
        goto fail;
    }
    header->xmllen = gwy_get_guint32_le(&p);
    gwy_debug("XML length = %d", header->xmllen);
    if (size < 13 + header->xmllen * 2) {
        err_TOO_SHORT(error);
        goto fail;
    }

    remaining -= 13;

    header->xmlheader = g_convert((const gchar*)p, 2 * header->xmllen,
                                  "UTF-8", "UTF-16", NULL, NULL, NULL);
    p += header->xmllen * 2;

    remaining -= header->xmllen * 2;

    // gwy_debug("%s", header->xmlheader);
    /* Parse XML header */
    xmldata = g_new0(XMLParserData, 1);
    xmldata->file = g_new0(LIFFile, 1);
    xmldata->file->elements = g_array_new(FALSE, TRUE,
                                          sizeof(LIFElement));
    xmldata->elements = g_ptr_array_new();

    context = g_markup_parse_context_new(&parser,
                                         G_MARKUP_TREAT_CDATA_AS_TEXT,
                                         (gpointer)xmldata,
                                         NULL);

    if (!g_markup_parse_context_parse(context, header->xmlheader, -1, &err)
        || !g_markup_parse_context_end_parse(context, &err)) {
        error = &err;
        g_clear_error(&err);
    }
    g_markup_parse_context_free(context);
    file = xmldata->file;
    file->header = header;
    g_ptr_array_free(xmldata->elements, TRUE);
    g_free(xmldata);

    /* Reading memblocks */
    file->memblocks = g_hash_table_new(g_str_hash, g_str_equal);
    while (remaining > 0) {
        memblock = lif_read_memblock(p, &memblock_size, file->version);
        if (!memblock) {
            break;
        }
        remaining -= memblock_size;
        if (remaining >= 0) {
            gwy_debug("remaining = %" G_GUINT64_FORMAT "", remaining);
            p += memblock_size;
            g_hash_table_insert(file->memblocks, memblock->memid,
                                memblock);
        }
    }

    container = gwy_container_new();

    for (i = 0; i < file->elements->len; i++) {
        element = &g_array_index(file->elements, LIFElement, i);

        if ((element->dimensions == NULL)
                                       || (element->channels == NULL)) {
            gwy_debug("Empty element");
            continue;
        }

        gwy_debug("Dimensions = %d channels=%d",
                  element->dimensions->len,
                  element->channels->len);
        gwy_debug("memid=%s", element->memid);

        /* check if we can load this type of data into
         * Gwyddion structures */
        res = 0;
        if ((element->dimensions->len != 2)
                                   && (element->dimensions->len != 3)) {

            /* check for case ndim == 4 && res == 1 */
            for (i = 0; i < element->dimensions->len; i++) {
                dimension = &g_array_index(element->dimensions,
                                           LIFDimension, i);
                xres = dimension->res;
                gwy_debug("dim[%d].res=%d", i, xres);
                if (i == 2) {
                    res = xres;
                }
            }
            if ((element->dimensions->len == 4) && (res == 1)) {
                gwy_debug("4D volume");
            }
            else {
                gwy_debug("not loading");
                continue;
            }
        }

        memblock = (LIFMemBlock *)g_hash_table_lookup(file->memblocks,
                                                      element->memid);
        if (!memblock) {
            gwy_debug("Failed to locate memblock with key %s",
                      element->memid);

            continue;
        }

        p = memblock->data;
        if (element->dimensions->len == 2) { /* Image */
            for (j = 0; j < element->channels->len; j++) {
                dimension = &g_array_index(element->dimensions,
                                           LIFDimension, 0);
                xres = dimension->res;
                xreal = dimension->length;
                xoffset = dimension->origin;
                xstep = dimension->bytesinc;
                siunitxy = gwy_si_unit_new_parse(dimension->unit,
                                                 &power10xy);

                dimension = &g_array_index(element->dimensions,
                                           LIFDimension, 1);
                yres = dimension->res;
                yreal = dimension->length;
                yoffset = dimension->origin;
                ystep = dimension->bytesinc;

                if (xreal <= 0.0)
                    xreal = 1.0;
                if (yreal <= 0.0)
                    yreal = 1.0;

                channel = &g_array_index(element->channels,
                                         LIFChannel, j);
                offset = channel->bytesinc;
                siunitz = gwy_si_unit_new_parse(channel->unit,
                                                &power10z);

                zscale = pow10(power10z);
                if (offset + (xres - 1) * xstep + (yres - 1)* ystep
                                                  > memblock->memsize) {
                    gwy_debug("Memblock too small");
                    gwy_debug("%d %" G_GUINT64_FORMAT "",
                              offset + (xres-1)*xstep + (yres-1)*ystep,
                              memblock->memsize);
                    err_SIZE_MISMATCH(error,
                                      memblock->memsize,
                                      offset+(xres-1)*xstep
                                                        +(yres-1)*ystep,
                                      FALSE);
                    goto fail;
                }

                dfield = gwy_data_field_new(xres, yres,
                                            xreal*pow10(power10xy),
                                            yreal*pow10(power10xy),
                                            TRUE);
                gwy_data_field_set_xoffset(dfield,
                                           xoffset*pow10(power10xy));
                gwy_data_field_set_yoffset(dfield,
                                           yoffset*pow10(power10xy));

                data = gwy_data_field_get_data(dfield);
                for (y = 0; y < yres; y++)
                    for (x = 0; x < xres; x++) {
                        *(data++) = zscale
                           * (gdouble)*(p + offset + x*xstep + y*ystep);
                }

                if (siunitxy) {
                    gwy_data_field_set_si_unit_xy(dfield, siunitxy);
                    g_object_unref(siunitxy);
                }
                if (siunitz) {
                    gwy_data_field_set_si_unit_z(dfield, siunitz);
                    g_object_unref(siunitz);
                }

                strkey = g_strdup_printf("/%d/data", channelno);
                gwy_container_set_object_by_name(container,
                                                 strkey,
                                                 dfield);
                g_object_unref(dfield);
                g_free(strkey);

                if (element->name) {
                    strkey = g_strdup_printf("/%d/data/title",
                                             channelno);
                    gwy_container_set_string_by_name(container, strkey,
                                               g_strdup(element->name));
                    g_free(strkey);
                }

                if (element->metadata) {
                    strkey = g_strdup_printf("/%d/meta",
                                             channelno);
                    gwy_container_set_object_by_name(container,
                                                     strkey,
                                                     element->metadata);
                    g_free(strkey);
                }

                if (channel->lut) {
                    lutname = NULL;
                    if (gwy_strequal(channel->lut, "Red"))
                        lutname = g_strdup_printf("RGB-Red");
                    else if (gwy_strequal(channel->lut, "Green"))
                        lutname = g_strdup_printf("RGB-Green");
                    else if (gwy_strequal(channel->lut, "Blue"))
                        lutname = g_strdup_printf("RGB-Blue");
                    else if (gwy_strequal(channel->lut, "Gray"))
                        lutname = g_strdup_printf("Gray");
                    if (lutname) {
                        strkey = g_strdup_printf("/%u/base/palette",
                                                 channelno);
                        gwy_container_set_string_by_name(container,
                                                         strkey,
                                                         lutname);
                        g_free(strkey);
                    }
                }

                gwy_file_channel_import_log_add(container, channelno,
                                                NULL, filename);

                channelno++;
            }
        }
        else if ((element->dimensions->len == 3)
             || ((element->dimensions->len == 4) && (res == 1))) {
            /* Volume */
            for (j = 0; j < element->channels->len; j++) {
                dimension = &g_array_index(element->dimensions,
                                           LIFDimension, 0);
                xres = dimension->res;
                xreal = dimension->length;
                xoffset = dimension->origin;
                xstep = dimension->bytesinc;
                siunitx = gwy_si_unit_new_parse(dimension->unit,
                                                &power10x);

                dimension = &g_array_index(element->dimensions,
                                           LIFDimension, 1);
                yres = dimension->res;
                yreal = dimension->length;
                yoffset = dimension->origin;
                ystep = dimension->bytesinc;
                siunity = gwy_si_unit_new_parse(dimension->unit,
                                                &power10y);

                if (element->dimensions->len == 3) {
                    dimension = &g_array_index(element->dimensions,
                                               LIFDimension, 2);
                }
                else {
                    dimension = &g_array_index(element->dimensions,
                                               LIFDimension, 3);
                }
                zres = dimension->res;
                zreal = dimension->length;
                zoffset = dimension->origin;
                zstep = dimension->bytesinc;
                siunitz = gwy_si_unit_new_parse(dimension->unit,
                                                &power10z);

                channel = &g_array_index(element->channels,
                                         LIFChannel, j);
                offset = channel->bytesinc;
                siunitw = gwy_si_unit_new_parse(channel->unit,
                                                &power10w);
                wscale = pow10(power10w);

                if (offset
                      + (xres-1)*xstep + (yres-1)*ystep + (zres-1)*zstep
                                                  > memblock->memsize) {
                    gwy_debug("Memblock too small");
                    gwy_debug("%d %" G_GUINT64_FORMAT "",
                              offset + (xres-1)*xstep
                                      + (yres-1)*ystep + (zres-1)*zstep,
                              memblock->memsize);
                    err_SIZE_MISMATCH(error,
                                      memblock->memsize,
                                      offset + (xres-1)*xstep
                                      + (yres-1)*ystep + (zres-1)*zstep,
                                      FALSE);
                    goto fail;
                }
                brick = gwy_brick_new(xres, yres, zres,
                                      xreal*pow10(power10x),
                                      yreal*pow10(power10y),
                                      zreal*pow10(power10z),
                                      TRUE);
                gwy_brick_set_xoffset(brick, xoffset*pow10(power10x));
                gwy_brick_set_yoffset(brick, yoffset*pow10(power10y));
                gwy_brick_set_zoffset(brick, zoffset*pow10(power10z));

                data = gwy_brick_get_data(brick);

                for (z = 0; z < zres; z++)
                    for (y = 0; y < yres; y++)
                        for (x = 0; x < xres; x++) {
                            *(data++) = wscale * (gdouble)*(p + offset
                                         + x*xstep + y*ystep + z*zstep);
                    }

                if (siunitx) {
                    gwy_brick_set_si_unit_x(brick, siunitx);
                    g_object_unref(siunitx);
                }
                if (siunity) {
                    gwy_brick_set_si_unit_y(brick, siunity);
                    g_object_unref(siunity);
                }
                if (siunitz) {
                    gwy_brick_set_si_unit_z(brick, siunitz);
                    g_object_unref(siunitz);
                }
                if (siunitw) {
                    gwy_brick_set_si_unit_w(brick, siunitw);
                    g_object_unref(siunitw);
                }

                strkey = g_strdup_printf("/brick/%d", volumeno);
                gwy_container_set_object_by_name(container,
                                                 strkey,
                                                 brick);
                g_free(strkey);

                if (element->name) {
                    strkey = g_strdup_printf("/brick/%d/title",
                                             volumeno);
                    gwy_container_set_string_by_name(container, strkey,
                                               g_strdup(element->name));
                    g_free(strkey);
                }

                if (element->metadata) {
                    strkey = g_strdup_printf("/brick/%d/meta",
                                             volumeno);
                    gwy_container_set_object_by_name(container,
                                                     strkey,
                                                     element->metadata);
                    g_free(strkey);
                }

                if (channel->lut) {
                    lutname = NULL;
                    if (gwy_strequal(channel->lut, "Red"))
                        lutname = g_strdup_printf("RGB-Red");
                    else if (gwy_strequal(channel->lut, "Green"))
                        lutname = g_strdup_printf("RGB-Green");
                    else if (gwy_strequal(channel->lut, "Blue"))
                        lutname = g_strdup_printf("RGB-Blue");
                    else if (gwy_strequal(channel->lut, "Gray"))
                        lutname = g_strdup_printf("Gray");
                    if (lutname) {
                        strkey = g_strdup_printf("/brick/%d/preview/palette",
                                                 volumeno);
                        gwy_container_set_string_by_name(container,
                                                         strkey,
                                                         lutname);
                        g_free(strkey);
                    }
                }

                dfield = gwy_data_field_new(xres, yres,
                                            xreal, yreal, FALSE);
                gwy_brick_mean_plane(brick, dfield,
                                     0, 0, 0,
                                     xres, yres, -1, FALSE);
                strkey = g_strdup_printf("/brick/%d/preview",
                                         volumeno);
                gwy_container_set_object_by_name(container,
                                                 strkey,
                                                 dfield);
                g_free(strkey);
                g_object_unref(brick);
                g_object_unref(dfield);
                gwy_file_volume_import_log_add(container, volumeno,
                                               NULL, filename);

                volumeno++;
            } /* for (channels) */
        } /* if (volume) */
    }

fail:
    /* freeing all stuff */
    if (file) {
        if (file->memblocks) {
            g_hash_table_foreach_remove(file->memblocks,
                                        lif_remove_memblock,
                                        NULL);
            g_hash_table_unref(file->memblocks);
        }
        if (file->elements) {
            for (i = 0; i < file->elements->len; i++) {
                element = &g_array_index(file->elements, LIFElement, i);
                if (element->dimensions) {
                    for (j = 0; j < element->dimensions->len; j++) {
                        dimension = &g_array_index(element->dimensions,
                                                   LIFDimension, j);
                        if (dimension->unit)
                            g_free(dimension->unit);
                    }
                    g_array_free(element->dimensions, TRUE);
                }
                if (element->channels) {
                    for (j = 0; j < element->channels->len; j++) {
                        channel = &g_array_index(element->channels,
                                                 LIFChannel, j);
                        if (channel->unit)
                            g_free(channel->unit);
                        if (channel->lut)
                            g_free(channel->lut);
                    }
                    g_array_free(element->channels, TRUE);
                }

                if (element->name)
                    g_free(element->name);
                if (element->memid)
                    g_free(element->memid);
                if (element->metadata)
                    g_object_unref(element->metadata);
            }
            g_array_free(file->elements, TRUE);
        }
        g_free(file);
    }
    if (header->xmlheader)
        g_free(header->xmlheader);
    if (header) {
        g_free(header);
    }

    return container;
}
Example #5
0
static GwyContainer*
pt3file_load(const gchar *filename,
             G_GNUC_UNUSED GwyRunType mode,
             GError **error)
{
    PicoHarpFile pt3file;
    GwyContainer *meta, *container = NULL;
    GwyDataField *dfield = NULL;
    GwyGraphModel *gmodel = NULL;
    guchar *buffer = NULL;
    const guchar *p;
    gsize header_len, size = 0;
    GError *err = NULL;
    LineTrigger *linetriggers = NULL;

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

    gwy_clear(&pt3file, 1);
    if (!(header_len = pt3file_read_header(buffer, size, &pt3file, error)))
        goto fail;

    if (err_SIZE_MISMATCH
        (error, header_len + pt3file.number_of_records*sizeof(guint32), size,
         FALSE))
        goto fail;

    if (pt3file.measurement_mode != 3) {
        g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA,
                    _("T2 measurement mode is not implemented."));
        goto fail;
    }
    if (pt3file.imaging.common.instrument != PICO_HARP_PIE710
        && pt3file.imaging.common.instrument != PICO_HARP_KDT180) {
        g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA,
                    _("Only PI E710 and KDT180-100-Im imaging formats are "
                      "implemented."));
        goto fail;
    }

    /* Scan the records and find the line triggers */
    p = buffer + header_len;
    if (!(linetriggers = pt3file_scan_line_triggers(&pt3file, p, error)))
        goto fail;

    container = gwy_container_new();

    dfield = pt3file_extract_counts(&pt3file, linetriggers, p);
    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("Photon count"));

    meta = pt3file_get_metadata(&pt3file);
    gwy_container_set_object_by_name(container, "/0/meta", meta);
    g_object_unref(meta);

    gwy_file_channel_import_log_add(container, 0, NULL, filename);

    gmodel = pt3file_extract_decay(&pt3file, p);
    gwy_container_set_object_by_name(container, "/0/graph/graph/1", gmodel);
    g_object_unref(gmodel);

fail:
    g_free(linetriggers);
    gwy_file_abandon_contents(buffer, size, NULL);

    return container;
}
Example #6
0
static GwyContainer*
sly_load(const gchar *filename,
         G_GNUC_UNUSED GwyRunType mode,
         GError **error)
{
    GwyContainer *container = NULL, *meta = NULL;
    gchar *buffer = NULL;
    GError *err = NULL;
    GHashTable *hash = NULL;
    gchar *p, *line, *value;
    guint expecting_data = 0;
    SensolyticsChannel *channels = NULL;
    Dimensions dimensions;
    gint ndata = 0, i;

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

    p = buffer;
    line = gwy_str_next_line(&p);
    g_strstrip(line);
    if (!gwy_strequal(line, MAGIC)) {
        err_FILE_TYPE(error, "Sensolytics");
        goto fail;
    }

    hash = g_hash_table_new(g_str_hash, g_str_equal);
    for (line = gwy_str_next_line(&p); line; line = gwy_str_next_line(&p)) {
        if (!line[0])
            continue;

        if (expecting_data) {
            expecting_data--;

            /* The columns are comma-separated and numbers use decimal points.
             * Do not tempt the number parsing functions more than necessary
             * and fix commas to tab characters. */
            g_strdelimit(line, ",", '\t');

            /* Ignore X, Y and Z, each is two values */
            for (i = 0; i < 6; i++)
                g_ascii_strtod(line, &line);

            for (i = 0; i < ndata; i++)
                channels[i].data[expecting_data]
                    = channels[i].q * g_ascii_strtod(line, &line);
        }
        else {
            g_strstrip(line);
            if (line[0] != '#') {
                g_warning("Comment line does not start with #.");
                continue;
            }

            do {
                line++;
            } while (g_ascii_isspace(*line));

            if (g_str_has_prefix(line, "X [")) {
                if (channels) {
                    g_warning("Multiple data headers!?");
                    continue;
                }

                if (!read_dimensions(hash, &ndata, &dimensions, error)
                    || !(channels = create_fields(hash, line,
                                                  ndata, &dimensions)))
                    goto fail;
                expecting_data = dimensions.xres * dimensions.yres;
                continue;
            }

            value = strchr(line, ':');
            if (!value) {
                if (!gwy_strequal(line, "ArrayScan"))
                    g_warning("Non-parameter-like line %s", line);
                continue;
            }
            *value = '\0';
            g_strchomp(line);
            do {
                value++;
            } while (g_ascii_isspace(*value));

            if (gwy_strequal(line, "Warning"))
                continue;

            gwy_debug("<%s>=<%s>", line, value);
            g_hash_table_insert(hash, line, value);
        }
    }

    if (!channels) {
        err_NO_DATA(error);
        goto fail;
    }

    container = gwy_container_new();
    for (i = 0; i < ndata; i++) {
        GQuark key = gwy_app_get_data_key_for_id(i);

        gwy_data_field_invert(channels[i].dfield, FALSE, TRUE, FALSE);
        gwy_container_set_object(container, key, channels[i].dfield);
        gwy_app_channel_check_nonsquare(container, i);
        if (channels[i].name) {
            gchar *s = g_strconcat(g_quark_to_string(key), "/title", NULL);
            gwy_container_set_string_by_name(container, s,
                                             g_strdup(channels[i].name));
            g_free(s);
        }
        else
            gwy_app_channel_title_fall_back(container, i);

        gwy_file_channel_import_log_add(container, i, NULL, filename);
    }

    meta = get_meta(hash);
    clone_meta(container, meta, ndata);
    g_object_unref(meta);

fail:
    g_free(buffer);
    if (hash)
        g_hash_table_destroy(hash);
    if (channels) {
        for (i = 0; i < ndata; i++)
            g_object_unref(channels[i].dfield);
        g_free(channels);
    }

    return container;
}
Example #7
0
static void
apedax_get_channels_data(unzFile uFile,
                         guchar *scanXmlContent,
                         gsize contentSize,
                         const gchar *filename,
                         GwyContainer *container,
                         GwyContainer *meta,
                         const APEScanSize *scanSize,
                         GError **error)
{
    xmlDocPtr doc = NULL;
    xmlNodePtr cur = NULL;
    xmlXPathContextPtr context;
    xmlXPathObjectPtr pathObj;
    xmlNodeSetPtr nodeset;
    xmlChar *buffer = NULL;
    gchar key[256];
    gint i;
    gint power10 = 0;
    gdouble scaleFactor = 1.0;
    GwySIUnit *zUnit;
    gchar *zUnitString = NULL;
    gchar *binFileName = NULL;
    GwyDataField *dfield;
    GwyContainer *tmp;

    if (scanXmlContent == NULL || contentSize == 0)
        return;

    gwy_clear(key, sizeof(key));

    doc = xmlReadMemory(scanXmlContent,
                        contentSize,
                        "scan.xml",
                        NULL,
                        0);

    if (doc == NULL)
        goto fail;

    context = xmlXPathNewContext(doc);

    if (context == NULL)
        goto fail;

    pathObj = xmlXPathEvalExpression("/Scan/Channels/Channel", context);

    if (pathObj == NULL) {
        xmlXPathFreeContext(context);
        goto fail;
    }

    /*There must be at least one channel*/
    if (xmlXPathNodeSetIsEmpty(pathObj->nodesetval)) {
        xmlXPathFreeObject(pathObj);
        xmlXPathFreeContext(context);
        err_NO_DATA(error);
        return;
    }

    nodeset = pathObj->nodesetval;

    if (nodeset->nodeNr <= 0)
        goto fail;

    for (i = 0; i < nodeset->nodeNr; i++) {

        cur = nodeset->nodeTab[i]->xmlChildrenNode;

        while (cur) {
            /*Label*/
            if (gwy_strequal((gchar*)cur->name, "Label")) {
                buffer = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
                g_snprintf(key, sizeof(key), "/%d/data/title", i);
                gwy_container_set_string_by_name(container, key, g_strdup(buffer));
                xmlFree(buffer);
            }
            /*Factor*/
            if (gwy_strequal((gchar*)cur->name, "ConversionFactor")) {
                buffer = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
                scaleFactor = g_ascii_strtod((gchar*)buffer, NULL);
                xmlFree(buffer);
            }
            /*Unit*/
            if (gwy_strequal((gchar*)cur->name, "DataUnit")) {
                buffer = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
                zUnitString = g_strdup((gchar*)buffer);
                zUnit = gwy_si_unit_new_parse(zUnitString, &power10);
                xmlFree(buffer);
                g_object_unref(zUnit);
            }
            /*Binary file name*/
            if (gwy_strequal((gchar*)cur->name, "BINFile")) {
                buffer = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
                binFileName = g_strdup((gchar*)buffer);
                xmlFree(buffer);
            }
            cur = cur->next;
        }

        scaleFactor *= pow(10.0, power10);

        dfield = apedax_get_data_field(uFile,
                                       binFileName,
                                       scanSize,
                                       zUnitString,
                                       scaleFactor,
                                       error);
        if (dfield) {
            g_snprintf(key, sizeof(key), "/%d/data", i);
            gwy_container_set_object_by_name(container, key, dfield);
            g_object_unref(dfield);
            gwy_file_channel_import_log_add(container, i, NULL,
                                            filename);

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

    xmlXPathFreeObject(pathObj);
    xmlXPathFreeContext(context);
    xmlFreeDoc(doc);

    return;

fail:
    err_FILE_TYPE(error, FILE_TYPE);
    if (doc)
        xmlFreeDoc(doc);
    return;
}
Example #8
0
static GwyContainer*
burleigh_exp_load(const gchar *filename,
                  G_GNUC_UNUSED GwyRunType mode,
                  GError **error)
{
    GwyContainer *container = NULL;
    gchar *buffer = NULL;
    BurleighExpHeader header;
    gsize size = 0;
    GError *err = NULL;
    GwyDataField *dfield;
    gdouble *data;
    guint i, n;

    if (!g_file_get_contents(filename, &buffer, &size, &err)) {
        err_GET_FILE_CONTENTS(error, &err);
        return NULL;
    }
    if (size < MIN_FILE_SIZE + 2) {
        err_TOO_SHORT(error);
        g_free(buffer);
        return NULL;
    }

    if (!burleigh_exp_read_header(&header, buffer, error))
        goto fail;

    n = header.xres * header.yres;
    if (header.binary) {
        if (header.bpp != 16) {
            err_BPP(error, header.bpp);
            goto fail;
        }
        else if (err_SIZE_MISMATCH(error, header.length + 2*n, size, TRUE))
            goto fail;
    }

    dfield = gwy_data_field_new(header.xres, header.yres,
                                header.xscale, header.yscale,
                                FALSE);
    data = gwy_data_field_get_data(dfield);

    if (header.binary) {
        const gint16 *d16 = (const gint16*)(buffer + header.length);

        for (i = 0; i < n; i++)
            data[i] = GINT16_FROM_LE(d16[i]);
    }
    else {
        gchar *p = buffer + header.length;

        for (i = 0; i < n; i++)
            data[i] = strtol(p, &p, 10);
    }

    gwy_data_field_multiply(dfield, header.zscale/32768.0);

    /* Units references released in free_header() */
    gwy_data_field_set_si_unit_xy(dfield, header.xyunits);
    gwy_data_field_set_si_unit_z(dfield, header.zunits);

    container = gwy_container_new();
    gwy_container_set_object(container, gwy_app_get_data_key_for_id(0), dfield);
    g_object_unref(dfield);
    gwy_app_channel_title_fall_back(container, 0);
    gwy_file_channel_import_log_add(container, 0, NULL, filename);

fail:
    free_header(&header);
    g_free(buffer);

    return container;
}
Example #9
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;
}
Example #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;
}
Example #11
0
static GwyContainer*
text_dump_import(gchar *buffer,
                 gsize size,
                 const gchar *filename,
                 GError **error)
{
    gchar *val, *key, *pos, *line, *title;
    GwyContainer *data;
    GwyDataField *dfield;
    gdouble xreal, yreal;
    gint xres, yres, id;
    GwySIUnit *uxy, *uz;
    const guchar *s;
    gdouble *d;
    gsize n;

    data = gwy_container_new();

    pos = buffer;
    while ((line = gwy_str_next_line(&pos)) && *line) {
        val = strchr(line, '=');
        if (!val || *line != '/') {
            g_warning("Garbage key: %s", line);
            continue;
        }
        if ((gsize)(val - buffer) + 1 > size) {
            g_set_error(error, GWY_MODULE_FILE_ERROR,
                        GWY_MODULE_FILE_ERROR_DATA,
                        _("End of file reached when value was expected."));
            goto fail;
        }
        *val = '\0';
        val++;
        if (!gwy_strequal(val, "[") || !pos || *pos != '[') {
            gwy_debug("<%s>=<%s>", line, val);
            if (*val)
                gwy_container_set_string_by_name(data, line, g_strdup(val));
            else
                gwy_container_remove_by_name(data, line);
            continue;
        }

        g_assert(pos && *pos == '[');
        pos++;
        dfield = NULL;
        gwy_container_gis_object_by_name(data, line, &dfield);

        id = 0;
        sscanf(line, "/%d", &id);

        /* get datafield parameters from already read values, failing back
         * to values of original data field */
        key = g_strconcat(line, "/xres", NULL);
        if (gwy_container_gis_string_by_name(data, key, &s))
            xres = atoi(s);
        else if (dfield)
            xres = gwy_data_field_get_xres(dfield);
        else {
            g_set_error(error, GWY_MODULE_FILE_ERROR,
                        GWY_MODULE_FILE_ERROR_DATA,
                        _("Missing data field width."));
            goto fail;
        }
        g_free(key);

        key = g_strconcat(line, "/yres", NULL);
        if (gwy_container_gis_string_by_name(data, key, &s))
            yres = atoi(s);
        else if (dfield)
            yres = gwy_data_field_get_yres(dfield);
        else {
            g_set_error(error, GWY_MODULE_FILE_ERROR,
                        GWY_MODULE_FILE_ERROR_DATA,
                        _("Missing data field height."));
            goto fail;
        }
        g_free(key);

        key = g_strconcat(line, "/xreal", NULL);
        if (gwy_container_gis_string_by_name(data, key, &s))
            xreal = g_ascii_strtod(s, NULL);
        else if (dfield)
            xreal = gwy_data_field_get_xreal(dfield);
        else {
            g_warning("Missing real data field width.");
            xreal = 1.0;   /* 0 could cause troubles */
        }
        g_free(key);

        key = g_strconcat(line, "/yreal", NULL);
        if (gwy_container_gis_string_by_name(data, key, &s))
            yreal = g_ascii_strtod(s, NULL);
        else if (dfield)
            yreal = gwy_data_field_get_yreal(dfield);
        else {
            g_warning("Missing real data field height.");
            yreal = 1.0;   /* 0 could cause troubles */
        }
        g_free(key);

        if (!(xres > 0 && yres > 0 && xreal > 0 && yreal > 0)) {
            g_set_error(error, GWY_MODULE_FILE_ERROR,
                        GWY_MODULE_FILE_ERROR_DATA,
                        _("Data field dimensions are not positive numbers."));
            goto fail;
        }

        key = g_strconcat(line, "/unit-xy", NULL);
        if (gwy_container_gis_string_by_name(data, key, &s))
            uxy = gwy_si_unit_new((const gchar*)s);
        else if (dfield) {
            uxy = gwy_data_field_get_si_unit_xy(dfield);
            uxy = gwy_si_unit_duplicate(uxy);
        }
        else {
            g_warning("Missing lateral units.");
            uxy = gwy_si_unit_new("m");
        }
        g_free(key);

        key = g_strconcat(line, "/unit-z", NULL);
        if (gwy_container_gis_string_by_name(data, key, &s))
            uz = gwy_si_unit_new((const gchar*)s);
        else if (dfield) {
            uz = gwy_data_field_get_si_unit_z(dfield);
            uz = gwy_si_unit_duplicate(uz);
        }
        else {
            g_warning("Missing value units.");
            uz = gwy_si_unit_new("m");
        }
        g_free(key);

        key = g_strconcat(line, "/title", NULL);
        title = NULL;
        gwy_container_gis_string_by_name(data, key, (const guchar**)&title);
        /* We got the contained string but that would disappear. */
        title = g_strdup(title);
        g_free(key);

        n = xres*yres*sizeof(gdouble);
        if ((gsize)(pos - buffer) + n + 3 > size) {
            g_set_error(error, GWY_MODULE_FILE_ERROR,
                        GWY_MODULE_FILE_ERROR_DATA,
                        _("End of file reached inside a data field."));
            goto fail;
        }
        dfield = GWY_DATA_FIELD(gwy_data_field_new(xres, yres, xreal, yreal,
                                                   FALSE));
        gwy_data_field_set_si_unit_xy(dfield, GWY_SI_UNIT(uxy));
        gwy_object_unref(uxy);
        gwy_data_field_set_si_unit_z(dfield, GWY_SI_UNIT(uz));
        gwy_object_unref(uz);
        d = gwy_data_field_get_data(dfield);
#if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
        memcpy(d, pos, n);
#else
        gwy_memcpy_byte_swap(pos, (guint8*)d,
                             sizeof(gdouble), xres*yres, sizeof(gdouble)-1);
#endif
        pos += n;
        val = gwy_str_next_line(&pos);
        if (!gwy_strequal(val, "]]")) {
            g_set_error(error, GWY_MODULE_FILE_ERROR,
                        GWY_MODULE_FILE_ERROR_DATA,
                        _("Missing end of data field marker."));
            gwy_object_unref(dfield);
            goto fail;
        }
        gwy_container_remove_by_prefix(data, line);
        gwy_container_set_object_by_name(data, line, dfield);
        g_object_unref(dfield);

        if (title) {
            key = g_strconcat(line, "/title", NULL);
            gwy_container_set_string_by_name(data, key, title);
            g_free(key);
        }

        gwy_file_channel_import_log_add(data, id, NULL, filename);
    }
    return data;

fail:
    gwy_container_remove_by_prefix(data, NULL);
    g_object_unref(data);
    return NULL;
}
Example #12
0
static GwyContainer*
stmprg_load(const gchar *filename,
            G_GNUC_UNUSED GwyRunType mode,
            GError **error)
{
    GwyContainer *meta, *container = NULL;
    StmprgFile stmprgfile;
    guchar *buffer = NULL;
    gsize size = 0;
    GError *err = NULL;
    GwyDataField *dfield;
    char *filename_ta, *ptr;
    gboolean ok;

    if (!gwy_file_get_contents(filename, &buffer, &size, &err)) {
        err_GET_FILE_CONTENTS(error, &err);
        return NULL;
    }
    if (size < MAGIC_SIZE || memcmp(buffer, MAGIC_TXT, MAGIC_SIZE) != 0) {
        err_FILE_TYPE(error, "Omicron STMPRG");
        gwy_file_abandon_contents(buffer, size, NULL);
        return NULL;
    }

    gwy_clear(&stmprgfile, 1);
    ok = read_parameters(buffer, size, &stmprgfile, error);
    gwy_file_abandon_contents(buffer, size, NULL);
    if (!ok)
        return NULL;

    filename_ta = g_strdup(filename);
    ptr = filename_ta + strlen(filename_ta) - 1;
    while (g_ascii_isdigit(*ptr) && ptr > filename_ta+1)
        ptr--;

    if (ptr == filename_ta+1) {
        err_DATA_PART(error, filename);
        g_free(filename_ta);
        return NULL;
    }

    /* Accept lowercase and uppercase and try the same case for data file */
    if (*ptr == 'p' && *(ptr - 1) == 't')
        *ptr = 'a';
    if (*ptr == 'P' && *(ptr - 1) == 'T')
        *ptr = 'A';

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

    dfield = read_datafield(buffer, size, &stmprgfile, error);
    if (dfield) {
        container = gwy_container_new();
        gwy_container_set_object_by_name(container, "/0/data", dfield);
        g_object_unref(dfield);
        /* FIXME: with documentation, we could perhaps do better */
        gwy_app_channel_title_fall_back(container, 0);

        meta = stmprg_get_metadata(&stmprgfile);
        gwy_container_set_object_by_name(container, "/0/meta", meta);
        g_object_unref(meta);

        gwy_file_channel_import_log_add(container, 0, NULL, filename);
    }
    gwy_file_abandon_contents(buffer, size, NULL);

    return container;
}
Example #13
0
static GwyContainer*
mif_load(const gchar *filename,
         G_GNUC_UNUSED GwyRunType mode,
         GError **error)
{
    GwyContainer *container = NULL;
    guchar *buffer = NULL;
    gsize size = 0;
    GError *err = NULL;
    MIFFile mfile;
    GwyDataField *dfield;
    guint i;

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

    if (!mif_read_header(buffer, size, &mfile.header, error)) {
        gwy_file_abandon_contents(buffer, size, NULL);
        return NULL;
    }
    /* TODO: Check file version */
    if (!mif_read_image_items(mfile.images, buffer, size, &mfile.header.info,
                              error)) {
        gwy_file_abandon_contents(buffer, size, NULL);
        return NULL;
    }

    /* FIXME: Only v1.7! */
    for (i = 0; i < mfile.header.nimages; i++) {
        MIFInfoItem *item = mfile.images + i;
        MIFImageHeader image_header;
        MIFBlock raster, macro_geometry, preview, image, curve, calc;
        G_GNUC_UNUSED guint ncalculations;
        const guchar *p = buffer + item->image.offset;
        GQuark quark;

        if (!item->image.size)
            continue;
        if (item->image.offset > size
            || item->image.size > size
            || item->image.offset + item->image.size > size) {
            continue;
        }

        /* XXX: We cannot use item->image.size because it's bogus, i.e.
         * too short.  Apparently there is some unaccounted-for space until
         * the next block starts, 120 bytes for v1.7 files, after the image
         * header which is in fact still occupied by the image header.
         * MIFBlock says 714 bytes but the true size is 834 = 714 + 120. */
        if (!mif_read_image_header(&image_header, &p, size - (p - buffer),
                                   mfile.header.file_version,
                                   error))
            continue;

        if (p - buffer + 52 > size)
            continue;

        mif_read_block(&raster, "raster", &p);
        mif_read_block(&macro_geometry, "macro_geometry", &p);
        mif_read_block(&preview, "preview", &p);
        mif_read_block(&image, "image", &p);
        mif_read_block(&curve, "curve", &p);
        ncalculations = gwy_get_guint32_le(&p);
        mif_read_block(&calc, "calc", &p);

        gwy_debug("image header true size: %zu",
                  (gsize)(p - (buffer + item->image.offset)));

        dfield = mif_read_data_field(&image_header, &image, buffer, size, NULL);
        if (!dfield)
            continue;

        if (!container)
            container = gwy_container_new();

        quark = gwy_app_get_data_key_for_id(i);
        gwy_container_set_object(container, quark, dfield);
        g_object_unref(dfield);
        gwy_app_channel_title_fall_back(container, i);
        gwy_file_channel_import_log_add(container, i, NULL, filename);
    }

    if (!container)
        err_NO_DATA(error);

    gwy_file_abandon_contents(buffer, size, NULL);
    return container;
}
Example #14
0
static GwyContainer*
quesant_load(const gchar *filename,
             G_GNUC_UNUSED GwyRunType mode,
             GError **error)
{
    GwyContainer *container = NULL;
    guchar *buffer = NULL;
    gsize size = 0;
    GError *err = NULL;
    GwySIUnit *units = NULL;
    gint32 power10;
    FileInfo info;
    int row, col;
    GwyDataField *dfield;
    gdouble multiplier;
    const guint16 *p;
    gdouble *d;

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

    if (size <= HEADER_SIZE) {
        gwy_file_abandon_contents(buffer, size, NULL);
        err_TOO_SHORT(error);
        return NULL;
    }

    if (!read_file_info(buffer, size, &info, error)) {
        gwy_file_abandon_contents(buffer, size, NULL);
        return NULL;
    }

    // create units and datafield
    units = gwy_si_unit_new_parse("um", &power10);
    dfield = gwy_data_field_new(info.img_res, info.img_res, 
                                info.real_size * pow10(power10),
                                info.real_size * pow10(power10),
                                FALSE);
    // set units for XY axes
    gwy_data_field_set_si_unit_xy(dfield, units);
    g_object_unref(units);
    // set units for Z axis
    units = gwy_si_unit_new_parse("um", &power10);
    gwy_data_field_set_si_unit_z(dfield, units);
    g_object_unref(units);

    multiplier = info.z_scale * pow10(power10);
    p = info.image_data;
    d = gwy_data_field_get_data(dfield);
    // values are stored in unsigned int16 type
    for (row = 0; row < info.img_res; row++) {
        for (col = 0; col < info.img_res; col++) {
            d[row*info.img_res + col] = GUINT16_FROM_LE(*p) * multiplier;
            p++;
        }
    }

    // create container
    container = gwy_container_new();
    // put datafield into container
    gwy_container_set_object_by_name(container, "/0/data", dfield);
    g_object_unref(dfield);
    gwy_app_channel_title_fall_back(container, 0);
    gwy_file_channel_import_log_add(container, 0, NULL, filename);

    gwy_file_abandon_contents(buffer, size, NULL);
    return container;
}
Example #15
0
static GwyContainer*
gsf_load(const gchar *filename,
         G_GNUC_UNUSED GwyRunType mode,
         GError **error)
{
    GwyContainer *container = NULL, *meta = NULL;
    GwyDataField *dfield = NULL;
    GwyTextHeaderParser parser;
    GwySIUnit *unit;
    guchar *p, *value, *buffer = NULL, *header = NULL;
    const guchar *datap;
    GHashTable *hash = NULL;
    gsize size, expected_size;
    GError *err = NULL;
    gdouble xreal, yreal, xoff, yoff;
    guint i, xres, yres;
    gdouble *d;

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

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

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

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

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

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

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

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

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

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

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

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

    if ((value = g_hash_table_lookup(hash, "Title"))) {
        /* FIXME: Ensure valid UTF-8 */
        gwy_container_set_string_by_name(container, "/0/data/title",
                                         g_strdup(value));
    }
    else
        gwy_app_channel_title_fall_back(container, 0);

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

    gwy_file_channel_import_log_add(container, 0, NULL, filename);

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

    return container;
}
Example #16
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;
}
Example #17
0
static GwyContainer*
spmlab_load(const gchar *filename,
            G_GNUC_UNUSED GwyRunType mode,
            GError **error)
{
    GwyContainer *container = NULL;
    guchar *buffer = NULL;
    gsize size = 0;
    GError *err = NULL;
    GwyDataField *dfield = NULL;
    gchar *title = NULL;
    gint dir;

    if (!gwy_file_get_contents(filename, &buffer, &size, &err)) {
        err_GET_FILE_CONTENTS(error, &err);
        return NULL;
    }
    /* 2048 is wrong. moreover it differs for r5 and r4, kasigra uses 5752 for
     * r5 */
    if (size < 2048) {
        err_TOO_SHORT(error);
        gwy_file_abandon_contents(buffer, size, NULL);
        return NULL;
    }
    if (buffer[0] != '#' || buffer[1] != 'R') {
        err_FILE_TYPE(error, "Thermicroscopes SpmLab");
        gwy_file_abandon_contents(buffer, size, NULL);
        return NULL;
    }
    switch (buffer[2]) {
    case '3':
    case '4':
    case '5':
    case '6':
    case '7':
        dfield = read_data_field(buffer, size, buffer[2], &title, &dir, error);
        break;

    default:
        g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA,
                    _("Unknown format version %c."), buffer[2]);
        break;
    }

    gwy_file_abandon_contents(buffer, size, NULL);
    if (!dfield)
        return NULL;

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

    if (title)
        gwy_container_set_string_by_name(container, "/0/data/title", title);
    else
        gwy_app_channel_title_fall_back(container, 0);


    gwy_file_channel_import_log_add(container, 0, NULL, filename);
    /* TODO: Store direction to metadata, if known */

    return container;
}
Example #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;
}
Example #19
0
static GwyContainer*
rhkspm32_load(const gchar *filename,
              G_GNUC_UNUSED GwyRunType mode,
              GError **error)
{
    GArray *rhkfile;
    RHKPage *rhkpage;
    GwyContainer *meta, *container = NULL;
    guchar *buffer = NULL;
    gsize size = 0;
    GError *err = NULL;
    GwyDataField *dfield = NULL;
    gsize totalpos, pagesize;
    GString *key;
    guint i;

    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);
        gwy_file_abandon_contents(buffer, size, NULL);
        return NULL;
    }

    // niv - rhkfile is an array of rhkpage's, but buffer is where the actual
    // raw file data is stored
    rhkfile = g_array_new(FALSE, TRUE, sizeof(RHKPage));
    totalpos = 0;

    while (totalpos < size) {
        g_array_set_size(rhkfile, rhkfile->len + 1);
        rhkpage = &g_array_index(rhkfile, RHKPage, rhkfile->len - 1);
        rhkpage->buffer = buffer + totalpos;
        // niv - if the header seems illegal, skip all the next ones as well
        // (and cancel the element addition to the g_array)
        if (!rhkspm32_read_header(rhkpage, &err)) {
            g_warning("failed to read rhk header after %u", rhkfile->len);
            g_array_set_size(rhkfile, rhkfile->len - 1);
            break;
        }

        pagesize = rhkpage->data_offset
                   + rhkpage->item_size*rhkpage->xres*rhkpage->yres;
        if (size < totalpos + pagesize) {
            rhkspm32_free(rhkpage);
            g_array_set_size(rhkfile, rhkfile->len - 1);
            break;
        }

        totalpos += pagesize;
    }

    /* Be tolerant and don't fail when we were able to import at least
     * something */
    if (!rhkfile->len) {
        if (err)
            g_propagate_error(error, err);
        else
            err_NO_DATA(error);
        gwy_file_abandon_contents(buffer, size, NULL);
        g_array_free(rhkfile, TRUE);
        return NULL;
    }
    g_clear_error(&err);

    container = gwy_container_new();
    key = g_string_new(NULL);
    for (i = 0; i < rhkfile->len; i++) {
        const gchar *cs;
        gchar *s;

        gwy_debug("rhk-spm32: processing page %d of %d\n", i+1, rhkfile->len);
        rhkpage = &g_array_index(rhkfile, RHKPage, i);
        if (rhkpage->type == RHK_TYPE_IMAGE) { // niv - just leaving this alone
            dfield = rhkspm32_read_data(rhkpage);
            g_string_printf(key, "/%d/data", i);
            gwy_container_set_object_by_name(container, key->str, dfield);
            g_object_unref(dfield);
            g_string_append(key, "/title");
            cs = gwy_enum_to_string(rhkpage->scan,
                                    scan_directions,
                                    G_N_ELEMENTS(scan_directions));
            if (rhkpage->label) {
                if (cs)
                    s = g_strdup_printf("%s [%s]", rhkpage->label, cs);
                else
                    s = g_strdup(rhkpage->label);
                gwy_container_set_string_by_name(container, key->str, s);
            }
            else
                gwy_app_channel_title_fall_back(container, i);

            gwy_file_channel_import_log_add(container, i, NULL,
                                            filename);
        }
        else if (rhkpage->type == RHK_TYPE_LINE) { // niv - after omicron.c

            GwySpectra* spectra;
            GwyGraphModel *gmodel;

            spectra = rhkspm32_read_spectra(rhkpage);
            /* converting to graphs, as there is no point in leaving these as
             * sps - no xy coordinates, so the spectro tool is kinda clueless */
            gwy_debug("processing graph in page %d\n", i);
            if ((gmodel = spectra_to_graph(spectra)) != NULL) {
                gchar *container_key = NULL;
                /* add gmodel to container */
                container_key = g_strdup_printf("%s/%d", GRAPH_PREFIX, i);
                gwy_container_set_object_by_name(container, container_key,
                                                gmodel);
                g_free(container_key);
            }
            g_object_unref(gmodel);
            g_object_unref(spectra);
        }
        gwy_debug("rhk-spm32: finished parsing page %d \n", i);
        meta = rhkspm32_get_metadata(rhkpage);
        if (rhkpage->type == RHK_TYPE_IMAGE) {
            /* this doesn't really work, but at least the meta data stays
               with the graph, even if the metadata viewer won't show it*/
            g_string_printf(key, "/%d/meta", i);
        }
        else if (rhkpage->type == RHK_TYPE_LINE) {
            g_string_printf(key, "%s/%d/meta", GRAPH_PREFIX, i);
        }
        gwy_container_set_object_by_name(container, key->str, meta);
        g_object_unref(meta);
    }
    g_string_free(key, TRUE);

    gwy_file_abandon_contents(buffer, size, NULL);
    for (i = 0; i < rhkfile->len; i++)
        rhkspm32_free(&g_array_index(rhkfile, RHKPage, i));
    g_array_free(rhkfile, TRUE);

    return container;
}
Example #20
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;
}
Example #21
0
static gboolean
read_aist_raster(const guchar **p, gsize *size, AistContext *context)
{
    AistRaster raster;
    GwyDataField *dfield, *mfield;
    GwySIUnit *xyunit, *zunit;
    gboolean ok = FALSE;
    guint i, j, n, len;
    const guchar *data;
    gchar *s;
    gchar key[32];
    gdouble *d;
    gdouble qxy, qz;

    gwy_clear(&raster, 1);

    gwy_debug("reading common");
    if (!read_aist_common(p, size, &raster.common))
        goto fail;

    gwy_debug("reading raster");
    if (!read_qt_int(p, size, &raster.xres)
        || !read_qt_int(p, size, &raster.yres)
        || !read_qt_double(p, size, &raster.left)
        || !read_qt_double(p, size, &raster.right)
        || !read_qt_double(p, size, &raster.top)
        || !read_qt_double(p, size, &raster.bottom)
        || !read_qt_string(p, size, &raster.xunits)
        || !read_qt_string(p, size, &raster.yunits)
        || !read_qt_string(p, size, &raster.zunits))
        goto fail;

    if (!read_qt_byte_array(p, size, &len, &data))
        goto fail;
    n = raster.xres * raster.yres;
    if (len != n*sizeof(gdouble))
        goto fail;

    xyunit = extract_units(raster.xunits, &qxy);
    zunit = extract_units(raster.zunits, &qz);
    dfield = gwy_data_field_new(raster.xres, raster.yres,
                                qxy*fabs(raster.right - raster.left),
                                qxy*fabs(raster.bottom - raster.top),
                                FALSE);
    gwy_data_field_set_si_unit_xy(dfield, xyunit);
    gwy_data_field_set_si_unit_z(dfield, zunit);
    /* Apparently this is not generally wanted.
    gwy_data_field_set_xoffset(dfield, qxy*MIN(raster.left, raster.right));
    gwy_data_field_set_yoffset(dfield, qxy*MIN(raster.top, raster.bottom));
    */

    g_object_unref(xyunit);
    g_object_unref(zunit);

    d = gwy_data_field_get_data(dfield);
    for (i = 0; i < raster.yres; i++) {
        for (j = 0; j < raster.xres; j++) {
            d[(raster.yres-1 - i)*raster.xres + j]
                = qz*gwy_get_gdouble_le(&data);
        }
    }

    g_snprintf(key, sizeof(key), "/%d/data", context->channel_id);
    gwy_container_set_object_by_name(context->container, key, dfield);
    g_object_unref(dfield);
    gwy_file_channel_import_log_add(context->container, context->channel_id,
                                    NULL, context->filename);

    if ((s = strchr(raster.common.name, '[')))
        s = g_strchomp(g_strndup(raster.common.name, s - raster.common.name));
    else
        s = g_strdup(raster.common.name);
    g_snprintf(key, sizeof(key), "/%d/data/title", context->channel_id);
    gwy_container_set_string_by_name(context->container, key, s);

    g_snprintf(key, sizeof(key), "/%d/mask", context->channel_id);

    context->channel_id++;

    /* At this moment we consider the loading successful. */
    ok = TRUE;

    /* The mask raster is byte-valued.   It contains nonzeroes in points that
     * were measured (the opposite of how we normally create masks upon
     * import). */
    if (read_qt_byte_array(p, size, &len, &data)) {
        if (len == raster.xres*raster.yres) {
            mfield = make_mask_field(dfield, data);
            if (mfield) {
                gwy_app_channel_remove_bad_data(dfield, mfield);
                gwy_container_set_object_by_name(context->container, key,
                                                 mfield);
                g_object_unref(mfield);
            }
        }

        /* Here's something called view data.  It means the data was processed
         * (by whatever means) hence we are not interesed in it. */
        read_qt_byte_array(p, size, &len, &data);
    }

fail:
    free_aist_common(&raster.common);
    g_free(raster.xunits);
    g_free(raster.yunits);
    g_free(raster.zunits);
    return ok;
}
Example #22
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;
}
Example #23
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;
}
Example #24
0
static GwyContainer*
unisoku_load(const gchar *filename,
             G_GNUC_UNUSED GwyRunType mode,
             GError **error)
{
    UnisokuFile ufile;
    GwyContainer *meta, *container = NULL;
    guchar *buffer = NULL;
    gchar *text = NULL;
    gsize i, size = 0;
    GError *err = NULL;
    GwyDataField *dfield = NULL;
    gchar *data_name;

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

    for (i = 0; i < size; i++) {
        if (!text[i])
            text[i] = ' ';
    }

    gwy_clear(&ufile, 1);
    if (!unisoku_read_header(text, &ufile, error)) {
        unisoku_file_free(&ufile);
        g_free(text);
        return NULL;
    }
    g_free(text);

    if (ufile.data_type < UNISOKU_UINT8
        || ufile.data_type > UNISOKU_FLOAT
        || type_sizes[ufile.data_type] == 0) {
        err_DATA_TYPE(error, ufile.data_type);
        unisoku_file_free(&ufile);
        return NULL;
    }

    if (!(data_name = unisoku_find_data_name(filename))) {
        g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA,
                    _("No corresponding data file was found for header file."));
        unisoku_file_free(&ufile);
        return NULL;
    }

    if (!gwy_file_get_contents(data_name, &buffer, &size, &err)) {
        err_GET_FILE_CONTENTS(error, &err);
        unisoku_file_free(&ufile);
        g_free(data_name);
        return NULL;
    }

    dfield = unisoku_read_data_field(buffer, size, &ufile, error);
    gwy_file_abandon_contents(buffer, size, NULL);

    if (!dfield) {
        unisoku_file_free(&ufile);
        g_free(data_name);
        return NULL;
    }

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

    meta = unisoku_get_metadata(&ufile);
    gwy_container_set_object_by_name(container, "/0/meta", meta);
    g_object_unref(meta);

    gwy_file_channel_import_log_add(container, 0, NULL, data_name);

    unisoku_file_free(&ufile);
    g_free(data_name);

    return container;
}
Example #25
0
static GwyContainer*
shimadzu_load(const gchar *filename,
              G_GNUC_UNUSED GwyRunType mode,
              GError **error)
{
    GwyContainer *meta, *container = NULL;
    GwyDataField *dfield = NULL;
    GError *err = NULL;
    gchar *buffer = NULL;
    GHashTable *hash;
    gchar *head;
    gsize size = 0;
    gboolean ok;
    gint text_data_start;

    if (!g_file_get_contents(filename, &buffer, &size, &err)) {
        err_GET_FILE_CONTENTS(error, &err);
        return NULL;
    }
    if (size < HEADER_SIZE + 2) {
        err_TOO_SHORT(error);
        return NULL;
    }
    if (memcmp(buffer, MAGIC, MAGIC_SIZE) != 0
        && !(memcmp(buffer, MAGIC_ASCII, MAGIC_ASCII_SIZE) == 0
             && (memcmp(buffer + MAGIC_ASCII_SIZE+1,
                        MAGIC, MAGIC_SIZE) == 0
                 || memcmp(buffer + MAGIC_ASCII_SIZE+2,
                           MAGIC, MAGIC_SIZE) == 0))) {
        err_FILE_TYPE(error, "Shimadzu");
        g_free(buffer);
        return NULL;
    }

    head = g_memdup(buffer, HEADER_SIZE+1);
    head[HEADER_SIZE] = '\0';

    /* text_data_start is set to nonzero if data are text */
    hash = read_hash(head, &text_data_start, error);
    ok = !!hash;
    if (ok) {
        if (text_data_start)
            dfield = read_text_data(buffer, text_data_start, hash, error);
        else
            dfield = read_binary_data(buffer, size, hash, error);

        ok = !!dfield;
    }

    if (ok) {
        GQuark quark;
        const gchar *title;

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

        meta = shimadzu_get_metadata(hash);
        gwy_container_set_object_by_name(container, "/0/meta", meta);
        g_object_unref(meta);

        title = g_hash_table_lookup(hash, "Channel");
        if (title && *title)
            gwy_container_set_string_by_name(container, "/0/data/title",
                                             g_strdup(title));
        else
            gwy_app_channel_title_fall_back(container, 0);

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

    g_free(head);
    g_free(buffer);
    g_hash_table_destroy(hash);

    return container;
}
Example #26
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;
}
Example #27
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;
}
Example #28
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;
}
Example #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;
}
Example #30
0
static GwyContainer*
microprof_txt_load(const gchar *filename,
                   G_GNUC_UNUSED GwyRunType mode,
                   GError **error)
{
    GwyContainer *container = NULL;
    guchar *p, *buffer = NULL;
    GwyTextHeaderParser parser;
    GHashTable *meta = NULL;
    GwySIUnit *siunit;
    gchar *header = NULL, *s, *prev;
    gsize size = 0;
    GError *err = NULL;
    GwyDataField *dfield = NULL;
    gdouble xreal, yreal, zscale, v;
    gint hlines, xres, yres, i, j;
    gdouble *d;

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

    if (size < MICROPROF_MIN_TEXT_SIZE
        || memcmp(buffer, MAGIC_TXT, MAGIC_TXT_SIZE) != 0) {
        err_FILE_TYPE(error, "MicroProf");
        goto fail;
    }

    hlines = atoi(buffer + MAGIC_TXT_SIZE);
    if (hlines < 7) {
        err_FILE_TYPE(error, "MicroProf");
        goto fail;
    }

    /* Skip specified number of lines */
    for (p = buffer, i = 0; i < hlines; i++) {
        while (*p != '\n' && (gsize)(p - buffer) < size)
            p++;
        if ((gsize)(p - buffer) == size) {
            err_FILE_TYPE(error, "MicroProf");
            goto fail;
        }
        /* Now skip the \n */
        p++;
    }

    header = g_memdup(buffer, p - buffer + 1);
    header[p - buffer] = '\0';

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

    if (!(s = g_hash_table_lookup(meta, "XSize"))
        || !((xres = atoi(s)) > 0)) {
        err_INVALID(error, "XSize");
        goto fail;
    }

    if (!(s = g_hash_table_lookup(meta, "YSize"))
        || !((yres = atoi(s)) > 0)) {
        err_INVALID(error, "YSize");
        goto fail;
    }

    if (!(s = g_hash_table_lookup(meta, "XRange"))
        || !((xreal = g_ascii_strtod(s, NULL)) > 0.0)) {
        err_INVALID(error, "YRange");
        goto fail;
    }

    if (!(s = g_hash_table_lookup(meta, "YRange"))
        || !((yreal = g_ascii_strtod(s, NULL)) > 0.0)) {
        err_INVALID(error, "YRange");
        goto fail;
    }

    if (!(s = g_hash_table_lookup(meta, "ZScale"))
        || !((zscale = g_ascii_strtod(s, NULL)) > 0.0)) {
        err_INVALID(error, "ZScale");
        goto fail;
    }

    dfield = gwy_data_field_new(xres, yres, xreal, yreal, FALSE);
    d = gwy_data_field_get_data(dfield);
    s = (gchar*)p;
    for (i = 0; i < yres; i++) {
        for (j = 0; j < xres; j++) {
            prev = s;
            /* Skip x */
            v = strtol(s, &s, 10);
            if (v != j)
                g_warning("Column number mismatch");
            /* Skip y */
            v = strtol(s, &s, 10);
            if (v != i)
                g_warning("Row number mismatch");
            /* Read value */
            d[(yres-1 - i)*xres + j] = strtol(s, &s, 10)*zscale;

            /* Check whether we moved in the file */
            if (s == prev) {
                g_set_error(error, GWY_MODULE_FILE_ERROR,
                            GWY_MODULE_FILE_ERROR_DATA,
                            _("File contains fewer than XSize*YSize data "
                              "points."));
                goto fail;
            }
        }
    }

    siunit = gwy_si_unit_new("m");
    gwy_data_field_set_si_unit_xy(dfield, siunit);
    g_object_unref(siunit);

    siunit = gwy_si_unit_new("m");
    gwy_data_field_set_si_unit_z(dfield, siunit);
    g_object_unref(siunit);

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

    gwy_file_channel_import_log_add(container, 0, NULL, filename);

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

    return container;
}