changeset 3276:9b0e67161600

More tolerance wrt. invalid DICOM files that must be returned by Orthanc C-FIND SCP
author Sebastien Jodogne <s.jodogne@gmail.com>
date Thu, 21 Feb 2019 10:21:12 +0100
parents 5cd4c672d63c
children 7d4e06beb1ec
files Core/DicomNetworking/DicomFindAnswers.cpp Core/DicomParsing/ParsedDicomFile.cpp Core/DicomParsing/ParsedDicomFile.h NEWS UnitTestsSources/FromDcmtkTests.cpp
diffstat 5 files changed, 36 insertions(+), 18 deletions(-) [+]
line wrap: on
line diff
--- a/Core/DicomNetworking/DicomFindAnswers.cpp	Wed Feb 20 17:21:39 2019 +0100
+++ b/Core/DicomNetworking/DicomFindAnswers.cpp	Thu Feb 21 10:21:12 2019 +0100
@@ -119,7 +119,10 @@
 
   void DicomFindAnswers::Add(const DicomMap& map)
   {
-    AddAnswerInternal(new ParsedDicomFile(map, encoding_));
+    // We use the permissive mode to be tolerant wrt. invalid DICOM
+    // files that contain some tags with out-of-range values (such
+    // tags are removed from the answers)
+    AddAnswerInternal(new ParsedDicomFile(map, encoding_, true /* permissive */));
   }
 
 
--- a/Core/DicomParsing/ParsedDicomFile.cpp	Wed Feb 20 17:21:39 2019 +0100
+++ b/Core/DicomParsing/ParsedDicomFile.cpp	Thu Feb 21 10:21:12 2019 +0100
@@ -956,7 +956,8 @@
 
 
   void ParsedDicomFile::CreateFromDicomMap(const DicomMap& source,
-                                           Encoding defaultEncoding)
+                                           Encoding defaultEncoding,
+                                           bool permissive)
   {
     pimpl_->file_.reset(new DcmFileFormat);
 
@@ -998,24 +999,35 @@
       if (it->first != DICOM_TAG_SPECIFIC_CHARACTER_SET &&
           !it->second->IsNull())
       {
-        ReplacePlainString(it->first, it->second->GetContent());
+        try
+        {
+          ReplacePlainString(it->first, it->second->GetContent());
+        }
+        catch (OrthancException&)
+        {
+          if (!permissive)
+          {
+            throw;
+          }
+        }
       }
     }
   }
 
 
   ParsedDicomFile::ParsedDicomFile(const DicomMap& map,
-                                   Encoding defaultEncoding) :
+                                   Encoding defaultEncoding,
+                                   bool permissive) :
     pimpl_(new PImpl)
   {
-    CreateFromDicomMap(map, defaultEncoding);
+    CreateFromDicomMap(map, defaultEncoding, permissive);
   }
 
 
   ParsedDicomFile::ParsedDicomFile(const DicomMap& map) : 
     pimpl_(new PImpl)
   {
-    CreateFromDicomMap(map, GetDefaultDicomEncoding());
+    CreateFromDicomMap(map, GetDefaultDicomEncoding(), false /* be strict by default */);
   }
 
 
--- a/Core/DicomParsing/ParsedDicomFile.h	Wed Feb 20 17:21:39 2019 +0100
+++ b/Core/DicomParsing/ParsedDicomFile.h	Thu Feb 21 10:21:12 2019 +0100
@@ -81,7 +81,8 @@
                     bool keepSopInstanceUid);
 
     void CreateFromDicomMap(const DicomMap& source,
-                            Encoding defaultEncoding);
+                            Encoding defaultEncoding,
+                            bool permissive);
 
     void RemovePrivateTagsInternal(const std::set<DicomTag>* toKeep);
 
@@ -97,7 +98,8 @@
     ParsedDicomFile(bool createIdentifiers);  // Create a minimal DICOM instance
 
     ParsedDicomFile(const DicomMap& map,
-                    Encoding defaultEncoding);
+                    Encoding defaultEncoding,
+                    bool permissive);
 
     ParsedDicomFile(const DicomMap& map);
 
--- a/NEWS	Wed Feb 20 17:21:39 2019 +0100
+++ b/NEWS	Thu Feb 21 10:21:12 2019 +0100
@@ -9,6 +9,7 @@
 * Basic support for character sets with code extensions (ISO 2022 escape sequences)
 * Fix issue #134 (/patient/modify gives 500, should really be 400)
 * Support of SOP classes: BreastProjectionXRayImageStorageForProcessing/Presentation
+* More tolerance wrt. invalid DICOM files that must be returned by Orthanc C-FIND SCP
 
 
 Version 1.5.4 (2019-02-08)
