diff Framework/Loaders/OrthancMultiframeVolumeLoader.cpp @ 1381:f4a06ad1580b

Branch broker is now the new default
author Benjamin Golinvaux <bgo@osimis.io>
date Wed, 22 Apr 2020 14:05:47 +0200
parents 8a0a62189f46 104e0b0f2316
children 30deba7bc8e2 75ac66d5f4b2
line wrap: on
line diff
--- a/Framework/Loaders/OrthancMultiframeVolumeLoader.cpp	Mon Apr 20 18:26:32 2020 +0200
+++ b/Framework/Loaders/OrthancMultiframeVolumeLoader.cpp	Wed Apr 22 14:05:47 2020 +0200
@@ -44,7 +44,7 @@
 
     }
 
-    virtual void Handle(const OrthancRestApiCommand::SuccessMessage& message)
+    virtual void Handle(const OrthancStone::OrthancRestApiCommand::SuccessMessage& message)
     {
       // Complete the DICOM tags with just-received "Grid Frame Offset Vector"
       std::string s = Orthanc::Toolbox::StripSpaces(message.GetAnswer());
@@ -78,7 +78,7 @@
     {
     }
       
-    virtual void Handle(const OrthancRestApiCommand::SuccessMessage& message)
+    virtual void Handle(const OrthancStone::OrthancRestApiCommand::SuccessMessage& message)
     {
       OrthancMultiframeVolumeLoader& loader = GetLoader<OrthancMultiframeVolumeLoader>();
         
@@ -93,15 +93,15 @@
       std::unique_ptr<Orthanc::DicomMap> dicom(new Orthanc::DicomMap);
       dicom->FromDicomAsJson(body);
 
-      if (StringToSopClassUid(GetSopClassUid(*dicom)) == SopClassUid_RTDose)
+      if (OrthancStone::StringToSopClassUid(GetSopClassUid(*dicom)) == OrthancStone::SopClassUid_RTDose)
       {
         // Download the "Grid Frame Offset Vector" DICOM tag, that is
         // mandatory for RT-DOSE, but is too long to be returned by default
           
-        std::unique_ptr<OrthancRestApiCommand> command(new OrthancRestApiCommand);
+        std::unique_ptr<OrthancStone::OrthancRestApiCommand> command(new OrthancStone::OrthancRestApiCommand);
         command->SetUri("/instances/" + loader.GetInstanceId() + "/content/" +
                         Orthanc::DICOM_TAG_GRID_FRAME_OFFSET_VECTOR.Format());
-        command->SetPayload(new LoadRTDoseGeometry(loader, dicom.release()));
+        command->AcquirePayload(new LoadRTDoseGeometry(loader, dicom.release()));
 
         Schedule(command.release());
       }
@@ -120,7 +120,7 @@
     {
     }
       
-    virtual void Handle(const OrthancRestApiCommand::SuccessMessage& message)
+    virtual void Handle(const OrthancStone::OrthancRestApiCommand::SuccessMessage& message)
     {
       GetLoader<OrthancMultiframeVolumeLoader>().SetTransferSyntax(message.GetAnswer());
     }
@@ -134,7 +134,7 @@
     {
     }
       
-    virtual void Handle(const OrthancRestApiCommand::SuccessMessage& message)
+    virtual void Handle(const OrthancStone::OrthancRestApiCommand::SuccessMessage& message)
     {
       GetLoader<OrthancMultiframeVolumeLoader>().SetUncompressedPixelData(message.GetAnswer());
     }
@@ -171,11 +171,11 @@
         transferSyntaxUid_ == "1.2.840.10008.1.2.1" ||
         transferSyntaxUid_ == "1.2.840.10008.1.2.2")
     {
-      std::unique_ptr<OrthancRestApiCommand> command(new OrthancRestApiCommand);
+      std::unique_ptr<OrthancStone::OrthancRestApiCommand> command(new OrthancStone::OrthancRestApiCommand);
       command->SetHttpHeader("Accept-Encoding", "gzip");
       command->SetUri("/instances/" + instanceId_ + "/content/" +
                       Orthanc::DICOM_TAG_PIXEL_DATA.Format() + "/0");
-      command->SetPayload(new LoadUncompressedPixelData(*this));
+      command->AcquirePayload(new LoadUncompressedPixelData(*this));
       Schedule(command.release());
     }
     else
@@ -194,7 +194,7 @@
 
   void OrthancMultiframeVolumeLoader::SetGeometry(const Orthanc::DicomMap& dicom)
   {
-    DicomInstanceParameters parameters(dicom);
+    OrthancStone::DicomInstanceParameters parameters(dicom);
     volume_->SetDicomParameters(parameters);
       
     Orthanc::PixelFormat format;
@@ -206,7 +206,7 @@
     double spacingZ;
     switch (parameters.GetSopClassUid())
     {
-      case SopClassUid_RTDose:
+      case OrthancStone::SopClassUid_RTDose:
         spacingZ = parameters.GetThickness();
         break;
 
@@ -221,7 +221,7 @@
     const unsigned int depth = parameters.GetImageInformation().GetNumberOfFrames();
 
     {
-      VolumeImageGeometry geometry;
+      OrthancStone::VolumeImageGeometry geometry;
       geometry.SetSizeInVoxels(width, height, depth);
       geometry.SetAxialGeometry(parameters.GetGeometry());
       geometry.SetVoxelDimensions(parameters.GetPixelSpacingX(),
@@ -235,7 +235,7 @@
 
 
 
-    BroadcastMessage(DicomVolumeImage::GeometryReadyMessage(*volume_));
+    BroadcastMessage(OrthancStone::DicomVolumeImage::GeometryReadyMessage(*volume_));
   }
 
 
@@ -266,7 +266,7 @@
   void OrthancMultiframeVolumeLoader::CopyPixelDataAndComputeDistribution(
     const std::string& pixelData, std::map<T,uint64_t>& distribution)
   {
-    ImageBuffer3D& target = volume_->GetPixelData();
+    OrthancStone::ImageBuffer3D& target = volume_->GetPixelData();
       
     const unsigned int bpp = target.GetBytesPerPixel();
     const unsigned int width = target.GetWidth();
@@ -308,11 +308,11 @@
 
       for (unsigned int z = 0; z < depth; z++)
       {
-        ImageBuffer3D::SliceWriter writer(target, VolumeProjection_Axial, z);
+        OrthancStone::ImageBuffer3D::SliceWriter writer(target, OrthancStone::VolumeProjection_Axial, z);
 
         assert(writer.GetAccessor().GetWidth() == width &&
           writer.GetAccessor().GetHeight() == height);
-
+#if 0
         for (unsigned int y = 0; y < height; y++)
         {
           assert(sizeof(T) == Orthanc::GetBytesPerPixel(target.GetFormat()));
@@ -329,6 +329,28 @@
             source += bpp;
           }
         }
+#else
+        // optimized version (fixed) as of 2020-04-15
+        unsigned int pitch = writer.GetAccessor().GetPitch();
+        T* targetAddrLine = reinterpret_cast<T*>(writer.GetAccessor().GetRow(0));
+        assert(sizeof(T) == Orthanc::GetBytesPerPixel(target.GetFormat()));
+
+        for (unsigned int y = 0; y < height; y++)
+        {
+          T* targetAddrPix = targetAddrLine;
+          for (unsigned int x = 0; x < width; x++)
+          {
+            CopyPixel(*targetAddrPix, source);
+
+            distribution[*targetAddrPix] += 1;
+
+            targetAddrPix++;
+            source += bpp;
+          }
+          uint8_t* targetAddrLineBytes = reinterpret_cast<uint8_t*>(targetAddrLine) + pitch;
+          targetAddrLine = reinterpret_cast<T*>(targetAddrLineBytes);
+        }
+#endif
       }
     }
   }
@@ -343,7 +365,7 @@
     }
     else
     {
-      ImageBuffer3D& target = volume_->GetPixelData();
+      OrthancStone::ImageBuffer3D& target = volume_->GetPixelData();
 
       const uint64_t width = target.GetWidth();
       const uint64_t height = target.GetHeight();
@@ -494,7 +516,7 @@
     volume_->IncrementRevision();
 
     pixelDataLoaded_ = true;
-    BroadcastMessage(DicomVolumeImage::ContentUpdatedMessage(*volume_));
+    BroadcastMessage(OrthancStone::DicomVolumeImage::ContentUpdatedMessage(*volume_));
   }
   
   bool OrthancMultiframeVolumeLoader::HasGeometry() const
@@ -508,19 +530,17 @@
   }
 
   OrthancMultiframeVolumeLoader::OrthancMultiframeVolumeLoader(
-    boost::shared_ptr<DicomVolumeImage> volume,
-    IOracle& oracle,
-    IObservable& oracleObservable,
-    float outliersHalfRejectionRate) :
-    LoaderStateMachine(oracle, oracleObservable),
-    IObservable(oracleObservable.GetBroker()),
-    volume_(volume),
-    pixelDataLoaded_(false),
-    outliersHalfRejectionRate_(outliersHalfRejectionRate),
-    distributionRawMin_(0),
-    distributionRawMax_(0),
-    computedDistributionMin_(0),
-    computedDistributionMax_(0)
+    OrthancStone::ILoadersContext& loadersContext,
+    boost::shared_ptr<OrthancStone::DicomVolumeImage> volume,
+    float outliersHalfRejectionRate) 
+    : LoaderStateMachine(loadersContext)
+    , volume_(volume)
+    , pixelDataLoaded_(false)
+    , outliersHalfRejectionRate_(outliersHalfRejectionRate)
+    , distributionRawMin_(0)
+    , distributionRawMax_(0)
+    , computedDistributionMin_(0)
+    , computedDistributionMax_(0)
   {
     if (volume.get() == NULL)
     {
@@ -528,12 +548,27 @@
     }
   }
 
