Mercurial > hg > orthanc-stone
comparison OrthancStone/Sources/Loaders/OrthancMultiframeVolumeLoader.cpp @ 2076:990f396484b1
fix rendering of RT-DOSE with negative GridFrameOffsetVector
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Tue, 11 Jul 2023 15:58:16 +0200 |
parents | 7053b8a0aaec |
children | 07964689cb0b |
comparison
equal
deleted
inserted
replaced
2075:d84bdcbd8bf1 | 2076:990f396484b1 |
---|---|
213 | 213 |
214 double spacingZ; | 214 double spacingZ; |
215 switch (parameters.GetSopClassUid()) | 215 switch (parameters.GetSopClassUid()) |
216 { | 216 { |
217 case SopClassUid_RTDose: | 217 case SopClassUid_RTDose: |
218 spacingZ = parameters.GetSliceThickness(); | 218 if (!parameters.ComputeFrameOffsetsSpacing(spacingZ)) |
219 { | |
220 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented, | |
221 "Cannot load RT-DOSE with incorrect GridFrameOffsetVector (3004,000C)"); | |
222 } | |
219 break; | 223 break; |
220 | 224 |
221 default: | 225 default: |
222 throw Orthanc::OrthancException( | 226 throw Orthanc::OrthancException( |
223 Orthanc::ErrorCode_NotImplemented, | 227 Orthanc::ErrorCode_NotImplemented, |
224 "No support for multiframe instances with SOP class UID: " + GetSopClassUid(dicom)); | 228 "No support for multiframe instances with SOP class UID: " + GetSopClassUid(dicom)); |
225 } | 229 } |
226 | 230 |
231 isReversedFrameOffsets_ = parameters.IsReversedFrameOffsets(); | |
232 | |
227 const unsigned int width = parameters.GetImageInformation().GetWidth(); | 233 const unsigned int width = parameters.GetImageInformation().GetWidth(); |
228 const unsigned int height = parameters.GetImageInformation().GetHeight(); | 234 const unsigned int height = parameters.GetImageInformation().GetHeight(); |
229 const unsigned int depth = parameters.GetImageInformation().GetNumberOfFrames(); | 235 const unsigned int depth = parameters.GetImageInformation().GetNumberOfFrames(); |
230 | 236 |
231 { | 237 { |
232 VolumeImageGeometry geometry; | 238 VolumeImageGeometry geometry; |
233 geometry.SetSizeInVoxels(width, height, depth); | 239 geometry.SetSizeInVoxels(width, height, depth); |
234 geometry.SetAxialGeometry(parameters.GetGeometry()); | 240 geometry.SetAxialGeometry(parameters.GetMultiFrameGeometry()); |
235 geometry.SetVoxelDimensions(parameters.GetPixelSpacingX(), | 241 geometry.SetVoxelDimensions(parameters.GetPixelSpacingX(), |
236 parameters.GetPixelSpacingY(), spacingZ); | 242 parameters.GetPixelSpacingY(), spacingZ); |
237 volume_->Initialize(geometry, format, true /* Do compute range */); | 243 volume_->Initialize(geometry, format, true /* Do compute range */); |
238 } | 244 } |
239 | 245 |
240 volume_->GetPixelData().Clear(); | 246 volume_->GetPixelData().Clear(); |
241 | 247 |
242 ScheduleFrameDownloads(); | 248 ScheduleFrameDownloads(); |
243 | |
244 | |
245 | 249 |
246 BroadcastMessage(DicomVolumeImage::GeometryReadyMessage(*volume_)); | 250 BroadcastMessage(DicomVolumeImage::GeometryReadyMessage(*volume_)); |
247 } | 251 } |
248 | 252 |
249 | 253 |
320 { | 324 { |
321 const uint8_t* source = reinterpret_cast<const uint8_t*>(pixelData.c_str()); | 325 const uint8_t* source = reinterpret_cast<const uint8_t*>(pixelData.c_str()); |
322 | 326 |
323 for (unsigned int z = 0; z < depth; z++) | 327 for (unsigned int z = 0; z < depth; z++) |
324 { | 328 { |
325 ImageBuffer3D::SliceWriter writer(target, VolumeProjection_Axial, z); | 329 unsigned targetZ; |
330 if (isReversedFrameOffsets_) | |
331 { | |
332 targetZ = depth - 1 - z; | |
333 } | |
334 else | |
335 { | |
336 targetZ = z; | |
337 } | |
338 | |
339 ImageBuffer3D::SliceWriter writer(target, VolumeProjection_Axial, targetZ); | |
326 | 340 |
327 assert(writer.GetAccessor().GetWidth() == width && | 341 assert(writer.GetAccessor().GetWidth() == width && |
328 writer.GetAccessor().GetHeight() == height); | 342 writer.GetAccessor().GetHeight() == height); |
329 #if 0 | 343 #if 0 |
330 for (unsigned int y = 0; y < height; y++) | 344 for (unsigned int y = 0; y < height; y++) |
552 ILoadersContext& loadersContext, | 566 ILoadersContext& loadersContext, |
553 boost::shared_ptr<DicomVolumeImage> volume, | 567 boost::shared_ptr<DicomVolumeImage> volume, |
554 float outliersHalfRejectionRate) | 568 float outliersHalfRejectionRate) |
555 : LoaderStateMachine(loadersContext) | 569 : LoaderStateMachine(loadersContext) |
556 , volume_(volume) | 570 , volume_(volume) |
571 , isReversedFrameOffsets_(false) | |
557 , pixelDataLoaded_(false) | 572 , pixelDataLoaded_(false) |
558 , outliersHalfRejectionRate_(outliersHalfRejectionRate) | 573 , outliersHalfRejectionRate_(outliersHalfRejectionRate) |
559 , distributionRawMin_(0) | 574 , distributionRawMin_(0) |
560 , distributionRawMax_(0) | 575 , distributionRawMax_(0) |
561 , computedDistributionMin_(0) | 576 , computedDistributionMin_(0) |