changeset 2554:ea63d9f90377

/tags now returns multiple numerical values in a \ separated string
author am@osimis.io
date Wed, 02 May 2018 11:50:47 +0200
parents 7853c9a67605
children 50d80af0719e
files Core/DicomParsing/FromDcmtkBridge.cpp NEWS Resources/CMake/OrthancFrameworkParameters.cmake
diffstat 3 files changed, 65 insertions(+), 31 deletions(-) [+]
line wrap: on
line diff
--- a/Core/DicomParsing/FromDcmtkBridge.cpp	Thu Apr 19 16:26:17 2018 +0200
+++ b/Core/DicomParsing/FromDcmtkBridge.cpp	Wed May 02 11:50:47 2018 +0200
@@ -57,6 +57,7 @@
 #include <boost/lexical_cast.hpp>
 #include <boost/filesystem.hpp>
 #include <boost/algorithm/string/predicate.hpp>
+#include <boost/algorithm/string/join.hpp>
 
 #include <dcmtk/dcmdata/dcdeftag.h>
 #include <dcmtk/dcmdata/dcdicent.h>
@@ -198,6 +199,56 @@
         return &dictionary_;
       }
     };
+
+    
+#define DCMTK_TO_CTYPE_CONVERTER(converter, cType, dcmtkType, getter) \
+ \
+    struct converter \
+    { \
+      typedef cType CType; \
+ \
+      static bool Apply(CType& result, \
+                        DcmElement& element, \
+                        size_t i) \
+      { \
+        return dynamic_cast<dcmtkType&>(element).getter(result, i).good(); \
+      } \
+    };
+
+DCMTK_TO_CTYPE_CONVERTER(DcmtkToSint32Converter, Sint32, DcmSignedLong, getSint32)
+DCMTK_TO_CTYPE_CONVERTER(DcmtkToSint16Converter, Sint16, DcmSignedShort, getSint16)
+DCMTK_TO_CTYPE_CONVERTER(DcmtkToUint32Converter, Uint32, DcmUnsignedLong, getUint32)
+DCMTK_TO_CTYPE_CONVERTER(DcmtkToUint16Converter, Uint16, DcmUnsignedShort, getUint16)
+DCMTK_TO_CTYPE_CONVERTER(DcmtkToFloat32Converter, Float32, DcmFloatingPointSingle, getFloat32)
+DCMTK_TO_CTYPE_CONVERTER(DcmtkToFloat64Converter, Float64, DcmFloatingPointDouble, getFloat64)
+
+
+    template <typename F>
+    static DicomValue* ApplyDcmtkToCTypeConverter(DcmElement& element)
+    {
+      F f;
+      typename F::CType value;
+
+      if (element.getLength() > sizeof(typename F::CType)
+          && (element.getLength() % sizeof(typename F::CType)) == 0)
+      {
+        size_t count = element.getLength() / sizeof(typename F::CType);
+        std::vector<std::string> strings;
+        for (size_t i = 0; i < count; i++) {
+          if (f.Apply(value, element, i)) {
+            strings.push_back(boost::lexical_cast<std::string>(value));
+          }
+        }
+        return new DicomValue(boost::algorithm::join(strings, "\\"), false);
+      }
+      else if (f.Apply(value, element, 0)) {
+        return new DicomValue(boost::lexical_cast<std::string>(value), false);
+      }
+      else {
+        return new DicomValue;
+      }
+    }
+
   }
 
 
@@ -572,56 +623,32 @@
       
         case EVR_SL:  // signed long
         {
-          Sint32 f;
-          if (dynamic_cast<DcmSignedLong&>(element).getSint32(f).good())
-            return new DicomValue(boost::lexical_cast<std::string>(f), false);
-          else
-            return new DicomValue;
+          return ApplyDcmtkToCTypeConverter<DcmtkToSint32Converter>(element);
         }
 
         case EVR_SS:  // signed short
         {
-          Sint16 f;
-          if (dynamic_cast<DcmSignedShort&>(element).getSint16(f).good())
-            return new DicomValue(boost::lexical_cast<std::string>(f), false);
-          else
-            return new DicomValue;
+          return ApplyDcmtkToCTypeConverter<DcmtkToSint16Converter>(element);
         }
 
         case EVR_UL:  // unsigned long
         {
-          Uint32 f;
-          if (dynamic_cast<DcmUnsignedLong&>(element).getUint32(f).good())
-            return new DicomValue(boost::lexical_cast<std::string>(f), false);
-          else
-            return new DicomValue;
+          return ApplyDcmtkToCTypeConverter<DcmtkToUint32Converter>(element);
         }
 
         case EVR_US:  // unsigned short
         {
-          Uint16 f;
-          if (dynamic_cast<DcmUnsignedShort&>(element).getUint16(f).good())
-            return new DicomValue(boost::lexical_cast<std::string>(f), false);
-          else
-            return new DicomValue;
+          return ApplyDcmtkToCTypeConverter<DcmtkToUint16Converter>(element);
         }
 
         case EVR_FL:  // float single-precision
         {
-          Float32 f;
-          if (dynamic_cast<DcmFloatingPointSingle&>(element).getFloat32(f).good())
-            return new DicomValue(boost::lexical_cast<std::string>(f), false);
-          else
-            return new DicomValue;
+          return ApplyDcmtkToCTypeConverter<DcmtkToFloat32Converter>(element);
         }
 
         case EVR_FD:  // float double-precision
         {
-          Float64 f;
-          if (dynamic_cast<DcmFloatingPointDouble&>(element).getFloat64(f).good())
-            return new DicomValue(boost::lexical_cast<std::string>(f), false);
-          else
-            return new DicomValue;
+          return ApplyDcmtkToCTypeConverter<DcmtkToFloat64Converter>(element);
         }
 
 
--- a/NEWS	Thu Apr 19 16:26:17 2018 +0200
+++ b/NEWS	Wed May 02 11:50:47 2018 +0200
@@ -1,6 +1,13 @@
 Pending changes in the mainline
 ===============================
 
+REST API
+--------
+* ".../tags" URI was returning only the first value of DicomTags containing 
+  multiple numerical value.  It now returns all values in a string separated
+  by \\ (i.e.: "1\\2\\3").  Note that, for data already in Orthanc, you'll need
+  to reconstruct the data by sending a POST request to the ".../reconstruct" URI.
+  This change triggered an update of ORTHANC_API_VERSION from 1.0 to 1.1
 
 Version 1.3.2 (2018-04-18)
 ==========================
--- a/Resources/CMake/OrthancFrameworkParameters.cmake	Thu Apr 19 16:26:17 2018 +0200
+++ b/Resources/CMake/OrthancFrameworkParameters.cmake	Wed May 02 11:50:47 2018 +0200
@@ -17,7 +17,7 @@
 # Version of the Orthanc API, can be retrieved from "/system" URI in
 # order to check whether new URI endpoints are available even if using
 # the mainline version of Orthanc
-set(ORTHANC_API_VERSION "1.0")
+set(ORTHANC_API_VERSION "1.1")
 
 
 #####################################################################