예제 #1
0
static gint
ecs_detect(const GwyFileDetectInfo *fileinfo,
           gboolean only_name)
{
    guint xres, yres;
    const guchar *p;

    if (only_name)
        return g_str_has_suffix(fileinfo->name_lowercase, EXTENSION) ? 10 : 0;

    if (fileinfo->buffer_len < ECS_RESOLUTION + 2*2
        || fileinfo->file_size < HEADER_SIZE + 2
        || memcmp(fileinfo->head, MAGIC, MAGIC_SIZE) != 0)
        return 0;

    /* Check if file size matches */
    p = fileinfo->head + ECS_RESOLUTION;
    xres = gwy_get_guint16_le(&p);
    yres = gwy_get_guint16_le(&p);

    if (fileinfo->file_size != 2*xres*yres + HEADER_SIZE)
        return 0;

    return 100;
}
예제 #2
0
static gint
hitachi_old_detect(const GwyFileDetectInfo *fileinfo,
                   gboolean only_name)
{
    guint xres, yres;
    const guchar *p;

    if (only_name)
        return g_str_has_suffix(fileinfo->name_lowercase, EXTENSION) ? 10 : 0;

    if (fileinfo->buffer_len < HEADER_SIZE_OLD
        || fileinfo->file_size < HEADER_SIZE_OLD + 2
        /* This is actually header size (0x100), just weed out non-AFM files */
        || fileinfo->head[0] != 0 || fileinfo->head[1] != 1)
        return 0;

    p = fileinfo->head + RES_OFFSET_OLD;
    xres = gwy_get_guint16_le(&p);
    yres = gwy_get_guint16_le(&p);

    if (fileinfo->file_size == 2*xres*yres + HEADER_SIZE_OLD)
        return 100;

    return 0;
}
예제 #3
0
static guchar*
rhk_sm3_read_string(const guchar **buffer,
                    gsize len)
{
    gchar *s, *p;
    guint i, n;
    gunichar chr;

    if (len < 2)
        return NULL;

    n = gwy_get_guint16_le(buffer);
    len -= 2;
    if (len < 2*n)
        return NULL;

    if (!n)
        return g_strdup("");

    p = s = g_new(gchar, 6*n + 1);
    for (i = 0; i < n; i++) {
        chr = gwy_get_guint16_le(buffer);
        p += g_unichar_to_utf8(chr, p);
    }
    *p = '\0';
    g_strstrip(s);
    gwy_debug("String: <%s>", s);

    return s;
}
예제 #4
0
static gint
burleigh_detect(const GwyFileDetectInfo *fileinfo,
                gboolean only_name)
{
    const guchar *buffer;
    guint version_int, xres, yres;
    gdouble version;

    if (only_name)
        return g_str_has_suffix(fileinfo->name_lowercase, EXTENSION) ? 10 : 0;

    if (fileinfo->buffer_len < 4)
        return 0;

    buffer = fileinfo->head;
    version = gwy_get_gfloat_le(&buffer);
    version_int = GWY_ROUND(10*version);
    gwy_debug("Version: %g", version);

    if (version_int == 21) {
        if (fileinfo->file_size < TOTAL_SIZE_V21 + 2)
            return 0;

        xres = gwy_get_guint16_le(&buffer);
        yres = gwy_get_guint16_le(&buffer);
        if (fileinfo->file_size == TOTAL_SIZE_V21 + 2*xres*yres)
            return 100;
        return 0;
    }

    return 0;
}
예제 #5
0
static gint
apefile_detect(const GwyFileDetectInfo *fileinfo,
               gboolean only_name)
{
    const guchar *buffer;
    gint score = 0;
    guint version, mode, vbtype;

    if (only_name)
        return g_str_has_suffix(fileinfo->name_lowercase, ".dat") ? 10 : 0;

    if (fileinfo->buffer_len < HEADER_SIZE)
        return 0;

    buffer = fileinfo->head;
    version = *(buffer++);
    mode = *(buffer++);
    vbtype = gwy_get_guint16_le(&buffer);
    if (version >= 1 && version <= 2
        && mode < SPM_MODE_LAST+2  /* reserve */
        && vbtype == 7) {
        score = 60;
        /* This works for new file format only */
        if (!strncmp(fileinfo->head + 234, "APERES", 6))
            score = 100;
    }

    return score;
}
예제 #6
0
static gboolean
mif_read_header(const guchar *buffer,
                gsize size,
                MIFHeader *header,
                GError **error)
{
    const guchar *p = buffer;

    if (size <= HEADER_SIZE) {
        err_TOO_SHORT(error);
        return FALSE;
    }

    if (memcmp(buffer, MAGIC, MAGIC_SIZE)) {
        err_FILE_TYPE(error, "MIF");
        return FALSE;
    }

    gwy_clear(header, 1);
    get_CHARARRAY(header->magic, &p);
    header->software_version = gwy_get_guint16_be(&p);
    header->file_version = gwy_get_guint16_be(&p);
    gwy_debug("sw version: %u.%u, file version: %u.%u",
              header->software_version/0x100, header->software_version % 0x100,
              header->file_version/0x100, header->file_version % 0x100);
    /* Version 1.7 is the only actually implemented.  Other can be added upon
     * request and, namely, provision of the files as each file version is
     * different. */
    if (header->file_version != 0x107) {
        g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA,
                    _("Loading of file version %u.%u is not implemented."),
                    header->file_version/0x100, header->file_version % 0x100);
        return FALSE;
    }
    get_CHARARRAY(header->time, &p);
    get_CHARARRAY(header->comment, &p);
    header->nimages = gwy_get_guint16_le(&p);
    gwy_debug("n images: %u", header->nimages);
    header->info.offset = gwy_get_guint32_le(&p);
    header->info.size = gwy_get_guint32_le(&p);
    gwy_debug("info offset: %zu, info size: %zu", header->info.offset, header->info.size);
    get_CHARARRAY(header->unused, &p);

    if (header->info.offset < HEADER_SIZE
        || header->info.offset > size
        || header->info.size > size
        || header->info.offset + header->info.size > size) {
        g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA,
                    _("File information block is outside the file."));
        return FALSE;
    }

    return TRUE;
}
예제 #7
0
파일: csmfile.c 프로젝트: cbuehler/gwyddion
/* XXX: Code identical to nxiifile.c */
static gboolean
read_bmp_header(const guchar *p,
                guint *xres,
                guint *yres,
                guint *size)
{
    guint x;

    if (p[0] != 'B' || p[1] != 'M')
        return FALSE;
    p += 2;

    if ((*size = gwy_get_guint32_le(&p)) < BMP_HEADER_SIZE)   /* Size */
        return FALSE;
    if ((x = gwy_get_guint32_le(&p)) != 0)   /* Reserved */
        return FALSE;
    if ((x = gwy_get_guint32_le(&p)) != 54)   /* Offset */
        return FALSE;
    if ((x = gwy_get_guint32_le(&p)) != 40)   /* Header size */
        return FALSE;
    if ((*xres = gwy_get_guint32_le(&p)) == 0)   /* Width */
        return FALSE;
    if ((*yres = gwy_get_guint32_le(&p)) == 0)   /* Height */
        return FALSE;
    if ((x = gwy_get_guint16_le(&p)) != 1)   /* Bit planes */
        return FALSE;
    if ((x = gwy_get_guint16_le(&p)) != 24)   /* BPP */
        return FALSE;
    if ((x = gwy_get_guint32_le(&p)) != 0)   /* Compression */
        return FALSE;
    if ((x = gwy_get_guint32_le(&p))
        && x + BMP_HEADER_SIZE != *size)   /* Compresed size, may be 0 */
        return FALSE;

    if (3*(*xres)*(*yres) + BMP_HEADER_SIZE != *size)
        return FALSE;

    return TRUE;
}
예제 #8
0
static gboolean
sdfile_read_header_bin(const guchar **p,
                       gsize *len,
                       SDFile *sdfile,
                       GError **error)
{
    if (*len < SDF_HEADER_SIZE_BIN) {
        err_TOO_SHORT(error);
        return FALSE;
    }

    gwy_clear(sdfile, 1);
    get_CHARARRAY(sdfile->version, p);
    get_CHARARRAY(sdfile->manufacturer, p);
    get_CHARARRAY(sdfile->creation, p);
    get_CHARARRAY(sdfile->modification, p);
    sdfile->xres = gwy_get_guint16_le(p);
    sdfile->yres = gwy_get_guint16_le(p);
    sdfile->xscale = gwy_get_gdouble_le(p);
    sdfile->yscale = gwy_get_gdouble_le(p);
    sdfile->zscale = gwy_get_gdouble_le(p);
    sdfile->zres = gwy_get_gdouble_le(p);
    sdfile->compression = **p;
    (*p)++;
    sdfile->data_type = **p;
    (*p)++;
    sdfile->check_type = **p;
    (*p)++;
    sdfile->data = (gchar*)*p;

    if (sdfile->data_type < SDF_NTYPES)
        sdfile->expected_size = type_sizes[sdfile->data_type]
                                * sdfile->xres * sdfile->yres;
    else
        sdfile->expected_size = -1;

    *len -= SDF_HEADER_SIZE_BIN;
    return TRUE;
}
예제 #9
0
static gboolean
mif_read_scan_setup(MIFScanSetup *setup,
                    const guchar **p,
                    gsize size,
                    guint file_version,
                    GError **error)
{
    if (file_version >= 0x103 && file_version <= 0x107) {
        if (size < SCAN_SETUP_SIZE_1_2)
            return err_IMAGE_HEADER_TOO_SHORT(error);
        setup->xres = gwy_get_guint32_le(p);
        setup->yres = gwy_get_guint32_le(p);
        gwy_debug("xres: %u, yres: %u", setup->xres, setup->yres);
        setup->xreal = gwy_get_gdouble_le(p);
        setup->yreal = gwy_get_gdouble_le(p);
        gwy_debug("xreal: %g, yreal: %g", setup->xreal, setup->yreal);
        /* Use negated positive conditions to catch NaNs */
        if (!((setup->xreal = fabs(setup->xreal)) > 0)) {
            g_warning("Real x size is 0.0, fixing to 1.0");
            setup->xreal = 1.0;
        }
        if (!((setup->yreal = fabs(setup->yreal)) > 0)) {
            g_warning("Real y size is 0.0, fixing to 1.0");
            setup->yreal = 1.0;
        }
        setup->xoff = gwy_get_gdouble_le(p);
        setup->yoff = gwy_get_gdouble_le(p);
        gwy_debug("xoff: %g, yoff: %g", setup->xoff, setup->yoff);
        setup->xscandir = gwy_get_gdouble_le(p);
        setup->yscandir = gwy_get_gdouble_le(p);
        gwy_debug("xscandir: %g, yscandir: %g", setup->xscandir, setup->yscandir);
        setup->scan_speed = gwy_get_gfloat_le(p);
        gwy_debug("scan_speed: %g", setup->scan_speed);
        setup->sample_pause = gwy_get_guint16_le(p);
        gwy_debug("sample_pause: %u", setup->sample_pause);
        setup->loop_gain = gwy_get_gfloat_le(p);
        gwy_debug("loop_gain: %g", setup->loop_gain);
        get_CHARARRAY(setup->loop_filter, p);
        gwy_debug_chars(setup, loop_filter);
        get_CHARARRAY(setup->lead_filter, p);
        gwy_debug_chars(setup, lead_filter);
        get_CHARARRAY(setup->lead_lag_mix, p);
        gwy_debug_chars(setup, lead_lag_mix);
    }
    else {
        g_return_val_if_reached(FALSE);
    }

    return TRUE;
}
예제 #10
0
static gboolean
rhk_sm4_read_string_data(RHKPage *page,
                         const RHKObject *obj,
                         guint count,
                         const guchar *buffer)
{
    const guchar *p;
    gchar *s;
    guint i, len;

    gwy_debug("count: %u, known strings: %u", count, RHK_STRING_NSTRINGS);
    count = MIN(count, RHK_STRING_NSTRINGS);
    p = buffer + obj->offset;
    for (i = 0; i < count; i++) {
        /* Not enough strings */
        if (p - buffer + 2 > obj->offset + obj->size)
            return FALSE;

        len = gwy_get_guint16_le(&p);
        if (!len)
            continue;

        /* String does not fit */
        if (p - buffer + 2*len > obj->offset + obj->size)
            return FALSE;

        s = page->strings[i] = g_new0(gchar, 6*len + 1);
        while (len--)
            s += g_unichar_to_utf8(gwy_get_guint16_le(&p), s);

        if (s != page->strings[i]) {
            gwy_debug("string[%u]: <%s>", i, page->strings[i]);
        }
    }

    return TRUE;
}
예제 #11
0
static gboolean
rhk_sm4_read_drift_header(RHKSpecDriftHeader *drift_header,
                          const RHKObject *obj,
                          const guchar *buffer)
{
    const guchar *p = buffer + obj->offset;

    if (obj->size < 16)
        return FALSE;

    drift_header->start_time = gwy_get_guint64_le(&p);
    drift_header->drift_opt = gwy_get_gint16_le(&p);
    drift_header->nstrings = gwy_get_guint16_le(&p);
    /* TODO: Read the strings. */
    return TRUE;
}
예제 #12
0
static RHKSpecDriftHeader*
rhk_sm4_read_drift_header(const RHKObject *obj,
                          const guchar *buffer)
{
    RHKSpecDriftHeader *drift_header = NULL;
    const guchar *p = buffer + obj->offset;

    if (obj->size < 16)
        return drift_header;

    drift_header = g_new0(RHKSpecDriftHeader, 1);
    drift_header->start_time = gwy_get_guint64_le(&p);
    drift_header->drift_opt = gwy_get_gint16_le(&p);
    drift_header->nstrings = gwy_get_guint16_le(&p);
    /* TODO: Read the strings. */

    return drift_header;
}
예제 #13
0
static const gint16*
burleigh_load_v21(IMGFile *imgfile,
                  const guchar *buffer,
                  gsize size,
                  GError **error)
{
    const guchar *p = buffer + 4; /* size of version */
    guint32 n;

    /* Header */
    imgfile->xres = gwy_get_guint16_le(&p);
    imgfile->yres = gwy_get_guint16_le(&p);
    n = imgfile->xres * imgfile->yres;
    if (err_SIZE_MISMATCH(error, 2*n + TOTAL_SIZE_V21, size, TRUE))
        return NULL;

    /* Skip to footer */
    p += 2*n;
    imgfile->xrangemax = gwy_get_guint32_le(&p);
    imgfile->yrangemax = gwy_get_guint32_le(&p);
    imgfile->zrangemax = gwy_get_guint32_le(&p);
    imgfile->xrange = gwy_get_guint32_le(&p);
    imgfile->yrange = gwy_get_guint32_le(&p);
    gwy_debug("xrange: %u, yrange: %u", imgfile->xrange, imgfile->yrange);
    imgfile->zrange = gwy_get_guint32_le(&p);
    gwy_debug("zrange: %u", imgfile->zrange);
    imgfile->scan_speed = gwy_get_guint16_le(&p);
    imgfile->zoom_level = gwy_get_guint16_le(&p);
    gwy_debug("zoom_level: %u", imgfile->zoom_level);
    imgfile->data_type = gwy_get_guint16_le(&p);
    gwy_debug("data_type: %u", imgfile->data_type);
    imgfile->z_gain = gwy_get_guint16_le(&p);
    imgfile->bias_volts = gwy_get_gfloat_le(&p);
    imgfile->tunneling_current = gwy_get_gfloat_le(&p);

    /* Use negated positive conditions to catch NaNs */
    if (!((imgfile->xrange = fabs(imgfile->xrange)) > 0)) {
        g_warning("Real x size is 0.0, fixing to 1.0");
        imgfile->xrange = 1.0;
    }
    if (!((imgfile->yrange = fabs(imgfile->yrange)) > 0)) {
        g_warning("Real y size is 0.0, fixing to 1.0");
        imgfile->yrange = 1.0;
    }

    return (const gint16*)(buffer + HEADER_SIZE_V21);
}
예제 #14
0
static const gint16*
burleigh_load_v21(IMGFile *imgfile,
                  const guchar *buffer,
                  gsize size,
                  GError **error)
{
    const guchar *p = buffer + 4; /* size of version */
    guint32 n;

    /* Header */
    imgfile->xres = gwy_get_guint16_le(&p);
    imgfile->yres = gwy_get_guint16_le(&p);
    n = imgfile->xres * imgfile->yres;
    if (size != 2*n + TOTAL_SIZE_V21) {
        err_SIZE_MISMATCH(error, 2*n + TOTAL_SIZE_V21, size);
        return NULL;
    }
    /* Skip to footer */
    p += 2*n;
    imgfile->xrangemax = gwy_get_guint32_le(&p);
    imgfile->yrangemax = gwy_get_guint32_le(&p);
    imgfile->zrangemax = gwy_get_guint32_le(&p);
    imgfile->xrange = gwy_get_guint32_le(&p);
    imgfile->yrange = gwy_get_guint32_le(&p);
    gwy_debug("xrange: %u, yrange: %u", imgfile->xrange, imgfile->yrange);
    imgfile->zrange = gwy_get_guint32_le(&p);
    gwy_debug("zrange: %u", imgfile->zrange);
    imgfile->scan_speed = gwy_get_guint16_le(&p);
    imgfile->zoom_level = gwy_get_guint16_le(&p);
    gwy_debug("zoom_level: %u", imgfile->zoom_level);
    imgfile->data_type = gwy_get_guint16_le(&p);
    gwy_debug("data_type: %u", imgfile->data_type);
    imgfile->z_gain = gwy_get_guint16_le(&p);
    imgfile->bias_volts = gwy_get_gfloat_le(&p);
    imgfile->tunneling_current = gwy_get_gfloat_le(&p);

    return (const gint16*)(buffer + HEADER_SIZE_V21);
}
예제 #15
0
static GwyContainer*
ecs_load(const gchar *filename,
         G_GNUC_UNUSED GwyRunType mode,
         GError **error)
{
    GwyContainer *meta, *container = NULL;
    guchar *buffer = NULL;
    gsize size = 0;
    GError *err = NULL;
    GwyDataField *dfield = NULL;
    gchar *s = NULL, *s2 = NULL;
    GwySIUnit *siunit;
    const guchar *p;
    gdouble *data, *row;
    guint xres, yres, i, j;
    gdouble xreal, q;
    const gint16 *pdata;
    guchar c;

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

    p = buffer + ECS_RESOLUTION;
    xres = gwy_get_guint16_le(&p);
    yres = gwy_get_guint16_le(&p);
    gwy_debug("xres: %u, yres: %u", xres, yres);
    if (size != HEADER_SIZE + 2*xres*yres) {
        err_SIZE_MISMATCH(error, HEADER_SIZE + 2*xres*yres, size);
        goto fail;
    }

    /* Scan size */
    p = buffer + ECS_SCAN_SIZE;
    s = get_PASCAL_STRING(&p, HEADER_SIZE - ECS_SCAN_SIZE);
    if (!s) {
        g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA,
                    _("Scan size header field overlaps with data."));
        goto fail;
    }
    gwy_debug("Scan size str: <%s>", s);
    if (!g_str_has_prefix(s, "Scan Size: ")) {
        err_FILE_TYPE(error, "ECS");
        goto fail;
    }
    if (sscanf(s + strlen("Scan Size: "), "%lf %lf%c", &xreal, &q, &c)
        != 3) {
        err_INVALID(error, "Scan Size");
        goto fail;
    }
    g_free(s);
    s = NULL;
    gwy_debug("xreal: %g q: %g unit: %s",
              xreal, q, c == 0x8f ? "Angstrom" : "Nanometer");

    if (c == 0x8f) {
        xreal *= 1e-10;
        q *= 1e-10;
    }
    else {
        xreal *= 1e-9;
        q *= 1e-9;
    }
    q /= 65536.0;

    /* This does not make much sense when xres != yres, but it is what
     * Snomputz does. */
    dfield = gwy_data_field_new(xres, yres, xreal, xreal, FALSE);
    data = gwy_data_field_get_data(dfield);
    pdata = (const gint16*)(buffer + HEADER_SIZE);
    for (i = 0; i < yres; i++) {
        row = data + (yres-1 - i)*xres;
        for (j = 0; j < xres; j++)
            row[j] = GINT16_TO_LE(pdata[i*xres + j])*q;
    }

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

    /* Channel title */
    p = buffer + ECS_CHANNEL;
    s = get_PASCAL_STRING(&p, HEADER_SIZE - ECS_CHANNEL);
    if (!s || !*s)
        s = g_strdup("Topography");
    gwy_container_set_string_by_name(container, "/0/data/title", s);
    s = NULL;

    meta = gwy_container_new();

    /* Date & time */
    p = buffer + ECS_DATE;
    s = get_PASCAL_STRING(&p, HEADER_SIZE - ECS_DATE);
    if (s) {
        p = buffer + ECS_TIME;
        s2 = get_PASCAL_STRING(&p, HEADER_SIZE - ECS_TIME);
        if (s2) {
            gwy_container_set_string_by_name(meta, "Date",
                                             g_strconcat(s, " ", s2, NULL));
            g_free(s2);
            s2 = NULL;
        }
        g_free(s);
        s = NULL;
    }

    /* Channel title */
    p = buffer + ECS_CHANNEL;
    s = get_PASCAL_STRING(&p, HEADER_SIZE - ECS_CHANNEL);
    if (s && *s) {
        gwy_container_set_string_by_name(meta, "Comment", s);
        s = NULL;
    }

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

