comparison OrthancStone/Sources/Loaders/OrthancSeriesVolumeProgressiveLoader.cpp @ 1640:52b8b96cb55f

cleaning namespaces
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 10 Nov 2020 16:55:22 +0100
parents 8563ea5d8ae4
children 9ac2a65d4172
comparison
equal deleted inserted replaced
1639:5cdc5b98f14d 1640:52b8b96cb55f
34 #include <OrthancException.h> 34 #include <OrthancException.h>
35 35
36 36
37 namespace OrthancStone 37 namespace OrthancStone
38 { 38 {
39 using OrthancStone::ILoadersContext; 39 class OrthancSeriesVolumeProgressiveLoader::ExtractedSlice : public DicomVolumeImageMPRSlicer::Slice
40
41 class OrthancSeriesVolumeProgressiveLoader::ExtractedSlice : public OrthancStone::DicomVolumeImageMPRSlicer::Slice
42 { 40 {
43 private: 41 private:
44 const OrthancSeriesVolumeProgressiveLoader& that_; 42 const OrthancSeriesVolumeProgressiveLoader& that_;
45 43
46 public: 44 public:
47 ExtractedSlice(const OrthancSeriesVolumeProgressiveLoader& that, 45 ExtractedSlice(const OrthancSeriesVolumeProgressiveLoader& that,
48 const OrthancStone::CoordinateSystem3D& plane) : 46 const CoordinateSystem3D& plane) :
49 OrthancStone::DicomVolumeImageMPRSlicer::Slice(*that.volume_, plane), 47 DicomVolumeImageMPRSlicer::Slice(*that.volume_, plane),
50 that_(that) 48 that_(that)
51 { 49 {
52 if (IsValid()) 50 if (IsValid())
53 { 51 {
54 if (GetProjection() == OrthancStone::VolumeProjection_Axial) 52 if (GetProjection() == VolumeProjection_Axial)
55 { 53 {
56 // For coronal and sagittal projections, we take the global 54 // For coronal and sagittal projections, we take the global
57 // revision of the volume because even if a single slice changes, 55 // revision of the volume because even if a single slice changes,
58 // this means the projection will yield a different result --> 56 // this means the projection will yield a different result -->
59 // we must increase the revision as soon as any slice changes 57 // we must increase the revision as soon as any slice changes
60 SetRevision(that_.seriesGeometry_.GetSliceRevision(GetSliceIndex())); 58 SetRevision(that_.seriesGeometry_.GetSliceRevision(GetSliceIndex()));
61 } 59 }
62 60
63 if (that_.strategy_.get() != NULL && 61 if (that_.strategy_.get() != NULL &&
64 GetProjection() == OrthancStone::VolumeProjection_Axial) 62 GetProjection() == VolumeProjection_Axial)
65 { 63 {
66 that_.strategy_->SetCurrent(GetSliceIndex()); 64 that_.strategy_->SetCurrent(GetSliceIndex());
67 } 65 }
68 } 66 }
69 } 67 }
70 }; 68 };
71 69
72 void OrthancSeriesVolumeProgressiveLoader::SeriesGeometry::CheckSlice( 70 void OrthancSeriesVolumeProgressiveLoader::SeriesGeometry::CheckSlice(
73 size_t index, const OrthancStone::DicomInstanceParameters& reference) const 71 size_t index, const DicomInstanceParameters& reference) const
74 { 72 {
75 const OrthancStone::DicomInstanceParameters& slice = *slices_[index]; 73 const DicomInstanceParameters& slice = *slices_[index];
76 74
77 if (!OrthancStone::GeometryToolbox::IsParallel( 75 if (!GeometryToolbox::IsParallel(
78 reference.GetGeometry().GetNormal(), 76 reference.GetGeometry().GetNormal(),
79 slice.GetGeometry().GetNormal())) 77 slice.GetGeometry().GetNormal()))
80 { 78 {
81 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadGeometry, 79 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadGeometry,
82 "A slice in the volume image is not parallel to the others"); 80 "A slice in the volume image is not parallel to the others");
93 { 91 {
94 throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageSize, 92 throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageSize,
95 "The width/height of slices are not constant in the volume image"); 93 "The width/height of slices are not constant in the volume image");
96 } 94 }
97 95
98 if (!OrthancStone::LinearAlgebra::IsNear(reference.GetPixelSpacingX(), slice.GetPixelSpacingX()) || 96 if (!LinearAlgebra::IsNear(reference.GetPixelSpacingX(), slice.GetPixelSpacingX()) ||
99 !OrthancStone::LinearAlgebra::IsNear(reference.GetPixelSpacingY(), slice.GetPixelSpacingY())) 97 !LinearAlgebra::IsNear(reference.GetPixelSpacingY(), slice.GetPixelSpacingY()))
100 { 98 {
101 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadGeometry, 99 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadGeometry,
102 "The pixel spacing of the slices change across the volume image"); 100 "The pixel spacing of the slices change across the volume image");
103 } 101 }
104 } 102 }
116 } 114 }
117 } 115 }
118 116
119 if (slices_.size() != 0) 117 if (slices_.size() != 0)
120 { 118 {
121 const OrthancStone::DicomInstanceParameters& reference = *slices_[0]; 119 const DicomInstanceParameters& reference = *slices_[0];
122 120
123 for (size_t i = 1; i < slices_.size(); i++) 121 for (size_t i = 1; i < slices_.size(); i++)
124 { 122 {
125 CheckSlice(i, reference); 123 CheckSlice(i, reference);
126 } 124 }
160 } 158 }
161 159
162 160
163 // WARNING: The payload of "slices" must be of class "DicomInstanceParameters" 161 // WARNING: The payload of "slices" must be of class "DicomInstanceParameters"
164 // (called with the slices created in LoadGeometry) 162 // (called with the slices created in LoadGeometry)
165 void OrthancSeriesVolumeProgressiveLoader::SeriesGeometry::ComputeGeometry(OrthancStone::SlicesSorter& slices) 163 void OrthancSeriesVolumeProgressiveLoader::SeriesGeometry::ComputeGeometry(SlicesSorter& slices)
166 { 164 {
167 Clear(); 165 Clear();
168 166
169 if (!slices.Sort()) 167 if (!slices.Sort())
170 { 168 {
172 "Cannot sort the 3D slices of a DICOM series"); 170 "Cannot sort the 3D slices of a DICOM series");
173 } 171 }
174 172
175 if (slices.GetSlicesCount() == 0) 173 if (slices.GetSlicesCount() == 0)
176 { 174 {
177 geometry_.reset(new OrthancStone::VolumeImageGeometry); 175 geometry_.reset(new VolumeImageGeometry);
178 } 176 }
179 else 177 else
180 { 178 {
181 slices_.reserve(slices.GetSlicesCount()); 179 slices_.reserve(slices.GetSlicesCount());
182 slicesRevision_.resize(slices.GetSlicesCount(), 0); 180 slicesRevision_.resize(slices.GetSlicesCount(), 0);
183 181
184 for (size_t i = 0; i < slices.GetSlicesCount(); i++) 182 for (size_t i = 0; i < slices.GetSlicesCount(); i++)
185 { 183 {
186 const OrthancStone::DicomInstanceParameters& slice = 184 const DicomInstanceParameters& slice =
187 dynamic_cast<const OrthancStone::DicomInstanceParameters&>(slices.GetSlicePayload(i)); 185 dynamic_cast<const DicomInstanceParameters&>(slices.GetSlicePayload(i));
188 slices_.push_back(new OrthancStone::DicomInstanceParameters(slice)); 186 slices_.push_back(new DicomInstanceParameters(slice));
189 } 187 }
190 188
191 CheckVolume(); 189 CheckVolume();
192 190
193 double spacingZ; 191 double spacingZ;
194 192
195 if (slices.ComputeSpacingBetweenSlices(spacingZ)) 193 if (slices.ComputeSpacingBetweenSlices(spacingZ))
196 { 194 {
197 LOG(TRACE) << "Computed spacing between slices: " << spacingZ << "mm"; 195 LOG(TRACE) << "Computed spacing between slices: " << spacingZ << "mm";
198 196
199 const OrthancStone::DicomInstanceParameters& parameters = *slices_[0]; 197 const DicomInstanceParameters& parameters = *slices_[0];
200 198
201 geometry_.reset(new OrthancStone::VolumeImageGeometry); 199 geometry_.reset(new VolumeImageGeometry);
202 geometry_->SetSizeInVoxels(parameters.GetImageInformation().GetWidth(), 200 geometry_->SetSizeInVoxels(parameters.GetImageInformation().GetWidth(),
203 parameters.GetImageInformation().GetHeight(), 201 parameters.GetImageInformation().GetHeight(),
204 static_cast<unsigned int>(slices.GetSlicesCount())); 202 static_cast<unsigned int>(slices.GetSlicesCount()));
205 geometry_->SetAxialGeometry(slices.GetSliceGeometry(0)); 203 geometry_->SetAxialGeometry(slices.GetSliceGeometry(0));
206 geometry_->SetVoxelDimensions(parameters.GetPixelSpacingX(), 204 geometry_->SetVoxelDimensions(parameters.GetPixelSpacingX(),
213 } 211 }
214 } 212 }
215 } 213 }
216 214
217 215
218 const OrthancStone::VolumeImageGeometry& OrthancSeriesVolumeProgressiveLoader::SeriesGeometry::GetImageGeometry() const 216 const VolumeImageGeometry& OrthancSeriesVolumeProgressiveLoader::SeriesGeometry::GetImageGeometry() const
219 { 217 {
220 if (!HasGeometry()) 218 if (!HasGeometry())
221 { 219 {
222 LOG(ERROR) << "OrthancSeriesVolumeProgressiveLoader::SeriesGeometry::GetImageGeometry(): (!HasGeometry())"; 220 LOG(ERROR) << "OrthancSeriesVolumeProgressiveLoader::SeriesGeometry::GetImageGeometry(): (!HasGeometry())";
223 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); 221 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
228 return *geometry_; 226 return *geometry_;
229 } 227 }
230 } 228 }
231 229
232 230
233 const OrthancStone::DicomInstanceParameters& OrthancSeriesVolumeProgressiveLoader::SeriesGeometry::GetSliceParameters(size_t index) const 231 const DicomInstanceParameters& OrthancSeriesVolumeProgressiveLoader::SeriesGeometry::GetSliceParameters(size_t index) const
234 { 232 {
235 CheckSliceIndex(index); 233 CheckSliceIndex(index);
236 return *slices_[index]; 234 return *slices_[index];
237 } 235 }
238 236
249 CheckSliceIndex(index); 247 CheckSliceIndex(index);
250 slicesRevision_[index] ++; 248 slicesRevision_[index] ++;
251 } 249 }
252 250
253 251
254 static unsigned int GetSliceIndexPayload(const OrthancStone::OracleCommandBase& command) 252 static unsigned int GetSliceIndexPayload(const OracleCommandBase& command)
255 { 253 {
256 assert(command.HasPayload()); 254 assert(command.HasPayload());
257 return dynamic_cast< const Orthanc::SingleValueObject<unsigned int>& >(command.GetPayload()).GetValue(); 255 return dynamic_cast< const Orthanc::SingleValueObject<unsigned int>& >(command.GetPayload()).GetValue();
258 } 256 }
259 257
270 { 268 {
271 ORTHANC_ASSERT(quality == QUALITY_00, "INTERNAL ERROR. quality != QUALITY_00 in " 269 ORTHANC_ASSERT(quality == QUALITY_00, "INTERNAL ERROR. quality != QUALITY_00 in "
272 << "OrthancSeriesVolumeProgressiveLoader::ScheduleNextSliceDownload"); 270 << "OrthancSeriesVolumeProgressiveLoader::ScheduleNextSliceDownload");
273 } 271 }
274 272
275 const OrthancStone::DicomInstanceParameters& slice = seriesGeometry_.GetSliceParameters(sliceIndex); 273 const DicomInstanceParameters& slice = seriesGeometry_.GetSliceParameters(sliceIndex);
276 274
277 const std::string& instance = slice.GetOrthancInstanceIdentifier(); 275 const std::string& instance = slice.GetOrthancInstanceIdentifier();
278 if (instance.empty()) 276 if (instance.empty())
279 { 277 {
280 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); 278 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
281 } 279 }
282 280
283 std::unique_ptr<OrthancStone::OracleCommandBase> command; 281 std::unique_ptr<OracleCommandBase> command;
284 282
285 if (!progressiveQuality_ || quality == QUALITY_02) 283 if (!progressiveQuality_ || quality == QUALITY_02)
286 { 284 {
287 std::unique_ptr<OrthancStone::GetOrthancImageCommand> tmp(new OrthancStone::GetOrthancImageCommand); 285 std::unique_ptr<GetOrthancImageCommand> tmp(new GetOrthancImageCommand);
288 // TODO: review the following comment. 286 // TODO: review the following comment.
289 // - Commented out by bgo on 2019-07-19 | reason: Alain has seen cases 287 // - Commented out by bgo on 2019-07-19 | reason: Alain has seen cases
290 // where gzipping the uint16 image took 11 sec to produce 5mb. 288 // where gzipping the uint16 image took 11 sec to produce 5mb.
291 // The unzipped request was much much faster. 289 // The unzipped request was much much faster.
292 // - Re-enabled on 2019-07-30. Reason: in Web Assembly, the browser 290 // - Re-enabled on 2019-07-30. Reason: in Web Assembly, the browser
302 // << " URI = " << tmp->GetUri(); 300 // << " URI = " << tmp->GetUri();
303 command.reset(tmp.release()); 301 command.reset(tmp.release());
304 } 302 }
305 else // progressive mode is true AND quality is not final (different from QUALITY_02 303 else // progressive mode is true AND quality is not final (different from QUALITY_02
306 { 304 {
307 std::unique_ptr<OrthancStone::GetOrthancWebViewerJpegCommand> tmp( 305 std::unique_ptr<GetOrthancWebViewerJpegCommand> tmp(
308 new OrthancStone::GetOrthancWebViewerJpegCommand); 306 new GetOrthancWebViewerJpegCommand);
309 307
310 // TODO: review the following comment. Commented out by bgo on 2019-07-19 308 // TODO: review the following comment. Commented out by bgo on 2019-07-19
311 // (gzip for jpeg seems overkill) 309 // (gzip for jpeg seems overkill)
312 //tmp->SetHttpHeader("Accept-Encoding", "gzip"); 310 //tmp->SetHttpHeader("Accept-Encoding", "gzip");
313 tmp->SetInstance(instance); 311 tmp->SetInstance(instance);
320 } 318 }
321 319
322 command->AcquirePayload(new Orthanc::SingleValueObject<unsigned int>(sliceIndex)); 320 command->AcquirePayload(new Orthanc::SingleValueObject<unsigned int>(sliceIndex));
323 321
324 { 322 {
325 std::unique_ptr<OrthancStone::ILoadersContext::ILock> lock(loadersContext_.Lock()); 323 std::unique_ptr<ILoadersContext::ILock> lock(loadersContext_.Lock());
326 boost::shared_ptr<IObserver> observer(GetSharedObserver()); 324 boost::shared_ptr<IObserver> observer(GetSharedObserver());
327 lock->Schedule(observer, sliceSchedulingPriority_, command.release()); 325 lock->Schedule(observer, sliceSchedulingPriority_, command.release());
328 } 326 }
329 } 327 }
330 else 328 else
336 } 334 }
337 335
338 /** 336 /**
339 This is called in response to GET "/series/XXXXXXXXXXXXX/instances-tags" 337 This is called in response to GET "/series/XXXXXXXXXXXXX/instances-tags"
340 */ 338 */
341 void OrthancSeriesVolumeProgressiveLoader::LoadGeometry(const OrthancStone::OrthancRestApiCommand::SuccessMessage& message) 339 void OrthancSeriesVolumeProgressiveLoader::LoadGeometry(const OrthancRestApiCommand::SuccessMessage& message)
342 { 340 {
343 Json::Value body; 341 Json::Value body;
344 message.ParseJsonBody(body); 342 message.ParseJsonBody(body);
345 343
346 if (body.type() != Json::objectValue) 344 if (body.type() != Json::objectValue)
349 } 347 }
350 348
351 { 349 {
352 Json::Value::Members instances = body.getMemberNames(); 350 Json::Value::Members instances = body.getMemberNames();
353 351
354 OrthancStone::SlicesSorter slices; 352 SlicesSorter slices;
355 353
356 for (size_t i = 0; i < instances.size(); i++) 354 for (size_t i = 0; i < instances.size(); i++)
357 { 355 {
358 Orthanc::DicomMap dicom; 356 Orthanc::DicomMap dicom;
359 dicom.FromDicomAsJson(body[instances[i]]); 357 dicom.FromDicomAsJson(body[instances[i]]);
360 358
361 std::unique_ptr<OrthancStone::DicomInstanceParameters> instance(new OrthancStone::DicomInstanceParameters(dicom)); 359 std::unique_ptr<DicomInstanceParameters> instance(new DicomInstanceParameters(dicom));
362 instance->SetOrthancInstanceIdentifier(instances[i]); 360 instance->SetOrthancInstanceIdentifier(instances[i]);
363 361
364 // the 3D plane corresponding to the slice 362 // the 3D plane corresponding to the slice
365 OrthancStone::CoordinateSystem3D geometry = instance->GetGeometry(); 363 CoordinateSystem3D geometry = instance->GetGeometry();
366 slices.AddSlice(geometry, instance.release()); 364 slices.AddSlice(geometry, instance.release());
367 365
368 if (slicePostProcessor_) 366 if (slicePostProcessor_)
369 slicePostProcessor_->ProcessCTDicomSlice(dicom); 367 slicePostProcessor_->ProcessCTDicomSlice(dicom);
370 } 368 }
378 { 376 {
379 volume_->Initialize(seriesGeometry_.GetImageGeometry(), Orthanc::PixelFormat_Grayscale8); 377 volume_->Initialize(seriesGeometry_.GetImageGeometry(), Orthanc::PixelFormat_Grayscale8);
380 } 378 }
381 else 379 else
382 { 380 {
383 const OrthancStone::DicomInstanceParameters& parameters = seriesGeometry_.GetSliceParameters(0); 381 const DicomInstanceParameters& parameters = seriesGeometry_.GetSliceParameters(0);
384 382
385 volume_->Initialize(seriesGeometry_.GetImageGeometry(), parameters.GetExpectedPixelFormat()); 383 volume_->Initialize(seriesGeometry_.GetImageGeometry(), parameters.GetExpectedPixelFormat());
386 volume_->SetDicomParameters(parameters); 384 volume_->SetDicomParameters(parameters);
387 volume_->GetPixelData().Clear(); 385 volume_->GetPixelData().Clear();
388 386
390 // QUALITY_02... Otherwise, it's only QUALITY_00 388 // QUALITY_02... Otherwise, it's only QUALITY_00
391 unsigned int maxQuality = QUALITY_00; 389 unsigned int maxQuality = QUALITY_00;
392 if (progressiveQuality_) 390 if (progressiveQuality_)
393 maxQuality = QUALITY_02; 391 maxQuality = QUALITY_02;
394 392
395 strategy_.reset(new OrthancStone::BasicFetchingStrategy( 393 strategy_.reset(new BasicFetchingStrategy(
396 sorter_->CreateSorter(static_cast<unsigned int>(slicesCount)), 394 sorter_->CreateSorter(static_cast<unsigned int>(slicesCount)),
397 maxQuality)); 395 maxQuality));
398 396
399 assert(simultaneousDownloads_ != 0); 397 assert(simultaneousDownloads_ != 0);
400 for (unsigned int i = 0; i < simultaneousDownloads_; i++) 398 for (unsigned int i = 0; i < simultaneousDownloads_; i++)
403 } 401 }
404 } 402 }
405 403
406 slicesQuality_.resize(slicesCount, 0); 404 slicesQuality_.resize(slicesCount, 0);
407 405
408 BroadcastMessage(OrthancStone::DicomVolumeImage::GeometryReadyMessage(*volume_)); 406 BroadcastMessage(DicomVolumeImage::GeometryReadyMessage(*volume_));
409 } 407 }
410 408
411 409
412 void OrthancSeriesVolumeProgressiveLoader::SetSliceContent(unsigned int sliceIndex, 410 void OrthancSeriesVolumeProgressiveLoader::SetSliceContent(unsigned int sliceIndex,
413 const Orthanc::ImageAccessor& image, 411 const Orthanc::ImageAccessor& image,
423 } 421 }
424 422
425 if (quality >= slicesQuality_[sliceIndex]) 423 if (quality >= slicesQuality_[sliceIndex])
426 { 424 {
427 { 425 {
428 OrthancStone::ImageBuffer3D::SliceWriter writer(volume_->GetPixelData(), 426 ImageBuffer3D::SliceWriter writer(volume_->GetPixelData(),
429 OrthancStone::VolumeProjection_Axial, 427 VolumeProjection_Axial,
430 sliceIndex); 428 sliceIndex);
431 429
432 Orthanc::ImageProcessing::Copy(writer.GetAccessor(), image); 430 Orthanc::ImageProcessing::Copy(writer.GetAccessor(), image);
433 } 431 }
434 432
435 volume_->IncrementRevision(); 433 volume_->IncrementRevision();
436 seriesGeometry_.IncrementSliceRevision(sliceIndex); 434 seriesGeometry_.IncrementSliceRevision(sliceIndex);
437 slicesQuality_[sliceIndex] = quality; 435 slicesQuality_[sliceIndex] = quality;
438 436
439 BroadcastMessage(OrthancStone::DicomVolumeImage::ContentUpdatedMessage(*volume_)); 437 BroadcastMessage(DicomVolumeImage::ContentUpdatedMessage(*volume_));
440 } 438 }
441 LOG(TRACE) << "SetSliceContent sliceIndex = " << sliceIndex << " -- will " 439 LOG(TRACE) << "SetSliceContent sliceIndex = " << sliceIndex << " -- will "
442 << " now call ScheduleNextSliceDownload()"; 440 << " now call ScheduleNextSliceDownload()";
443 ScheduleNextSliceDownload(); 441 ScheduleNextSliceDownload();
444 } 442 }
445 443
446 void OrthancSeriesVolumeProgressiveLoader::LoadBestQualitySliceContent( 444 void OrthancSeriesVolumeProgressiveLoader::LoadBestQualitySliceContent(
447 const OrthancStone::GetOrthancImageCommand::SuccessMessage& message) 445 const GetOrthancImageCommand::SuccessMessage& message)
448 { 446 {
449 unsigned int quality = QUALITY_00; 447 unsigned int quality = QUALITY_00;
450 if (progressiveQuality_) 448 if (progressiveQuality_)
451 quality = QUALITY_02; 449 quality = QUALITY_02;
452 450
454 message.GetImage(), 452 message.GetImage(),
455 quality); 453 quality);
456 } 454 }
457 455
458 void OrthancSeriesVolumeProgressiveLoader::LoadJpegSliceContent( 456 void OrthancSeriesVolumeProgressiveLoader::LoadJpegSliceContent(
459 const OrthancStone::GetOrthancWebViewerJpegCommand::SuccessMessage& message) 457 const GetOrthancWebViewerJpegCommand::SuccessMessage& message)
460 { 458 {
461 ORTHANC_ASSERT(progressiveQuality_, "INTERNAL ERROR: OrthancSeriesVolumeProgressiveLoader::LoadJpegSliceContent" 459 ORTHANC_ASSERT(progressiveQuality_, "INTERNAL ERROR: OrthancSeriesVolumeProgressiveLoader::LoadJpegSliceContent"
462 << " called while progressiveQuality_ is false!"); 460 << " called while progressiveQuality_ is false!");
463 461
464 LOG(TRACE) << "OrthancSeriesVolumeProgressiveLoader::LoadJpegSliceContent"; 462 LOG(TRACE) << "OrthancSeriesVolumeProgressiveLoader::LoadJpegSliceContent";
465 unsigned int quality; 463 unsigned int quality;
466 464
467 switch (dynamic_cast<const OrthancStone::GetOrthancWebViewerJpegCommand&>(message.GetOrigin()).GetQuality()) 465 switch (dynamic_cast<const GetOrthancWebViewerJpegCommand&>(message.GetOrigin()).GetQuality())
468 { 466 {
469 case 50: 467 case 50:
470 quality = QUALITY_00; 468 quality = QUALITY_00;
471 break; 469 break;
472 470
507 medadataSchedulingPriority_ = p; 505 medadataSchedulingPriority_ = p;
508 sliceSchedulingPriority_ = p; 506 sliceSchedulingPriority_ = p;
509 } 507 }
510 508
511 OrthancSeriesVolumeProgressiveLoader::OrthancSeriesVolumeProgressiveLoader( 509 OrthancSeriesVolumeProgressiveLoader::OrthancSeriesVolumeProgressiveLoader(
512 OrthancStone::ILoadersContext& loadersContext, 510 ILoadersContext& loadersContext,
513 boost::shared_ptr<OrthancStone::DicomVolumeImage> volume, 511 boost::shared_ptr<DicomVolumeImage> volume,
514 bool progressiveQuality) 512 bool progressiveQuality)
515 : loadersContext_(loadersContext) 513 : loadersContext_(loadersContext)
516 , active_(false) 514 , active_(false)
517 , progressiveQuality_(progressiveQuality) 515 , progressiveQuality_(progressiveQuality)
518 , simultaneousDownloads_(4) 516 , simultaneousDownloads_(4)
519 , volume_(volume) 517 , volume_(volume)
520 , sorter_(new OrthancStone::BasicFetchingItemsSorter::Factory) 518 , sorter_(new BasicFetchingItemsSorter::Factory)
521 , volumeImageReadyInHighQuality_(false) 519 , volumeImageReadyInHighQuality_(false)
522 , medadataSchedulingPriority_(0) 520 , medadataSchedulingPriority_(0)
523 , sliceSchedulingPriority_(0) 521 , sliceSchedulingPriority_(0)
524 { 522 {
525 } 523 }
526 524
527 boost::shared_ptr<OrthancSeriesVolumeProgressiveLoader> 525 boost::shared_ptr<OrthancSeriesVolumeProgressiveLoader>
528 OrthancSeriesVolumeProgressiveLoader::Create( 526 OrthancSeriesVolumeProgressiveLoader::Create(
529 OrthancStone::ILoadersContext& loadersContext, 527 ILoadersContext& loadersContext,
530 boost::shared_ptr<OrthancStone::DicomVolumeImage> volume, 528 boost::shared_ptr<DicomVolumeImage> volume,
531 bool progressiveQuality) 529 bool progressiveQuality)
532 { 530 {
533 std::unique_ptr<OrthancStone::ILoadersContext::ILock> lock(loadersContext.Lock()); 531 std::unique_ptr<ILoadersContext::ILock> lock(loadersContext.Lock());
534 532
535 boost::shared_ptr<OrthancSeriesVolumeProgressiveLoader> obj( 533 boost::shared_ptr<OrthancSeriesVolumeProgressiveLoader> obj(
536 new OrthancSeriesVolumeProgressiveLoader( 534 new OrthancSeriesVolumeProgressiveLoader(
537 loadersContext, volume, progressiveQuality)); 535 loadersContext, volume, progressiveQuality));
538 536
539 obj->Register<OrthancStone::OrthancRestApiCommand::SuccessMessage>( 537 obj->Register<OrthancRestApiCommand::SuccessMessage>(
540 lock->GetOracleObservable(), 538 lock->GetOracleObservable(),
541 &OrthancSeriesVolumeProgressiveLoader::LoadGeometry); 539 &OrthancSeriesVolumeProgressiveLoader::LoadGeometry);
542 540
543 obj->Register<OrthancStone::GetOrthancImageCommand::SuccessMessage>( 541 obj->Register<GetOrthancImageCommand::SuccessMessage>(
544 lock->GetOracleObservable(), 542 lock->GetOracleObservable(),
545 &OrthancSeriesVolumeProgressiveLoader::LoadBestQualitySliceContent); 543 &OrthancSeriesVolumeProgressiveLoader::LoadBestQualitySliceContent);
546 544
547 obj->Register<OrthancStone::GetOrthancWebViewerJpegCommand::SuccessMessage>( 545 obj->Register<GetOrthancWebViewerJpegCommand::SuccessMessage>(
548 lock->GetOracleObservable(), 546 lock->GetOracleObservable(),
549 &OrthancSeriesVolumeProgressiveLoader::LoadJpegSliceContent); 547 &OrthancSeriesVolumeProgressiveLoader::LoadJpegSliceContent);
550 548
551 return obj; 549 return obj;
552 } 550 }
584 } 582 }
585 else 583 else
586 { 584 {
587 active_ = true; 585 active_ = true;
588 586
589 std::unique_ptr<OrthancStone::OrthancRestApiCommand> command(new OrthancStone::OrthancRestApiCommand); 587 std::unique_ptr<OrthancRestApiCommand> command(new OrthancRestApiCommand);
590 command->SetUri("/series/" + seriesId + "/instances-tags"); 588 command->SetUri("/series/" + seriesId + "/instances-tags");
591 { 589 {
592 std::unique_ptr<OrthancStone::ILoadersContext::ILock> lock(loadersContext_.Lock()); 590 std::unique_ptr<ILoadersContext::ILock> lock(loadersContext_.Lock());
593 boost::shared_ptr<IObserver> observer(GetSharedObserver()); 591 boost::shared_ptr<IObserver> observer(GetSharedObserver());
594 lock->Schedule(observer, medadataSchedulingPriority_, command.release()); 592 lock->Schedule(observer, medadataSchedulingPriority_, command.release());
595 } 593 }
596 } 594 }
597 } 595 }
598 596
599 597
600 OrthancStone::IVolumeSlicer::IExtractedSlice* 598 IVolumeSlicer::IExtractedSlice*
601 OrthancSeriesVolumeProgressiveLoader::ExtractSlice(const OrthancStone::CoordinateSystem3D& cuttingPlane) 599 OrthancSeriesVolumeProgressiveLoader::ExtractSlice(const CoordinateSystem3D& cuttingPlane)
602 { 600 {
603 if (volume_->HasGeometry()) 601 if (volume_->HasGeometry())
604 { 602 {
605 return new ExtractedSlice(*this, cuttingPlane); 603 return new ExtractedSlice(*this, cuttingPlane);
606 } 604 }