static GwyDataField* read_text_data(const gchar *buffer, gint text_data_start, GHashTable *hash, GError **error) { const gchar *p; gchar *end; gint xres, yres, i, power10; gdouble xreal, yreal, zscale, xoff, yoff, zoff; GwySIUnit *unitxy, *unitz; GwyDataField *dfield = NULL; gdouble *d; unitxy = gwy_si_unit_new(NULL); unitz = gwy_si_unit_new(NULL); if (!get_scales(hash, TRUE, &xres, &yres, &xreal, &yreal, &xoff, &yoff, unitxy, &zscale, &zoff, unitz, error)) goto fail; p = g_hash_table_lookup(hash, "DATA Unit"); gwy_si_unit_set_from_string_parse(unitz, p, &power10); zscale = pow10(power10); dfield = gwy_data_field_new(xres, yres, xreal, yreal, FALSE); gwy_data_field_set_xoffset(dfield, xoff); gwy_data_field_set_yoffset(dfield, yoff); gwy_data_field_set_si_unit_xy(dfield, unitxy); gwy_data_field_set_si_unit_z(dfield, unitz); d = gwy_data_field_get_data(dfield); p = (const gchar*)buffer + text_data_start; for (i = 0; i < xres*yres; i++) { d[i] = zscale*g_ascii_strtod(p, &end) + zoff; if (end == p) { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA, _("Cannot parse data values after %d of %d."), i, xres*yres); gwy_object_unref(dfield); goto fail; } p = end + (*end == ','); } fail: g_object_unref(unitxy); g_object_unref(unitz); return dfield; }
static GwyDataField* mif_read_data_field(const MIFImageHeader *image_header, const MIFBlock *block, const guchar *buffer, gsize size, GError **error) { gint xres = image_header->setup.xres; gint yres = image_header->setup.yres; gdouble xreal = image_header->setup.xreal; gdouble yreal = image_header->setup.yreal; gdouble xoff = image_header->setup.xoff; gdouble yoff = image_header->setup.yoff; gdouble q = image_header->configuration.scan_int_to_meter; GwyDataField *dfield; gdouble *data; const gint16 *d16; gint i, j; if (err_DIMENSION(error, xres) || err_DIMENSION(error, yres)) return NULL; if (!block->size || block->offset > size || block->size > size || block->offset + block->size > size) { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA, _("Image data are outside the file.")); return NULL; } if (err_SIZE_MISMATCH(error, xres*yres*sizeof(gint16), block->size, FALSE)) return NULL; dfield = gwy_data_field_new(xres, yres, xreal, yreal, FALSE); gwy_data_field_set_xoffset(dfield, xoff); gwy_data_field_set_yoffset(dfield, yoff); data = gwy_data_field_get_data(dfield); d16 = (const gint16*)(buffer + block->offset); 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"); // FIXME: Don't know why this factor. It seems to match what MIF spmview // profile reader shows though. q *= 1.0e4; for (i = 0; i < yres; i++) { for (j = 0; j < yres; j++) { data[(yres-1 - i)*xres + j] = q*GINT16_FROM_LE(d16[i*xres + j]); } } return dfield; }
static void null_offsets(GwyContainer *data, GwyRunType run) { GwyDataField *dfields[3]; GQuark quarks[3]; guint i; gint id; g_return_if_fail(run & BASICOPS_RUN_MODES); gwy_app_data_browser_get_current(GWY_APP_DATA_FIELD, dfields + 0, GWY_APP_MASK_FIELD, dfields + 1, GWY_APP_SHOW_FIELD, dfields + 2, GWY_APP_DATA_FIELD_KEY, quarks + 0, GWY_APP_MASK_FIELD_KEY, quarks + 1, GWY_APP_SHOW_FIELD_KEY, quarks + 2, GWY_APP_DATA_FIELD_ID, &id, 0); clean_quarks(G_N_ELEMENTS(quarks), quarks, dfields); for (i = 0; i < G_N_ELEMENTS(dfields); i++) { if (dfields[i] && !gwy_data_field_get_xoffset(dfields[i]) && !gwy_data_field_get_yoffset(dfields[i])) { quarks[i] = 0; dfields[i] = NULL; } } if (!dfields[0] && !dfields[1] && !dfields[2]) return; gwy_app_undo_qcheckpointv(data, G_N_ELEMENTS(quarks), quarks); for (i = 0; i < G_N_ELEMENTS(dfields); i++) { if (dfields[i]) { gwy_data_field_set_xoffset(dfields[i], 0.0); gwy_data_field_set_yoffset(dfields[i], 0.0); gwy_data_field_data_changed(dfields[i]); } } gwy_app_channel_log_add_proc(data, id, id); }
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; }
static GwyDataField* read_binary_data(const gchar *buffer, gsize size, GHashTable *hash, GError **error) { ShimadzuDataType data_type; gint xres, yres, i; guint expected; gdouble xreal, yreal, zscale, xoff, yoff, zoff; GwySIUnit *unitxy, *unitz; GwyDataField *dfield = NULL; gdouble *d; const gchar *s; if (!(s = g_hash_table_lookup(hash, "DataType"))) { err_MISSING_FIELD(error, "DataType"); return NULL; } if (g_ascii_strcasecmp(s, "short") == 0) data_type = SHIMADZU_SHORT; else if (g_ascii_strcasecmp(s, "float") == 0) data_type = SHIMADZU_FLOAT; else { err_UNSUPPORTED(error, "DataType"); return NULL; } unitxy = gwy_si_unit_new(NULL); unitz = gwy_si_unit_new(NULL); if (!get_scales(hash, FALSE, &xres, &yres, &xreal, &yreal, &xoff, &yoff, unitxy, &zscale, &zoff, unitz, error)) goto fail; expected = data_type*xres*yres + HEADER_SIZE; if (err_SIZE_MISMATCH(error, expected, size, FALSE)) goto fail; dfield = gwy_data_field_new(xres, yres, xreal, yreal, FALSE); gwy_data_field_set_xoffset(dfield, xoff); gwy_data_field_set_yoffset(dfield, yoff); gwy_data_field_set_si_unit_xy(dfield, unitxy); gwy_data_field_set_si_unit_z(dfield, unitz); d = gwy_data_field_get_data(dfield); if (data_type == SHIMADZU_SHORT) { const gint16 *d16 = (const gint16*)(buffer + HEADER_SIZE); for (i = 0; i < xres*yres; i++) d[i] = zscale*GUINT16_FROM_LE(d16[i]) + zoff; } else if (data_type == SHIMADZU_FLOAT) { const guchar *p = buffer + HEADER_SIZE; for (i = 0; i < xres*yres; i++) d[i] = zscale*gwy_get_gfloat_le(&p) + zoff; } else { g_assert_not_reached(); } gwy_data_field_invert(dfield, TRUE, FALSE, FALSE); fail: g_object_unref(unitxy); g_object_unref(unitz); return dfield; }
static GwyDataField* mif_read_data_field(const MIFImageHeader *image_header, const MIFBlock *block, const guchar *buffer, gsize size, GError **error) { const MIFScanSetup *setup = &image_header->setup; const MIFImageConfiguration *configuration = &image_header->configuration; gint xres = setup->xres; gint yres = setup->yres; gdouble xreal = setup->xreal * image_header->configuration.xcal; gdouble yreal = setup->yreal * image_header->configuration.ycal; gdouble xoff = setup->xoff; gdouble yoff = setup->yoff; gdouble q = configuration->zcal/65536.0; GwyDataField *dfield; gdouble *data, *linecorrdata = NULL; gsize datasize; const gint16 *d16; gint i, j; if (err_DIMENSION(error, xres) || err_DIMENSION(error, yres)) return NULL; if (!block->size || block->offset > size || block->size > size || block->offset + block->size > size) { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA, _("Image data are outside the file.")); return NULL; } datasize = xres*yres*sizeof(gint16); if (err_SIZE_MISMATCH(error, datasize, block->size, FALSE)) return NULL; if (datasize + yres*sizeof(gint16) <= block->size) { gwy_debug("There may be %u correction data after the image.", yres); linecorrdata = g_new(gdouble, yres); d16 = (const gint16*)(buffer + block->offset + datasize); for (i = 0; i < yres; i++) { linecorrdata[i] = pow(2.0, d16[i] - 13); gwy_debug("corr[%u] %g", i, linecorrdata[i]); } } dfield = gwy_data_field_new(xres, yres, xreal, yreal, FALSE); gwy_data_field_set_xoffset(dfield, xoff); gwy_data_field_set_yoffset(dfield, yoff); data = gwy_data_field_get_data(dfield); d16 = (const gint16*)(buffer + block->offset); 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"); // XXX: Don't know why this range. A user got it from DME. Have no idea // why scan_int_to_meter does not appear here. if (!configuration->z_linearized) q *= 15e-6; else q *= 20e-6; for (i = 0; i < yres; i++) { gdouble qi = linecorrdata ? q*linecorrdata[i] : q; for (j = 0; j < yres; j++) { data[(yres-1 - i)*xres + j] = qi*GINT16_FROM_LE(d16[i*xres + j]); } } g_free(linecorrdata); return dfield; }
static void psdflp_do(const PSDFLPArgs *args, GwyDataField *dfield, GwyDataField *lpsdf) { enum { N = 4 }; GwyDataField *reout, *imout; gint pxres, pyres, fxres, fyres; gint i, j, fi, pi; gdouble *ldata, *redata, *imdata; gdouble *cosphi, *sinphi; gdouble xreal, yreal, f0, f_max, b, p; reout = gwy_data_field_new_alike(dfield, FALSE); imout = gwy_data_field_new_alike(dfield, FALSE); gwy_data_field_2dfft(dfield, NULL, reout, imout, args->window, GWY_TRANSFORM_DIRECTION_FORWARD, GWY_INTERPOLATION_ROUND, /* Ignored */ TRUE, 1); pxres = reout->xres; pyres = reout->yres; redata = gwy_data_field_get_data(reout); imdata = gwy_data_field_get_data(imout); for (i = 0; i < pxres*pyres; i++) redata[i] = redata[i]*redata[i] + imdata[i]*imdata[i]; gwy_data_field_2dfft_humanize(reout); gwy_data_field_filter_gaussian(reout, args->sigma); for (i = 0; i < pxres*pyres; i++) redata[i] = sqrt(redata[i]); fxres = pxres/2; fyres = pyres/2; gwy_data_field_resample(lpsdf, fxres, fyres, GWY_INTERPOLATION_NONE); ldata = gwy_data_field_get_data(lpsdf); xreal = dfield->xreal; yreal = dfield->yreal; f0 = 2.0/MIN(xreal, yreal); f_max = 0.5*MIN(pxres/xreal, pyres/yreal); if (f_max <= f0) { g_warning("Minimum frequency is not smaller than maximum frequency."); } b = log(f_max/f0)/fyres; /* Incorporate some prefactors to sinphi[] and cosphi[], knowing that * cosine is only ever used for x and sine for y frequencies. */ cosphi = g_new(gdouble, (N+1)*fxres); sinphi = g_new(gdouble, (N+1)*fxres); for (j = 0; j < fxres; j++) { gdouble phi_from = 2.0*G_PI*j/fxres; gdouble phi_to = 2.0*G_PI*(j + 1.0)/fxres; for (pi = 0; pi <= N; pi++) { gdouble phi = ((pi + 0.5)*phi_from + (N - 0.5 - pi)*phi_to)/N; cosphi[j*(N+1) + pi] = cos(phi)*xreal; sinphi[j*(N+1) + pi] = sin(phi)*yreal; } } for (i = 0; i < fyres; i++) { gdouble f_from = f0*exp(b*i); gdouble f_to = f0*exp(b*(i + 1.0)); for (j = 0; j < fxres; j++) { const gdouble *cosphi_j = cosphi + j*(N+1); const gdouble *sinphi_j = sinphi + j*(N+1); guint n = 0; gdouble s = 0.0; for (fi = 0; fi <= N; fi++) { gdouble f = ((fi + 0.5)*f_from + (N - 0.5 - fi)*f_to)/N; for (pi = 0; pi <= N; pi++) { gdouble x = f*cosphi_j[pi] + pxres/2.0, y = f*sinphi_j[pi] + pyres/2.0; if (G_UNLIKELY(x < 0.5 || y < 0.5 || x > pxres - 1.5 || y > pyres - 1.5)) continue; p = gwy_data_field_get_dval(reout, x, y, GWY_INTERPOLATION_SCHAUM); s += p; n++; } } if (!n) n = 1; ldata[i*fxres + j] = 2.0*G_PI/fxres * s/n*(f_to - f_from); } } g_object_unref(imout); g_object_unref(reout); gwy_data_field_set_xreal(lpsdf, 2.0*G_PI); gwy_data_field_set_xoffset(lpsdf, 0.0); gwy_data_field_set_yreal(lpsdf, log(f_max/f0)); gwy_data_field_set_yoffset(lpsdf, log(f0)); gwy_si_unit_set_from_string(gwy_data_field_get_si_unit_xy(lpsdf), ""); gwy_si_unit_set_from_string(gwy_data_field_get_si_unit_z(lpsdf), ""); gwy_data_field_normalize(lpsdf); }
static GwyContainer* gsf_load(const gchar *filename, G_GNUC_UNUSED GwyRunType mode, GError **error) { GwyContainer *container = NULL, *meta = NULL; GwyDataField *dfield = NULL; GwyTextHeaderParser parser; GwySIUnit *unit; guchar *p, *value, *buffer = NULL, *header = NULL; const guchar *datap; GHashTable *hash = NULL; gsize size, expected_size; GError *err = NULL; gdouble xreal, yreal, xoff, yoff; guint i, xres, yres; gdouble *d; if (!gwy_file_get_contents(filename, &buffer, &size, &err)) { err_GET_FILE_CONTENTS(error, &err); return NULL; } if (size < MAGIC_SIZE || memcmp(buffer, MAGIC, MAGIC_SIZE) != 0) { err_FILE_TYPE(error, "Gwyddion Simple Field"); goto fail; } p = buffer + MAGIC_SIZE; datap = memchr(p, '\0', size - (p - buffer)); if (!datap) { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA, _("File header is truncated.")); goto fail; } header = g_strdup(p); datap += 4 - ((datap - buffer) % 4); gwy_clear(&parser, 1); parser.key_value_separator = "="; if (!(hash = gwy_text_header_parse(header, &parser, NULL, NULL))) { g_propagate_error(error, err); goto fail; } xres = read_pixel_size(hash, "XRes", error); yres = read_pixel_size(hash, "YRes", error); if (!xres || !yres) goto fail; expected_size = (datap - buffer) + sizeof(gfloat)*xres*yres; if (err_SIZE_MISMATCH(error, expected_size, size, TRUE)) goto fail; xreal = read_real_size(hash, "XReal"); yreal = read_real_size(hash, "YReal"); dfield = gwy_data_field_new(xres, yres, xreal, yreal, FALSE); xoff = read_real_offset(hash, "XOffset"); yoff = read_real_offset(hash, "YOffset"); gwy_data_field_set_xoffset(dfield, xoff); gwy_data_field_set_yoffset(dfield, yoff); value = g_hash_table_lookup(hash, "XYUnits"); unit = gwy_si_unit_new(value); gwy_data_field_set_si_unit_xy(dfield, unit); g_object_unref(unit); value = g_hash_table_lookup(hash, "ZUnits"); unit = gwy_si_unit_new(value); gwy_data_field_set_si_unit_z(dfield, unit); g_object_unref(unit); d = gwy_data_field_get_data(dfield); for (i = xres*yres; i; i--) *(d++) = gwy_get_gfloat_le(&datap); container = gwy_container_new(); gwy_container_set_object(container, gwy_app_get_data_key_for_id(0), dfield); g_object_unref(dfield); if ((value = g_hash_table_lookup(hash, "Title"))) { /* FIXME: Ensure valid UTF-8 */ gwy_container_set_string_by_name(container, "/0/data/title", g_strdup(value)); } else gwy_app_channel_title_fall_back(container, 0); meta = gwy_container_new(); g_hash_table_foreach(hash, add_meta, meta); if (gwy_container_get_n_items(meta)) gwy_container_set_object_by_name(container, "/0/meta", meta); g_object_unref(meta); gwy_file_channel_import_log_add(container, 0, NULL, filename); fail: gwy_file_abandon_contents(buffer, size, NULL); if (header) g_free(header); if (hash) g_hash_table_destroy(hash); return container; }
static GwyContainer* fits_load(const gchar *filename, G_GNUC_UNUSED GwyRunType mode, GError **error) { GwyContainer *container = NULL; fitsfile *fptr = NULL; GwyDataField *field = NULL, *mask; gint status = 0; /* Must be initialised to zero! */ gint hdutype, naxis, anynull, nkeys, k; glong res[3]; /* First index is the fast looping one. */ char strvalue[FLEN_VALUE]; gchar *invalid = NULL; gdouble real, off; if (fits_open_image(&fptr, filename, READONLY, &status)) { err_FITS(error, status); return NULL; } if (fits_get_hdu_type(fptr, &hdutype, &status)) { err_FITS(error, status); goto fail; } gwy_debug("hdutype %d", hdutype); if (hdutype != IMAGE_HDU) { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA, _("Only two-dimensional images are supported.")); goto fail; } if (fits_get_img_dim(fptr, &naxis, &status)) { err_FITS(error, status); goto fail; } gwy_debug("naxis %d", naxis); if (naxis != 2 && naxis != 3) { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA, _("Only two-dimensional images are supported.")); goto fail; } if (fits_get_img_size(fptr, naxis, res, &status)) { err_FITS(error, status); goto fail; } if (naxis == 3 && res[2] != 1) { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA, _("Only two-dimensional images are supported.")); goto fail; } gwy_debug("xres %ld, yres %ld", res[0], res[1]); if (err_DIMENSION(error, res[0]) || err_DIMENSION(error, res[1])) goto fail; field = gwy_data_field_new(res[0], res[1], res[0], res[1], FALSE); invalid = g_new(gchar, res[0]*res[1]); if (fits_read_imgnull(fptr, TDOUBLE, 1, res[0]*res[1], field->data, invalid, &anynull, &status)) { err_FITS(error, status); goto fail; } container = gwy_container_new(); gwy_container_set_object_by_name(container, "/0/data", field); /* Failures here are non-fatal. We already have an image. */ if (fits_get_hdrspace(fptr, &nkeys, NULL, &status)) { g_warning("Cannot get the first hdrspace."); goto fail; } if (!fits_read_key(fptr, TSTRING, "BUINT ", strvalue, NULL, &status)) { gint power10; gwy_debug("BUINT = <%s>", strvalue); gwy_si_unit_set_from_string_parse(gwy_data_field_get_si_unit_z(field), strvalue, &power10); if (power10) gwy_data_field_multiply(field, pow10(power10)); } status = 0; if (get_real_and_offset(fptr, 1, res[0], &real, &off)) { if (real < 0.0) { off += real; real = -real; gwy_data_field_invert(field, FALSE, TRUE, FALSE); } gwy_data_field_set_xreal(field, real); gwy_data_field_set_xoffset(field, off); } if (get_real_and_offset(fptr, 2, res[1], &real, &off)) { if (real < 0.0) { off += real; real = -real; gwy_data_field_invert(field, TRUE, FALSE, FALSE); } gwy_data_field_set_yreal(field, real); gwy_data_field_set_yoffset(field, off); } /* Create a mask of invalid data. */ for (k = 0; k < field->xres*field->yres; k++) { if (invalid[k]) field->data[k] = NAN; } if ((mask = gwy_app_channel_mask_of_nans(field, TRUE))) { gwy_container_set_object_by_name(container, "/0/mask", mask); g_object_unref(mask); } fail: fits_close_file(fptr, &status); gwy_object_unref(field); g_free(invalid); return container; }