fail:
    g_free(s);
    g_free(s2);
    gwy_object_unref(dfield);
    gwy_file_abandon_contents(buffer, size, NULL);

    return container;
}
예제 #16
0
static GwyContainer*
microprof_load(const gchar *filename,
               G_GNUC_UNUSED GwyRunType mode,
               GError **error)
{
    enum {
        XRES = 0x0026, YRES = 0x002a,
        XRANGE = 0x0038, YRANGE = 0x0040,
        ZRANGE = 0x006e,
    };
    GwyContainer *container = NULL;
    guchar *buffer = NULL;
    const guchar *p;
    MicroProfFile mfile;
    gsize size = 0;
    GError *err = NULL;
    guint i, ndata, datasize;

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

    if (size < MICROPROF_HEADER_SIZE) {
        err_TOO_SHORT(error);
        goto fail;
    }

    if (memcmp(buffer, MAGIC, MAGIC_SIZE) != 0) {
        err_FILE_TYPE(error, "MicroProf");
        goto fail;
    }

    p = buffer + XRES;
    mfile.xres = gwy_get_guint16_le(&p);
    if (err_DIMENSION(error, mfile.xres))
        goto fail;

    p = buffer + YRES;
    mfile.yres = gwy_get_guint16_le(&p);
    if (err_DIMENSION(error, mfile.xres))
        goto fail;

    p = buffer + XRANGE;
    mfile.xrange = gwy_get_gdouble_le(&p);
    if (!(mfile.xrange = fabs(mfile.xrange))) {
        g_warning("Real x size is 0.0, fixing to 1.0");
        mfile.xrange = 1.0;
    }

    p = buffer + YRANGE;
    mfile.yrange = gwy_get_gdouble_le(&p);
    if (!(mfile.yrange = fabs(mfile.yrange))) {
        g_warning("Real y size is 0.0, fixing to 1.0");
        mfile.yrange = 1.0;
    }

    p = buffer + ZRANGE;
    mfile.zscale = gwy_get_gdouble_le(&p);

    datasize = 2*mfile.xres*mfile.yres;
    if (err_SIZE_MISMATCH(error, datasize, size - MICROPROF_HEADER_SIZE, FALSE))
        goto fail;
    /* FIXME: There is weird stuff between channels.  Need specs.
    ndata = (size - MICROPROF_HEADER_SIZE)/datasize;
    if (!ndata) {
        err_NO_DATA(error);
        goto fail;
    }
    */
    ndata = 1;
    container = gwy_container_new();

    mfile.data = buffer + MICROPROF_HEADER_SIZE;
    for (i = 0; i < ndata; i++) {
        GwyDataField *dfield;
        GQuark quark;

        dfield = microprof_read_data_field(&mfile,
                                           mfile.data + i*datasize);
        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);
    }

