static gint ecs_detect(const GwyFileDetectInfo *fileinfo, gboolean only_name) { guint xres, yres; const guchar *p; if (only_name) return g_str_has_suffix(fileinfo->name_lowercase, EXTENSION) ? 10 : 0; if (fileinfo->buffer_len < ECS_RESOLUTION + 2*2 || fileinfo->file_size < HEADER_SIZE + 2 || memcmp(fileinfo->head, MAGIC, MAGIC_SIZE) != 0) return 0; /* Check if file size matches */ p = fileinfo->head + ECS_RESOLUTION; xres = gwy_get_guint16_le(&p); yres = gwy_get_guint16_le(&p); if (fileinfo->file_size != 2*xres*yres + HEADER_SIZE) return 0; return 100; }
static gint hitachi_old_detect(const GwyFileDetectInfo *fileinfo, gboolean only_name) { guint xres, yres; const guchar *p; if (only_name) return g_str_has_suffix(fileinfo->name_lowercase, EXTENSION) ? 10 : 0; if (fileinfo->buffer_len < HEADER_SIZE_OLD || fileinfo->file_size < HEADER_SIZE_OLD + 2 /* This is actually header size (0x100), just weed out non-AFM files */ || fileinfo->head[0] != 0 || fileinfo->head[1] != 1) return 0; p = fileinfo->head + RES_OFFSET_OLD; xres = gwy_get_guint16_le(&p); yres = gwy_get_guint16_le(&p); if (fileinfo->file_size == 2*xres*yres + HEADER_SIZE_OLD) return 100; return 0; }
static guchar* rhk_sm3_read_string(const guchar **buffer, gsize len) { gchar *s, *p; guint i, n; gunichar chr; if (len < 2) return NULL; n = gwy_get_guint16_le(buffer); len -= 2; if (len < 2*n) return NULL; if (!n) return g_strdup(""); p = s = g_new(gchar, 6*n + 1); for (i = 0; i < n; i++) { chr = gwy_get_guint16_le(buffer); p += g_unichar_to_utf8(chr, p); } *p = '\0'; g_strstrip(s); gwy_debug("String: <%s>", s); return s; }
static gint burleigh_detect(const GwyFileDetectInfo *fileinfo, gboolean only_name) { const guchar *buffer; guint version_int, xres, yres; gdouble version; if (only_name) return g_str_has_suffix(fileinfo->name_lowercase, EXTENSION) ? 10 : 0; if (fileinfo->buffer_len < 4) return 0; buffer = fileinfo->head; version = gwy_get_gfloat_le(&buffer); version_int = GWY_ROUND(10*version); gwy_debug("Version: %g", version); if (version_int == 21) { if (fileinfo->file_size < TOTAL_SIZE_V21 + 2) return 0; xres = gwy_get_guint16_le(&buffer); yres = gwy_get_guint16_le(&buffer); if (fileinfo->file_size == TOTAL_SIZE_V21 + 2*xres*yres) return 100; return 0; } return 0; }
static gint apefile_detect(const GwyFileDetectInfo *fileinfo, gboolean only_name) { const guchar *buffer; gint score = 0; guint version, mode, vbtype; if (only_name) return g_str_has_suffix(fileinfo->name_lowercase, ".dat") ? 10 : 0; if (fileinfo->buffer_len < HEADER_SIZE) return 0; buffer = fileinfo->head; version = *(buffer++); mode = *(buffer++); vbtype = gwy_get_guint16_le(&buffer); if (version >= 1 && version <= 2 && mode < SPM_MODE_LAST+2 /* reserve */ && vbtype == 7) { score = 60; /* This works for new file format only */ if (!strncmp(fileinfo->head + 234, "APERES", 6)) score = 100; } return score; }
static gboolean mif_read_header(const guchar *buffer, gsize size, MIFHeader *header, GError **error) { const guchar *p = buffer; if (size <= HEADER_SIZE) { err_TOO_SHORT(error); return FALSE; } if (memcmp(buffer, MAGIC, MAGIC_SIZE)) { err_FILE_TYPE(error, "MIF"); return FALSE; } gwy_clear(header, 1); get_CHARARRAY(header->magic, &p); header->software_version = gwy_get_guint16_be(&p); header->file_version = gwy_get_guint16_be(&p); gwy_debug("sw version: %u.%u, file version: %u.%u", header->software_version/0x100, header->software_version % 0x100, header->file_version/0x100, header->file_version % 0x100); /* Version 1.7 is the only actually implemented. Other can be added upon * request and, namely, provision of the files as each file version is * different. */ if (header->file_version != 0x107) { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA, _("Loading of file version %u.%u is not implemented."), header->file_version/0x100, header->file_version % 0x100); return FALSE; } get_CHARARRAY(header->time, &p); get_CHARARRAY(header->comment, &p); header->nimages = gwy_get_guint16_le(&p); gwy_debug("n images: %u", header->nimages); header->info.offset = gwy_get_guint32_le(&p); header->info.size = gwy_get_guint32_le(&p); gwy_debug("info offset: %zu, info size: %zu", header->info.offset, header->info.size); get_CHARARRAY(header->unused, &p); if (header->info.offset < HEADER_SIZE || header->info.offset > size || header->info.size > size || header->info.offset + header->info.size > size) { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA, _("File information block is outside the file.")); return FALSE; } return TRUE; }
/* XXX: Code identical to nxiifile.c */ static gboolean read_bmp_header(const guchar *p, guint *xres, guint *yres, guint *size) { guint x; if (p[0] != 'B' || p[1] != 'M') return FALSE; p += 2; if ((*size = gwy_get_guint32_le(&p)) < BMP_HEADER_SIZE) /* Size */ return FALSE; if ((x = gwy_get_guint32_le(&p)) != 0) /* Reserved */ return FALSE; if ((x = gwy_get_guint32_le(&p)) != 54) /* Offset */ return FALSE; if ((x = gwy_get_guint32_le(&p)) != 40) /* Header size */ return FALSE; if ((*xres = gwy_get_guint32_le(&p)) == 0) /* Width */ return FALSE; if ((*yres = gwy_get_guint32_le(&p)) == 0) /* Height */ return FALSE; if ((x = gwy_get_guint16_le(&p)) != 1) /* Bit planes */ return FALSE; if ((x = gwy_get_guint16_le(&p)) != 24) /* BPP */ return FALSE; if ((x = gwy_get_guint32_le(&p)) != 0) /* Compression */ return FALSE; if ((x = gwy_get_guint32_le(&p)) && x + BMP_HEADER_SIZE != *size) /* Compresed size, may be 0 */ return FALSE; if (3*(*xres)*(*yres) + BMP_HEADER_SIZE != *size) return FALSE; return TRUE; }
static gboolean sdfile_read_header_bin(const guchar **p, gsize *len, SDFile *sdfile, GError **error) { if (*len < SDF_HEADER_SIZE_BIN) { err_TOO_SHORT(error); return FALSE; } gwy_clear(sdfile, 1); get_CHARARRAY(sdfile->version, p); get_CHARARRAY(sdfile->manufacturer, p); get_CHARARRAY(sdfile->creation, p); get_CHARARRAY(sdfile->modification, p); sdfile->xres = gwy_get_guint16_le(p); sdfile->yres = gwy_get_guint16_le(p); sdfile->xscale = gwy_get_gdouble_le(p); sdfile->yscale = gwy_get_gdouble_le(p); sdfile->zscale = gwy_get_gdouble_le(p); sdfile->zres = gwy_get_gdouble_le(p); sdfile->compression = **p; (*p)++; sdfile->data_type = **p; (*p)++; sdfile->check_type = **p; (*p)++; sdfile->data = (gchar*)*p; if (sdfile->data_type < SDF_NTYPES) sdfile->expected_size = type_sizes[sdfile->data_type] * sdfile->xres * sdfile->yres; else sdfile->expected_size = -1; *len -= SDF_HEADER_SIZE_BIN; return TRUE; }
static gboolean mif_read_scan_setup(MIFScanSetup *setup, const guchar **p, gsize size, guint file_version, GError **error) { if (file_version >= 0x103 && file_version <= 0x107) { if (size < SCAN_SETUP_SIZE_1_2) return err_IMAGE_HEADER_TOO_SHORT(error); setup->xres = gwy_get_guint32_le(p); setup->yres = gwy_get_guint32_le(p); gwy_debug("xres: %u, yres: %u", setup->xres, setup->yres); setup->xreal = gwy_get_gdouble_le(p); setup->yreal = gwy_get_gdouble_le(p); gwy_debug("xreal: %g, yreal: %g", setup->xreal, setup->yreal); /* Use negated positive conditions to catch NaNs */ if (!((setup->xreal = fabs(setup->xreal)) > 0)) { g_warning("Real x size is 0.0, fixing to 1.0"); setup->xreal = 1.0; } if (!((setup->yreal = fabs(setup->yreal)) > 0)) { g_warning("Real y size is 0.0, fixing to 1.0"); setup->yreal = 1.0; } setup->xoff = gwy_get_gdouble_le(p); setup->yoff = gwy_get_gdouble_le(p); gwy_debug("xoff: %g, yoff: %g", setup->xoff, setup->yoff); setup->xscandir = gwy_get_gdouble_le(p); setup->yscandir = gwy_get_gdouble_le(p); gwy_debug("xscandir: %g, yscandir: %g", setup->xscandir, setup->yscandir); setup->scan_speed = gwy_get_gfloat_le(p); gwy_debug("scan_speed: %g", setup->scan_speed); setup->sample_pause = gwy_get_guint16_le(p); gwy_debug("sample_pause: %u", setup->sample_pause); setup->loop_gain = gwy_get_gfloat_le(p); gwy_debug("loop_gain: %g", setup->loop_gain); get_CHARARRAY(setup->loop_filter, p); gwy_debug_chars(setup, loop_filter); get_CHARARRAY(setup->lead_filter, p); gwy_debug_chars(setup, lead_filter); get_CHARARRAY(setup->lead_lag_mix, p); gwy_debug_chars(setup, lead_lag_mix); } else { g_return_val_if_reached(FALSE); } return TRUE; }
static gboolean rhk_sm4_read_string_data(RHKPage *page, const RHKObject *obj, guint count, const guchar *buffer) { const guchar *p; gchar *s; guint i, len; gwy_debug("count: %u, known strings: %u", count, RHK_STRING_NSTRINGS); count = MIN(count, RHK_STRING_NSTRINGS); p = buffer + obj->offset; for (i = 0; i < count; i++) { /* Not enough strings */ if (p - buffer + 2 > obj->offset + obj->size) return FALSE; len = gwy_get_guint16_le(&p); if (!len) continue; /* String does not fit */ if (p - buffer + 2*len > obj->offset + obj->size) return FALSE; s = page->strings[i] = g_new0(gchar, 6*len + 1); while (len--) s += g_unichar_to_utf8(gwy_get_guint16_le(&p), s); if (s != page->strings[i]) { gwy_debug("string[%u]: <%s>", i, page->strings[i]); } } return TRUE; }
static gboolean rhk_sm4_read_drift_header(RHKSpecDriftHeader *drift_header, const RHKObject *obj, const guchar *buffer) { const guchar *p = buffer + obj->offset; if (obj->size < 16) return FALSE; drift_header->start_time = gwy_get_guint64_le(&p); drift_header->drift_opt = gwy_get_gint16_le(&p); drift_header->nstrings = gwy_get_guint16_le(&p); /* TODO: Read the strings. */ return TRUE; }
static RHKSpecDriftHeader* rhk_sm4_read_drift_header(const RHKObject *obj, const guchar *buffer) { RHKSpecDriftHeader *drift_header = NULL; const guchar *p = buffer + obj->offset; if (obj->size < 16) return drift_header; drift_header = g_new0(RHKSpecDriftHeader, 1); drift_header->start_time = gwy_get_guint64_le(&p); drift_header->drift_opt = gwy_get_gint16_le(&p); drift_header->nstrings = gwy_get_guint16_le(&p); /* TODO: Read the strings. */ return drift_header; }
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 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* microprof_load(const gchar *filename, G_GNUC_UNUSED GwyRunType mode, GError **error) { enum { XRES = 0x0026, YRES = 0x002a, XRANGE = 0x0038, YRANGE = 0x0040, ZRANGE = 0x006e, }; GwyContainer *container = NULL; guchar *buffer = NULL; const guchar *p; MicroProfFile mfile; gsize size = 0; GError *err = NULL; guint i, ndata, datasize; if (!gwy_file_get_contents(filename, &buffer, &size, &err)) { err_GET_FILE_CONTENTS(error, &err); return NULL; } if (size < MICROPROF_HEADER_SIZE) { err_TOO_SHORT(error); goto fail; } if (memcmp(buffer, MAGIC, MAGIC_SIZE) != 0) { err_FILE_TYPE(error, "MicroProf"); goto fail; } p = buffer + XRES; mfile.xres = gwy_get_guint16_le(&p); if (err_DIMENSION(error, mfile.xres)) goto fail; p = buffer + YRES; mfile.yres = gwy_get_guint16_le(&p); if (err_DIMENSION(error, mfile.xres)) goto fail; p = buffer + XRANGE; mfile.xrange = gwy_get_gdouble_le(&p); if (!(mfile.xrange = fabs(mfile.xrange))) { g_warning("Real x size is 0.0, fixing to 1.0"); mfile.xrange = 1.0; } p = buffer + YRANGE; mfile.yrange = gwy_get_gdouble_le(&p); if (!(mfile.yrange = fabs(mfile.yrange))) { g_warning("Real y size is 0.0, fixing to 1.0"); mfile.yrange = 1.0; } p = buffer + ZRANGE; mfile.zscale = gwy_get_gdouble_le(&p); datasize = 2*mfile.xres*mfile.yres; if (err_SIZE_MISMATCH(error, datasize, size - MICROPROF_HEADER_SIZE, FALSE)) goto fail; /* FIXME: There is weird stuff between channels. Need specs. ndata = (size - MICROPROF_HEADER_SIZE)/datasize; if (!ndata) { err_NO_DATA(error); goto fail; } */ ndata = 1; container = gwy_container_new(); mfile.data = buffer + MICROPROF_HEADER_SIZE; for (i = 0; i < ndata; i++) { GwyDataField *dfield; GQuark quark; dfield = microprof_read_data_field(&mfile, mfile.data + i*datasize); quark = gwy_app_get_data_key_for_id(i); gwy_container_set_object(container, quark, dfield); g_object_unref(dfield); gwy_app_channel_title_fall_back(container, i); gwy_file_channel_import_log_add(container, i, NULL, filename); } fail: gwy_file_abandon_contents(buffer, size, NULL); return container; }
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 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 GwyContainer* aafm_load(const gchar *filename, G_GNUC_UNUSED GwyRunType mode, GError **error) { GwySIUnit *unit; GwyContainer *container = NULL; guchar *buffer = NULL; const guchar *p; gsize size = 0; GError *err = NULL; AFMFile afmfile; GwyDataField *dfield; gdouble min, max; if (!gwy_file_get_contents(filename, &buffer, &size, &err)) { err_GET_FILE_CONTENTS(error, &err); return NULL; } if (size < 12) { err_TOO_SHORT(error); gwy_file_abandon_contents(buffer, size, NULL); return NULL; } p = buffer; afmfile.res = gwy_get_guint16_le(&p); if (err_DIMENSION(error, afmfile.res)) { gwy_file_abandon_contents(buffer, size, NULL); return NULL; } if (err_SIZE_MISMATCH(error, afmfile.res * afmfile.res + 10, size, FALSE)) { gwy_file_abandon_contents(buffer, size, NULL); return NULL; } afmfile.real = Angstrom*gwy_get_gfloat_le(&p); if (!(afmfile.real = fabs(afmfile.real))) { g_warning("Real size is 0.0, fixing to 1.0"); afmfile.real = 1.0; } dfield = gwy_data_field_new(afmfile.res, afmfile.res, afmfile.real, afmfile.real, FALSE); read_binary_data(afmfile.res, gwy_data_field_get_data(dfield), p); p += 2*afmfile.res*afmfile.res; afmfile.range = gwy_get_gfloat_le(&p); gwy_data_field_get_min_max(dfield, &min, &max); if (min == max) gwy_data_field_clear(dfield); else gwy_data_field_multiply(dfield, afmfile.range/(max - min)*Angstrom); unit = gwy_si_unit_new("m"); gwy_data_field_set_si_unit_xy(dfield, unit); g_object_unref(unit); unit = gwy_si_unit_new("m"); gwy_data_field_set_si_unit_z(dfield, unit); g_object_unref(unit); container = gwy_container_new(); gwy_container_set_object_by_name(container, "/0/data", dfield); gwy_container_set_string_by_name(container, "/0/data/title", g_strdup("Topography")); g_object_unref(dfield); gwy_file_channel_import_log_add(container, 0, NULL, filename); gwy_file_abandon_contents(buffer, size, NULL); return container; }
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 gboolean rhk_sm4_read_page_header(RHKPage *page, const RHKObject *obj, const guchar *buffer, gsize size, GError **error) { const guchar *p; guint i; if (obj->size < PAGE_HEADER_SIZE) { err_OBJECT_TRUNCATED(error, RHK_OBJECT_PAGE_HEADER); return FALSE; } p = buffer + obj->offset; page->field_size = gwy_get_guint16_le(&p); if (obj->size < page->field_size) { err_OBJECT_TRUNCATED(error, RHK_OBJECT_PAGE_HEADER); return FALSE; } page->string_count = gwy_get_guint16_le(&p); gwy_debug("string_count = %u", page->string_count); page->page_type = gwy_get_guint32_le(&p); gwy_debug("page_type = %u", page->page_type); page->data_sub_source = gwy_get_guint32_le(&p); page->line_type = gwy_get_guint32_le(&p); page->x_coord = gwy_get_gint32_le(&p); page->y_coord = gwy_get_gint32_le(&p); gwy_debug("x_coord = %u, y_coord = %u", page->x_coord, page->y_coord); page->x_size = gwy_get_guint32_le(&p); page->y_size = gwy_get_guint32_le(&p); gwy_debug("x_size = %u, y_size = %u", page->x_size, page->y_size); if (err_DIMENSION(error, page->x_size) || err_DIMENSION(error, page->y_size)) return FALSE; page->image_type = gwy_get_guint32_le(&p); gwy_debug("image_type = %u", page->image_type); page->scan_dir = gwy_get_guint32_le(&p); gwy_debug("scan_dir = %u", page->scan_dir); page->group_id = gwy_get_guint32_le(&p); gwy_debug("group_id = 0x%08x", page->group_id); page->data_size = gwy_get_guint32_le(&p); gwy_debug("data_size = %u", page->data_size); page->min_z_value = gwy_get_gint32_le(&p); page->max_z_value = gwy_get_gint32_le(&p); gwy_debug("min,max_z_value = %d %d", page->min_z_value, page->max_z_value); page->x_scale = gwy_get_gfloat_le(&p); page->y_scale = gwy_get_gfloat_le(&p); page->z_scale = gwy_get_gfloat_le(&p); gwy_debug("x,y,z_scale = %g %g %g", page->x_scale, page->y_scale, page->z_scale); /* Use negated positive conditions to catch NaNs */ /* Must not take the absolute value here, spectra may have valid negative * scales. */ if (!(page->x_scale != 0)) { g_warning("Real x scale is 0.0, fixing to 1.0"); page->x_scale = 1.0; } if (!(page->y_scale != 0)) { g_warning("Real y scale is 0.0, fixing to 1.0"); page->y_scale = 1.0; } page->xy_scale = gwy_get_gfloat_le(&p); page->x_offset = gwy_get_gfloat_le(&p); page->y_offset = gwy_get_gfloat_le(&p); page->z_offset = gwy_get_gfloat_le(&p); gwy_debug("x,y,z_offset = %g %g %g", page->x_offset, page->y_offset, page->z_offset); page->period = gwy_get_gfloat_le(&p); page->bias = gwy_get_gfloat_le(&p); page->current = gwy_get_gfloat_le(&p); page->angle = gwy_get_gfloat_le(&p); gwy_debug("period = %g, bias = %g, current = %g, angle = %g", page->period, page->bias, page->current, page->angle); page->color_info_count = gwy_get_guint32_le(&p); gwy_debug("color_info_count = %u", page->color_info_count); page->grid_x_size = gwy_get_guint32_le(&p); page->grid_y_size = gwy_get_guint32_le(&p); gwy_debug("gird_x,y = %u %u", page->grid_x_size, page->grid_y_size); page->object_count = gwy_get_guint32_le(&p); for (i = 0; i < G_N_ELEMENTS(page->reserved); i++) page->reserved[i] = gwy_get_guint32_le(&p); if (!(page->objects = rhk_sm4_read_objects(buffer, p, size, page->object_count, RHK_OBJECT_PAGE_HEADER, error))) return FALSE; return TRUE; }
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 void jeol_read_image_header(const guchar *p, JEOLImageHeader *header) { p += TIFF_HEADER_SIZE; header->winspm_version = gwy_get_guint16_le(&p); gwy_debug("version: %u", header->winspm_version); p += 80; /* there isn't anything interesting in internal_filename_old */ header->xres = gwy_get_guint16_le(&p); header->yres = gwy_get_guint16_le(&p); header->xreal = gwy_get_gfloat_le(&p); header->yreal = gwy_get_gfloat_le(&p); gwy_debug("res: (%d,%d), real: (%g,%g)", header->xres, header->yres, header->xreal, header->yreal); header->z0 = gwy_get_gfloat_le(&p); header->z255 = gwy_get_gfloat_le(&p); header->adc_min = gwy_get_guint16_le(&p); header->adc_max = gwy_get_guint16_le(&p); header->initial_scan_scale = gwy_get_gfloat_le(&p); get_CHARARRAY0(header->internal_filename, &p); get_CHARARRAY0(header->info[0], &p); get_CHARARRAY0(header->info[1], &p); get_CHARARRAY0(header->info[2], &p); get_CHARARRAY0(header->info[3], &p); get_CHARARRAY0(header->info[4], &p); get_CHARARRAY(header->history, &p); header->has_current_info = gwy_get_guint16_le(&p); header->bias = gwy_get_gfloat_le(&p); gwy_debug("bias: %g", header->bias); header->reference_value = gwy_get_gfloat_le(&p); gwy_debug("reference_value: %g", header->reference_value); p += 2; /* reserved */ header->measurement_date.day = *(p++); header->measurement_date.month = *(p++); header->measurement_date.year_1980 = gwy_get_guint16_le(&p); header->measurement_date.weekday_sun = *(p++); header->save_date.day = *(p++); header->save_date.month = *(p++); header->save_date.year_1980 = gwy_get_guint16_le(&p); header->save_date.weekday_sun = *(p++); header->measurement_time.hour = *(p++); header->measurement_time.minute = *(p++); header->measurement_time.second= *(p++); header->measurement_time.second_100 = *(p++); header->save_time.hour = *(p++); header->save_time.minute = *(p++); header->save_time.second= *(p++); header->save_time.second_100 = *(p++); p += 0x100; /* lookup table */ header->fft_offset = gwy_get_guint32_le(&p); header->transform_off = gwy_get_guint16_le(&p); p += 8; /* extra */ header->compressed = gwy_get_gboolean8(&p); header->bpp = *(p++); gwy_debug("bpp: %d", header->bpp); header->cits_offset = gwy_get_guint32_le(&p); header->backscan_tip_voltage = gwy_get_gfloat_le(&p); header->sts_point_x = gwy_get_guint16_le(&p); header->sts_point_y = gwy_get_guint16_le(&p); p += 20; /* reserved */ header->tip_speed_x = gwy_get_gfloat_le(&p); header->tip_speed_y = gwy_get_gfloat_le(&p); p += 42; /* piezo_sensitivity */ header->spm_param.clock = gwy_get_gfloat_le(&p); header->spm_param.rotation = gwy_get_gfloat_le(&p); header->spm_param.feedback_filter = gwy_get_gfloat_le(&p); header->spm_param.present_filter = gwy_get_gfloat_le(&p); header->spm_param.head_amp_gain = gwy_get_gfloat_le(&p); header->spm_param.loop_gain = gwy_get_guint16_le(&p); header->spm_param.x_off = gwy_get_gfloat_le(&p); header->spm_param.y_off = gwy_get_gfloat_le(&p); header->spm_param.z_gain = gwy_get_gfloat_le(&p); header->spm_param.z_off = gwy_get_gfloat_le(&p); header->spm_param.o_gain = gwy_get_gfloat_le(&p); header->spm_param.o_off = gwy_get_gfloat_le(&p); gwy_debug("z_gain: %g o_gain: %g", header->spm_param.z_gain, header->spm_param.o_gain); header->spm_param.back_scan_bias = gwy_get_gfloat_le(&p); /* XXX: This does not match what the documentation says, there seems to be * a four-byte quantity missing between back_scan_bias and mode (the size * of SPM params struct is also 4 bytes shorter than the space alloted for * it). */ p += 4; /* whatever */ header->spm_param.mode = gwy_get_guint32_le(&p); gwy_debug("mode: %d", header->spm_param.mode); p += 2; /* reserved */ header->montage_offset = gwy_get_guint32_le(&p); get_CHARARRAY0(header->image_location, &p); p += 2*4; /* reserved */ header->spm_misc_param.dds_frequency = gwy_get_gfloat_le(&p); header->spm_misc_param.dds_low_filter = gwy_get_guint16_le(&p); header->spm_misc_param.dds_high_filter = gwy_get_guint16_le(&p); header->spm_misc_param.dds_center_filter = gwy_get_guint16_le(&p); header->spm_misc_param.dds_enable = gwy_get_guint16_le(&p); header->spm_misc_param.scan_filter = gwy_get_guint16_le(&p); header->spm_misc_param.afm_mode = gwy_get_guint32_le(&p); gwy_debug("afm_mode: 0x%x", header->spm_misc_param.afm_mode); header->spm_misc_param.slope_gain = gwy_get_guint32_le(&p); header->spm_misc_param.x_addition_signal = gwy_get_guint16_le(&p); header->spm_misc_param.y_addition_signal = gwy_get_guint16_le(&p); header->spm_misc_param.z_addition_signal = gwy_get_guint16_le(&p); header->spm_misc_param.bias_addition_signal = gwy_get_guint16_le(&p); header->spm_misc_param.active_dialog = gwy_get_guint32_le(&p); header->spm_misc_param.spm_mode = gwy_get_guint32_le(&p); gwy_debug("spm_mode: 0x%x", header->spm_misc_param.spm_mode); header->spm_misc_param.measurement_signal = gwy_get_guint32_le(&p); gwy_debug("signal: 0x%x", header->spm_misc_param.measurement_signal); header->spm_misc_param.phase_vco_scan = gwy_get_guint16_le(&p); header->spm_misc_param.sps_mode = gwy_get_guint32_le(&p); header->spm_misc_param.dds_amplitude = gwy_get_gdouble_le(&p); header->spm_misc_param.dds_center_locked_freq = gwy_get_gdouble_le(&p); header->spm_misc_param.dds_phase_shift = gwy_get_gfloat_le(&p); header->spm_misc_param.dds_high_gain = gwy_get_guint16_le(&p); header->spm_misc_param.dds_phase_polarity = gwy_get_guint16_le(&p); header->spm_misc_param.dds_pll_excitation = gwy_get_guint16_le(&p); header->spm_misc_param.dds_external = gwy_get_guint16_le(&p); header->spm_misc_param.dds_rms_filter = gwy_get_guint32_le(&p); header->spm_misc_param.dds_pll_loop_gain = gwy_get_guint32_le(&p); header->spm_misc_param.dds_beat_noise = gwy_get_guint32_le(&p); header->spm_misc_param.dds_dynamic_range = gwy_get_guint32_le(&p); header->spm_misc_param.cantilever_peak_freq = gwy_get_guint32_le(&p); header->spm_misc_param.cantilever_q_factor = gwy_get_guint32_le(&p); p += 10; /* reserved */ p += 0x300; /* RGB lookup table */ header->sub_revision_no = gwy_get_guint32_le(&p); header->image_type = gwy_get_guint32_le(&p); gwy_debug("image_type: %d", header->image_type); header->data_source = gwy_get_guint32_le(&p); gwy_debug("data_source: %d", header->data_source); header->display_mode = gwy_get_guint32_le(&p); p += 2*8; /* measurement_start_time, measurement_end_time */ p += 254; /* profile_roughness */ p += 446; /* settings_3d */ header->lut_brightness = gwy_get_gfloat_le(&p); header->lut_contrast = gwy_get_gfloat_le(&p); header->software_version = gwy_get_guint16_le(&p); header->software_subversion = gwy_get_guint32_le(&p); p += 20; /* extracted_region */ header->lut_gamma = gwy_get_gfloat_le(&p); header->n_of_sps = gwy_get_guint16_le(&p); header->sps_offset = gwy_get_guint32_le(&p); header->line_trace_end_x = gwy_get_guint16_le(&p); header->line_trace_end_y = gwy_get_guint16_le(&p); header->forward = gwy_get_guint16_le(&p); gwy_debug("forward: %d", header->forward); header->lift_signal = gwy_get_guint16_le(&p); /* stuff... */ }
static GwyContainer* apefile_load(const gchar *filename, G_GNUC_UNUSED GwyRunType mode, GError **error) { APEFile apefile; GwyContainer *meta, *container = NULL; guchar *buffer = NULL; const guchar *p; gsize size = 0; GError *err = NULL; GwyDataField *dfield = NULL; guint b, i, n; if (!gwy_file_get_contents(filename, &buffer, &size, &err)) { err_GET_FILE_CONTENTS(error, &err); return NULL; } p = buffer; apefile.version = *(p++); if (size < 1294) { err_TOO_SHORT(error); gwy_file_abandon_contents(buffer, size, NULL); return NULL; } apefile.spm_mode = *(p++); p += 2; /* Skip VisualBasic VARIANT type type */ apefile.scan_date = gwy_get_gdouble_le(&p); apefile.maxr_x = gwy_get_gfloat_le(&p); apefile.maxr_y = gwy_get_gfloat_le(&p); apefile.x_offset = gwy_get_guint32_le(&p); apefile.y_offset = gwy_get_guint32_le(&p); apefile.size_flag = gwy_get_guint16_le(&p); apefile.res = 16 << apefile.size_flag; if (err_DIMENSION(error, apefile.res)) { gwy_file_abandon_contents(buffer, size, NULL); return NULL; } apefile.acquire_delay = gwy_get_gfloat_le(&p); apefile.raster_delay = gwy_get_gfloat_le(&p); apefile.tip_dist = gwy_get_gfloat_le(&p); apefile.v_ref = gwy_get_gfloat_le(&p); if (apefile.version == 1) { apefile.vpmt1 = gwy_get_guint16_le(&p); apefile.vpmt2 = gwy_get_guint16_le(&p); } else { apefile.vpmt1 = gwy_get_gfloat_le(&p); apefile.vpmt2 = gwy_get_gfloat_le(&p); } apefile.remark = g_strndup(p, 120); p += 120; apefile.x_piezo_factor = gwy_get_guint32_le(&p); apefile.y_piezo_factor = gwy_get_guint32_le(&p); apefile.z_piezo_factor = gwy_get_guint32_le(&p); apefile.hv_gain = gwy_get_gfloat_le(&p); apefile.freq_osc_tip = gwy_get_gdouble_le(&p); apefile.rotate = gwy_get_gfloat_le(&p); apefile.slope_x = gwy_get_gfloat_le(&p); apefile.slope_y = gwy_get_gfloat_le(&p); apefile.topo_means = gwy_get_guint16_le(&p); apefile.optical_means = gwy_get_guint16_le(&p); apefile.error_means = gwy_get_guint16_le(&p); /* g_printerr("%04x %04x %04x\n", apefile.topo_means, apefile.optical_means, apefile.error_means); */ apefile.channels = gwy_get_guint32_le(&p); apefile.ndata = 0; for (b = apefile.channels; b; b = b >> 1) apefile.ndata += (b & 1); apefile.range_x = gwy_get_gfloat_le(&p); apefile.range_y = gwy_get_gfloat_le(&p); apefile.subversion = gwy_get_guint16_le(&p); /* Read everything since the header is long enough, check the version * later when we decide whether to use these values or not. */ /* Since 2.1 */ apefile.hv_gain_z = gwy_get_gfloat_le(&p); /* Since 2.2 */ apefile.fast2_0 = gwy_get_gdouble_le(&p); apefile.fast2_1 = gwy_get_gdouble_le(&p); apefile.fast2_2 = gwy_get_gdouble_le(&p); apefile.fast2_3 = gwy_get_gdouble_le(&p); /* Since 2.3 */ apefile.pg850_image = !!gwy_get_guint16_le(&p); /* Since 2.4 */ apefile.xy_hv_status = gwy_get_gint16_le(&p); apefile.z_hv_status = gwy_get_gint16_le(&p); /* reserved */ p += 2; apefile.xreal = apefile.maxr_x * apefile.x_piezo_factor * apefile.range_x * apefile.hv_gain/65535.0 * 1e-9; apefile.yreal = apefile.maxr_y * apefile.y_piezo_factor * apefile.range_y * apefile.hv_gain/65535.0 * 1e-9; /* Use negated positive conditions to catch NaNs */ if (!((apefile.xreal = fabs(apefile.xreal)) > 0)) { g_warning("Real x size is 0.0, fixing to 1.0"); apefile.xreal = 1.0; } if (!((apefile.yreal = fabs(apefile.yreal)) > 0)) { g_warning("Real y size is 0.0, fixing to 1.0"); apefile.yreal = 1.0; } gwy_debug("version = %u.%u, spm_mode = %u", apefile.version, apefile.subversion, apefile.spm_mode); gwy_debug("scan_date = %f", apefile.scan_date); gwy_debug("maxr_x = %g, maxr_y = %g", apefile.maxr_x, apefile.maxr_y); gwy_debug("x_offset = %u, y_offset = %u", apefile.x_offset, apefile.y_offset); gwy_debug("size_flag = %u", apefile.size_flag); gwy_debug("acquire_delay = %g, raster_delay = %g, tip_dist = %g", apefile.acquire_delay, apefile.raster_delay, apefile.tip_dist); gwy_debug("v_ref = %g, vpmt1 = %g, vpmt2 = %g", apefile.v_ref, apefile.vpmt1, apefile.vpmt2); gwy_debug("x_piezo_factor = %u, y_piezo_factor = %u, z_piezo_factor = %u", apefile.x_piezo_factor, apefile.y_piezo_factor, apefile.z_piezo_factor); gwy_debug("hv_gain = %g, freq_osc_tip = %g, rotate = %g", apefile.hv_gain, apefile.freq_osc_tip, apefile.rotate); gwy_debug("slope_x = %g, slope_y = %g", apefile.slope_x, apefile.slope_y); gwy_debug("topo_means = %u, optical_means = %u, error_means = %u", apefile.topo_means, apefile.optical_means, apefile.error_means); gwy_debug("channel bitmask = %03x, ndata = %u", apefile.channels, apefile.ndata); gwy_debug("range_x = %g, range_y = %g", apefile.range_x, apefile.range_y); n = (apefile.res + 1)*(apefile.res + 1)*sizeof(float); if (size - (p - buffer) != n*apefile.ndata) { g_warning("Expected data size %u, but it's %u.", n*apefile.ndata, (guint)(size - (p - buffer))); apefile.ndata = MIN(apefile.ndata, (size - (p - buffer))/n); } if (!apefile.ndata) { err_NO_DATA(error); gwy_file_abandon_contents(buffer, size, NULL); return NULL; } fill_data_fields(&apefile, p); gwy_file_abandon_contents(buffer, size, NULL); container = gwy_container_new(); /* All metadata seems to be per-file (global) */ meta = apefile_get_metadata(&apefile); for (b = apefile.channels, n = 0, i = 0; b; b = b >> 1, i++) { GwyContainer *tmp; gchar *title; gchar key[32]; if (!(b & 1)) continue; g_snprintf(key, sizeof(key), "/%d/data", n); dfield = apefile.data[n]; gwy_container_set_object_by_name(container, key, dfield); g_object_unref(apefile.data[n]); g_snprintf(key, sizeof(key), "/%d/data/title", n); /* * Channel labelling based on SPM Mode */ switch (apefile.spm_mode) { case SPM_MODE_SNOM: title = gwy_enuml_to_string(i, "Height", APE_HEIGHT, "Height-R", APE_HEIGHT_R, "NSOM", APE_NSOM, "NSOM-R", APE_NSOM_R, "Error", APE_ERROR, "Error-R", APE_ERROR_R, "NSOM2", APE_NSOM2, "NSOM2-R", APE_NSOM2_R, "Lateral", APE_AUX1, "Z-Z0", APE_AUX2, "Lateral-R", APE_AUX1_R, "Z-Z0-R", APE_AUX2_R, NULL); break; case SPM_MODE_AFM_NONCONTACT: case SPM_MODE_AFM_CONTACT: case SPM_MODE_PHASE_DETECT_AFM: title = gwy_enuml_to_string(i, "Height", APE_HEIGHT, "Height-R", APE_HEIGHT_R, "IN1", APE_NSOM, "IN1-R", APE_NSOM_R, "Error", APE_ERROR, "Error-R", APE_ERROR_R, "IN2", APE_NSOM2, "IN2-R", APE_NSOM2_R, "Lateral", APE_AUX1, "Z-Z0", APE_AUX2, "Lateral-R", APE_AUX1_R, "Z-Z0-R", APE_AUX2_R, NULL); break; default: title = gwy_enuml_to_string(i, "Height", APE_HEIGHT, "Height-R", APE_HEIGHT_R, "IN1", APE_NSOM, "IN1-R", APE_NSOM_R, "Error", APE_ERROR, "Error-R", APE_ERROR_R, "IN2", APE_NSOM2, "IN2-R", APE_NSOM2_R, "Aux1", APE_AUX1, "Z-Z0", APE_AUX2, "Aux1-R", APE_AUX1_R, "Z-Z0-R", APE_AUX2_R, NULL); break; } if (title && *title) gwy_container_set_string_by_name(container, key, g_strdup(title)); tmp = gwy_container_duplicate(meta); g_snprintf(key, sizeof(key), "/%d/meta", n); gwy_container_set_object_by_name(container, key, tmp); g_object_unref(tmp); gwy_file_channel_import_log_add(container, n, NULL, filename); n++; } g_object_unref(meta); g_free(apefile.remark); return container; }
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; }
/* Reads @header and initializes @reader for the correct byte order. Returns * the number of bytes read, 0 on error. */ static guint igor_read_headers(IgorFile *igorfile, const guchar *buffer, gsize size, gboolean check_only, GError **error) { IgorBinHeader *header; gsize headers_size; guint version, chksum, i; gboolean lsb; const guchar *p = buffer; if (size < HEADER_SIZE1) { err_TOO_SHORT(error); return 0; } /* The lower byte of version is nonzero. Use it to detect endianess. */ version = gwy_get_guint16_le(&p); gwy_debug("raw version: 0x%04x", version); /* Keep the rejection code path fast by performing version sanity check * as the very first thing. */ if ((lsb = (version & 0xff))) { gwy_debug("little endian"); } else { gwy_debug("big endian"); version /= 0x100; } /* Check if version is known and the buffer size */ if (version == 1) headers_size = HEADER_SIZE1 + WAVE_SIZE2; else if (version == 2) headers_size = HEADER_SIZE2 + WAVE_SIZE2; else if (version == 3) headers_size = HEADER_SIZE3 + WAVE_SIZE2; else if (version == 5) headers_size = HEADER_SIZE5 + WAVE_SIZE5; else { err_FILE_TYPE(error, "IGOR Pro"); return 0; } gwy_debug("expected headers_size %lu", (gulong)headers_size); if (size < headers_size) { err_TOO_SHORT(error); return 0; } /* Check the checksum */ chksum = igor_checksum(buffer, headers_size, lsb); gwy_debug("checksum %u", chksum); if (chksum) { err_FILE_TYPE(error, "IGOR Pro"); return 0; } /* If only detection is required, we can stop now. */ if (check_only) return headers_size; /* If the checksum is correct the file is likely IGOR file and we can * start the expensive actions. */ gwy_clear(igorfile, 1); header = &igorfile->header; header->version = version; igorfile->headers_size = headers_size; gwy_debug("format version: %u", header->version); if (lsb) { igorfile->get_guint16 = gwy_get_guint16_le; igorfile->get_gint16 = gwy_get_gint16_le; igorfile->get_guint32 = gwy_get_guint32_le; igorfile->get_gint32 = gwy_get_gint32_le; igorfile->get_gfloat = gwy_get_gfloat_le; igorfile->get_gdouble = gwy_get_gdouble_le; } else { igorfile->get_guint16 = gwy_get_guint16_be; igorfile->get_gint16 = gwy_get_gint16_be; igorfile->get_guint32 = gwy_get_guint32_be; igorfile->get_gint32 = gwy_get_gint32_be; igorfile->get_gfloat = gwy_get_gfloat_be; igorfile->get_gdouble = gwy_get_gdouble_be; } /* Read the rest of the binary header */ if (header->version == 1) { igorfile->wave_header_size = 110; header->wfm_size = igorfile->get_guint32(&p); header->checksum = igorfile->get_guint16(&p); } else if (header->version == 2) { igorfile->wave_header_size = 110; header->wfm_size = igorfile->get_guint32(&p); header->note_size = igorfile->get_guint32(&p); header->pict_size = igorfile->get_guint32(&p); header->checksum = igorfile->get_guint16(&p); } else if (header->version == 3) { igorfile->wave_header_size = 110; header->wfm_size = igorfile->get_guint32(&p); header->note_size = igorfile->get_guint32(&p); header->formula_size = igorfile->get_guint32(&p); header->pict_size = igorfile->get_guint32(&p); header->checksum = igorfile->get_guint16(&p); } else if (header->version == 5) { igorfile->wave_header_size = 320; header->checksum = igorfile->get_guint16(&p); header->wfm_size = igorfile->get_guint32(&p); header->formula_size = igorfile->get_guint32(&p); gwy_debug("formula_size: %u", header->formula_size); header->note_size = igorfile->get_guint32(&p); gwy_debug("note_size: %u", header->note_size); header->data_e_units_size = igorfile->get_guint32(&p); gwy_debug("data_e_units_size: %u", header->data_e_units_size); for (i = 0; i < MAXDIMS; i++) { header->dim_e_units_size[i] = igorfile->get_guint32(&p); gwy_debug("dim_e_units_size[%u]: %u", i, header->dim_e_units_size[i]); } for (i = 0; i < MAXDIMS; i++) { header->dim_labels_size[i] = igorfile->get_guint32(&p); gwy_debug("dim_labels_size[%u]: %u", i, header->dim_labels_size[i]); } header->indices_size = igorfile->get_guint32(&p); header->options_size1 = igorfile->get_guint32(&p); header->options_size2 = igorfile->get_guint32(&p); } else { g_assert_not_reached(); } gwy_debug("wfm_size: %u", header->wfm_size); /* Read the wave header */ if (version == 5) { IgorWaveHeader5 *wave5 = &igorfile->wave5; wave5->next = igorfile->get_guint32(&p); wave5->creation_date = igorfile->get_guint32(&p); wave5->mod_date = igorfile->get_guint32(&p); wave5->npts = igorfile->get_guint32(&p); wave5->type = igorfile->get_guint16(&p); gwy_debug("type: %u, npts: %u", wave5->type, wave5->npts); wave5->lock = igorfile->get_guint16(&p); get_CHARARRAY(wave5->whpad1, &p); wave5->wh_version = igorfile->get_guint16(&p); get_CHARARRAY0(wave5->bname, &p); wave5->whpad2 = igorfile->get_guint32(&p); wave5->dfolder = igorfile->get_guint32(&p); for (i = 0; i < MAXDIMS; i++) { wave5->n_dim[i] = igorfile->get_guint32(&p); gwy_debug("n_dim[%u]: %u", i, wave5->n_dim[i]); } for (i = 0; i < MAXDIMS; i++) wave5->sfA[i] = igorfile->get_gdouble(&p); for (i = 0; i < MAXDIMS; i++) wave5->sfB[i] = igorfile->get_gdouble(&p); get_CHARARRAY0(wave5->data_units, &p); gwy_debug("data_units: <%s>", wave5->data_units); for (i = 0; i < MAXDIMS; i++) { get_CHARARRAY0(wave5->dim_units[i], &p); gwy_debug("dim_units[%u]: <%s>", i, wave5->dim_units[i]); } wave5->fs_valid = !!igorfile->get_guint16(&p); wave5->whpad3 = igorfile->get_guint16(&p); wave5->top_full_scale = igorfile->get_gdouble(&p); wave5->bot_full_scale = igorfile->get_gdouble(&p); } return headers_size; }