static gboolean
rhk_sm4_read_page_index_header(RHKPageIndexHeader *header,
                               const RHKObject *obj,
                               const guchar *buffer,
                               gsize size,
                               GError **error)
{
    const guchar *p;

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

    p = buffer + obj->offset;
    header->page_count = gwy_get_guint32_le(&p);
    header->object_count = gwy_get_guint32_le(&p);
    gwy_debug("page_count: %u, object_count: %u",
              header->page_count, header->object_count);
    header->reserved1 = gwy_get_guint32_le(&p);
    header->reserved2 = gwy_get_guint32_le(&p);

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

    return TRUE;
}
static gboolean
rhk_sm4_read_page_index(RHKPageIndex *header,
                        const RHKObject *obj,
                        const guchar *buffer,
                        gsize size,
                        GError **error)
{
    const guchar *p;

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

    p = buffer + obj->offset;
    memcpy(header->id, p, sizeof(header->id));
    p += sizeof(header->id);
    header->data_type = gwy_get_guint32_le(&p);
    header->source = gwy_get_guint32_le(&p);
    header->object_count = gwy_get_guint32_le(&p);
    header->minor_version = gwy_get_guint32_le(&p);
    gwy_debug("data_type: %u, source: %u, object_count: %u, minorv: %u",
              header->data_type, header->source,
              header->object_count, header->minor_version);

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

    return TRUE;
}
Exemple #3
0
static void
mif_read_block(MIFBlock *block,
               G_GNUC_UNUSED const gchar *name,
               const guchar **p)
{
    block->offset = gwy_get_guint32_le(p);
    block->size = gwy_get_guint32_le(p);
    if (block->size) {
        gwy_debug("%s offset: %zu (0x%zx), size: %zu (0x%zx)", name, block->offset, block->offset, block->size, block->size);
    }
}
Exemple #4
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;
}
Exemple #5
0
static LIFMemBlock*
lif_read_memblock(const guchar *buffer, gsize *size, gint version)
{
    LIFMemBlock *memblock;
    const guchar *p;
    int i;

    p = buffer;
    memblock = g_new0(LIFMemBlock, 1);
    memblock->magic = gwy_get_gint32_le(&p);
    gwy_debug("Magic = %d", memblock->magic);

    if (memcmp(&memblock->magic, MAGIC, MAGIC_SIZE) != 0) {
        gwy_debug("Wrong magic for memblock");
        size = 0;
        g_free(memblock);
        return NULL;
    }
    memblock->size = gwy_get_guint32_le(&p);
    gwy_debug("Size = %d", memblock->size);
    memblock->testcode = *(p++);
    gwy_debug("Testcode = 0x%x", memblock->testcode);
    if (memblock->testcode != TESTCODE) {
        gwy_debug("Wrong testcode for memblock");
        g_free(memblock);
        size = 0;
        return NULL;
    }
    if (version == 1) {
        memblock->memsize = gwy_get_guint32_le(&p);
    }
    else if (version >= 2) {
        memblock->memsize = gwy_get_guint64_le(&p);
    }
    gwy_debug("data length = %" G_GUINT64_FORMAT "", memblock->memsize);

    i = 0;
    while (*(p++) != TESTCODE) {
        i++;
    }
    gwy_debug("skipped %d bytes", i);
    memblock->desclen = gwy_get_guint32_le(&p);
    gwy_debug("description length = %d", memblock->desclen);
    memblock->memid = g_convert((const gchar*)p, 2 * memblock->desclen,
                                "UTF-8", "UTF-16", NULL, NULL, NULL);
    gwy_debug("description = %s", memblock->memid);
    p += memblock->desclen * 2;
    memblock->data = (gpointer)p;

    *size = (gsize)(p - buffer) + memblock->memsize;
    return memblock;
}
Exemple #6
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;
}
Exemple #7
0
static inline const guchar*
read_t2_record(PicoHarpT2Record *rec,
               const guchar *p)
{
    guint32 r = gwy_get_guint32_le(&p);

    rec->time = r & 0x0fffffffU;
    rec->channel = r >> 28;

    return p;
}
Exemple #8
0
static const guchar*
read_pie710_imaging_header(PicoHarpImagingHeader *header,
                           const guchar *p)
{
    header->pie710.time_per_pixel = gwy_get_guint32_le(&p);
    header->pie710.acceleration = gwy_get_guint32_le(&p);
    header->pie710.bidirectional = !!gwy_get_guint32_le(&p);
    header->pie710.reserved = gwy_get_guint32_le(&p);
    header->pie710.xoff = gwy_get_gfloat_le(&p);
    header->pie710.yoff = gwy_get_gfloat_le(&p);
    header->pie710.xres = gwy_get_guint32_le(&p);
    header->pie710.yres = gwy_get_guint32_le(&p);
    header->pie710.pix_resol = gwy_get_gfloat_le(&p);
    header->pie710.t_start_to = gwy_get_gfloat_le(&p);
    header->pie710.t_stop_to = gwy_get_gfloat_le(&p);
    header->pie710.t_start_from = gwy_get_gfloat_le(&p);
    header->pie710.t_stop_from = gwy_get_gfloat_le(&p);
    gwy_debug("accel %u, bidirectional: %d",
              header->pie710.acceleration, header->pie710.bidirectional);
    gwy_debug("%g %g %g %g",
              header->pie710.t_start_to, header->pie710.t_stop_to,
              header->pie710.t_start_from, header->pie710.t_stop_from);

    return p;
}
Exemple #9
0
static inline const guchar*
read_t3_record(PicoHarpT3Record *rec,
               const guchar *p)
{
    guint32 r = gwy_get_guint32_le(&p);

    rec->nsync = r & 0x0000ffffU;
    r = r >> 16;
    rec->time = r & 0x000000fffU;
    rec->channel = r >> 12;

    return p;
}
/* FIXME: Some of the objects read are of type 0 and size 0, but maybe
 * that's right and they allow empty object slots */
