-
Notifications
You must be signed in to change notification settings - Fork 11
Description
Following up here since #14 is about something else. Using @Falcury's tool and my function to create a read_region function:
Note: This does not happen in SlideScape! Not even a minor shift. Would this be due to the calculate of the shift in um? I will implement a non-integer shift using bilinear interpolation to check
isyntax_error_t libisyntax_read_region(isyntax_t* isyntax, isyntax_cache_t* isyntax_cache, int32_t level,
int64_t x, int64_t y, int64_t width, int64_t height, uint32_t** out_pixels) {
// Get the level
assert(level < &isyntax->images[0].level_count);
isyntax_level_t* current_level = &isyntax->images[0].levels[level];
int32_t level_count = isyntax->images[0].level_count;
// Setup the origin offset
int32_t offset = current_level->origin_offset_in_pixels;
int PER_LEVEL_PADDING = 3;
// int32_t offset = ((PER_LEVEL_PADDING << level_count) - PER_LEVEL_PADDING) >> level;
x += offset + level;
y += offset + level;
// Check bounds
// assert(x + width - offset <= current_level->width_in_pixels);
// assert(y + height - offset <= current_level->height_in_pixels);
int32_t tile_width = isyntax->tile_width;
int32_t tile_height = isyntax->tile_height;
int64_t start_tile_x = x / tile_width;
int64_t end_tile_x = (x + width - 1) / tile_width;
int64_t start_tile_y = y / tile_height;
int64_t end_tile_y = (y + height - 1) / tile_height;
// Allocate memory for region
*out_pixels = (uint32_t*)malloc(width * height * sizeof(uint32_t));
// Read tiles and copy the relevant portion of each tile to the region
for (int64_t tile_y = start_tile_y; tile_y <= end_tile_y; ++tile_y) {
for (int64_t tile_x = start_tile_x; tile_x <= end_tile_x; ++tile_x) {
// Calculate the portion of the tile to be copied
int64_t src_x = (tile_x == start_tile_x) ? x % tile_width : 0;
int64_t src_y = (tile_y == start_tile_y) ? y % tile_height : 0;
int64_t dest_x = (tile_x == start_tile_x) ? 0 : (tile_x - start_tile_x) * tile_width - (x % tile_width);
int64_t dest_y = (tile_y == start_tile_y) ? 0 : (tile_y - start_tile_y) * tile_height -
(y % tile_height);
int64_t copy_width = (tile_x == end_tile_x) ? (x + width) % tile_width : tile_width - src_x;
int64_t copy_height = (tile_y == end_tile_y) ? (y + height) % tile_height : tile_height - src_y;
uint32_t *pixels = NULL;
// Check if tile exists, if not, don't use the function to read the tile and immediately return an empty
// tile.
int64_t tile_index = tile_y * current_level->width_in_tiles + tile_x;
bool tile_exists = (isyntax->images[0].levels[level].tiles + tile_index)->exists;
if (tile_exists) {
// Read tile
assert(libisyntax_tile_read(isyntax, isyntax_cache, level, tile_x, tile_y, &pixels) == LIBISYNTAX_OK);
// Copy the relevant portion of the tile to the region
for (int64_t i = 0; i < copy_height; ++i) {
memcpy((*out_pixels) + (dest_y + i) * width + dest_x,
pixels + (src_y + i) * tile_width + src_x,
copy_width * sizeof(uint32_t));
}
} else {
// Fill up with transparent white pixels (R=255, G=255, B=255, A=0)
for (int64_t i = 0; i < copy_height; ++i) {
for (int64_t j = 0; j < copy_width; ++j) {
(*out_pixels)[(dest_y + i) * width + dest_x + j] = 0x00FFFFFFu;
}
}
}
// Free the tile data
free(pixels);
}
}
return LIBISYNTAX_OK;
}Using the origin_offset_in_pixels as defined in the header, I get a big shift between level 3 and 4 (and beyond, 0, 1, 2 are fine).
If I use ((PER_LEVEL_PADDING << level_count) - PER_LEVEL_PADDING) >> level it's rather stable, but there are very minor visual shifts. You also have these shifts in level 0, 1, 2.
This is the conversion tool. If --cache-size is too small it tends to segfault, which I couldn't locate yet (I will run Valgrind, but that doesn't work on M1, so needs to wait a bit), the conversion is here: https://github.com/NKI-AI/libisyntax/blob/add-read-region/src/isyntax_to_tiff.c
The absolute offset compared to the Philips SDK is slightly annoying, because we are annotating in a platform that uses the SDK and they output absolute coordinates in level 0.