fail:
    gwy_file_abandon_contents(buffer, size, NULL);
    return container;
}
예제 #17
0
static GwyContainer*
surffile_load(const gchar *filename,
             G_GNUC_UNUSED GwyRunType mode,
             GError **error)
{
    SurfFile surffile;
    GwyContainer *meta, *container = NULL;
    guchar *buffer = NULL;
    const guchar *p;
    gsize expected_size, size = 0;
    GError *err = NULL;
    gchar signature[12];
    gdouble max, min;
    gint add = 0;

    if (!gwy_file_get_contents(filename, &buffer, &size, &err)) {
        err_GET_FILE_CONTENTS(error, &err);
        g_clear_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.measurement_duration = gwy_get_guint16_le(&p);
    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);

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

    p = buffer + SURF_HEADER_SIZE + add;
    if (!fill_data_fields(&surffile, p, error)) {
        gwy_file_abandon_contents(buffer, size, NULL);
        return NULL;
    }

    if (!surffile.absolute) {
        max = gwy_data_field_get_max(surffile.dfield);
        min = gwy_data_field_get_min(surffile.dfield);
        gwy_data_field_add(surffile.dfield, -min);

        gwy_data_field_multiply(surffile.dfield,
                                (surffile.zmax - surffile.zmin)/(max-min));
    }

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

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

    return container;
}
예제 #18
0
파일: quesant.c 프로젝트: cbuehler/gwyddion
static gboolean
read_file_info(const guchar *buffer, gsize size,
               FileInfo *info,
               GError **error)
{
    guint expected_size, i;
    const guchar *p;

    gwy_clear(info, 1);
    p = buffer + MAGIC_SIZE;
    /* read structure variables from buffer */
    for (i = 0; i < (HEADER_SIZE - MAGIC_SIZE)/8; i++) {
        gchar key[5];
        guint32 value;

        key[4] = '\0';
        memcpy(key, p, 4);
        p += 4;
        value = gwy_get_guint32_le(&p);
        if (!key[0])
            continue;

        gwy_debug("%s: 0x%04x", key, value);

        /* Do not take values past the end of file and zeros into account at
         * all.   The software seems to sometimes emit silly extra fields. */
        if (!value || value >= size)
            continue;

        else if (gwy_strequal(key, "DESC"))
            info->desc_offset = value;
        else if (gwy_strequal(key, "DATE"))
            info->date_offset = value;
        else if (gwy_strequal(key, "PLET"))
            info->palette_offset = value;
        else if (gwy_strequal(key, "IMAG"))
            info->image_offset = value;
        else if (gwy_strequal(key, "HARD"))
            info->hard_offset = value;
        else if (gwy_strequal(key, "IMGP"))
            info->img_p_offset = value;
        else if (gwy_strequal(key, "SDES"))
            info->short_desc_offset = value;
        else if (gwy_strequal(key, "KEYS"))
            info->keys_offset = value;
        else {
            gwy_debug("Unknown field %s", key);
        }
    }

    /* Pixel image size */
    if (!(p = get_param_pointer(buffer, size,
                                info->image_offset, sizeof(guint16),
                                "IMAG", error)))
        return FALSE;
    info->img_res = gwy_get_guint16_le(&p);
    if (err_DIMENSION(error, info->img_res))
        return FALSE;

    /* Image data.  It is the *same* pointer, just after the pixel size.  */
    info->image_data = (const guint16*)p;
    expected_size = (p - buffer) + info->img_res*info->img_res*sizeof(guint16);
    if (err_SIZE_MISMATCH(error, expected_size, size, FALSE))
        return FALSE;

    /* Real image size */
    if (!(p = get_param_pointer(buffer, size,
                                info->hard_offset, sizeof(gfloat),
                                "HARD", error)))
        return FALSE;
    info->real_size = gwy_get_gfloat_le(&p);
    if (!((info->real_size = fabs(info->real_size)) > 0)) {
        g_warning("Real size is 0.0, fixing to 1.0");
        info->real_size = 1.0;
    }

    /* Value scale factor */
    if (!(p = get_param_pointer(buffer, size,
                                info->img_p_offset + 8, sizeof(gfloat),
                                "IMGP", error)))
        return FALSE;
    info->z_scale = gwy_get_gfloat_le(&p);

    return TRUE;
}
예제 #19
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;
}
예제 #20
0
static RHKPage*
rhk_sm3_read_page(const guchar **buffer,
                  gsize *len,
                  GError **error)
{
    RHKPage *page;
    const guchar *p = *buffer;
    guint i, expected;

    if (!*len)
        return NULL;

    if (*len < HEADER_SIZE + 4) {
        g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA,
                    _("End of file reached in page header."));
        return NULL;
    }
    if (memcmp(p + MAGIC_OFFSET, MAGIC, MAGIC_SIZE) != 0) {
        err_INVALID(error, _("magic page header"));
        return NULL;
    }

    page = g_new0(RHKPage, 1);
    page->param_size = gwy_get_guint16_le(&p);
    gwy_debug("param_size = %u", page->param_size);
    if (*len < page->param_size + 4) {
        g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA,
                    _("End of file reached in page header."));
        goto FAIL;
    }
    /* TODO: Convert to UTF-8, store to meta */
    memcpy(page->version, p, MAGIC_TOTAL_SIZE);
    p += MAGIC_TOTAL_SIZE;
    page->string_count = gwy_get_guint16_le(&p);
    gwy_debug("string_count = %u", page->string_count);
    page->type = gwy_get_guint32_le(&p);
    gwy_debug("type = %u", page->type);
    page->page_type = gwy_get_guint32_le(&p);
    gwy_debug("page_type = %u", page->page_type);
    page->data_sub_source = gwy_get_guint32_le(&p);
    page->line_type = gwy_get_guint32_le(&p);
    page->x_coord = gwy_get_gint32_le(&p);
    page->y_coord = gwy_get_gint32_le(&p);
    page->x_size = gwy_get_guint32_le(&p);
    page->y_size = gwy_get_guint32_le(&p);
    gwy_debug("x_size = %u, y_size = %u", page->x_size, page->y_size);
    page->source_type = gwy_get_guint32_le(&p);
    page->image_type = gwy_get_guint32_le(&p);
    gwy_debug("image_type = %u", page->image_type);
    page->scan_dir = gwy_get_guint32_le(&p);
    gwy_debug("scan_dir = %u", page->scan_dir);
    page->group_id = gwy_get_guint32_le(&p);
    gwy_debug("group_id = %u", page->group_id);
    page->data_size = gwy_get_guint32_le(&p);
    gwy_debug("data_size = %u", page->data_size);
    page->min_z_value = gwy_get_gint32_le(&p);
    page->max_z_value = gwy_get_gint32_le(&p);
    gwy_debug("min,max_z_value = %d %d", page->min_z_value, page->max_z_value);
    page->x_scale = gwy_get_gfloat_le(&p);
    page->y_scale = gwy_get_gfloat_le(&p);
    page->z_scale = gwy_get_gfloat_le(&p);
    gwy_debug("x,y,z_scale = %g %g %g",
              page->x_scale, page->y_scale, page->z_scale);
    page->xy_scale = gwy_get_gfloat_le(&p);
    page->x_offset = gwy_get_gfloat_le(&p);
    page->y_offset = gwy_get_gfloat_le(&p);
    page->z_offset = gwy_get_gfloat_le(&p);
    gwy_debug("x,y,z_offset = %g %g %g",
              page->x_offset, page->y_offset, page->z_offset);
    page->period = gwy_get_gfloat_le(&p);
    page->bias = gwy_get_gfloat_le(&p);
    page->current = gwy_get_gfloat_le(&p);
    page->angle = gwy_get_gfloat_le(&p);
    gwy_debug("period = %g, bias = %g, current = %g, angle = %g",
              page->period, page->bias, page->current, page->angle);
    get_CHARARRAY(page->page_id, &p);

    p = *buffer + 2 + page->param_size;
    for (i = 0; i < page->string_count; i++) {
        gchar *s;

        gwy_debug("position %04x", p - *buffer);
        s = rhk_sm3_read_string(&p, *len - (p - *buffer));
        if (!s) {
            g_set_error(error, GWY_MODULE_FILE_ERROR,
                        GWY_MODULE_FILE_ERROR_DATA,
                        _("End of file reached in string #%u."), i);
            goto FAIL;
        }
        if (i < RHK_STRING_NSTRINGS)
            page->strings[i] = s;
        else
            g_free(s);
    }

    expected = page->x_size * page->y_size * sizeof(gint32);
    gwy_debug("expecting %u bytes of page data now", expected);
    if (*len < (p - *buffer) + expected) {
        err_SIZE_MISMATCH(error, expected, *len - (p - *buffer));
        goto FAIL;
    }

    if (page->type == RHK_TYPE_IMAGE)
        page->page_data = p;
    else
        page->spectral_data = p;
    p += expected;

    if (page->type == RHK_TYPE_IMAGE) {
        if (*len < (p - *buffer) + 4) {
            g_set_error(error, GWY_MODULE_FILE_ERROR,
                        GWY_MODULE_FILE_ERROR_DATA,
                        _("End of file reached in color data header."));
            goto FAIL;
        }
        /* Info size includes itself */
        page->color_info.size = gwy_get_guint32_le(&p) - 2;
        if (*len < (p - *buffer) + page->color_info.size) {
            g_set_error(error, GWY_MODULE_FILE_ERROR,
                        GWY_MODULE_FILE_ERROR_DATA,
                        _("End of file reached in color data."));
            goto FAIL;
        }

        p += page->color_info.size;
    }

    *len -= p - *buffer;
    *buffer = p;
    return page;

