static void parse_trestle_image_description(openslide_t *osr, const char *description, int32_t *overlap_count_OUT, int32_t **overlaps_OUT) { char **first_pass = g_strsplit(description, ";", -1); int32_t overlap_count = 0; int32_t *overlaps = NULL; if (osr) { add_properties(osr->properties, first_pass); } for (char **cur_str = first_pass; *cur_str != NULL; cur_str++) { //g_debug(" XX: %s", *cur_str); if (g_str_has_prefix(*cur_str, OVERLAPS_XY)) { // found it char **second_pass = g_strsplit(*cur_str, " ", -1); overlap_count = g_strv_length(second_pass) - 1; // skip fieldname overlaps = g_new(int32_t, overlap_count); int i = 0; // skip fieldname for (char **cur_str2 = second_pass + 1; *cur_str2 != NULL; cur_str2++) { overlaps[i] = g_ascii_strtoull(*cur_str2, NULL, 10); i++; } g_strfreev(second_pass); } else if (g_str_has_prefix(*cur_str, BACKGROUND_COLOR)) { // found background color errno = 0; uint64_t bg = g_ascii_strtoull((*cur_str) + strlen(BACKGROUND_COLOR), NULL, 16); if (bg || !errno) { if (osr) { _openslide_set_background_color_property(osr->properties, (bg >> 16) & 0xFF, (bg >> 8) & 0xFF, bg & 0xFF); } } } }
/** * @inheritDoc */ void PlayerInputObject::createShot(void) { Proto::Object shotProto; shotProto.set_id(ObjectId::gen().str()); shotProto.set_name("Shot"); shotProto.set_template_("ShotTemplate"); auto physicSystemObject = shotProto.add_systemobjects(); physicSystemObject->set_systemtype(Proto::SystemType::Physic); physicSystemObject->set_type("Movable"); auto positionProperty = physicSystemObject->add_properties(); positionProperty->set_name("Position"); getVector3(&m_position, positionProperty->mutable_value()); auto orientationProperty = physicSystemObject->add_properties(); orientationProperty->set_name("Orientation"); getQuaternion(&m_orientation, orientationProperty->mutable_value()); auto networkSystemObject = shotProto.add_systemobjects(); networkSystemObject->set_systemtype(Proto::SystemType::Network); networkSystemObject->set_type("Replicable"); m_createObjectQueue->push_back(shotProto); PostChanges(System::Changes::Generic::CreateObject); }
bool _openslide_try_trestle(openslide_t *osr, TIFF *tiff, struct _openslide_hash *quickhash1) { int32_t overlap_count = 0; int32_t *overlaps = NULL; int32_t layer_count = 0; int32_t *layers = NULL; if (!TIFFIsTiled(tiff)) { goto FAIL; } char *tagval; int tiff_result; tiff_result = TIFFGetField(tiff, TIFFTAG_SOFTWARE, &tagval); if (!tiff_result || (strncmp(TRESTLE_SOFTWARE, tagval, strlen(TRESTLE_SOFTWARE)) != 0)) { // not trestle goto FAIL; } // parse tiff_result = TIFFGetField(tiff, TIFFTAG_IMAGEDESCRIPTION, &tagval); if (!tiff_result) { // no description, not trestle goto FAIL; } char **first_pass = g_strsplit(tagval, ";", -1); if (osr) { add_properties(osr->properties, first_pass); } for (char **cur_str = first_pass; *cur_str != NULL; cur_str++) { //g_debug(" XX: %s", *cur_str); if (g_str_has_prefix(*cur_str, OVERLAPS_XY)) { // found it char **second_pass = g_strsplit(*cur_str, " ", -1); overlap_count = g_strv_length(second_pass) - 1; // skip fieldname overlaps = g_new(int32_t, overlap_count); int i = 0; // skip fieldname for (char **cur_str2 = second_pass + 1; *cur_str2 != NULL; cur_str2++) { overlaps[i] = g_ascii_strtoull(*cur_str2, NULL, 10); i++; } g_strfreev(second_pass); } else if (g_str_has_prefix(*cur_str, BACKGROUND_COLOR)) { // found background color errno = 0; uint64_t bg = g_ascii_strtoull((*cur_str) + strlen(BACKGROUND_COLOR), NULL, 16); if (bg || !errno) { if (osr) { _openslide_set_background_color_property(osr->properties, (bg >> 16) & 0xFF, (bg >> 8) & 0xFF, bg & 0xFF); } } } }
bool _openslide_try_hamamatsu(openslide_t *osr, const char *filename, struct _openslide_hash *quickhash1, GError **err) { // initialize any variables destroyed/used in DONE bool success = false; char *dirname = g_path_get_dirname(filename); int num_images = 0; char **image_filenames = NULL; int num_cols = -1; int num_rows = -1; char **all_keys = NULL; int num_layers = -1; // first, see if it's a VMS/VMU file GKeyFile *key_file = g_key_file_new(); if (!_openslide_read_key_file(key_file, filename, G_KEY_FILE_NONE, NULL)) { g_set_error(err, OPENSLIDE_ERROR, OPENSLIDE_ERROR_FORMAT_NOT_SUPPORTED, "Can't load key file"); goto DONE; } // select group or fail, then read dimensions const char *groupname; if (g_key_file_has_group(key_file, GROUP_VMS)) { groupname = GROUP_VMS; num_cols = g_key_file_get_integer(key_file, groupname, KEY_NUM_JPEG_COLS, NULL); num_rows = g_key_file_get_integer(key_file, groupname, KEY_NUM_JPEG_ROWS, NULL); } else if (g_key_file_has_group(key_file, GROUP_VMU)) { groupname = GROUP_VMU; num_cols = 1; // not specified in file for VMU num_rows = 1; } else { g_set_error(err, OPENSLIDE_ERROR, OPENSLIDE_ERROR_FORMAT_NOT_SUPPORTED, "Not VMS or VMU file"); goto DONE; } // validate cols/rows if (num_cols < 1) { g_set_error(err, OPENSLIDE_ERROR, OPENSLIDE_ERROR_FORMAT_NOT_SUPPORTED, "File has no columns"); goto DONE; } if (num_rows < 1) { g_set_error(err, OPENSLIDE_ERROR, OPENSLIDE_ERROR_FORMAT_NOT_SUPPORTED, "File has no rows"); goto DONE; } // init the image filenames // this format has cols*rows image files, plus the map num_images = (num_cols * num_rows) + 1; image_filenames = g_new0(char *, num_images); // hash in the key file if (!_openslide_hash_file(quickhash1, filename, err)) { goto DONE; } // make sure values are within known bounds num_layers = g_key_file_get_integer(key_file, groupname, KEY_NUM_LAYERS, NULL); if (num_layers < 1) { g_set_error(err, OPENSLIDE_ERROR, OPENSLIDE_ERROR_BAD_DATA, "Cannot handle Hamamatsu files with NoLayers < 1"); goto DONE; } // add properties if (osr) { add_properties(osr->properties, key_file, groupname); } // extract MapFile char *tmp; tmp = g_key_file_get_string(key_file, groupname, KEY_MAP_FILE, NULL); if (tmp) { char *map_filename = g_build_filename(dirname, tmp, NULL); g_free(tmp); image_filenames[num_images - 1] = map_filename; // hash in the map file if (!_openslide_hash_file(quickhash1, map_filename, err)) { goto DONE; } } else { g_set_error(err, OPENSLIDE_ERROR, OPENSLIDE_ERROR_BAD_DATA, "Can't read map file"); goto DONE; } // now each ImageFile all_keys = g_key_file_get_keys(key_file, groupname, NULL, NULL); for (char **tmp = all_keys; *tmp != NULL; tmp++) { char *key = *tmp; char *value = g_key_file_get_string(key_file, groupname, key, NULL); // g_debug("%s", key); if (strncmp(KEY_IMAGE_FILE, key, strlen(KEY_IMAGE_FILE)) == 0) { // starts with ImageFile char *suffix = key + strlen(KEY_IMAGE_FILE); int layer; int col; int row; char **split = g_strsplit(suffix, ",", 0); switch (g_strv_length(split)) { case 0: // all zero layer = 0; col = 0; row = 0; break; case 1: // (z) // first item, skip '(' layer = g_ascii_strtoll(split[0] + 1, NULL, 10); col = 0; row = 0; break; case 2: // (x,y) layer = 0; // first item, skip '(' col = g_ascii_strtoll(split[0] + 1, NULL, 10); row = g_ascii_strtoll(split[1], NULL, 10); break; case 3: // (z,x,y) // first item, skip '(' layer = g_ascii_strtoll(split[0] + 1, NULL, 10); col = g_ascii_strtoll(split[1], NULL, 10); row = g_ascii_strtoll(split[2], NULL, 10); break; default: // we just don't know g_set_error(err, OPENSLIDE_ERROR, OPENSLIDE_ERROR_BAD_DATA, "Unknown number of image dimensions: %d", g_strv_length(split)); g_free(value); g_strfreev(split); g_strfreev(all_keys); goto DONE; } g_strfreev(split); //g_debug("layer: %d, col: %d, row: %d", layer, col, row); if (layer != 0) { // skip non-zero layers for now g_free(value); continue; } if (col >= num_cols || row >= num_rows || col < 0 || row < 0) { g_set_error(err, OPENSLIDE_ERROR, OPENSLIDE_ERROR_BAD_DATA, "Invalid row or column in Hamamatsu file (%d,%d)", col, row); g_free(value); g_strfreev(all_keys); goto DONE; } // compute index from x,y int i = row * num_cols + col; // init the file if (image_filenames[i]) { g_set_error(err, OPENSLIDE_ERROR, OPENSLIDE_ERROR_BAD_DATA, "Duplicate image for (%d,%d)", col, row); g_free(value); g_strfreev(all_keys); goto DONE; } image_filenames[i] = g_build_filename(dirname, value, NULL); } g_free(value); } g_strfreev(all_keys); // ensure all image filenames are filled for (int i = 0; i < num_images; i++) { if (!image_filenames[i]) { g_set_error(err, OPENSLIDE_ERROR, OPENSLIDE_ERROR_BAD_DATA, "Can't read image filename %d", i); goto DONE; } } // add macro image tmp = g_key_file_get_string(key_file, groupname, KEY_MACRO_IMAGE, NULL); if (tmp) { char *macro_filename = g_build_filename(dirname, tmp, NULL); bool result = _openslide_add_jpeg_associated_image(osr ? osr->associated_images : NULL, "macro", macro_filename, 0, err); g_free(macro_filename); g_free(tmp); if (!result) { g_prefix_error(err, "Could not read macro image: "); goto DONE; } } // finalize depending on what format if (groupname == GROUP_VMS) { // open OptimisationFile FILE *optimisation_file = NULL; char *tmp = g_key_file_get_string(key_file, GROUP_VMS, KEY_OPTIMISATION_FILE, NULL); if (tmp) { char *optimisation_filename = g_build_filename(dirname, tmp, NULL); g_free(tmp); optimisation_file = _openslide_fopen(optimisation_filename, "rb", NULL); if (optimisation_file == NULL) { // g_debug("Can't open optimisation file"); } g_free(optimisation_filename); } else { // g_debug("Optimisation file key not present"); } // do all the jpeg stuff success = hamamatsu_vms_part2(osr, num_images, image_filenames, num_cols, optimisation_file, err); // clean up if (optimisation_file) { fclose(optimisation_file); } } else if (groupname == GROUP_VMU) { // verify a few assumptions for VMU int bits_per_pixel = g_key_file_get_integer(key_file, GROUP_VMU, KEY_BITS_PER_PIXEL, NULL); char *pixel_order = g_key_file_get_string(key_file, GROUP_VMU, KEY_PIXEL_ORDER, NULL); if (bits_per_pixel != 36) { g_set_error(err, OPENSLIDE_ERROR, OPENSLIDE_ERROR_BAD_DATA, "%s must be 36", KEY_BITS_PER_PIXEL); } else if (!pixel_order || (strcmp(pixel_order, "RGB") != 0)) { g_set_error(err, OPENSLIDE_ERROR, OPENSLIDE_ERROR_BAD_DATA, "%s must be RGB", KEY_PIXEL_ORDER); } else { // assumptions verified success = hamamatsu_vmu_part2(osr, num_images, image_filenames, err); } g_free(pixel_order); } else { g_assert_not_reached(); } DONE: g_free(dirname); if (image_filenames) { for (int i = 0; i < num_images; i++) { g_free(image_filenames[i]); } g_free(image_filenames); } g_key_file_free(key_file); return success; }
bool _openslide_try_hamamatsu_ndpi(openslide_t *osr, const char *filename, struct _openslide_hash *quickhash1, GError **err) { bool success = false; char *image_filenames = NULL; char *dirname = g_path_get_dirname(filename); image_filenames = g_new0(char, 1); image_filenames = g_build_filename(dirname, filename, NULL); FILE *f = _openslide_fopen(image_filenames, "rb", NULL); if (!f) { g_set_error(err, OPENSLIDE_ERROR, OPENSLIDE_ERROR_FORMAT_NOT_SUPPORTED, "Can't open file"); return false; } //dump data from NDPI file. from this function, we get all information about //NDPI file (number of image, size of image, offset, etc) GSList *dump = _openslide_tiffdump_create(f, err); if (!dump) { fclose(f); return false; } fclose(f); const char *groupname = GROUP_VMS; GKeyFile *key_file = g_key_file_new(); //NDPI file dont have key file. So, I am create the key using this method //but, the problem is I can not show the property using : //openslide_get_property_names(osr) //are you know why? g_key_file_set_string(key_file, groupname, "ImageFile", image_filenames); //I dont get information about number of layers from NDPI file. //So, I set this num_layers to 1 int num_layers = 1; g_key_file_set_integer(key_file, groupname, "NoLayers", num_layers); //create NDPI key from from dump variable //create key_file from this GSList. //We will get some of image from NDPI file with jpeg format //I save the count number of all jpeg image in "num_images" variable //some of the jpeg file dont have complete header (dont have restart marker offset) //"num_jpegs" is total number of jpeg with complete header int num_images; //the total number of jpegs images int num_jpegs; //the total number of jpegs with complete header //I am still confused how to create index name from extracted //NDPI file. So, I am create a file with symbols [%]. //please check this function ndpi_create_key_file(dump, key_file, groupname, &num_images, &num_jpegs); //I dont get information about num_cols and num_rows //So, I set this "num_cols" variable like this int num_cols; if(num_jpegs>1) num_cols = 2; else num_cols = 1; // add properties if (osr) { add_properties(osr->properties, key_file, groupname); } //I am not yet add the macros file //we can get the macros file from key_file success = hamamatsu_ndpi_part2(osr, num_jpegs, image_filenames, num_cols, key_file, err); _openslide_tiffdump_destroy(dump); g_key_file_free(key_file); return success; }
bool _openslide_try_aperio(openslide_t *osr, TIFF *tiff, struct _openslide_hash *quickhash1, GError **err) { int32_t level_count = 0; int32_t *levels = NULL; int32_t i = 0; if (!TIFFIsTiled(tiff)) { g_set_error(err, OPENSLIDE_ERROR, OPENSLIDE_ERROR_FORMAT_NOT_SUPPORTED, "TIFF is not tiled"); goto FAIL; } char *tagval; int tiff_result; tiff_result = TIFFGetField(tiff, TIFFTAG_IMAGEDESCRIPTION, &tagval); if (!tiff_result || (strncmp(APERIO_DESCRIPTION, tagval, strlen(APERIO_DESCRIPTION)) != 0)) { g_set_error(err, OPENSLIDE_ERROR, OPENSLIDE_ERROR_FORMAT_NOT_SUPPORTED, "Not an Aperio slide"); goto FAIL; } /* * http://www.aperio.com/documents/api/Aperio_Digital_Slides_and_Third-party_data_interchange.pdf * page 14: * * The first image in an SVS file is always the baseline image (full * resolution). This image is always tiled, usually with a tile size * of 240 x 240 pixels. The second image is always a thumbnail, * typically with dimensions of about 1024 x 768 pixels. Unlike the * other slide images, the thumbnail image is always * stripped. Following the thumbnail there may be one or more * intermediate "pyramid" images. These are always compressed with * the same type of compression as the baseline image, and have a * tiled organization with the same tile size. * * Optionally at the end of an SVS file there may be a slide label * image, which is a low resolution picture taken of the slide’s * label, and/or a macro camera image, which is a low resolution * picture taken of the entire slide. The label and macro images are * always stripped. */ // for aperio, the tiled directories are the ones we want do { if (TIFFIsTiled(tiff)) { level_count++; } } while (TIFFReadDirectory(tiff)); levels = g_new(int32_t, level_count); TIFFSetDirectory(tiff, 0); i = 0; do { tdir_t dir = TIFFCurrentDirectory(tiff); if (TIFFIsTiled(tiff)) { levels[i++] = dir; //g_debug("tiled directory: %d", dir); } else { // associated image const char *name = (dir == 1) ? "thumbnail" : NULL; if (!add_associated_image(osr ? osr->associated_images : NULL, name, tiff, err)) { g_prefix_error(err, "Can't read associated image: "); goto FAIL; } //g_debug("associated image: %d", dir); } // check depth uint32_t depth; tiff_result = TIFFGetField(tiff, TIFFTAG_IMAGEDEPTH, &depth); if (tiff_result && depth != 1) { // we can't handle depth != 1 g_set_error(err, OPENSLIDE_ERROR, OPENSLIDE_ERROR_BAD_DATA, "Cannot handle ImageDepth=%d", depth); goto FAIL; } // check compression uint16_t compression; if (!TIFFGetField(tiff, TIFFTAG_COMPRESSION, &compression)) { g_set_error(err, OPENSLIDE_ERROR, OPENSLIDE_ERROR_BAD_DATA, "Can't read compression scheme"); goto FAIL; } if ((compression != APERIO_COMPRESSION_JP2K_YCBCR) && (compression != APERIO_COMPRESSION_JP2K_RGB) && !TIFFIsCODECConfigured(compression)) { g_set_error(err, OPENSLIDE_ERROR, OPENSLIDE_ERROR_BAD_DATA, "Unsupported TIFF compression: %u", compression); goto FAIL; } } while (TIFFReadDirectory(tiff)); // read properties if (osr) { TIFFSetDirectory(tiff, 0); TIFFGetField(tiff, TIFFTAG_IMAGEDESCRIPTION, &tagval); // XXX? should be safe, we just did it char **props = g_strsplit(tagval, "|", -1); add_properties(osr->properties, props); g_strfreev(props); } // special jpeg 2000 aperio thing (with fallback) _openslide_add_tiff_ops(osr, tiff, 0, 0, NULL, level_count, levels, aperio_tiff_tilereader, quickhash1); return true; FAIL: g_free(levels); return false; }
int add_udi(LibHalContext *hal_ctx, char *arg) { DBusError error; dbus_bool_t dev_exists = FALSE; char *udi = NULL, buf[1024]; lh_prop_t *prop; int err; if (!arg) return 21; if (*arg == '/') { udi = arg; } else { #ifdef HAVE_ASPRINTF asprintf(&udi, "/org/freedesktop/Hal/devices/%s", arg); #else udi = calloc(1, sizeof ("/org/freedesktop/Hal/devices/%s") + strlen(arg)); sprintf(udi, "/org/freedesktop/Hal/devices/%s", arg); #endif } if (udi) new_dev.udi = strdup(udi); dbus_error_init(&error); if (udi) dev_exists = libhal_device_exists(hal_ctx, udi, &error); if (dev_exists) { new_dev.real_udi = strdup(new_dev.udi); } else { new_dev.real_udi = libhal_new_device(hal_ctx, &error); if (!new_dev.real_udi) { fprintf(stderr, "%s: %s\n", error.name, error.message); LIBHAL_FREE_DBUS_ERROR (&error); free(new_dev.real_udi); return 22; } printf("tmp udi: %s\n", new_dev.real_udi); } prop = NULL; while (fgets(buf, sizeof buf, stdin)) { process_property(hal_ctx, buf, &prop); } err = add_properties(hal_ctx, &new_dev, prop); prop = free_properties(prop); if (!dev_exists) { if (!libhal_device_commit_to_gdl(hal_ctx, new_dev.real_udi, new_dev.udi, &error)) { fprintf(stderr, "%s: %s\n", error.name, error.message); LIBHAL_FREE_DBUS_ERROR (&error); free(new_dev.real_udi); err = err ? err : 23; } } printf("%s: %s\n", dev_exists ? "merged": "created", new_dev.udi); return err; }