comparison ViewerPlugin/IIIF.cpp @ 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 ca605878dc73
children c766c25fe492
comparison
equal deleted inserted replaced
270:0040ce361d4c 271:45e3b5adf4ae
50 const std::string seriesId(request->groups[0]); 50 const std::string seriesId(request->groups[0]);
51 51
52 LOG(INFO) << "IIIF: Image API call to whole-slide pyramid of series " << seriesId; 52 LOG(INFO) << "IIIF: Image API call to whole-slide pyramid of series " << seriesId;
53 53
54 OrthancWSI::DicomPyramidCache::Locker locker(seriesId); 54 OrthancWSI::DicomPyramidCache::Locker locker(seriesId);
55 55 const OrthancWSI::ITiledPyramid& pyramid = locker.GetPyramid();
56 if (locker.GetPyramid().GetLevelCount() == 0) 56
57 if (pyramid.GetLevelCount() == 0)
57 { 58 {
58 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); 59 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
59 } 60 }
60 61
61 if (locker.GetPyramid().GetTileWidth(0) != locker.GetPyramid().GetTileHeight(0)) 62 if (pyramid.GetTileWidth(0) != pyramid.GetTileHeight(0))
62 { 63 {
63 throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageFormat, 64 throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageFormat,
64 "IIIF doesn't support non-isotropic tile sizes"); 65 "IIIF doesn't support non-isotropic tile sizes");
65 } 66 }
66 67
67 for (unsigned int i = 1; i < locker.GetPyramid().GetLevelCount(); i++) 68 for (unsigned int i = 1; i < pyramid.GetLevelCount(); i++)
68 { 69 {
69 if (locker.GetPyramid().GetTileWidth(i) != locker.GetPyramid().GetTileWidth(0) || 70 if (pyramid.GetTileWidth(i) != pyramid.GetTileWidth(0) ||
70 locker.GetPyramid().GetTileHeight(i) != locker.GetPyramid().GetTileHeight(0)) 71 pyramid.GetTileHeight(i) != pyramid.GetTileHeight(0))
71 { 72 {
72 throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageFormat, 73 throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageFormat,
73 "IIIF doesn't support levels with varying tile sizes"); 74 "IIIF doesn't support levels with varying tile sizes");
74 } 75 }
75 } 76 }
76 77
77 Json::Value sizes = Json::arrayValue; 78 Json::Value sizes = Json::arrayValue;
78 Json::Value scaleFactors = Json::arrayValue; 79 Json::Value scaleFactors = Json::arrayValue;
79 80
80 for (unsigned int i = locker.GetPyramid().GetLevelCount(); i > 0; i--) 81 for (unsigned int i = pyramid.GetLevelCount(); i > 0; i--)
81 { 82 {
82 /** 83 /**
83 * Openseadragon seems to have difficulties in rendering 84 * According to the IIIF Image API 3.0 specification,
84 * non-integer scale factors. Consequently, we only keep the 85 * "scaleFactors" is: "The set of resolution scaling factors for
85 * levels with an integer scale factor. 86 * the image's predefined tiles, expressed as POSITIVE INTEGERS by
87 * which to divide the full size of the image. For example, a
88 * scale factor of 4 indicates that the service can efficiently
89 * deliver images at 1/4 or 25% of the height and width of the
90 * full image." => We can only serve the levels for which the full
91 * width/height of the image is divisible by the width/height of
92 * the level.
86 **/ 93 **/
87 if (locker.GetPyramid().GetLevelWidth(0) % locker.GetPyramid().GetLevelWidth(i - 1) == 0 && 94 if (pyramid.GetLevelWidth(0) % pyramid.GetLevelWidth(i - 1) == 0 &&
88 locker.GetPyramid().GetLevelHeight(0) % locker.GetPyramid().GetLevelHeight(i - 1) == 0) 95 pyramid.GetLevelHeight(0) % pyramid.GetLevelHeight(i - 1) == 0)
89 { 96 {
90 Json::Value level; 97 Json::Value level;
91 level["width"] = locker.GetPyramid().GetLevelWidth(i - 1); 98 level["width"] = pyramid.GetLevelWidth(i - 1);
92 level["height"] = locker.GetPyramid().GetLevelHeight(i - 1); 99 level["height"] = pyramid.GetLevelHeight(i - 1);
93 sizes.append(level); 100 sizes.append(level);
94 101
95 scaleFactors.append(static_cast<float>(locker.GetPyramid().GetLevelWidth(0)) / 102 scaleFactors.append(pyramid.GetLevelWidth(0) /
96 static_cast<float>(locker.GetPyramid().GetLevelWidth(i - 1))); 103 pyramid.GetLevelWidth(i - 1));
104 }
105 else
106 {
107 LOG(WARNING) << "IIIF - Dropping level " << i << " of series " << seriesId
108 << ", as the full width/height ("
109 << pyramid.GetLevelWidth(0) << "x" << pyramid.GetLevelHeight(0)
110 << ") of the image is not an integer multiple of the level width/height ("
111 << pyramid.GetLevelWidth(i - 1) << "x" << pyramid.GetLevelHeight(i - 1) << ")";
97 } 112 }
98 } 113 }
99 114
100 Json::Value tiles; 115 Json::Value tiles;
101 tiles["width"] = locker.GetPyramid().GetTileWidth(0); 116 tiles["width"] = pyramid.GetTileWidth(0);
102 tiles["height"] = locker.GetPyramid().GetTileHeight(0); 117 tiles["height"] = pyramid.GetTileHeight(0);
103 tiles["scaleFactors"] = scaleFactors; 118 tiles["scaleFactors"] = scaleFactors;
104 119
105 Json::Value result; 120 Json::Value result;
106 result["@context"] = "http://iiif.io/api/image/2/context.json"; 121 result["@context"] = "http://iiif.io/api/image/2/context.json";
107 result["@id"] = iiifPublicUrl_ + "tiles/" + seriesId; 122 result["@id"] = iiifPublicUrl_ + "tiles/" + seriesId;
108 result["profile"] = "http://iiif.io/api/image/2/level0.json"; 123 result["profile"] = "http://iiif.io/api/image/2/level0.json";
109 result["protocol"] = "http://iiif.io/api/image"; 124 result["protocol"] = "http://iiif.io/api/image";
110 result["width"] = locker.GetPyramid().GetLevelWidth(0); 125 result["width"] = pyramid.GetLevelWidth(0);
111 result["height"] = locker.GetPyramid().GetLevelHeight(0); 126 result["height"] = pyramid.GetLevelHeight(0);
112 result["sizes"] = sizes; 127 result["sizes"] = sizes;
113 128
114 result["tiles"] = Json::arrayValue; 129 result["tiles"] = Json::arrayValue;
115 result["tiles"].append(tiles); 130 result["tiles"].append(tiles);
116 131