Mercurial > hg > orthanc-wsi
changeset 271:45e3b5adf4ae iiif
opened issue #2379 in OpenSeadragon
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Wed, 12 Jul 2023 07:38:59 +0200 |
parents | 0040ce361d4c |
children | c766c25fe492 |
files | Applications/Dicomizer.cpp ViewerPlugin/IIIF.cpp ViewerPlugin/openseadragon.html |
diffstat | 3 files changed, 44 insertions(+), 21 deletions(-) [+] |
line wrap: on
line diff
--- a/Applications/Dicomizer.cpp Mon Jul 10 17:16:32 2023 +0200 +++ b/Applications/Dicomizer.cpp Wed Jul 12 07:38:59 2023 +0200 @@ -344,7 +344,7 @@ } // VL Whole Slide Microscopy Image IOD - OrthancWSI::DicomToolbox::SetStringTag(*dataset, DCM_SOPClassUID, VL_WHOLE_SLIDE_MICROSCOPY_IMAGE_STORAGE_IOD); + OrthancWSI::DicomToolbox::SetStringTag(*dataset, DCM_SOPClassUID, OrthancWSI::VL_WHOLE_SLIDE_MICROSCOPY_IMAGE_STORAGE_IOD); // Slide Microscopy OrthancWSI::DicomToolbox::SetStringTag(*dataset, DCM_Modality, "SM");
--- a/ViewerPlugin/IIIF.cpp Mon Jul 10 17:16:32 2023 +0200 +++ b/ViewerPlugin/IIIF.cpp Wed Jul 12 07:38:59 2023 +0200 @@ -52,22 +52,23 @@ LOG(INFO) << "IIIF: Image API call to whole-slide pyramid of series " << seriesId; OrthancWSI::DicomPyramidCache::Locker locker(seriesId); + const OrthancWSI::ITiledPyramid& pyramid = locker.GetPyramid(); - if (locker.GetPyramid().GetLevelCount() == 0) + if (pyramid.GetLevelCount() == 0) { throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); } - if (locker.GetPyramid().GetTileWidth(0) != locker.GetPyramid().GetTileHeight(0)) + if (pyramid.GetTileWidth(0) != pyramid.GetTileHeight(0)) { throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageFormat, "IIIF doesn't support non-isotropic tile sizes"); } - for (unsigned int i = 1; i < locker.GetPyramid().GetLevelCount(); i++) + for (unsigned int i = 1; i < pyramid.GetLevelCount(); i++) { - if (locker.GetPyramid().GetTileWidth(i) != locker.GetPyramid().GetTileWidth(0) || - locker.GetPyramid().GetTileHeight(i) != locker.GetPyramid().GetTileHeight(0)) + if (pyramid.GetTileWidth(i) != pyramid.GetTileWidth(0) || + pyramid.GetTileHeight(i) != pyramid.GetTileHeight(0)) { throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageFormat, "IIIF doesn't support levels with varying tile sizes"); @@ -77,29 +78,43 @@ Json::Value sizes = Json::arrayValue; Json::Value scaleFactors = Json::arrayValue; - for (unsigned int i = locker.GetPyramid().GetLevelCount(); i > 0; i--) + for (unsigned int i = pyramid.GetLevelCount(); i > 0; i--) { /** - * Openseadragon seems to have difficulties in rendering - * non-integer scale factors. Consequently, we only keep the - * levels with an integer scale factor. + * According to the IIIF Image API 3.0 specification, + * "scaleFactors" is: "The set of resolution scaling factors for + * the image's predefined tiles, expressed as POSITIVE INTEGERS by + * which to divide the full size of the image. For example, a + * scale factor of 4 indicates that the service can efficiently + * deliver images at 1/4 or 25% of the height and width of the + * full image." => We can only serve the levels for which the full + * width/height of the image is divisible by the width/height of + * the level. **/ - if (locker.GetPyramid().GetLevelWidth(0) % locker.GetPyramid().GetLevelWidth(i - 1) == 0 && - locker.GetPyramid().GetLevelHeight(0) % locker.GetPyramid().GetLevelHeight(i - 1) == 0) + if (pyramid.GetLevelWidth(0) % pyramid.GetLevelWidth(i - 1) == 0 && + pyramid.GetLevelHeight(0) % pyramid.GetLevelHeight(i - 1) == 0) { Json::Value level; - level["width"] = locker.GetPyramid().GetLevelWidth(i - 1); - level["height"] = locker.GetPyramid().GetLevelHeight(i - 1); + level["width"] = pyramid.GetLevelWidth(i - 1); + level["height"] = pyramid.GetLevelHeight(i - 1); sizes.append(level); - scaleFactors.append(static_cast<float>(locker.GetPyramid().GetLevelWidth(0)) / - static_cast<float>(locker.GetPyramid().GetLevelWidth(i - 1))); + scaleFactors.append(pyramid.GetLevelWidth(0) / + pyramid.GetLevelWidth(i - 1)); + } + else + { + LOG(WARNING) << "IIIF - Dropping level " << i << " of series " << seriesId + << ", as the full width/height (" + << pyramid.GetLevelWidth(0) << "x" << pyramid.GetLevelHeight(0) + << ") of the image is not an integer multiple of the level width/height (" + << pyramid.GetLevelWidth(i - 1) << "x" << pyramid.GetLevelHeight(i - 1) << ")"; } } Json::Value tiles; - tiles["width"] = locker.GetPyramid().GetTileWidth(0); - tiles["height"] = locker.GetPyramid().GetTileHeight(0); + tiles["width"] = pyramid.GetTileWidth(0); + tiles["height"] = pyramid.GetTileHeight(0); tiles["scaleFactors"] = scaleFactors; Json::Value result; @@ -107,8 +122,8 @@ result["@id"] = iiifPublicUrl_ + "tiles/" + seriesId; result["profile"] = "http://iiif.io/api/image/2/level0.json"; result["protocol"] = "http://iiif.io/api/image"; - result["width"] = locker.GetPyramid().GetLevelWidth(0); - result["height"] = locker.GetPyramid().GetLevelHeight(0); + result["width"] = pyramid.GetLevelWidth(0); + result["height"] = pyramid.GetLevelHeight(0); result["sizes"] = sizes; result["tiles"] = Json::arrayValue;
--- a/ViewerPlugin/openseadragon.html Mon Jul 10 17:16:32 2023 +0200 +++ b/ViewerPlugin/openseadragon.html Wed Jul 12 07:38:59 2023 +0200 @@ -4,7 +4,15 @@ <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <meta name="theme-color" content="#000000"> <title>OpenSeadragon</title> - <script src="https://unpkg.com/openseadragon@4.1.0/build/openseadragon/openseadragon.js"></script> + + <!-- + + WARNING: OpenSeadragon v4.1.0 can sometimes request regions of + negative width. We thus stick to OSD v4.0.0 for the moment. + https://github.com/openseadragon/openseadragon/issues/2379 + + --> + <script src="https://unpkg.com/openseadragon@4.0.0/build/openseadragon/openseadragon.js"></script> </head> <body>