# HG changeset patch # User Sebastien Jodogne # Date 1689140339 -7200 # Node ID 45e3b5adf4ae7a8d01729f126506749a7b081cce # Parent 0040ce361d4cdeb992a14e703adabc0b84a03a4d opened issue 2379 in OpenSeadragon diff -r 0040ce361d4c -r 45e3b5adf4ae Applications/Dicomizer.cpp --- 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"); diff -r 0040ce361d4c -r 45e3b5adf4ae ViewerPlugin/IIIF.cpp --- 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(locker.GetPyramid().GetLevelWidth(0)) / - static_cast(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; diff -r 0040ce361d4c -r 45e3b5adf4ae ViewerPlugin/openseadragon.html --- 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 @@ OpenSeadragon - + + +