static RHKObject*
rhk_sm4_read_objects(const guchar *buffer,
                     const guchar *p, gsize size, guint count,
                     RHKObjectType intype, GError **error)
{
    RHKObject *objects, *obj;
    guint i;

    if ((p - buffer) + count*OBJECT_SIZE >= size) {
        g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA,
                    _("Object list in %s is truncated."),
                    rhk_sm4_describe_object(intype));
        return NULL;
    }

    objects = g_new(RHKObject, count);
    for (i = 0; i < count; i++) {
        obj = objects + i;
        obj->type = gwy_get_guint32_le(&p);
        obj->offset = gwy_get_guint32_le(&p);
        obj->size = gwy_get_guint32_le(&p);
        gwy_debug("object of type %u (%s) at %u, size %u",
                  obj->type, rhk_sm4_describe_object(obj->type),
                  obj->offset, obj->size);
        if ((gsize)obj->size + obj->offset > size) {
            g_set_error(error, GWY_MODULE_FILE_ERROR,
                        GWY_MODULE_FILE_ERROR_DATA,
                        _("Object of type %s is truncated."),
                        rhk_sm4_describe_object(obj->type));
            g_free(objects);
            return NULL;
        }
    }

    return objects;
}
Exemple #11
0
G_GNUC_UNUSED
static gboolean
mif_read_id(MIFUniqueID *id,
            const guchar **p,
            gsize size,
            GError **error)
{
    gwy_clear(id, 1);

    if (size < ID_SIZE) {
        g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA,
                    _("Unique id record is too short."));
        return FALSE;
    }

    id->ms = gwy_get_guint32_le(p);
    id->ls = gwy_get_guint32_le(p);
    gwy_debug("id: %08x %08x", id->ms, id->ls);
    id->index = gwy_get_guint32_le(p);
    gwy_debug("index: %u", id->index);
    get_CHARARRAY(id->workstation, p);
    gwy_debug_chars(id, workstation);
    return TRUE;
}
Exemple #12
0
static gint
pni_detect(const GwyFileDetectInfo *fileinfo,
           gboolean only_name)
{
    gint score = 0;
    guint32 xres, yres;

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

    if (fileinfo->buffer_len >= 0xa0
        && (memcmp(fileinfo->head, MAGIC1, MAGIC_SIZE) == 0
            || memcmp(fileinfo->head, MAGIC2, MAGIC_SIZE) == 0)) {
        const guchar *p = fileinfo->head + 0x90;

        xres = gwy_get_guint32_le(&p);
        yres = gwy_get_guint32_le(&p);
        gwy_debug("%u %u", xres, yres);
        if (fileinfo->file_size == DATA_START + 2*xres*yres)
            score = 95;
    }

    return score;
}
Exemple #13
0
static const guchar*
read_lsm_imaging_header(PicoHarpImagingHeader *header,
                        const guchar *p)
{
    header->lsm.frame_trigger_index = gwy_get_guint32_le(&p);
    header->lsm.line_start_trigger_index = gwy_get_guint32_le(&p);
    header->lsm.line_stop_trigger_index = gwy_get_guint32_le(&p);
    header->lsm.bidirectional = !!gwy_get_guint32_le(&p);
    header->lsm.xres = gwy_get_guint32_le(&p);
    header->lsm.yres = gwy_get_guint32_le(&p);

    return p;
}
Exemple #14
0
/* 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;
}
Exemple #15
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);
}
Exemple #16
0
static const guchar*
read_kdt180_imaging_header(PicoHarpImagingHeader *header,
                           const guchar *p)
{
    header->kdt180.velocity = gwy_get_guint32_le(&p);
    header->kdt180.acceleration = gwy_get_guint32_le(&p);
    header->kdt180.bidirectional = !!gwy_get_guint32_le(&p);
    header->kdt180.reserved = gwy_get_guint32_le(&p);
    header->kdt180.xoff = gwy_get_gfloat_le(&p);
    header->kdt180.yoff = gwy_get_gfloat_le(&p);
    header->kdt180.xres = gwy_get_guint32_le(&p);
    header->kdt180.yres = gwy_get_guint32_le(&p);
    header->kdt180.pix_resol = gwy_get_gfloat_le(&p);
    gwy_debug("accel %u, bidirectional: %d",
              header->pie710.acceleration, header->pie710.bidirectional);

    return p;
}
Exemple #17
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);
}
Exemple #18
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;
}
Exemple #19
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;
}
Exemple #20
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;
}
Exemple #21
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;
}
Exemple #22
0
static const guchar*
pt3file_read_board(PicoHarpBoard *board,
                   const guchar *p)
{
    guint i;

    get_CHARARRAY(board->hardware_ident, &p);
    get_CHARARRAY(board->hardware_version, &p);
    gwy_debug("<%.*s> <%.*s>",
              (gint)sizeof(board->hardware_ident), board->hardware_ident,
              (gint)sizeof(board->hardware_version), board->hardware_version);
    board->hardware_serial = gwy_get_guint32_le(&p);
    board->sync_divider = gwy_get_guint32_le(&p);
    board->cfd_zero_cross0 = gwy_get_guint32_le(&p);
    board->cfd_level0 = gwy_get_guint32_le(&p);
    board->cfd_zero_cross1 = gwy_get_guint32_le(&p);
    board->cfd_level1 = gwy_get_guint32_le(&p);
    board->resolution = gwy_get_gfloat_le(&p);
    board->router_model_code = gwy_get_guint32_le(&p);
    board->router_enabled = !!gwy_get_guint32_le(&p);
    for (i = 0; i < G_N_ELEMENTS(board->rt_channel); i++) {
        board->rt_channel[i].input_type = gwy_get_guint32_le(&p);
        board->rt_channel[i].input_level = gwy_get_gint32_le(&p);
        board->rt_channel[i].input_edge = gwy_get_guint32_le(&p);
        board->rt_channel[i].cfd_present = !!gwy_get_guint32_le(&p);
        board->rt_channel[i].cfd_level = gwy_get_gint32_le(&p);
        board->rt_channel[i].cfd_zero_cross = gwy_get_gint32_le(&p);
    }

    return p;
}
Exemple #23
0
static gsize
pt3file_read_header(const guchar *buffer,
                    gsize size,
                    PicoHarpFile *pt3file,
                    GError **error)
{
    const guchar* (*read_imaging_header)(PicoHarpImagingHeader *header,
                                         const guchar *p);
    PicoHarpInstrument instr;
    const guchar *p;
    guint i, expected_size;

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

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

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

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

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

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

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

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

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

    return (gsize)(p - buffer);
}
Exemple #24
0
static gboolean
mif_read_image_header(MIFImageHeader *header,
                      const guchar **p,
                      gsize size,
                      guint file_version,
                      GError **error)
{
    const guchar *buffer = *p;
    guint i;

    gwy_clear(header, 1);

    if (size < IMAGE_HEADER_START_SIZE)
        return err_IMAGE_HEADER_TOO_SHORT(error);
    get_CHARARRAY(header->time, p);
    get_CHARARRAY(header->title, p);
    get_CHARARRAY(header->comment, p);
    gwy_debug("image <%.*s>", (guint)sizeof(header->title), header->title);

    if (!mif_read_scan_setup(&header->setup,
                             p, size - (*p - buffer), file_version,
                             error))
        return FALSE;
    if (!mif_read_image_configuration(&header->configuration,
                                      p, size - (*p - buffer), file_version,
                                      error))
        return FALSE;

    if (file_version == 0x107) {
        /* TODO: Check size */
        header->tunnel_current = gwy_get_gfloat_le(p);
        gwy_debug("tunnel_current: %g", header->tunnel_current);
        header->bias_voltage = gwy_get_gfloat_le(p);
        gwy_debug("bias_voltage: %g", header->bias_voltage);
        header->force = gwy_get_gfloat_le(p);
        gwy_debug("force: %g", header->force);
        header->as_measured = *((*p)++);
        gwy_debug_bool(header, as_measured);
        header->n_curves = gwy_get_guint32_le(p);
        gwy_debug("n_curves: %u", header->n_curves);
        for (i = 0; i < MAX_CURVES; i++) {
            header->curve_points[i].x = gwy_get_guint32_le(p);
            header->curve_points[i].y = gwy_get_guint32_le(p);
        }
        header->low_fraction = gwy_get_gfloat_le(p);
        header->high_fraction = gwy_get_gfloat_le(p);
        gwy_debug("low_fraction: %g, high_fraction: %g", header->low_fraction, header->high_fraction);

        if (!mif_read_axis_info(&header->z_axis,
                                p, size - (*p - buffer), file_version, error))
            return FALSE;

        if (!mif_read_id(&header->id.primary, p, size - (*p - buffer),
                         error)
            || !mif_read_id(&header->id.secondary, p, size - (*p - buffer),
                            error))
            return FALSE;
    }
    else {
        g_return_val_if_reached(FALSE);
    }

    return TRUE;
}
Exemple #25
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;
        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);
    }

    if (!container)
        err_NO_DATA(error);

    gwy_file_abandon_contents(buffer, size, NULL);
    return container;
}
Exemple #26
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;
}
Exemple #27
0
static GwyGraphModel*
sensofar_read_profile(SensofarDataDesc *data_desc,
                      const guchar **p,
                      gsize size,
                      GError **error)
{
    GwyGraphModel *gmodel;
    GwyGraphCurveModel *gcmodel;
    guint xres, yres, j, n;
    GwySIUnit *units = NULL;
    gdouble *xdata, *ydata;
    gdouble dx;

    yres = gwy_get_guint32_le(p);
    if (yres != 1)
        g_warning("ysize is not 1 for profile");
    xres = gwy_get_guint32_le(p);
    gwy_debug("Data size: %dx%d", xres, yres);
    if (err_SIZE_MISMATCH(error, xres*yres*sizeof(gfloat),
                          size - 2*sizeof(guint32), FALSE))
        return NULL;
    if (err_DIMENSION(error, xres) || err_DIMENSION(error, yres))
        return NULL;
    if (!((data_desc->axes_config.mppx
           = fabs(data_desc->axes_config.mppx)) > 0)) {
        g_warning("Real x size is 0.0, fixing to 1.0");
        data_desc->axes_config.mppx = 1.0;
    }

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

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

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

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

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

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

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

    return gmodel;
}
static GwyContainer*
rhk_sm4_load(const gchar *filename,
             G_GNUC_UNUSED GwyRunType mode,
             GError **error)
{
    RHKFile rhkfile;
    RHKObject *obj, o;
    GwyContainer *meta, *container = NULL;
    guchar *buffer = NULL;
    gsize size = 0;
    GError *err = NULL;
    const guchar *p;
    GString *key = NULL;
    guint i, imageid = 0, graphid = 0;

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

    gwy_clear(&rhkfile, 1);
    if (size < HEADER_SIZE) {
        err_TOO_SHORT(error);
        goto fail;
    }

    /* File header */
    p = buffer + MAGIC_OFFSET + MAGIC_TOTAL_SIZE;
    rhkfile.page_count = gwy_get_guint32_le(&p);
    rhkfile.object_count = gwy_get_guint32_le(&p);
    rhkfile.object_field_size = gwy_get_guint32_le(&p);
    gwy_debug("page_count: %u, object_count: %u, object_field_size: %u",
              rhkfile.page_count, rhkfile.object_count,
              rhkfile.object_field_size);
    if (rhkfile.object_field_size != OBJECT_SIZE)
        g_warning("Object field size %u differs from %u",
                  rhkfile.object_field_size, OBJECT_SIZE);
    rhkfile.reserved1 = gwy_get_guint32_le(&p);
    rhkfile.reserved2 = gwy_get_guint32_le(&p);

    /* Header objects */
    if (!(rhkfile.objects = rhk_sm4_read_objects(buffer, p, size,
                                                 rhkfile.object_count,
                                                 RHK_OBJECT_FILE_HEADER,
                                                 error)))
        goto fail;

    /* Find page index header */
    if (!(obj = rhk_sm4_find_object(rhkfile.objects, rhkfile.object_count,
                                    RHK_OBJECT_PAGE_INDEX_HEADER,
                                    RHK_OBJECT_FILE_HEADER, error))
        || !rhk_sm4_read_page_index_header(&rhkfile.page_index_header,
                                           obj, buffer, size, error))
        goto fail;

    /* There, find the page index array.  That's a single object in the object
     * list but it contains a page_count-long sequence of page indices. */
    rhkfile.page_indices = g_new0(RHKPageIndex,
                                  rhkfile.page_index_header.page_count);
    if (!(obj = rhk_sm4_find_object(rhkfile.page_index_header.objects,
                                    rhkfile.page_index_header.object_count,
                                    RHK_OBJECT_PAGE_INDEX_ARRAY,
                                    RHK_OBJECT_PAGE_INDEX_HEADER, error)))
        goto fail;

    o = *obj;
    for (i = 0; i < rhkfile.page_index_header.page_count; i++) {
        if (!rhk_sm4_read_page_index(rhkfile.page_indices + i, &o,
                                     buffer, size, error))
            goto fail;

        /* Carefully move to the next page index */
        o.offset += o.size + OBJECT_SIZE*rhkfile.page_indices[i].object_count;
    }

    container = gwy_container_new();
    key = g_string_new(NULL);

    /* Read pages */
    for (i = 0; i < rhkfile.page_index_header.page_count; i++) {
        RHKPageIndex *pi = rhkfile.page_indices + i;
        RHKPage *page = &pi->page;

        /* Page must contain header */
        if (!(obj = rhk_sm4_find_object(pi->objects, pi->object_count,
                                        RHK_OBJECT_PAGE_HEADER,
                                        RHK_OBJECT_PAGE_INDEX, error))
            || !rhk_sm4_read_page_header(page, obj, buffer, size, error))
            goto fail;

        /* Page must contain data */
        if (!(obj = rhk_sm4_find_object(pi->objects, pi->object_count,
                                        RHK_OBJECT_PAGE_DATA,
                                        RHK_OBJECT_PAGE_INDEX, error))
            || !rhk_sm4_read_page_data(page, obj, buffer, error))
            goto fail;

        /* Page may contain strings */
        if (!(obj = rhk_sm4_find_object(page->objects, page->object_count,
                                        RHK_OBJECT_STRING_DATA,
                                        RHK_OBJECT_PAGE_HEADER, NULL))
            || !rhk_sm4_read_string_data(page, obj, pi->page.string_count,
                                         buffer)) {
            g_warning("Failed to read string data in page %u", i);
        }

        /* Read the data */
        if (pi->data_type == RHK_DATA_IMAGE) {
            GwyDataField *dfield = rhk_sm4_page_to_data_field(page);
            GQuark quark = gwy_app_get_data_key_for_id(imageid);
            const gchar *scandir, *name;
            gchar *title;

            gwy_container_set_object(container, quark, dfield);
            g_object_unref(dfield);

            if ((name = page->strings[RHK_STRING_LABEL])) {
                scandir = gwy_enum_to_string(page->scan_dir, scan_directions,
                                             G_N_ELEMENTS(scan_directions));
                g_string_assign(key, g_quark_to_string(quark));
                g_string_append(key, "/title");
                if (scandir && *scandir)
                    title = g_strdup_printf("%s [%s]", name, scandir);
                else
                    title = g_strdup(name);
                gwy_container_set_string_by_name(container, key->str, title);
            }

            meta = rhk_sm4_get_metadata(pi, page);
            g_string_printf(key, "/%u/meta", imageid);
            gwy_container_set_object_by_name(container, key->str, meta);
            g_object_unref(meta);

            imageid++;
        }
        else if (pi->data_type == RHK_DATA_LINE) {
            GwyGraphModel *gmodel;
            RHKSpecDriftHeader drift_header;
            RHKSpecInfo spec_info;
            G_GNUC_UNUSED gboolean have_header = FALSE, have_info = FALSE;

            gwy_debug("page_type %u", page->page_type);
            gwy_debug("line_type %u", page->line_type);
            gwy_debug("page_sizes %u %u", page->x_size, page->y_size);
            /* Page may contain drift header */
            if ((obj = rhk_sm4_find_object(page->objects, page->object_count,
                                           RHK_OBJECT_SPEC_DRIFT_HEADER,
                                           RHK_OBJECT_PAGE_HEADER, NULL))
                && rhk_sm4_read_drift_header(&drift_header, obj, buffer)) {
                gwy_debug("drift_header OK");
                have_header = TRUE;
            }
            if ((obj = rhk_sm4_find_object(page->objects, page->object_count,
                                           RHK_OBJECT_SPEC_DRIFT_DATA,
                                           RHK_OBJECT_PAGE_HEADER, NULL))
                && rhk_sm4_read_spec_info(&spec_info, obj, buffer)) {
                gwy_debug("spec_info OK");
                have_info = TRUE;
            }
            /* FIXME: RHK_STRING_PLL_PRO_STATUS may contain interesting
             * metadata.  But we have not place where to put it. */

            if ((gmodel = rhk_sm4_page_to_graph_model(page))) {
                graphid++;
                gwy_container_set_object(container,
                                         gwy_app_get_graph_key_for_id(graphid),
                                         gmodel);
                g_object_unref(gmodel);
            }
        }
    }

    if (!imageid && !graphid)
        err_NO_DATA(error);

fail:
    gwy_file_abandon_contents(buffer, size, NULL);
    rhk_sm4_free(&rhkfile);
    if (!imageid && !graphid) {
        gwy_object_unref(container);
    }
    if (key)
        g_string_free(key, TRUE);

    return container;
}
Exemple #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;
}
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;
}