FAIL:
    rhk_sm3_page_free(page);
    return NULL;
}
예제 #21
0
static gboolean
rhk_sm4_read_page_header(RHKPage *page,
                         const RHKObject *obj,
                         const guchar *buffer,
                         gsize size,
                         GError **error)
{
    const guchar *p;
    guint i;

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

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

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

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

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

    return TRUE;
}
예제 #22
0
static GwyDataField*
read_data_field_old(const guchar *buffer,
                    guint size,
                    GError **error)
{
    gint xres, yres, n, i, j, vx, vy;
    G_GNUC_UNUSED gint vz;
    gdouble xscale, yscale, zscale, xreal, yreal, q;
    G_GNUC_UNUSED gdouble xunit, yunit, zunit;
    GwyDataField *dfield;
    GwySIUnit *siunit;
    gdouble *data, *row;
    const gint16 *pdata;
    const guchar *p;

    p = buffer + RES_OFFSET_OLD;
    xres = gwy_get_guint16_le(&p);
    yres = gwy_get_guint16_le(&p);
    gwy_debug("xres: %d, yres: %d", xres, yres);
    if (err_DIMENSION(error, xres) || err_DIMENSION(error, yres))
        return NULL;

    n = xres*yres;
    if (err_SIZE_MISMATCH(error, 2*n + HEADER_SIZE_OLD, size, TRUE))
        return NULL;

    p = buffer + SCALE_OFFSET_OLD;
    xscale = gwy_get_gdouble_le(&p);
    yscale = gwy_get_gdouble_le(&p);
    zscale = gwy_get_gdouble_le(&p);
    p = buffer + UNIT_OFFSET_OLD;
    xunit = gwy_get_gdouble_le(&p);
    yunit = gwy_get_gdouble_le(&p);
    zunit = gwy_get_gdouble_le(&p);
    p = buffer + SPEED_OFFSET_OLD;
    vx = gwy_get_guint32_le(&p);
    vy = gwy_get_guint32_le(&p);
    vz = gwy_get_guint32_le(&p);

    xreal = xscale * vx;
    yreal = yscale * vy;
    q = zscale;
    gwy_debug("xreal: %g, yreal: %g, zscale: %g", xreal, yreal, q);
    /* 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);
    data = gwy_data_field_get_data(dfield);
    pdata = (const gint16*)(buffer + HEADER_SIZE_OLD);
    for (i = 0; i < yres; i++) {
        row = data + i*xres;
        for (j = 0; j < xres; j++)
            row[j] = GUINT16_FROM_LE(pdata[i*xres + j])*q;
    }

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

    return dfield;
}
예제 #23
0
static void
jeol_read_image_header(const guchar *p,
                       JEOLImageHeader *header)
{
    p += TIFF_HEADER_SIZE;

    header->winspm_version = gwy_get_guint16_le(&p);
    gwy_debug("version: %u", header->winspm_version);
    p += 80;  /* there isn't anything interesting in internal_filename_old */
    header->xres = gwy_get_guint16_le(&p);
    header->yres = gwy_get_guint16_le(&p);
    header->xreal = gwy_get_gfloat_le(&p);
    header->yreal = gwy_get_gfloat_le(&p);
    gwy_debug("res: (%d,%d), real: (%g,%g)",
              header->xres, header->yres, header->xreal, header->yreal);
    header->z0 = gwy_get_gfloat_le(&p);
    header->z255 = gwy_get_gfloat_le(&p);
    header->adc_min = gwy_get_guint16_le(&p);
    header->adc_max = gwy_get_guint16_le(&p);
    header->initial_scan_scale = gwy_get_gfloat_le(&p);
    get_CHARARRAY0(header->internal_filename, &p);
    get_CHARARRAY0(header->info[0], &p);
    get_CHARARRAY0(header->info[1], &p);
    get_CHARARRAY0(header->info[2], &p);
    get_CHARARRAY0(header->info[3], &p);
    get_CHARARRAY0(header->info[4], &p);
    get_CHARARRAY(header->history, &p);
    header->has_current_info = gwy_get_guint16_le(&p);
    header->bias = gwy_get_gfloat_le(&p);
    gwy_debug("bias: %g", header->bias);
    header->reference_value = gwy_get_gfloat_le(&p);
    gwy_debug("reference_value: %g", header->reference_value);
    p += 2;  /* reserved */
    header->measurement_date.day = *(p++);
    header->measurement_date.month = *(p++);
    header->measurement_date.year_1980 = gwy_get_guint16_le(&p);
    header->measurement_date.weekday_sun = *(p++);
    header->save_date.day = *(p++);
    header->save_date.month = *(p++);
    header->save_date.year_1980 = gwy_get_guint16_le(&p);
    header->save_date.weekday_sun = *(p++);
    header->measurement_time.hour = *(p++);
    header->measurement_time.minute = *(p++);
    header->measurement_time.second= *(p++);
    header->measurement_time.second_100 = *(p++);
    header->save_time.hour = *(p++);
    header->save_time.minute = *(p++);
    header->save_time.second= *(p++);
    header->save_time.second_100 = *(p++);
    p += 0x100;  /* lookup table */
    header->fft_offset = gwy_get_guint32_le(&p);
    header->transform_off = gwy_get_guint16_le(&p);
    p += 8;  /* extra */
    header->compressed = gwy_get_gboolean8(&p);
    header->bpp = *(p++);
    gwy_debug("bpp: %d", header->bpp);
    header->cits_offset = gwy_get_guint32_le(&p);
    header->backscan_tip_voltage = gwy_get_gfloat_le(&p);
    header->sts_point_x = gwy_get_guint16_le(&p);
    header->sts_point_y = gwy_get_guint16_le(&p);
    p += 20;  /* reserved */
    header->tip_speed_x = gwy_get_gfloat_le(&p);
    header->tip_speed_y = gwy_get_gfloat_le(&p);
    p += 42;  /* piezo_sensitivity */
    header->spm_param.clock = gwy_get_gfloat_le(&p);
    header->spm_param.rotation = gwy_get_gfloat_le(&p);
    header->spm_param.feedback_filter = gwy_get_gfloat_le(&p);
    header->spm_param.present_filter = gwy_get_gfloat_le(&p);
    header->spm_param.head_amp_gain = gwy_get_gfloat_le(&p);
    header->spm_param.loop_gain = gwy_get_guint16_le(&p);
    header->spm_param.x_off = gwy_get_gfloat_le(&p);
    header->spm_param.y_off = gwy_get_gfloat_le(&p);
    header->spm_param.z_gain = gwy_get_gfloat_le(&p);
    header->spm_param.z_off = gwy_get_gfloat_le(&p);
    header->spm_param.o_gain = gwy_get_gfloat_le(&p);
    header->spm_param.o_off = gwy_get_gfloat_le(&p);
    gwy_debug("z_gain: %g o_gain: %g",
              header->spm_param.z_gain, header->spm_param.o_gain);
    header->spm_param.back_scan_bias = gwy_get_gfloat_le(&p);
    /* XXX: This does not match what the documentation says, there seems to be
     * a four-byte quantity missing between back_scan_bias and mode (the size
     * of SPM params struct is also 4 bytes shorter than the space alloted for
     * it). */
    p += 4;  /* whatever */
    header->spm_param.mode = gwy_get_guint32_le(&p);
    gwy_debug("mode: %d", header->spm_param.mode);
    p += 2;  /* reserved */
    header->montage_offset = gwy_get_guint32_le(&p);
    get_CHARARRAY0(header->image_location, &p);
    p += 2*4;  /* reserved */
    header->spm_misc_param.dds_frequency = gwy_get_gfloat_le(&p);
    header->spm_misc_param.dds_low_filter = gwy_get_guint16_le(&p);
    header->spm_misc_param.dds_high_filter = gwy_get_guint16_le(&p);
    header->spm_misc_param.dds_center_filter = gwy_get_guint16_le(&p);
    header->spm_misc_param.dds_enable = gwy_get_guint16_le(&p);
    header->spm_misc_param.scan_filter = gwy_get_guint16_le(&p);
    header->spm_misc_param.afm_mode = gwy_get_guint32_le(&p);
    gwy_debug("afm_mode: 0x%x", header->spm_misc_param.afm_mode);
    header->spm_misc_param.slope_gain = gwy_get_guint32_le(&p);
    header->spm_misc_param.x_addition_signal = gwy_get_guint16_le(&p);
    header->spm_misc_param.y_addition_signal = gwy_get_guint16_le(&p);
    header->spm_misc_param.z_addition_signal = gwy_get_guint16_le(&p);
    header->spm_misc_param.bias_addition_signal = gwy_get_guint16_le(&p);
    header->spm_misc_param.active_dialog = gwy_get_guint32_le(&p);
    header->spm_misc_param.spm_mode = gwy_get_guint32_le(&p);
    gwy_debug("spm_mode: 0x%x", header->spm_misc_param.spm_mode);
    header->spm_misc_param.measurement_signal = gwy_get_guint32_le(&p);
    gwy_debug("signal: 0x%x", header->spm_misc_param.measurement_signal);
    header->spm_misc_param.phase_vco_scan = gwy_get_guint16_le(&p);
    header->spm_misc_param.sps_mode = gwy_get_guint32_le(&p);
    header->spm_misc_param.dds_amplitude = gwy_get_gdouble_le(&p);
    header->spm_misc_param.dds_center_locked_freq = gwy_get_gdouble_le(&p);
    header->spm_misc_param.dds_phase_shift = gwy_get_gfloat_le(&p);
    header->spm_misc_param.dds_high_gain = gwy_get_guint16_le(&p);
    header->spm_misc_param.dds_phase_polarity = gwy_get_guint16_le(&p);
    header->spm_misc_param.dds_pll_excitation = gwy_get_guint16_le(&p);
    header->spm_misc_param.dds_external = gwy_get_guint16_le(&p);
    header->spm_misc_param.dds_rms_filter = gwy_get_guint32_le(&p);
    header->spm_misc_param.dds_pll_loop_gain = gwy_get_guint32_le(&p);
    header->spm_misc_param.dds_beat_noise = gwy_get_guint32_le(&p);
    header->spm_misc_param.dds_dynamic_range = gwy_get_guint32_le(&p);
    header->spm_misc_param.cantilever_peak_freq = gwy_get_guint32_le(&p);
    header->spm_misc_param.cantilever_q_factor = gwy_get_guint32_le(&p);
    p += 10;  /* reserved */
    p += 0x300;  /* RGB lookup table */
    header->sub_revision_no = gwy_get_guint32_le(&p);
    header->image_type = gwy_get_guint32_le(&p);
    gwy_debug("image_type: %d", header->image_type);
    header->data_source = gwy_get_guint32_le(&p);
    gwy_debug("data_source: %d", header->data_source);
    header->display_mode = gwy_get_guint32_le(&p);
    p += 2*8;  /* measurement_start_time, measurement_end_time */
    p += 254;  /* profile_roughness */
    p += 446;  /* settings_3d */
    header->lut_brightness = gwy_get_gfloat_le(&p);
    header->lut_contrast = gwy_get_gfloat_le(&p);
    header->software_version = gwy_get_guint16_le(&p);
    header->software_subversion = gwy_get_guint32_le(&p);
    p += 20;  /* extracted_region */
    header->lut_gamma = gwy_get_gfloat_le(&p);
    header->n_of_sps = gwy_get_guint16_le(&p);
    header->sps_offset = gwy_get_guint32_le(&p);
    header->line_trace_end_x = gwy_get_guint16_le(&p);
    header->line_trace_end_y = gwy_get_guint16_le(&p);
    header->forward = gwy_get_guint16_le(&p);
    gwy_debug("forward: %d", header->forward);
    header->lift_signal = gwy_get_guint16_le(&p);
    /* stuff... */
}
예제 #24
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;
}
예제 #25
0
static GwyDataField*
read_data_field(const guchar *buffer,
                guint size,
                guchar version,
                gchar **title,
                gint *direction,
                GError **error)
{
    enum { MIN_REMAINDER = 2620 };
    /* information offsets in different versions, in r5+ relative to data
     * start, in order:
     * data offset,
     * pixel dimensions,
     * physical dimensions,
     * value multiplier,
     * unit string,
     * data type,       (if zero, use channel title)
     * channel title    (if zero, use data type)
     */
    const guint offsets34[] = {
        0x0104, 0x0196, 0x01a2, 0x01b2, 0x01c2, 0x0400, 0x0000
    };
    const guint offsets56[] = {
        0x0104, 0x025c, 0x0268, 0x0288, 0x02a0, 0x0708, 0x0000
    };
    const guint offsets7[] = {
        0x0104, 0x029c, 0x02a8, 0x02c8, 0x02e0, 0x0000, 0x0b90
    };
    gint xres, yres, doffset, i, power10, type;
    gdouble xreal, yreal, q, z0;
    GwyDataField *dfield;
    GwySIUnit *unitxy, *unitz;
    gdouble *data;
    const guint *offset;
    const guchar *p, *r, *last;
    /* get floats in single precision from r4 but double from r5+ */
    gdouble (*getflt)(const guchar**);

    *title = NULL;
    *direction = -1;

    if (version == '5' || version == '6' || version == '7') {
        /* There are more headers in r5,
         * try to find something that looks like #R5. */
        last = r = buffer;
        while ((p = memchr(r, '#', size - (r - buffer) - MIN_REMAINDER))) {
            if (p[1] == 'R' && p[2] == version && p[3] == '.') {
                gwy_debug("pos: %ld", (long)(p - buffer));
                last = p;
                r = p + MIN_REMAINDER-1;
            }
            else
                r = p + 1;
        }
        offset = (version == '7') ? &offsets7[0] : &offsets56[0];
        buffer = last;
        getflt = &gwy_get_gdouble_le;
    }
    else {
        offset = &offsets34[0];
        getflt = &get_gfloat_le_as_double;
    }

    p = buffer + *(offset++);
    doffset = gwy_get_guint32_le(&p);  /* this appears to be the same number
                                          as in the ASCII miniheader -- so get
                                          it here since it's easier */
    gwy_debug("data offset = %u", doffset);
    p = buffer + *(offset++);
    xres = gwy_get_guint32_le(&p);
    yres = gwy_get_guint32_le(&p);
    if (err_DIMENSION(error, xres) || err_DIMENSION(error, yres))
        return NULL;
    p = buffer + *(offset++);
    xreal = -getflt(&p);
    xreal += getflt(&p);
    yreal = -getflt(&p);
    yreal += getflt(&p);
    if (!((xreal = fabs(xreal)) > 0)) {
        g_warning("Real x size is 0.0, fixing to 1.0");
        xreal = 1.0;
    }
    if (!((yreal = fabs(yreal)) > 0)) {
        g_warning("Real y size is 0.0, fixing to 1.0");
        yreal = 1.0;
    }
    p = buffer + *(offset++);
    q = getflt(&p);
    z0 = getflt(&p);
    gwy_debug("xreal.raw = %g, yreal.raw = %g, q.raw = %g, z0.raw = %g",
              xreal, yreal, q, z0);
    p = buffer + *(offset++);
    unitz = gwy_si_unit_new_parse(p, &power10);
    q *= pow10(power10);
    z0 *= pow10(power10);
    unitxy = gwy_si_unit_new_parse(p + 10, &power10);
    xreal *= pow10(power10);
    yreal *= pow10(power10);
    gwy_debug("xres = %d, yres = %d, xreal = %g, yreal = %g, q = %g, z0 = %g",
              xres, yres, xreal, yreal, q, z0);
    gwy_debug("unitxy = %s, unitz = %s", p, p + 10);

    if (offset[1]) {
        /* We know channel title */
        offset++;
        p = buffer + *(offset++);
        *title = g_strndup(p, size - (p - buffer));
        gwy_debug("title = <%s>", *title);
    }
    else {
        /* We know data type */
        p = buffer + *(offset++);
        type = gwy_get_guint16_le(&p);
        *direction = gwy_get_guint16_le(&p);
        gwy_debug("type = %d, dir = %d", type, *direction);
        offset++;
        *title = type_to_title(type);
    }

    p = buffer + doffset;
    if (err_SIZE_MISMATCH(error, 2*xres*yres, size - (p - buffer), FALSE))
        return NULL;

    dfield = gwy_data_field_new(xres, yres, xreal, yreal, FALSE);
    gwy_data_field_set_si_unit_xy(dfield, unitxy);
    g_object_unref(unitxy);
    gwy_data_field_set_si_unit_z(dfield, unitz);
    g_object_unref(unitz);
    data = gwy_data_field_get_data(dfield);
    for (i = 0; i < xres*yres; i++)
        data[i] = (p[2*i] + 256.0*p[2*i + 1])*q + z0;

    return dfield;
}
예제 #26
0
/* Reads @header and initializes @reader for the correct byte order.  Returns
 * the number of bytes read, 0 on error. */
