changeset 6631:dfa66ab964c9

improved support for OL value representation
author Sebastien Jodogne <s.jodogne@gmail.com>
date Fri, 20 Mar 2026 09:28:18 +0100
parents 71400f1c6143
children b8e78ccac532
files NEWS OrthancFramework/Sources/DicomParsing/FromDcmtkBridge.cpp
diffstat 2 files changed, 60 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/NEWS	Wed Mar 18 12:13:09 2026 +0100
+++ b/NEWS	Fri Mar 20 09:28:18 2026 +0100
@@ -22,7 +22,7 @@
 * New option "Utf8" available in the "{...}/archive" and "/tools/create-archive" routes
   to use UTF-8 filenames in the generated ZIP archives. It defaults to the value
   of the new configuration option "ZipUseUtf8".
-* Support for OF and OD value representations in "/instances/{...}/file" with content type
+* Support for OD, OF, and OL value representations in "/instances/{...}/file" with content type
   "application/dicom+json" (i.e. DICOMweb) and in "/instances/{...}/tags" (contribution by
   Yusuf Sayıta, Philips).
 * New "Content.Resources" field in "DicomModalityStore", "OrthancPeerStore" and "ResourceModification" 
--- a/OrthancFramework/Sources/DicomParsing/FromDcmtkBridge.cpp	Wed Mar 18 12:13:09 2026 +0100
+++ b/OrthancFramework/Sources/DicomParsing/FromDcmtkBridge.cpp	Fri Mar 20 09:28:18 2026 +0100
@@ -932,6 +932,35 @@
         }
 #endif
 
+#if DCMTK_VERSION_NUMBER >= 362
+        case EVR_OL:  // other long - binary array of 32-bit unsigned integers (new in Orthanc 1.12.11)
+        {
+          /**
+           * OL stores a binary array of 32-bit unsigned integers. Like OF/OD,
+           * getVM() returns 1 for OL (the entire binary blob is one "value").
+           * We must use getUint32Array() to access the raw buffer.
+           * The resulting string is formatted as in ApplyDcmtkToCTypeConverter().
+           **/
+          DcmUnsignedLong& content = dynamic_cast<DcmUnsignedLong&>(element);
+          Uint32* uint32Array = NULL;
+          if (content.getUint32Array(uint32Array).good() && uint32Array != NULL)
+          {
+            const unsigned long numValues = element.getLength() / sizeof(Uint32);
+            std::string result;
+            for (unsigned long i = 0; i < numValues; i++)
+            {
+              if (i > 0)
+              {
+                result += "\\";
+              }
+              result += boost::lexical_cast<std::string>(uint32Array[i]);
+            }
+            return new DicomValue(result, false);
+          }
+          return new DicomValue;
+        }
+#endif
+
 
         /**
          * Attribute tag.
@@ -3052,9 +3081,6 @@
         }
 
         case EVR_UL:  // unsigned long
-#if DCMTK_VERSION_NUMBER >= 362
-        case EVR_OL:
-#endif
         {
           DcmUnsignedLong& content = dynamic_cast<DcmUnsignedLong&>(element);
 
@@ -3192,6 +3218,36 @@
         }
 #endif
 
+#if DCMTK_VERSION_NUMBER >= 362
+        case EVR_OL:  // other long - binary array of 32-bit unsigned integers (new in Orthanc 1.12.11)
+        {
+          /**
+           * OL stores a binary array of 32-bit unsigned integers. Like OF/OD,
+           * getVM() returns 1 for OL (the entire binary blob is one "value").
+           * We must use getUint32Array() to access the raw buffer, then iterate
+           * over all values based on element length.
+           **/
+          DcmUnsignedLong& content = dynamic_cast<DcmUnsignedLong&>(element);
+
+          std::vector<int64_t> values;
+
+          Uint32* uint32Array = NULL;
+          if (content.getUint32Array(uint32Array).good() && uint32Array != NULL)
+          {
+            const unsigned long numValues = static_cast<unsigned long>(element.getLength() / sizeof(Uint32));
+            values.reserve(numValues);
+
+            for (unsigned long i = 0; i < numValues; i++)
+            {
+              values.push_back(static_cast<int64_t>(uint32Array[i]));
+            }
+          }
+
+          action = visitor.VisitIntegers(parentTags, parentIndexes, tag, vr, values);
+          break;
+        }
+#endif
+
 
         /**
          * Attribute tag.