From 4c127f0d3c3dc7935c6b05d6769cbb1d88562004 Mon Sep 17 00:00:00 2001 From: Melissa Linkert Date: Fri, 13 Sep 2024 14:37:36 -0500 Subject: [PATCH 1/2] Calculate resolution sizes based on an integer scale factor, not the zoom level Fixes #8. This scales each rseolution by an integer amount, e.g. 2, 4, 8, etc. instead of directly using the zoom level returned by `imgData` which may introduce rounding errors. --- .../lib/images/servers/omero/OmeroWebImageServer.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/main/java/qupath/lib/images/servers/omero/OmeroWebImageServer.java b/src/main/java/qupath/lib/images/servers/omero/OmeroWebImageServer.java index a04ff6e9..507d5012 100644 --- a/src/main/java/qupath/lib/images/servers/omero/OmeroWebImageServer.java +++ b/src/main/java/qupath/lib/images/servers/omero/OmeroWebImageServer.java @@ -282,7 +282,15 @@ else if (map.has("channels")) { if (levels > 1) { JsonObject zoom = map.getAsJsonObject("zoomLevelScaling"); for (int i = 0; i < levels; i++) { - levelBuilder.addLevelByDownsample(1.0 / zoom.getAsJsonPrimitive(Integer.toString(i)).getAsDouble()); + double rawZoomFactor = zoom.getAsJsonPrimitive(Integer.toString(i)).getAsDouble(); + int scaleFactor = (int) Math.ceil(1 / rawZoomFactor); + logger.debug("level = {}, rawZoomFactor = {}, scaleFactor = {}", i, rawZoomFactor, scaleFactor); + + int levelWidth = sizeX / scaleFactor; + int levelHeight = sizeY / scaleFactor; + logger.debug(" level width = {}, level height = {}", levelWidth, levelHeight); + + levelBuilder.addLevel(scaleFactor, levelWidth, levelHeight); } } else { levelBuilder.addFullResolutionLevel(); From 2e3b745aec4433d523615970e8aa82b2971908d8 Mon Sep 17 00:00:00 2001 From: Melissa Linkert Date: Thu, 19 Sep 2024 14:19:45 -0500 Subject: [PATCH 2/2] Calculate resolutions based on both zoomLevelScaling and aspect ratio --- .../servers/omero/OmeroWebImageServer.java | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/main/java/qupath/lib/images/servers/omero/OmeroWebImageServer.java b/src/main/java/qupath/lib/images/servers/omero/OmeroWebImageServer.java index 507d5012..cb854e17 100644 --- a/src/main/java/qupath/lib/images/servers/omero/OmeroWebImageServer.java +++ b/src/main/java/qupath/lib/images/servers/omero/OmeroWebImageServer.java @@ -281,16 +281,28 @@ else if (map.has("channels")) { int levels = map.getAsJsonPrimitive("levels").getAsInt(); if (levels > 1) { JsonObject zoom = map.getAsJsonObject("zoomLevelScaling"); + double aspectRatio = (double) sizeX / sizeY; + logger.debug("image aspect ratio = {}", aspectRatio); for (int i = 0; i < levels; i++) { double rawZoomFactor = zoom.getAsJsonPrimitive(Integer.toString(i)).getAsDouble(); - int scaleFactor = (int) Math.ceil(1 / rawZoomFactor); - logger.debug("level = {}, rawZoomFactor = {}, scaleFactor = {}", i, rawZoomFactor, scaleFactor); + logger.debug("level = {}, rawZoomFactor = {}", i, rawZoomFactor); + + // level width and height calculation are best-effort, + // given that we cannot currently get the precise dimensions + // this needs to be fixed once web API is fixed + + // we expect the width calculation to be accurate, as zoomLevelScaling + // was calculated based upon the resolution widths alone + int levelWidth = (int) Math.floor(rawZoomFactor * sizeX); + + // now apply the image aspect ratio to find the height + // this assumes that the aspect ratio remains consistent across the whole pyramid + // subtract 1 to account for potential rounding issues + int levelHeight = (int) Math.floor(levelWidth / aspectRatio) - 1; - int levelWidth = sizeX / scaleFactor; - int levelHeight = sizeY / scaleFactor; logger.debug(" level width = {}, level height = {}", levelWidth, levelHeight); - levelBuilder.addLevel(scaleFactor, levelWidth, levelHeight); + levelBuilder.addLevel(1 / rawZoomFactor, levelWidth, levelHeight); } } else { levelBuilder.addFullResolutionLevel();