+
+  boost::shared_ptr<OrthancMultiframeVolumeLoader>
+    OrthancMultiframeVolumeLoader::Create(
+      OrthancStone::ILoadersContext& loadersContext, 
+      boost::shared_ptr<OrthancStone::DicomVolumeImage> volume, 
+      float outliersHalfRejectionRate /*= 0.0005*/)
+  {
+    boost::shared_ptr<OrthancMultiframeVolumeLoader> obj(
+      new OrthancMultiframeVolumeLoader(
+        loadersContext,
+        volume,
+        outliersHalfRejectionRate));
+    obj->LoaderStateMachine::PostConstructor();
+    return obj;
+  }
+
   OrthancMultiframeVolumeLoader::~OrthancMultiframeVolumeLoader()
   {
     LOG(TRACE) << "OrthancMultiframeVolumeLoader::~OrthancMultiframeVolumeLoader()";
   }
-
-
+  
   void OrthancMultiframeVolumeLoader::GetDistributionMinMax
   (float& minValue, float& maxValue) const
   {
@@ -563,17 +598,17 @@
     instanceId_ = instanceId;
 
     {
-      std::unique_ptr<OrthancRestApiCommand> command(new OrthancRestApiCommand);
+      std::unique_ptr<OrthancStone::OrthancRestApiCommand> command(new OrthancStone::OrthancRestApiCommand);
       command->SetHttpHeader("Accept-Encoding", "gzip");
       command->SetUri("/instances/" + instanceId + "/tags");
-      command->SetPayload(new LoadGeometry(*this));
+      command->AcquirePayload(new LoadGeometry(*this));
       Schedule(command.release());
     }
 
     {
-      std::unique_ptr<OrthancRestApiCommand> command(new OrthancRestApiCommand);
+      std::unique_ptr<OrthancStone::OrthancRestApiCommand> command(new OrthancStone::OrthancRestApiCommand);
       command->SetUri("/instances/" + instanceId + "/metadata/TransferSyntax");
-      command->SetPayload(new LoadTransferSyntax(*this));
+      command->AcquirePayload(new LoadTransferSyntax(*this));
       Schedule(command.release());
     }
   }