changeset 87:3d83d34cd4db

sync, optimizations
author Sebastien Jodogne <s.jodogne@gmail.com>
date Fri, 16 Dec 2016 16:44:14 +0100
parents 319b8c45c231
children 7dffa59c498d
files Applications/ApplicationToolbox.cpp Framework/ImageToolbox.cpp Framework/Inputs/DicomPyramidInstance.cpp Resources/Orthanc/Plugins/Samples/Common/DicomDatasetReader.cpp Resources/Orthanc/Plugins/Samples/Common/DicomDatasetReader.h Resources/Orthanc/Plugins/Samples/Common/DicomTag.h TODO
diffstat 7 files changed, 104 insertions(+), 30 deletions(-) [+]
line wrap: on
line diff
--- a/Applications/ApplicationToolbox.cpp	Fri Dec 16 14:55:19 2016 +0100
+++ b/Applications/ApplicationToolbox.cpp	Fri Dec 16 16:44:14 2016 +0100
@@ -28,6 +28,17 @@
 
 #include <boost/lexical_cast.hpp>
 #include <boost/regex.hpp>
+#include <cassert>
+
+
+static bool DisplayPerformanceWarning()
+{
+  (void) DisplayPerformanceWarning;   // Disable warning about unused function
+  LOG(WARNING) << "Performance warning in whole-slide imaging: "
+               << "Non-release build, runtime debug assertions are turned on";
+  return true;
+}
+
 
 namespace OrthancWSI
 {
@@ -39,6 +50,7 @@
       Orthanc::HttpClient::InitializeOpenSsl();
       Orthanc::HttpClient::GlobalInitialize();
       Orthanc::FromDcmtkBridge::InitializeDictionary(false /* don't load private dictionary */);
+      assert(DisplayPerformanceWarning());
     }
 
 
--- a/Framework/ImageToolbox.cpp	Fri Dec 16 14:55:19 2016 +0100
+++ b/Framework/ImageToolbox.cpp	Fri Dec 16 16:44:14 2016 +0100
@@ -221,9 +221,11 @@
                                  unsigned int y,
                                  unsigned int channel,
                                  int offsetX,
-                                 int offsetY)
+                                 int offsetY,
+                                 unsigned int bytesPerPixel)
     {
-      assert(channel < source.GetBytesPerPixel());
+      assert(bytesPerPixel == source.GetBytesPerPixel());
+      assert(channel < bytesPerPixel);
       assert(source.GetFormat() == Orthanc::PixelFormat_Grayscale8 ||
              source.GetFormat() == Orthanc::PixelFormat_RGB24 ||
              source.GetFormat() == Orthanc::PixelFormat_RGBA32);  // 16bpp is unsupported
@@ -255,14 +257,15 @@
       }
 
       return *(reinterpret_cast<const uint8_t*>(source.GetConstBuffer()) +
-               y * source.GetPitch() + x * source.GetBytesPerPixel() + channel);
+               y * source.GetPitch() + x * bytesPerPixel + channel);
     }
 
 
     static uint8_t SmoothPixelValue(const Orthanc::ImageAccessor& source,
                                     unsigned int x,
                                     unsigned int y,
-                                    unsigned int channel)
+                                    unsigned int channel,
+                                    unsigned int bytesPerPixel)
     {
       static const uint32_t kernel[5] = { 1, 4, 6, 4, 1 };
       static const uint32_t normalization = 2 * (1 + 4 + 6 + 4 + 1);
@@ -272,13 +275,13 @@
       // Horizontal smoothing
       for (int offset = -2; offset <= 2; offset++)
       {
-        accumulator += kernel[offset + 2] * GetPixelValue(source, x, y, channel, offset, 0);
+        accumulator += kernel[offset + 2] * GetPixelValue(source, x, y, channel, offset, 0, bytesPerPixel);
       }
 
       // Vertical smoothing
       for (int offset = -2; offset <= 2; offset++)
       {
-        accumulator += kernel[offset + 2] * GetPixelValue(source, x, y, channel, 0, offset);
+        accumulator += kernel[offset + 2] * GetPixelValue(source, x, y, channel, 0, offset, bytesPerPixel);
       }
 
       return static_cast<uint8_t>(accumulator / normalization);
@@ -307,6 +310,8 @@
                                                             source.GetWidth() / 2, 
                                                             source.GetHeight() / 2));
 
+      unsigned int bytesPerPixel = source.GetBytesPerPixel();
+
       for (unsigned int y = 0; y < source.GetHeight() / 2; y++)
       {
         uint8_t* q = reinterpret_cast<uint8_t*>(result->GetRow(y));
@@ -317,11 +322,11 @@
           {
             if (smooth)
             {
-              q[c] = SmoothPixelValue(source, 2 * x, 2 * y, c);
+              q[c] = SmoothPixelValue(source, 2 * x, 2 * y, c, bytesPerPixel);
             }
             else
             {
-              q[c] = GetPixelValue(source, 2 * x, 2 * y, c, 0, 0);
+              q[c] = GetPixelValue(source, 2 * x, 2 * y, c, 0, 0, bytesPerPixel);
             }
           }
         }
