Mercurial > hg > orthanc-wsi
annotate Framework/Inputs/DicomPyramid.cpp @ 288:a1efc5c39615
fix LSB build
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Wed, 12 Jul 2023 23:37:38 +0200 |
parents | fb689ed55c09 |
children | 7020852a8fa9 |
rev | line source |
---|---|
0 | 1 /** |
2 * Orthanc - A Lightweight, RESTful DICOM Store | |
3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics | |
4 * Department, University Hospital of Liege, Belgium | |
254 | 5 * Copyright (C) 2017-2023 Osimis S.A., Belgium |
6 * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium | |
0 | 7 * |
8 * This program is free software: you can redistribute it and/or | |
9 * modify it under the terms of the GNU Affero General Public License | |
10 * as published by the Free Software Foundation, either version 3 of | |
11 * the License, or (at your option) any later version. | |
12 * | |
13 * This program is distributed in the hope that it will be useful, but | |
14 * WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
16 * Affero General Public License for more details. | |
17 * | |
18 * You should have received a copy of the GNU Affero General Public License | |
19 * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
20 **/ | |
21 | |
22 | |
16
7a88c614be04
preparing for precompiled headers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
23 #include "../PrecompiledHeadersWSI.h" |
0 | 24 #include "DicomPyramid.h" |
25 | |
26 #include "../DicomToolbox.h" | |
219
ef3f8c5126a4
Don't display the thumbnail/overview instances in the Web viewer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
217
diff
changeset
|
27 |
ef3f8c5126a4
Don't display the thumbnail/overview instances in the Web viewer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
217
diff
changeset
|
28 #include <Compatibility.h> |
192 | 29 #include <Logging.h> |
30 #include <OrthancException.h> | |
219
ef3f8c5126a4
Don't display the thumbnail/overview instances in the Web viewer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
217
diff
changeset
|
31 #include <Toolbox.h> |
0 | 32 |
33 #include <algorithm> | |
34 #include <cassert> | |
35 | |
36 namespace OrthancWSI | |
37 { | |
38 struct DicomPyramid::Comparator | |
39 { | |
40 bool operator() (DicomPyramidInstance* const& a, | |
41 DicomPyramidInstance* const& b) const | |
42 { | |
43 return a->GetTotalWidth() > b->GetTotalWidth(); | |
44 } | |
45 }; | |
46 | |
47 | |
48 void DicomPyramid::Clear() | |
49 { | |
50 for (size_t i = 0; i < levels_.size(); i++) | |
51 { | |
52 if (levels_[i] != NULL) | |
53 { | |
54 delete levels_[i]; | |
55 } | |
56 } | |
57 | |
58 for (size_t i = 0; i < instances_.size(); i++) | |
59 { | |
60 if (instances_[i] != NULL) | |
61 { | |
62 delete instances_[i]; | |
63 } | |
64 } | |
65 } | |
66 | |
67 | |
69
d529d9ce3c7e
cache for DicomPyramidInstance
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
62
diff
changeset
|
68 void DicomPyramid::RegisterInstances(const std::string& seriesId, |
d529d9ce3c7e
cache for DicomPyramidInstance
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
62
diff
changeset
|
69 bool useCache) |
0 | 70 { |
71 Json::Value series; | |
196
b0bd22077cd8
sharing code with orthanc-stone
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
192
diff
changeset
|
72 OrthancStone::IOrthancConnection::RestApiGet(series, orthanc_, "/series/" + seriesId); |
0 | 73 |
62
f45cec2c32e2
Speed-up in the Web viewer plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
61
diff
changeset
|
74 if (series.type() != Json::objectValue || |
f45cec2c32e2
Speed-up in the Web viewer plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
61
diff
changeset
|
75 !series.isMember("Instances") || |
f45cec2c32e2
Speed-up in the Web viewer plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
61
diff
changeset
|
76 series["Instances"].type() != Json::arrayValue) |
0 | 77 { |
78 throw Orthanc::OrthancException(Orthanc::ErrorCode_NetworkProtocol); | |
79 } | |
80 | |
62
f45cec2c32e2
Speed-up in the Web viewer plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
61
diff
changeset
|
81 const Json::Value& instances = series["Instances"]; |
0 | 82 instances_.reserve(instances.size()); |
83 | |
84 for (Json::Value::ArrayIndex i = 0; i < instances.size(); i++) | |
85 { | |
86 if (instances[i].type() != Json::stringValue) | |
87 { | |
88 throw Orthanc::OrthancException(Orthanc::ErrorCode_NetworkProtocol); | |
89 } | |
90 | |
219
ef3f8c5126a4
Don't display the thumbnail/overview instances in the Web viewer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
217
diff
changeset
|
91 std::string instanceId = instances[i].asString(); |
0 | 92 |
93 try | |
94 { | |
219
ef3f8c5126a4
Don't display the thumbnail/overview instances in the Web viewer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
217
diff
changeset
|
95 std::unique_ptr<DicomPyramidInstance> instance(new DicomPyramidInstance(orthanc_, instanceId, useCache)); |
ef3f8c5126a4
Don't display the thumbnail/overview instances in the Web viewer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
217
diff
changeset
|
96 |
ef3f8c5126a4
Don't display the thumbnail/overview instances in the Web viewer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
217
diff
changeset
|
97 std::vector<std::string> tokens; |
ef3f8c5126a4
Don't display the thumbnail/overview instances in the Web viewer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
217
diff
changeset
|
98 Orthanc::Toolbox::TokenizeString(tokens, instance->GetImageType(), '\\'); |
ef3f8c5126a4
Don't display the thumbnail/overview instances in the Web viewer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
217
diff
changeset
|
99 |
224 | 100 // Don't consider the thumbnail and overview as part of the DICOM pyramid (new in 1.0) |
219
ef3f8c5126a4
Don't display the thumbnail/overview instances in the Web viewer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
217
diff
changeset
|
101 if (tokens.size() < 2 || |
267 | 102 (tokens[1] != "THUMBNAIL" && |
103 tokens[1] != "OVERVIEW")) | |
219
ef3f8c5126a4
Don't display the thumbnail/overview instances in the Web viewer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
217
diff
changeset
|
104 { |
ef3f8c5126a4
Don't display the thumbnail/overview instances in the Web viewer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
217
diff
changeset
|
105 instances_.push_back(instance.release()); |
ef3f8c5126a4
Don't display the thumbnail/overview instances in the Web viewer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
217
diff
changeset
|
106 } |
0 | 107 } |
108 catch (Orthanc::OrthancException&) | |
109 { | |
219
ef3f8c5126a4
Don't display the thumbnail/overview instances in the Web viewer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
217
diff
changeset
|
110 LOG(ERROR) << "Skipping a DICOM instance that is not part of a whole-slide image: " << instanceId; |
0 | 111 } |
112 } | |
113 } | |
114 | |
115 | |
116 void DicomPyramid::Check(const std::string& seriesId) const | |
117 { | |
118 if (instances_.empty()) | |
119 { | |
120 LOG(ERROR) << "This series does not contain a whole-slide image: " << seriesId; | |
121 throw Orthanc::OrthancException(Orthanc::ErrorCode_UnknownResource); | |
122 } | |
123 | |
124 const DicomPyramidInstance& a = *instances_[0]; | |
125 | |
126 for (size_t i = 1; i < instances_.size(); i++) | |
127 { | |
128 const DicomPyramidInstance& b = *instances_[i]; | |
129 | |
56
83cd735c885d
speedup the loading of DICOM sources
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
130 if (a.GetPixelFormat() != b.GetPixelFormat() || |
0 | 131 a.GetTotalWidth() < b.GetTotalWidth() || |
132 a.GetTotalHeight() < b.GetTotalHeight()) | |
133 { | |
134 throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageFormat); | |
135 } | |
136 | |
137 if (a.GetTotalWidth() == b.GetTotalWidth() && | |
138 a.GetTotalHeight() != b.GetTotalHeight()) | |
139 { | |
140 throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageFormat); | |
141 } | |
142 } | |
143 } | |
144 | |
145 | |
146 void DicomPyramid::CheckLevel(size_t level) const | |
147 { | |
148 if (level >= levels_.size()) | |
149 { | |
150 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); | |
151 } | |
152 } | |
153 | |
154 | |
196
b0bd22077cd8
sharing code with orthanc-stone
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
192
diff
changeset
|
155 DicomPyramid::DicomPyramid(OrthancStone::IOrthancConnection& orthanc, |
69
d529d9ce3c7e
cache for DicomPyramidInstance
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
62
diff
changeset
|
156 const std::string& seriesId, |
d529d9ce3c7e
cache for DicomPyramidInstance
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
62
diff
changeset
|
157 bool useCache) : |
0 | 158 orthanc_(orthanc), |
159 seriesId_(seriesId) | |
160 { | |
69
d529d9ce3c7e
cache for DicomPyramidInstance
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
62
diff
changeset
|
161 RegisterInstances(seriesId, useCache); |
0 | 162 |
163 // Sort the instances of the pyramid by decreasing total widths | |
164 std::sort(instances_.begin(), instances_.end(), Comparator()); | |
165 | |
166 try | |
167 { | |
168 Check(seriesId); | |
169 } | |
170 catch (Orthanc::OrthancException&) | |
171 { | |
172 Clear(); | |
173 throw; | |
174 } | |
175 | |
176 for (size_t i = 0; i < instances_.size(); i++) | |
177 { | |
178 if (i == 0 || | |
179 instances_[i - 1]->GetTotalWidth() != instances_[i]->GetTotalWidth()) | |
180 { | |
181 levels_.push_back(new DicomPyramidLevel(*instances_[i])); | |
182 } | |
183 else | |
184 { | |
185 assert(levels_.back() != NULL); | |
186 levels_.back()->AddInstance(*instances_[i]); | |
187 } | |
188 } | |
189 } | |
190 | |
191 | |
192 unsigned int DicomPyramid::GetLevelWidth(unsigned int level) const | |
193 { | |
194 CheckLevel(level); | |
195 return levels_[level]->GetTotalWidth(); | |
196 } | |
197 | |
198 | |
199 unsigned int DicomPyramid::GetLevelHeight(unsigned int level) const | |
200 { | |
201 CheckLevel(level); | |
202 return levels_[level]->GetTotalHeight(); | |
203 } | |
204 | |
205 | |
217
20bc074ec19a
Viewer can display DICOM pyramids whose tile sizes vary across levels
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
214
diff
changeset
|
206 unsigned int DicomPyramid::GetTileWidth(unsigned int level) const |
0 | 207 { |
217
20bc074ec19a
Viewer can display DICOM pyramids whose tile sizes vary across levels
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
214
diff
changeset
|
208 CheckLevel(level); |
20bc074ec19a
Viewer can display DICOM pyramids whose tile sizes vary across levels
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
214
diff
changeset
|
209 return levels_[level]->GetTileWidth(); |
0 | 210 } |
211 | |
212 | |
217
20bc074ec19a
Viewer can display DICOM pyramids whose tile sizes vary across levels
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
214
diff
changeset
|
213 unsigned int DicomPyramid::GetTileHeight(unsigned int level) const |
0 | 214 { |
217
20bc074ec19a
Viewer can display DICOM pyramids whose tile sizes vary across levels
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
214
diff
changeset
|
215 CheckLevel(level); |
20bc074ec19a
Viewer can display DICOM pyramids whose tile sizes vary across levels
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
214
diff
changeset
|
216 return levels_[level]->GetTileHeight(); |
0 | 217 } |
218 | |
219 | |
220 bool DicomPyramid::ReadRawTile(std::string& tile, | |
57
91fc9583b2de
big refactoring to support sparse tiling
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
56
diff
changeset
|
221 ImageCompression& compression, |
0 | 222 unsigned int level, |
223 unsigned int tileX, | |
224 unsigned int tileY) | |
225 { | |
226 CheckLevel(level); | |
227 | |
228 Orthanc::PixelFormat format; | |
229 | |
57
91fc9583b2de
big refactoring to support sparse tiling
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
56
diff
changeset
|
230 if (levels_[level]->DownloadRawTile(tile, format, compression, orthanc_, tileX, tileY)) |
0 | 231 { |
57
91fc9583b2de
big refactoring to support sparse tiling
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
56
diff
changeset
|
232 if (format != GetPixelFormat()) |
91fc9583b2de
big refactoring to support sparse tiling
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
56
diff
changeset
|
233 { |
91fc9583b2de
big refactoring to support sparse tiling
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
56
diff
changeset
|
234 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); |
91fc9583b2de
big refactoring to support sparse tiling
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
56
diff
changeset
|
235 } |
91fc9583b2de
big refactoring to support sparse tiling
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
56
diff
changeset
|
236 |
0 | 237 return true; |
238 } | |
239 else | |
240 { | |
241 return false; | |
242 } | |
243 } | |
244 | |
245 | |
246 Orthanc::PixelFormat DicomPyramid::GetPixelFormat() const | |
247 { | |
248 assert(!instances_.empty() && instances_[0] != NULL); | |
249 return instances_[0]->GetPixelFormat(); | |
250 } | |
166
f0dac1e8f736
access to photometric interpretation of source pyramids
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
157
diff
changeset
|
251 |
f0dac1e8f736
access to photometric interpretation of source pyramids
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
157
diff
changeset
|
252 |
f0dac1e8f736
access to photometric interpretation of source pyramids
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
157
diff
changeset
|
253 Orthanc::PhotometricInterpretation DicomPyramid::GetPhotometricInterpretation() const |
f0dac1e8f736
access to photometric interpretation of source pyramids
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
157
diff
changeset
|
254 { |
f0dac1e8f736
access to photometric interpretation of source pyramids
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
157
diff
changeset
|
255 assert(!instances_.empty() && instances_[0] != NULL); |
f0dac1e8f736
access to photometric interpretation of source pyramids
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
157
diff
changeset
|
256 return instances_[0]->GetPhotometricInterpretation(); |
f0dac1e8f736
access to photometric interpretation of source pyramids
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
157
diff
changeset
|
257 } |
0 | 258 } |