static gboolean check_params(const SDFile *sdfile, guint len, GError **error) { if (sdfile->data_type >= SDF_NTYPES) { err_DATA_TYPE(error, sdfile->data_type); return FALSE; } if (err_DIMENSION(error, sdfile->xres) || err_DIMENSION(error, sdfile->yres)) return FALSE; if (err_SIZE_MISMATCH(error, sdfile->expected_size, len, FALSE)) return FALSE; if (sdfile->compression) { err_UNSUPPORTED(error, "Compression"); return FALSE; } if (sdfile->check_type) { err_UNSUPPORTED(error, "CheckType"); return FALSE; } return TRUE; }
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 gboolean rhk_sm4_read_page_data(RHKPage *page, const RHKObject *obj, const guchar *buffer, GError **error) { gsize expected_size; expected_size = 4 * page->x_size * page->y_size; if (err_SIZE_MISMATCH(error, expected_size, obj->size, TRUE)) return FALSE; page->data = buffer + obj->offset; return TRUE; }
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); }
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); }
static GwyDataField* read_data_field(const guchar *buffer, guint size, GError **error) { gint xres, yres, n, i, j; gdouble xreal, yreal, q; GwyDataField *dfield; GwySIUnit *siunit; gdouble *data, *row; const gint16 *pdata; const guchar *p; p = buffer + RES_OFFSET; xres = gwy_get_guint32_le(&p); yres = gwy_get_guint32_le(&p); gwy_debug("xres: %d, yres: %d", xres, yres); if (err_DIMENSION(error, xres) || err_DIMENSION(error, yres)) return NULL; n = xres*yres; if (err_SIZE_MISMATCH(error, 2*n + HEADER_SIZE, size, TRUE)) return NULL; p = buffer + XREAL_OFFSET; xreal = gwy_get_gdouble_le(&p) * Nanometer; p = buffer + YREAL_OFFSET; yreal = gwy_get_gdouble_le(&p) * Nanometer; p = buffer + ZSCALE_OFFSET; q = gwy_get_gdouble_le(&p) * Nanometer; gwy_debug("xreal: %g, yreal: %g, zreal: %g", xreal/Nanometer, yreal/Nanometer, q/Nanometer); /* 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; } /* XXX: I don't know where the factor of 0.5 comes from. But it makes * the imported data match the original software. */ q /= 2.0; q /= 65536.0; dfield = gwy_data_field_new(xres, yres, xreal, yreal, FALSE); data = gwy_data_field_get_data(dfield); pdata = (const gint16*)(buffer + HEADER_SIZE); for (i = 0; i < yres; i++) { row = data + (yres-1 - i)*xres; for (j = 0; j < xres; j++) row[j] = GUINT16_FROM_LE(pdata[i*xres + j])*q; } siunit = gwy_si_unit_new("m"); gwy_data_field_set_si_unit_xy(dfield, siunit); g_object_unref(siunit); siunit = gwy_si_unit_new("m"); gwy_data_field_set_si_unit_z(dfield, siunit); g_object_unref(siunit); return dfield; }
static GwyContainer* ecs_load(const gchar *filename, G_GNUC_UNUSED GwyRunType mode, GError **error) { GwyContainer *meta, *container = NULL; guchar *buffer = NULL; gsize size = 0; GError *err = NULL; GwyDataField *dfield = NULL; gchar *s = NULL, *s2 = NULL; GwySIUnit *siunit; const guchar *p; gdouble *data, *row; guint xres, yres, i, j; gdouble xreal, q; const gint16 *pdata; guchar c; if (!gwy_file_get_contents(filename, &buffer, &size, &err)) { err_GET_FILE_CONTENTS(error, &err); g_clear_error(&err); return NULL; } if (size < HEADER_SIZE + 2) { err_TOO_SHORT(error); goto fail; } p = buffer + ECS_RESOLUTION; xres = gwy_get_guint16_le(&p); yres = gwy_get_guint16_le(&p); gwy_debug("xres: %u, yres: %u", xres, yres); if (size != HEADER_SIZE + 2*xres*yres) { err_SIZE_MISMATCH(error, HEADER_SIZE + 2*xres*yres, size); goto fail; } /* Scan size */ p = buffer + ECS_SCAN_SIZE; s = get_PASCAL_STRING(&p, HEADER_SIZE - ECS_SCAN_SIZE); if (!s) { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA, _("Scan size header field overlaps with data.")); goto fail; } gwy_debug("Scan size str: <%s>", s); if (!g_str_has_prefix(s, "Scan Size: ")) { err_FILE_TYPE(error, "ECS"); goto fail; } if (sscanf(s + strlen("Scan Size: "), "%lf %lf%c", &xreal, &q, &c) != 3) { err_INVALID(error, "Scan Size"); goto fail; } g_free(s); s = NULL; gwy_debug("xreal: %g q: %g unit: %s", xreal, q, c == 0x8f ? "Angstrom" : "Nanometer"); if (c == 0x8f) { xreal *= 1e-10; q *= 1e-10; } else { xreal *= 1e-9; q *= 1e-9; } q /= 65536.0; /* This does not make much sense when xres != yres, but it is what * Snomputz does. */ dfield = gwy_data_field_new(xres, yres, xreal, xreal, FALSE); data = gwy_data_field_get_data(dfield); pdata = (const gint16*)(buffer + HEADER_SIZE); for (i = 0; i < yres; i++) { row = data + (yres-1 - i)*xres; for (j = 0; j < xres; j++) row[j] = GINT16_TO_LE(pdata[i*xres + j])*q; } siunit = gwy_si_unit_new("m"); gwy_data_field_set_si_unit_xy(dfield, siunit); g_object_unref(siunit); siunit = gwy_si_unit_new("m"); gwy_data_field_set_si_unit_z(dfield, siunit); g_object_unref(siunit); container = gwy_container_new(); gwy_container_set_object_by_name(container, "/0/data", dfield); /* Channel title */ p = buffer + ECS_CHANNEL; s = get_PASCAL_STRING(&p, HEADER_SIZE - ECS_CHANNEL); if (!s || !*s) s = g_strdup("Topography"); gwy_container_set_string_by_name(container, "/0/data/title", s); s = NULL; meta = gwy_container_new(); /* Date & time */ p = buffer + ECS_DATE; s = get_PASCAL_STRING(&p, HEADER_SIZE - ECS_DATE); if (s) { p = buffer + ECS_TIME; s2 = get_PASCAL_STRING(&p, HEADER_SIZE - ECS_TIME); if (s2) { gwy_container_set_string_by_name(meta, "Date", g_strconcat(s, " ", s2, NULL)); g_free(s2); s2 = NULL; } g_free(s); s = NULL; } /* Channel title */ p = buffer + ECS_CHANNEL; s = get_PASCAL_STRING(&p, HEADER_SIZE - ECS_CHANNEL); if (s && *s) { gwy_container_set_string_by_name(meta, "Comment", s); s = NULL; } if (gwy_container_get_n_items(meta)) gwy_container_set_object_by_name(container, "/0/meta", meta); g_object_unref(meta); fail: g_free(s); g_free(s2); gwy_object_unref(dfield); gwy_file_abandon_contents(buffer, size, NULL); return container; }
static GwyContainer* burleigh_exp_load(const gchar *filename, G_GNUC_UNUSED GwyRunType mode, GError **error) { GwyContainer *container = NULL; gchar *buffer = NULL; BurleighExpHeader header; gsize size = 0; GError *err = NULL; GwyDataField *dfield; gdouble *data; guint i, n; if (!g_file_get_contents(filename, &buffer, &size, &err)) { err_GET_FILE_CONTENTS(error, &err); return NULL; } if (size < MIN_FILE_SIZE + 2) { err_TOO_SHORT(error); g_free(buffer); return NULL; } if (!burleigh_exp_read_header(&header, buffer, error)) goto fail; n = header.xres * header.yres; if (header.binary) { if (header.bpp != 16) { err_BPP(error, header.bpp); goto fail; } else if (err_SIZE_MISMATCH(error, header.length + 2*n, size, TRUE)) goto fail; } dfield = gwy_data_field_new(header.xres, header.yres, header.xscale, header.yscale, FALSE); data = gwy_data_field_get_data(dfield); if (header.binary) { const gint16 *d16 = (const gint16*)(buffer + header.length); for (i = 0; i < n; i++) data[i] = GINT16_FROM_LE(d16[i]); } else { gchar *p = buffer + header.length; for (i = 0; i < n; i++) data[i] = strtol(p, &p, 10); } gwy_data_field_multiply(dfield, header.zscale/32768.0); /* Units references released in free_header() */ gwy_data_field_set_si_unit_xy(dfield, header.xyunits); gwy_data_field_set_si_unit_z(dfield, header.zunits); container = gwy_container_new(); gwy_container_set_object(container, gwy_app_get_data_key_for_id(0), dfield); g_object_unref(dfield); gwy_app_channel_title_fall_back(container, 0); gwy_file_channel_import_log_add(container, 0, NULL, filename); fail: free_header(&header); g_free(buffer); return container; }
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 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; }
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 gboolean read_file_info(const guchar *buffer, gsize size, FileInfo *info, GError **error) { guint expected_size, i; const guchar *p; gwy_clear(info, 1); p = buffer + MAGIC_SIZE; /* read structure variables from buffer */ for (i = 0; i < (HEADER_SIZE - MAGIC_SIZE)/8; i++) { gchar key[5]; guint32 value; key[4] = '\0'; memcpy(key, p, 4); p += 4; value = gwy_get_guint32_le(&p); if (!key[0]) continue; gwy_debug("%s: 0x%04x", key, value); /* Do not take values past the end of file and zeros into account at * all. The software seems to sometimes emit silly extra fields. */ if (!value || value >= size) continue; else if (gwy_strequal(key, "DESC")) info->desc_offset = value; else if (gwy_strequal(key, "DATE")) info->date_offset = value; else if (gwy_strequal(key, "PLET")) info->palette_offset = value; else if (gwy_strequal(key, "IMAG")) info->image_offset = value; else if (gwy_strequal(key, "HARD")) info->hard_offset = value; else if (gwy_strequal(key, "IMGP")) info->img_p_offset = value; else if (gwy_strequal(key, "SDES")) info->short_desc_offset = value; else if (gwy_strequal(key, "KEYS")) info->keys_offset = value; else { gwy_debug("Unknown field %s", key); } } /* Pixel image size */ if (!(p = get_param_pointer(buffer, size, info->image_offset, sizeof(guint16), "IMAG", error))) return FALSE; info->img_res = gwy_get_guint16_le(&p); if (err_DIMENSION(error, info->img_res)) return FALSE; /* Image data. It is the *same* pointer, just after the pixel size. */ info->image_data = (const guint16*)p; expected_size = (p - buffer) + info->img_res*info->img_res*sizeof(guint16); if (err_SIZE_MISMATCH(error, expected_size, size, FALSE)) return FALSE; /* Real image size */ if (!(p = get_param_pointer(buffer, size, info->hard_offset, sizeof(gfloat), "HARD", error))) return FALSE; info->real_size = gwy_get_gfloat_le(&p); if (!((info->real_size = fabs(info->real_size)) > 0)) { g_warning("Real size is 0.0, fixing to 1.0"); info->real_size = 1.0; } /* Value scale factor */ if (!(p = get_param_pointer(buffer, size, info->img_p_offset + 8, sizeof(gfloat), "IMGP", error))) return FALSE; info->z_scale = gwy_get_gfloat_le(&p); return TRUE; }
static GwyDataField* omicron_read_data(OmicronFile *ofile, OmicronTopoChannel *channel, GError **error) { GError *err = NULL; GwyDataField *dfield; GwySIUnit *siunit; gchar *filename; gdouble *data; guchar *buffer; const gint16 *d; gdouble scale; gsize size; guint i, j, n; gint power10 = 0; filename = omicron_fix_file_name(ofile->filename, channel->filename, error); if (!filename) return NULL; gwy_debug("Succeeded with <%s>", filename); if (!gwy_file_get_contents(filename, &buffer, &size, &err)) { g_free(filename); err_GET_FILE_CONTENTS(error, &err); return NULL; } g_free(filename); n = ofile->xres*ofile->yres; if (err_SIZE_MISMATCH(error, 2*n, size, TRUE)) { gwy_file_abandon_contents(buffer, size, NULL); return NULL; } scale = (channel->max_phys - channel->min_phys) /(channel->max_raw - channel->min_raw); dfield = gwy_data_field_new(ofile->xres, ofile->yres, ofile->xreal, ofile->yreal, FALSE); data = gwy_data_field_get_data(dfield); d = (const gint16*)buffer; for (i = 0; i < ofile->yres; i++) { for (j = 0; j < ofile->xres; j++) data[(ofile->yres-1 - i)*ofile->xres + j] = scale*GINT16_FROM_BE(d[i*ofile->xres + j]); } 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); siunit = gwy_si_unit_new_parse(channel->units, &power10); gwy_data_field_set_si_unit_z(dfield, siunit); g_object_unref(siunit); if (power10) gwy_data_field_multiply(dfield, pow10(power10)); return dfield; }
static GwyDataField* unisoku_read_data_field(const guchar *buffer, gsize size, UnisokuFile *ufile, GError **error) { gint i, n, power10; const gchar *unit; GwyDataField *dfield; GwySIUnit *siunit; gdouble q, pmin, pmax, rmin, rmax; gdouble *data; n = ufile->xres * ufile->yres; if (err_SIZE_MISMATCH(error, n*type_sizes[ufile->data_type], size, FALSE)) return NULL; dfield = gwy_data_field_new(ufile->xres, ufile->yres, fabs((ufile->end_x - ufile->start_x)), fabs((ufile->end_y - ufile->start_y)), FALSE); data = gwy_data_field_get_data(dfield); /* FIXME: what to do when ascii_flag is set? */ switch (ufile->data_type) { case UNISOKU_UINT8: for (i = 0; i < n; i++) data[i] = buffer[i]; break; case UNISOKU_SINT8: for (i = 0; i < n; i++) data[i] = (signed char)buffer[i]; break; case UNISOKU_UINT16: { const guint16 *pdata = (const guint16*)buffer; for (i = 0; i < n; i++) data[i] = GUINT16_FROM_LE(pdata[i]); } break; case UNISOKU_SINT16: { const gint16 *pdata = (const gint16*)buffer; for (i = 0; i < n; i++) data[i] = GINT16_FROM_LE(pdata[i]); } break; case UNISOKU_FLOAT: for (i = 0; i < n; i++) data[i] = gwy_get_gfloat_le(&buffer); break; default: g_return_val_if_reached(NULL); break; } unit = ufile->unit_x; if (!*unit) unit = "nm"; siunit = gwy_si_unit_new_parse(unit, &power10); gwy_data_field_set_si_unit_xy(dfield, siunit); q = pow10((gdouble)power10); gwy_data_field_set_xreal(dfield, q*gwy_data_field_get_xreal(dfield)); gwy_data_field_set_yreal(dfield, q*gwy_data_field_get_yreal(dfield)); g_object_unref(siunit); unit = ufile->unit_z; /* XXX: No fallback yet, just make z unitless */ siunit = gwy_si_unit_new_parse(unit, &power10); gwy_data_field_set_si_unit_z(dfield, siunit); q = pow10((gdouble)power10); pmin = q*ufile->min_z; pmax = q*ufile->max_z; rmin = ufile->min_raw_z; rmax = ufile->max_raw_z; gwy_data_field_multiply(dfield, (pmax - pmin)/(rmax - rmin)); gwy_data_field_add(dfield, (pmin*rmax - pmax*rmin)/(rmax - rmin)); g_object_unref(siunit); return dfield; }
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 GwyDataField* sensofar_read_data_field(SensofarDataDesc *data_desc, GwyDataField **maskfield, const guchar **p, gsize size, GError **error) { GwyDataField *dfield, *mfield; guint xres, yres, i, j, mcount; GwySIUnit *units = NULL; gdouble *data, *mdata; if (maskfield) *maskfield = NULL; yres = gwy_get_guint32_le(p); 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; } if (!((data_desc->axes_config.mppy = fabs(data_desc->axes_config.mppy)) > 0)) { g_warning("Real y size is 0.0, fixing to 1.0"); data_desc->axes_config.mppy = 1.0; } dfield = gwy_data_field_new(xres, yres, data_desc->axes_config.mppx * xres * Micrometer, data_desc->axes_config.mppy * yres * Micrometer, FALSE); units = gwy_si_unit_new("m"); // values are in um only gwy_data_field_set_si_unit_xy(dfield, units); g_object_unref(units); units = gwy_si_unit_new("m"); gwy_data_field_set_si_unit_z(dfield, units); g_object_unref(units); mfield = gwy_data_field_new_alike(dfield, FALSE); gwy_data_field_fill(mfield, 1.0); data = gwy_data_field_get_data(dfield); mdata = gwy_data_field_get_data(mfield); for (i = 0; i < yres; i++) { for (j = 0; j < xres; j++) { gdouble v = gwy_get_gfloat_le(p); if (v == 1000001.0) mdata[i*xres + j] = 0.0; else data[i*xres + j] = v*Micrometer; } } gwy_debug("Offset: %g %g", data_desc->axes_config.x_0, data_desc->axes_config.y_0); //FIXME: offset later, support of offset determined by version? //gwy_data_field_set_xoffset(d, pow10(power10)*data_desc.axes_config.x_0); //gwy_data_field_set_yoffset(d, pow10(power10)*data_desc.axes_config.y_0); mcount = gwy_app_channel_remove_bad_data(dfield, mfield); if (maskfield && mcount) *maskfield = mfield; else g_object_unref(mfield); return dfield; }
static GwyContainer* jeol_load(const gchar *filename, G_GNUC_UNUSED GwyRunType mode, GError **error) { JEOLImageHeader image_header; GwyContainer *meta, *container = NULL; guchar *buffer = NULL; gsize expected_size, size = 0; GError *err = NULL; GwyDataField *dfield = NULL; const gchar *title; gchar *s; if (!gwy_file_get_contents(filename, &buffer, &size, &err)) { err_GET_FILE_CONTENTS(error, &err); return NULL; } if (size < JEOL_DATA_START) { err_TOO_SHORT(error); goto fail; } if (memcmp(buffer, MAGIC, MAGIC_SIZE) != 0) { err_FILE_TYPE(error, "JEOL"); goto fail; } jeol_read_image_header(buffer, &image_header); /* Elementrary sanity */ if (image_header.bpp != 16) { err_BPP(error, image_header.bpp); goto fail; } if (err_DIMENSION(error, image_header.xres) || err_DIMENSION(error, image_header.yres)) goto fail; expected_size = image_header.bpp/8 * image_header.xres*image_header.yres; if (err_SIZE_MISMATCH(error, JEOL_DATA_START + expected_size, size, FALSE)) goto fail; if (image_header.image_type != JEOL_IMAGE || image_header.compressed) { err_NO_DATA(error); goto fail; } /* Use negated positive conditions to catch NaNs */ if (!((image_header.xreal = fabs(image_header.xreal)) > 0)) { g_warning("Real x size is 0.0, fixing to 1.0"); image_header.xreal = 1.0; } if (!((image_header.yreal = fabs(image_header.yreal)) > 0)) { g_warning("Real y size is 0.0, fixing to 1.0"); image_header.yreal = 1.0; } dfield = jeol_read_data_field(buffer + JEOL_DATA_START, &image_header); if (!dfield) { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA, _("The type of data is unknown. " "Please report it to the developers.")); goto fail; } container = gwy_container_new(); gwy_container_set_object_by_name(container, "/0/data", dfield); g_object_unref(dfield); /* Title */ s = g_convert(image_header.internal_filename, -1, "iso-8859-1", "utf-8", NULL, NULL, NULL); if (s) g_strstrip(s); if (s && *s) gwy_container_set_string_by_name(container, "/0/data/title", s); else { title = gwy_flat_enum_to_string(image_header.data_source, G_N_ELEMENTS(data_sources), data_sources, data_sources_name); if (title) gwy_container_set_string_by_name(container, "/0/data/title", g_strdup(title)); } /* Meta */ meta = jeol_get_metadata(&image_header); gwy_container_set_object_by_name(container, "/0/meta", meta); g_object_unref(meta); gwy_file_channel_import_log_add(container, 0, NULL, filename); fail: gwy_file_abandon_contents(buffer, size, NULL); return container; }
static GwyDataField* hash_to_data_field(GHashTable *hash, GHashTable *scannerlist, GHashTable *scanlist, NanoscopeFileType file_type, gboolean has_version, guint bufsize, gchar *buffer, gint gxres, gint gyres, gchar **p, GError **error) { NanoscopeValue *val; GwyDataField *dfield; GwySIUnit *unitz, *unitxy; gchar *s, *end; gchar un[5]; gint xres, yres, bpp, offset, size, power10; gdouble xreal, yreal, q; gdouble *data; gboolean size_ok, use_global; if (!require_keys(hash, error, "Samps/line", "Number of lines", "Scan size", "Data offset", "Data length", NULL)) return NULL; val = g_hash_table_lookup(hash, "Samps/line"); xres = GWY_ROUND(val->hard_value); val = g_hash_table_lookup(hash, "Number of lines"); yres = GWY_ROUND(val->hard_value); val = g_hash_table_lookup(hash, "Bytes/pixel"); bpp = val ? GWY_ROUND(val->hard_value) : 2; /* scan size */ val = g_hash_table_lookup(hash, "Scan size"); xreal = g_ascii_strtod(val->hard_value_str, &end); if (errno || *end != ' ') { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA, _("Cannot parse `Scan size' field.")); return NULL; } gwy_debug("xreal = %g", xreal); s = end+1; yreal = g_ascii_strtod(s, &end); if (errno || *end != ' ') { /* Old files don't have two numbers here, assume equal dimensions */ yreal = xreal; end = s; } gwy_debug("yreal = %g", yreal); while (g_ascii_isspace(*end)) end++; if (sscanf(end, "%4s", un) != 1) { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA, _("Cannot parse `Scan size' field.")); return NULL; } gwy_debug("xy unit: <%s>", un); unitxy = gwy_si_unit_new_parse(un, &power10); q = pow10(power10); xreal *= q; yreal *= q; offset = size = 0; if (file_type == NANOSCOPE_FILE_TYPE_BIN) { val = g_hash_table_lookup(hash, "Data offset"); offset = GWY_ROUND(val->hard_value); val = g_hash_table_lookup(hash, "Data length"); size = GWY_ROUND(val->hard_value); size_ok = FALSE; use_global = FALSE; /* Try channel size and local size */ if (!size_ok && size == bpp*xres*yres) size_ok = TRUE; if (!size_ok && size == bpp*gxres*gyres) { size_ok = TRUE; use_global = TRUE; } /* If they don't match exactly, try whether they at least fit inside */ if (!size_ok && size > bpp*MAX(xres*yres, gxres*gyres)) { size_ok = TRUE; use_global = (xres*yres < gxres*gyres); } if (!size_ok && size > bpp*MIN(xres*yres, gxres*gyres)) { size_ok = TRUE; use_global = (xres*yres > gxres*gyres); } if (!size_ok) { err_SIZE_MISMATCH(error, size, bpp*xres*yres); return NULL; } if (use_global) { if (gxres) { xreal *= (gdouble)gxres/xres; xres = gxres; } if (gyres) { yreal *= (gdouble)gyres/yres; yres = gyres; } } if (offset + size > (gint)bufsize) { err_SIZE_MISMATCH(error, offset + size, bufsize); return NULL; } } q = 1.0; unitz = get_physical_scale(hash, scannerlist, scanlist, has_version, &q, error); if (!unitz) return NULL; dfield = gwy_data_field_new(xres, yres, xreal, yreal, FALSE); data = gwy_data_field_get_data(dfield); switch (file_type) { case NANOSCOPE_FILE_TYPE_TXT: if (!read_ascii_data(xres*yres, data, p, bpp, error)) { g_object_unref(dfield); return NULL; } break; case NANOSCOPE_FILE_TYPE_BIN: if (!read_binary_data(xres*yres, data, buffer + offset, bpp, error)) { g_object_unref(dfield); return NULL; } break; default: g_assert_not_reached(); break; } gwy_data_field_multiply(dfield, q); gwy_data_field_invert(dfield, TRUE, FALSE, FALSE); gwy_data_field_set_si_unit_z(dfield, unitz); g_object_unref(unitz); gwy_data_field_set_si_unit_xy(dfield, unitxy); g_object_unref(unitxy); return dfield; }
static GwyDataField* read_datafield(const guchar *buffer, guint size, const StmprgFile *stmprgfile, GError **error) { gint xres, yres, bpp; gdouble xreal, yreal, q; GwyDataField *dfield; gdouble *data; GwySIUnit *unit; bpp = 2; /* words, always */ xres = stmprgfile->mainfield.points; yres = stmprgfile->mainfield.lines; xreal = Angstrom * stmprgfile->mainfield.field_x; yreal = Angstrom * stmprgfile->mainfield.field_y; q = stmprgfile->mainfield.sol_z * 1.0e-5; /* 5 ?? */ /* resolution of z value in angstrom/bit, 1.0e-10 */ if (err_SIZE_MISMATCH(error, bpp*xres*yres, size, FALSE)) return NULL; dfield = gwy_data_field_new(xres, yres, xreal, yreal, FALSE); data = gwy_data_field_get_data(dfield); if (!read_binary_ubedata(xres * yres, data, buffer, bpp)) { err_BPP(error, bpp); g_object_unref(dfield); return NULL; } gwy_data_field_multiply(dfield, q); unit = gwy_si_unit_new("m"); gwy_data_field_set_si_unit_xy(dfield, unit); g_object_unref(unit); /* Assuming we are reading channel1... */ switch (stmprgfile->control.channel1) { case STMPRG_CHANNEL_OFF: g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA, _("First channel is switched off.")); return NULL; case STMPRG_CHANNEL_Z: unit = gwy_si_unit_new("m"); break; case STMPRG_CHANNEL_I: case STMPRG_CHANNEL_I_I0: case STMPRG_CHANNEL_I0: unit = gwy_si_unit_new("A"); break; case STMPRG_CHANNEL_EXT1: case STMPRG_CHANNEL_EXT2: case STMPRG_CHANNEL_U0: unit = gwy_si_unit_new("V"); break; default: g_assert_not_reached(); break; } gwy_data_field_set_si_unit_z(dfield, unit); g_object_unref(unit); return dfield; }
static GwyDataField* apedax_get_data_field(unzFile uFile, const gchar *chFileName, const APEScanSize *scanSize, gchar *zUnit, gdouble scale, GError **error) { GwyDataField *dfield = NULL; GwySIUnit *xyUnit; GwySIUnit *zSIUnit; gdouble *data; guchar *buffer; gsize size, expectedSize; unz_file_info uFileInfo; /*Checking the dimensions*/ if (err_DIMENSION(error, scanSize->XRes)) { return NULL; } if (err_DIMENSION(error, scanSize->YRes)) { return NULL; } /*If XReal it's not greater than 0 or XReal is NaN*/ if (!(fabs(scanSize->XReal) > 0)) { err_UNSUPPORTED(error, "X scan size"); return NULL; } /*Same for YReal*/ if (!(fabs(scanSize->YReal) > 0)) { err_UNSUPPORTED(error, "Y scan size"); return NULL; } expectedSize = scanSize->XRes * scanSize->YRes * sizeof(gdouble); unzGoToFirstFile(uFile); if (unzLocateFile(uFile, chFileName, 0) != UNZ_OK) { gwy_debug("Binary file not found"); err_NO_DATA(error); return NULL; } if (unzGetCurrentFileInfo(uFile, &uFileInfo, NULL, 0L, NULL, 0L, NULL, 0L) != UNZ_OK) { err_NO_DATA(error); return NULL; } buffer = apedax_get_file_content(uFile, &uFileInfo, &size, error); if (buffer == NULL) { err_NO_DATA(error); return NULL; } if (err_SIZE_MISMATCH(error, expectedSize, size, FALSE)) { return NULL; } dfield = gwy_data_field_new(scanSize->XRes, scanSize->YRes, scanSize->XReal, scanSize->YReal, FALSE); data = gwy_data_field_get_data(dfield); xyUnit = gwy_data_field_get_si_unit_xy(dfield); gwy_si_unit_set_from_string(xyUnit, "m"); zSIUnit = gwy_data_field_get_si_unit_z(dfield); gwy_si_unit_set_from_string(zSIUnit, zUnit); gwy_debug("Reading RAW data"); gwy_convert_raw_data(buffer, scanSize->XRes * scanSize->YRes, 1, GWY_RAW_DATA_DOUBLE, GWY_BYTE_ORDER_LITTLE_ENDIAN, data, scale, 0.0); return dfield; }
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; }
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; }
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 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* pt3file_load(const gchar *filename, G_GNUC_UNUSED GwyRunType mode, GError **error) { PicoHarpFile pt3file; GwyContainer *meta, *container = NULL; GwyDataField *dfield = NULL; GwyGraphModel *gmodel = NULL; guchar *buffer = NULL; const guchar *p; gsize header_len, size = 0; GError *err = NULL; LineTrigger *linetriggers = NULL; if (!gwy_file_get_contents(filename, &buffer, &size, &err)) { err_GET_FILE_CONTENTS(error, &err); return NULL; } gwy_clear(&pt3file, 1); if (!(header_len = pt3file_read_header(buffer, size, &pt3file, error))) goto fail; if (err_SIZE_MISMATCH (error, header_len + pt3file.number_of_records*sizeof(guint32), size, FALSE)) goto fail; if (pt3file.measurement_mode != 3) { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA, _("T2 measurement mode is not implemented.")); goto fail; } if (pt3file.imaging.common.instrument != PICO_HARP_PIE710 && pt3file.imaging.common.instrument != PICO_HARP_KDT180) { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA, _("Only PI E710 and KDT180-100-Im imaging formats are " "implemented.")); goto fail; } /* Scan the records and find the line triggers */ p = buffer + header_len; if (!(linetriggers = pt3file_scan_line_triggers(&pt3file, p, error))) goto fail; container = gwy_container_new(); dfield = pt3file_extract_counts(&pt3file, linetriggers, p); gwy_container_set_object_by_name(container, "/0/data", dfield); g_object_unref(dfield); gwy_container_set_string_by_name(container, "/0/data/title", g_strdup("Photon count")); meta = pt3file_get_metadata(&pt3file); gwy_container_set_object_by_name(container, "/0/meta", meta); g_object_unref(meta); gwy_file_channel_import_log_add(container, 0, NULL, filename); gmodel = pt3file_extract_decay(&pt3file, p); gwy_container_set_object_by_name(container, "/0/graph/graph/1", gmodel); g_object_unref(gmodel); fail: g_free(linetriggers); gwy_file_abandon_contents(buffer, size, NULL); return container; }
static gboolean read_binary_data(X3PFile *x3pfile, unzFile *zipfile, GError **error) { GwyRawDataType rawtype; gsize size; guchar *bindata; gchar *s; guint i; s = g_hash_table_lookup(x3pfile->hash, DATA_LINK_PREFIX "/PointDataLink"); if (!s) { err_NO_DATA(error); return FALSE; } gwy_debug("binary data file %s", s); if (unzLocateFile(zipfile, s, 1) != UNZ_OK) { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_IO, _("File %s is missing in the zip file."), s); return FALSE; } s = g_hash_table_lookup(x3pfile->hash, AXES_PREFIX "/CZ/DataType"); if (!s) { err_MISSING_FIELD(error, AXES_PREFIX "CZ/DataType"); return FALSE; } if (!x3p_file_get_data_type(s, &rawtype, error)) return FALSE; if (!(bindata = x3p_get_file_content(zipfile, &size, error))) return FALSE; if (err_SIZE_MISMATCH(error, x3pfile->ndata * gwy_raw_data_size(rawtype), size, TRUE)) { g_free(bindata); return FALSE; } gwy_convert_raw_data(bindata, x3pfile->ndata, 1, rawtype, GWY_BYTE_ORDER_LITTLE_ENDIAN, x3pfile->values, x3pfile->dz, x3pfile->zoff); g_free(bindata); for (i = 0; i < x3pfile->ndata; i++) x3pfile->valid[i] = TRUE; s = g_hash_table_lookup(x3pfile->hash, DATA_LINK_PREFIX "/ValidPointsLink"); if (!s) return TRUE; if (unzLocateFile(zipfile, s, 1) != UNZ_OK) { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_IO, _("File %s is missing in the zip file."), s); return FALSE; } if (!(bindata = x3p_get_file_content(zipfile, &size, error))) return FALSE; if (err_SIZE_MISMATCH(error, (x3pfile->ndata + 7)/8, size, TRUE)) { g_free(bindata); return FALSE; } for (i = 0; i < x3pfile->ndata; i++) x3pfile->valid[i] = bindata[i/8] & (1 << (i % 8)); g_free(bindata); return TRUE; }
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; }
static GwyDataField* read_data_field_old(const guchar *buffer, guint size, GError **error) { gint xres, yres, n, i, j, vx, vy; G_GNUC_UNUSED gint vz; gdouble xscale, yscale, zscale, xreal, yreal, q; G_GNUC_UNUSED gdouble xunit, yunit, zunit; GwyDataField *dfield; GwySIUnit *siunit; gdouble *data, *row; const gint16 *pdata; const guchar *p; p = buffer + RES_OFFSET_OLD; xres = gwy_get_guint16_le(&p); yres = gwy_get_guint16_le(&p); gwy_debug("xres: %d, yres: %d", xres, yres); if (err_DIMENSION(error, xres) || err_DIMENSION(error, yres)) return NULL; n = xres*yres; if (err_SIZE_MISMATCH(error, 2*n + HEADER_SIZE_OLD, size, TRUE)) return NULL; p = buffer + SCALE_OFFSET_OLD; xscale = gwy_get_gdouble_le(&p); yscale = gwy_get_gdouble_le(&p); zscale = gwy_get_gdouble_le(&p); p = buffer + UNIT_OFFSET_OLD; xunit = gwy_get_gdouble_le(&p); yunit = gwy_get_gdouble_le(&p); zunit = gwy_get_gdouble_le(&p); p = buffer + SPEED_OFFSET_OLD; vx = gwy_get_guint32_le(&p); vy = gwy_get_guint32_le(&p); vz = gwy_get_guint32_le(&p); xreal = xscale * vx; yreal = yscale * vy; q = zscale; gwy_debug("xreal: %g, yreal: %g, zscale: %g", xreal, yreal, q); /* Use negated positive conditions to catch NaNs */ if (!((xreal = fabs(xreal)) > 0)) { g_warning("Real x size is 0.0, fixing to 1.0"); xreal = 1.0; } if (!((yreal = fabs(yreal)) > 0)) { g_warning("Real y size is 0.0, fixing to 1.0"); yreal = 1.0; } dfield = gwy_data_field_new(xres, yres, xreal, yreal, FALSE); data = gwy_data_field_get_data(dfield); pdata = (const gint16*)(buffer + HEADER_SIZE_OLD); for (i = 0; i < yres; i++) { row = data + i*xres; for (j = 0; j < xres; j++) row[j] = GUINT16_FROM_LE(pdata[i*xres + j])*q; } siunit = gwy_si_unit_new("m"); gwy_data_field_set_si_unit_xy(dfield, siunit); g_object_unref(siunit); siunit = gwy_si_unit_new("m"); gwy_data_field_set_si_unit_z(dfield, siunit); g_object_unref(siunit); return dfield; }
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 GwyContainer* mprofile_load(const gchar *filename, G_GNUC_UNUSED GwyRunType mode, GError **error) { MProFile mprofile; GwyContainer *meta, *container = NULL; GwyDataField *dfield = NULL, *vpmask = NULL; guchar *buffer = NULL; gsize size = 0; GError *err = NULL; gsize expected; GString *key; const gchar *title; guint n, i; if (!gwy_file_get_contents(filename, &buffer, &size, &err)) { err_GET_FILE_CONTENTS(error, &err); return NULL; } if (!mprofile_read_header(buffer, size, &mprofile, error)) return NULL; expected = mprofile.header_size + 2*mprofile.nbuckets*mprofile.intens_xres*mprofile.intens_yres + 4*mprofile.phase_xres*mprofile.phase_yres; if (err_SIZE_MISMATCH(error, expected, size, TRUE)) { gwy_file_abandon_contents(buffer, size, NULL); return NULL; } n = fill_data_fields(&mprofile, buffer); gwy_file_abandon_contents(buffer, size, NULL); if (!n) { err_NO_DATA(error); return NULL; } key = g_string_new(NULL); container = gwy_container_new(); for (i = 0; i < n; i++) { if (i > 0) { dfield = mprofile.intensity_data[i-1]; vpmask = mprofile.intensity_mask[i-1]; title = "Intensity"; } else { dfield = mprofile.phase_data; vpmask = mprofile.phase_mask; title = "Phase"; } g_string_printf(key, "/%d/data", i); gwy_container_set_object_by_name(container, key->str, dfield); g_string_printf(key, "/%d/data/title", i); gwy_container_set_string_by_name(container, key->str, g_strdup(title)); if (vpmask) { g_string_printf(key, "/%d/mask", i); gwy_container_set_object_by_name(container, key->str, vpmask); } meta = mprofile_get_metadata(&mprofile); g_string_printf(key, "/%d/meta", i); gwy_container_set_object_by_name(container, key->str, meta); g_object_unref(meta); } g_string_free(key, TRUE); for (n = 0; n < mprofile.nbuckets; n++) { gwy_object_unref(mprofile.intensity_data[n]); gwy_object_unref(mprofile.intensity_mask[n]); } gwy_object_unref(mprofile.phase_data); gwy_object_unref(mprofile.phase_mask); return container; }