--- a/Framework/Inputs/DicomPyramidInstance.cpp	Fri Dec 16 14:55:19 2016 +0100
+++ b/Framework/Inputs/DicomPyramidInstance.cpp	Fri Dec 16 16:44:14 2016 +0100
@@ -40,8 +40,8 @@
   {
     using namespace OrthancPlugins;
 
-    DicomDatasetReader header(new FullOrthancDataset
-                              (orthanc, "/instances/" + instanceId + "/header"));
+    FullOrthancDataset dataset(orthanc, "/instances/" + instanceId + "/header");
+    DicomDatasetReader header(dataset);
 
     std::string s = Orthanc::Toolbox::StripSpaces
       (header.GetMandatoryStringValue(DICOM_TAG_TRANSFER_SYNTAX_UID));
@@ -131,7 +131,8 @@
   {
     using namespace OrthancPlugins;
 
-    DicomDatasetReader reader(new FullOrthancDataset(orthanc, "/instances/" + instanceId + "/tags"));
+    FullOrthancDataset dataset(orthanc, "/instances/" + instanceId + "/tags");
+    DicomDatasetReader reader(dataset);
 
     if (reader.GetMandatoryStringValue(DICOM_TAG_SOP_CLASS_UID) != "1.2.840.10008.5.1.4.1.1.77.1.6" ||
         reader.GetMandatoryStringValue(DICOM_TAG_MODALITY) != "SM")
--- a/Resources/Orthanc/Plugins/Samples/Common/DicomDatasetReader.cpp	Fri Dec 16 14:55:19 2016 +0100
+++ b/Resources/Orthanc/Plugins/Samples/Common/DicomDatasetReader.cpp	Fri Dec 16 16:44:14 2016 +0100
@@ -68,20 +68,31 @@
   }
 
 
-  DicomDatasetReader::DicomDatasetReader(IDicomDataset* dataset) :  // takes ownership
+  DicomDatasetReader::DicomDatasetReader(const IDicomDataset& dataset) :
     dataset_(dataset)
   {
-    if (dataset == NULL)
+  }
+  
+
+  std::string DicomDatasetReader::GetStringValue(const DicomPath& path,
+                                                 const std::string& defaultValue) const
+  {
+    std::string s;
+    if (dataset_.GetStringValue(s, path))
     {
-      ORTHANC_PLUGINS_THROW_EXCEPTION(ParameterOutOfRange);
+      return s;
+    }
+    else
+    {
+      return defaultValue;
     }
   }
-  
+
 
   std::string DicomDatasetReader::GetMandatoryStringValue(const DicomPath& path) const
   {
     std::string s;
-    if (dataset_->GetStringValue(s, path))
+    if (dataset_.GetStringValue(s, path))
     {
       return s;
     }
@@ -92,12 +103,22 @@
   }
 
 
-  int DicomDatasetReader::GetIntegerValue(const DicomPath& path)
+  template <typename T>
+  static T GetValueInternal(const IDicomDataset& dataset,
+                            const DicomPath& path)
   {
     try
     {
-      std::string s = StripSpaces(GetMandatoryStringValue(path));
-      return boost::lexical_cast<int>(s);
+      std::string s;
+
+      if (dataset.GetStringValue(s, path))
+      {
+        return boost::lexical_cast<T>(StripSpaces(s));
+      }
+      else
+      {
+        ORTHANC_PLUGINS_THROW_EXCEPTION(InexistentTag);
+      }
     }
     catch (boost::bad_lexical_cast&)
     {
@@ -106,10 +127,16 @@
   }
 
 
-  unsigned int DicomDatasetReader::GetUnsignedIntegerValue(const DicomPath& path)
+  int DicomDatasetReader::GetIntegerValue(const DicomPath& path) const
+  {
+    return GetValueInternal<int>(dataset_, path);
+  }
+
+
+  unsigned int DicomDatasetReader::GetUnsignedIntegerValue(const DicomPath& path) const
   {
     int value = GetIntegerValue(path);
-
+    
     if (value >= 0)
     {
       return static_cast<unsigned int>(value);
@@ -119,4 +146,16 @@
       ORTHANC_PLUGINS_THROW_EXCEPTION(ParameterOutOfRange);
     }
   }
+
+
+  float DicomDatasetReader::GetFloatValue(const DicomPath& path) const
+  {
+    return GetValueInternal<float>(dataset_, path);
+  }
+
+
+  double DicomDatasetReader::GetDoubleValue(const DicomPath& path) const
+  {
+    return GetValueInternal<double>(dataset_, path);
+  }
 }
--- a/Resources/Orthanc/Plugins/Samples/Common/DicomDatasetReader.h	Fri Dec 16 14:55:19 2016 +0100
+++ b/Resources/Orthanc/Plugins/Samples/Common/DicomDatasetReader.h	Fri Dec 16 16:44:14 2016 +0100
@@ -35,26 +35,34 @@
 #include "IDicomDataset.h"
 
 #include <memory>
+#include <vector>
 
 namespace OrthancPlugins
 {
   class DicomDatasetReader : public boost::noncopyable
   {
   private:
-    std::auto_ptr<IDicomDataset>  dataset_;
+    const IDicomDataset&  dataset_;
 
   public:
-    DicomDatasetReader(IDicomDataset* dataset);  // takes ownership
+    DicomDatasetReader(const IDicomDataset& dataset);
 
-    IDicomDataset& GetDataset() const
+    const IDicomDataset& GetDataset() const
     {
-      return *dataset_;
+      return dataset_;
     }
 
+    std::string GetStringValue(const DicomPath& path,
+                               const std::string& defaultValue) const;
+
     std::string GetMandatoryStringValue(const DicomPath& path) const;
 
-    int GetIntegerValue(const DicomPath& path);
+    int GetIntegerValue(const DicomPath& path) const;
+
+    unsigned int GetUnsignedIntegerValue(const DicomPath& path) const;
 
-    unsigned int GetUnsignedIntegerValue(const DicomPath& path);
+    float GetFloatValue(const DicomPath& path) const;
+
+    double GetDoubleValue(const DicomPath& path) const;
   };
 }
--- a/Resources/Orthanc/Plugins/Samples/Common/DicomTag.h	Fri Dec 16 14:55:19 2016 +0100
+++ b/Resources/Orthanc/Plugins/Samples/Common/DicomTag.h	Fri Dec 16 16:44:14 2016 +0100
@@ -77,19 +77,27 @@
 
 
   static const DicomTag DICOM_TAG_BITS_STORED(0x0028, 0x0101);
+  static const DicomTag DICOM_TAG_COLUMNS(0x0028, 0x0011);
   static const DicomTag DICOM_TAG_COLUMN_POSITION_IN_TOTAL_IMAGE_PIXEL_MATRIX(0x0048, 0x021e);
-  static const DicomTag DICOM_TAG_COLUMNS(0x0028, 0x0011);
+  static const DicomTag DICOM_TAG_IMAGE_ORIENTATION_PATIENT(0x0020, 0x0037);
+  static const DicomTag DICOM_TAG_IMAGE_POSITION_PATIENT(0x0020, 0x0032);
   static const DicomTag DICOM_TAG_MODALITY(0x0008, 0x0060);
   static const DicomTag DICOM_TAG_NUMBER_OF_FRAMES(0x0028, 0x0008);
   static const DicomTag DICOM_TAG_PER_FRAME_FUNCTIONAL_GROUPS_SEQUENCE(0x5200, 0x9230);
   static const DicomTag DICOM_TAG_PHOTOMETRIC_INTERPRETATION(0x0028, 0x0004);
   static const DicomTag DICOM_TAG_PIXEL_REPRESENTATION(0x0028, 0x0103);
+  static const DicomTag DICOM_TAG_PIXEL_SPACING(0x0028, 0x0030);
   static const DicomTag DICOM_TAG_PLANE_POSITION_SLIDE_SEQUENCE(0x0048, 0x021a);
-  static const DicomTag DICOM_TAG_ROW_POSITION_IN_TOTAL_IMAGE_PIXEL_MATRIX(0x0048, 0x021f);
+  static const DicomTag DICOM_TAG_RESCALE_INTERCEPT(0x0028, 0x1052);
+  static const DicomTag DICOM_TAG_RESCALE_SLOPE(0x0028, 0x1053);
   static const DicomTag DICOM_TAG_ROWS(0x0028, 0x0010);
+  static const DicomTag DICOM_TAG_ROW_POSITION_IN_TOTAL_IMAGE_PIXEL_MATRIX(0x0048, 0x021f);
+  static const DicomTag DICOM_TAG_SAMPLES_PER_PIXEL(0x0028, 0x0002);
+  static const DicomTag DICOM_TAG_SLICE_THICKNESS(0x0018, 0x0050);
   static const DicomTag DICOM_TAG_SOP_CLASS_UID(0x0008, 0x0016);
-  static const DicomTag DICOM_TAG_SAMPLES_PER_PIXEL(0x0028, 0x0002);
   static const DicomTag DICOM_TAG_TOTAL_PIXEL_MATRIX_COLUMNS(0x0048, 0x0006);
   static const DicomTag DICOM_TAG_TOTAL_PIXEL_MATRIX_ROWS(0x0048, 0x0007);
   static const DicomTag DICOM_TAG_TRANSFER_SYNTAX_UID(0x0002, 0x0010);
+  static const DicomTag DICOM_TAG_WINDOW_CENTER(0x0028, 0x1050);
+  static const DicomTag DICOM_TAG_WINDOW_WIDTH(0x0028, 0x1051);
 }
--- a/TODO	Fri Dec 16 14:55:19 2016 +0100
+++ b/TODO	Fri Dec 16 16:44:14 2016 +0100
@@ -16,6 +16,7 @@
 -----------
 
 * Check out rapidjson: https://github.com/miloyip/nativejson-benchmark
+* Optimize ImageToolbox::Set() and ImageToolbox::Halve()
 
 
 -------------