--- a/UnitTestsSources/FromDcmtkTests.cpp	Wed Feb 20 17:21:39 2019 +0100
+++ b/UnitTestsSources/FromDcmtkTests.cpp	Thu Feb 21 10:21:12 2019 +0100
@@ -1126,7 +1126,7 @@
 
   {
     DicomMap m;
-    ParsedDicomFile dicom(m, Encoding_Latin4);
+    ParsedDicomFile dicom(m, Encoding_Latin4, false);
     ASSERT_EQ(1u, dicom.GetDcmtkObject().getDataset()->card());
     CheckEncoding(dicom, Encoding_Latin4);
   }
@@ -1142,7 +1142,7 @@
   {
     DicomMap m;
     m.SetValue(DICOM_TAG_SPECIFIC_CHARACTER_SET, "ISO_IR 148", false);
-    ParsedDicomFile dicom(m, Encoding_Latin1);
+    ParsedDicomFile dicom(m, Encoding_Latin1, false);
     ASSERT_EQ(1u, dicom.GetDcmtkObject().getDataset()->card());
     CheckEncoding(dicom, Encoding_Latin5);
   }
@@ -1192,7 +1192,7 @@
         DicomMap m;
         m.SetValue(DICOM_TAG_PATIENT_NAME, testEncodingsExpected[i], false);
 
-        ParsedDicomFile dicom(m, testEncodings[i]);
+        ParsedDicomFile dicom(m, testEncodings[i], false);
     
         const char* encoded = NULL;
         ASSERT_TRUE(dicom.GetDcmtkObject().getDataset()->findAndGetString(DCM_PatientName, encoded).good());
@@ -1212,7 +1212,7 @@
         m.SetValue(DICOM_TAG_SPECIFIC_CHARACTER_SET, GetDicomSpecificCharacterSet(testEncodings[i]), false);
         m.SetValue(DICOM_TAG_PATIENT_NAME, testEncodingsExpected[i], false);
 
-        ParsedDicomFile dicom(m, testEncodings[i]);
+        ParsedDicomFile dicom(m, testEncodings[i], false);
 
         Json::Value v2;
         dicom.DatasetToJson(v2, DicomToJsonFormat_Human, DicomToJsonFlags_Default, 0);
@@ -1237,7 +1237,7 @@
 
       std::string tag;
 
-      ParsedDicomFile dicom(m, Encoding_Utf8);
+      ParsedDicomFile dicom(m, Encoding_Utf8, false);
       bool hasCodeExtensions;
       ASSERT_EQ(Encoding_Utf8, dicom.DetectEncoding(hasCodeExtensions));
       ASSERT_FALSE(hasCodeExtensions);
@@ -1288,7 +1288,7 @@
     DicomMap m;
     m.SetValue(DICOM_TAG_PATIENT_NAME, "HELLO", false);
 
-    ParsedDicomFile d(m, Encoding_Latin3 /* default encoding */);
+    ParsedDicomFile d(m, Encoding_Latin3 /* default encoding */, false);
 
     bool hasCodeExtensions;
     ASSERT_EQ(Encoding_Latin3, d.DetectEncoding(hasCodeExtensions));
@@ -1301,7 +1301,7 @@
     m.SetValue(DICOM_TAG_SPECIFIC_CHARACTER_SET, "ISO_IR 13", false);
     m.SetValue(DICOM_TAG_PATIENT_NAME, "HELLO", false);
 
-    ParsedDicomFile d(m, Encoding_Latin3 /* default encoding */);
+    ParsedDicomFile d(m, Encoding_Latin3 /* default encoding */, false);
 
     bool hasCodeExtensions;
     ASSERT_EQ(Encoding_Japanese, d.DetectEncoding(hasCodeExtensions));
@@ -1314,7 +1314,7 @@
     m.SetValue(DICOM_TAG_SPECIFIC_CHARACTER_SET, "nope", false);
     m.SetValue(DICOM_TAG_PATIENT_NAME, "HELLO", false);
 
-    ASSERT_THROW(ParsedDicomFile d(m, Encoding_Latin3), OrthancException);
+    ASSERT_THROW(ParsedDicomFile d(m, Encoding_Latin3, false), OrthancException);
   }
   
   {
@@ -1323,7 +1323,7 @@
     m.SetValue(DICOM_TAG_SPECIFIC_CHARACTER_SET, "ISO_IR 13", true);
     m.SetValue(DICOM_TAG_PATIENT_NAME, "HELLO", false);
 
-    ASSERT_THROW(ParsedDicomFile d(m, Encoding_Latin3), OrthancException);
+    ASSERT_THROW(ParsedDicomFile d(m, Encoding_Latin3, false), OrthancException);
   }
   
   {
@@ -1333,7 +1333,7 @@
     m.SetValue(DICOM_TAG_SPECIFIC_CHARACTER_SET, "", false);
     m.SetValue(DICOM_TAG_PATIENT_NAME, "HELLO", false);
 
-    ParsedDicomFile d(m, Encoding_Latin3 /* default encoding */);
+    ParsedDicomFile d(m, Encoding_Latin3 /* default encoding */, false);
 
     bool hasCodeExtensions;
     ASSERT_EQ(Encoding_Latin3, d.DetectEncoding(hasCodeExtensions));