static guint
igor_read_headers(IgorFile *igorfile,
                  const guchar *buffer,
                  gsize size,
                  gboolean check_only,
                  GError **error)
{
    IgorBinHeader *header;
    gsize headers_size;
    guint version, chksum, i;
    gboolean lsb;
    const guchar *p = buffer;

    if (size < HEADER_SIZE1) {
        err_TOO_SHORT(error);
        return 0;
    }

    /* The lower byte of version is nonzero.  Use it to detect endianess. */
    version = gwy_get_guint16_le(&p);
    gwy_debug("raw version: 0x%04x", version);

    /* Keep the rejection code path fast by performing version sanity check
     * as the very first thing. */
    if ((lsb = (version & 0xff))) {
        gwy_debug("little endian");
    }
    else {
        gwy_debug("big endian");
        version /= 0x100;
    }

    /* Check if version is known and the buffer size */
    if (version == 1)
        headers_size = HEADER_SIZE1 + WAVE_SIZE2;
    else if (version == 2)
        headers_size = HEADER_SIZE2 + WAVE_SIZE2;
    else if (version == 3)
        headers_size = HEADER_SIZE3 + WAVE_SIZE2;
    else if (version == 5)
        headers_size = HEADER_SIZE5 + WAVE_SIZE5;
    else {
        err_FILE_TYPE(error, "IGOR Pro");
        return 0;
    }
    gwy_debug("expected headers_size %lu", (gulong)headers_size);
    if (size < headers_size) {
        err_TOO_SHORT(error);
        return 0;
    }

    /* Check the checksum */
    chksum = igor_checksum(buffer, headers_size, lsb);
    gwy_debug("checksum %u", chksum);
    if (chksum) {
        err_FILE_TYPE(error, "IGOR Pro");
        return 0;
    }

    /* If only detection is required, we can stop now. */
    if (check_only)
        return headers_size;

    /* If the checksum is correct the file is likely IGOR file and we can
     * start the expensive actions. */
    gwy_clear(igorfile, 1);
    header = &igorfile->header;
    header->version = version;
    igorfile->headers_size = headers_size;
    gwy_debug("format version: %u", header->version);

    if (lsb) {
        igorfile->get_guint16 = gwy_get_guint16_le;
        igorfile->get_gint16 = gwy_get_gint16_le;
        igorfile->get_guint32 = gwy_get_guint32_le;
        igorfile->get_gint32 = gwy_get_gint32_le;
        igorfile->get_gfloat = gwy_get_gfloat_le;
        igorfile->get_gdouble = gwy_get_gdouble_le;
    }
    else {
        igorfile->get_guint16 = gwy_get_guint16_be;
        igorfile->get_gint16 = gwy_get_gint16_be;
        igorfile->get_guint32 = gwy_get_guint32_be;
        igorfile->get_gint32 = gwy_get_gint32_be;
        igorfile->get_gfloat = gwy_get_gfloat_be;
        igorfile->get_gdouble = gwy_get_gdouble_be;
    }

    /* Read the rest of the binary header */
    if (header->version == 1) {
        igorfile->wave_header_size = 110;
        header->wfm_size = igorfile->get_guint32(&p);
        header->checksum = igorfile->get_guint16(&p);
    }
    else if (header->version == 2) {
        igorfile->wave_header_size = 110;
        header->wfm_size = igorfile->get_guint32(&p);
        header->note_size = igorfile->get_guint32(&p);
        header->pict_size = igorfile->get_guint32(&p);
        header->checksum = igorfile->get_guint16(&p);
    }
    else if (header->version == 3) {
        igorfile->wave_header_size = 110;
        header->wfm_size = igorfile->get_guint32(&p);
        header->note_size = igorfile->get_guint32(&p);
        header->formula_size = igorfile->get_guint32(&p);
        header->pict_size = igorfile->get_guint32(&p);
        header->checksum = igorfile->get_guint16(&p);
    }
    else if (header->version == 5) {
        igorfile->wave_header_size = 320;
        header->checksum = igorfile->get_guint16(&p);
        header->wfm_size = igorfile->get_guint32(&p);
        header->formula_size = igorfile->get_guint32(&p);
        gwy_debug("formula_size: %u", header->formula_size);
        header->note_size = igorfile->get_guint32(&p);
        gwy_debug("note_size: %u", header->note_size);
        header->data_e_units_size = igorfile->get_guint32(&p);
        gwy_debug("data_e_units_size: %u", header->data_e_units_size);
        for (i = 0; i < MAXDIMS; i++) {
            header->dim_e_units_size[i] = igorfile->get_guint32(&p);
            gwy_debug("dim_e_units_size[%u]: %u", i, header->dim_e_units_size[i]);
        }
        for (i = 0; i < MAXDIMS; i++) {
            header->dim_labels_size[i] = igorfile->get_guint32(&p);
            gwy_debug("dim_labels_size[%u]: %u", i, header->dim_labels_size[i]);
        }
        header->indices_size = igorfile->get_guint32(&p);
        header->options_size1 = igorfile->get_guint32(&p);
        header->options_size2 = igorfile->get_guint32(&p);
    }
    else {
        g_assert_not_reached();
    }

    gwy_debug("wfm_size: %u", header->wfm_size);

    /* Read the wave header */
    if (version == 5) {
        IgorWaveHeader5 *wave5 = &igorfile->wave5;

        wave5->next = igorfile->get_guint32(&p);
        wave5->creation_date = igorfile->get_guint32(&p);
        wave5->mod_date = igorfile->get_guint32(&p);
        wave5->npts = igorfile->get_guint32(&p);
        wave5->type = igorfile->get_guint16(&p);
        gwy_debug("type: %u, npts: %u", wave5->type, wave5->npts);
        wave5->lock = igorfile->get_guint16(&p);
        get_CHARARRAY(wave5->whpad1, &p);
        wave5->wh_version = igorfile->get_guint16(&p);
        get_CHARARRAY0(wave5->bname, &p);
        wave5->whpad2 = igorfile->get_guint32(&p);
        wave5->dfolder = igorfile->get_guint32(&p);
        for (i = 0; i < MAXDIMS; i++) {
            wave5->n_dim[i] = igorfile->get_guint32(&p);
            gwy_debug("n_dim[%u]: %u", i, wave5->n_dim[i]);
        }
        for (i = 0; i < MAXDIMS; i++)
            wave5->sfA[i] = igorfile->get_gdouble(&p);
        for (i = 0; i < MAXDIMS; i++)
            wave5->sfB[i] = igorfile->get_gdouble(&p);
        get_CHARARRAY0(wave5->data_units, &p);
        gwy_debug("data_units: <%s>", wave5->data_units);
        for (i = 0; i < MAXDIMS; i++) {
            get_CHARARRAY0(wave5->dim_units[i], &p);
            gwy_debug("dim_units[%u]: <%s>", i, wave5->dim_units[i]);
        }
        wave5->fs_valid = !!igorfile->get_guint16(&p);
        wave5->whpad3 = igorfile->get_guint16(&p);
        wave5->top_full_scale = igorfile->get_gdouble(&p);
        wave5->bot_full_scale = igorfile->get_gdouble(&p);
    }

    return headers_size;
}