changeset 1565:4b23310eb7e8

add tags per instances in a series
author Sebastien Jodogne <s.jodogne@gmail.com>
date Fri, 21 Aug 2015 17:29:16 +0200
parents 1b7def486e62
children 3be6eb3757c8
files Core/Enumerations.cpp Core/Enumerations.h Core/Toolbox.cpp Core/Toolbox.h OrthancServer/OrthancRestApi/OrthancRestAnonymizeModify.cpp OrthancServer/ParsedDicomFile.cpp
diffstat 6 files changed, 176 insertions(+), 105 deletions(-) [+]
line wrap: on
line diff
--- a/Core/Enumerations.cpp	Fri Aug 21 15:01:21 2015 +0200
+++ b/Core/Enumerations.cpp	Fri Aug 21 17:29:16 2015 +0200
@@ -748,4 +748,56 @@
         throw OrthancException(ErrorCode_ParameterOutOfRange);
     }
   }
+
+
+
+  const char* GetDicomSpecificCharacterSet(Encoding encoding)
+  {
+    // http://www.dabsoft.ch/dicom/3/C.12.1.1.2/
+    switch (encoding)
+    {
+      case Encoding_Utf8:
+      case Encoding_Ascii:
+        return "ISO_IR 192";
+
+      case Encoding_Latin1:
+        return "ISO_IR 100";
+
+      case Encoding_Latin2:
+        return "ISO_IR 101";
+
+      case Encoding_Latin3:
+        return "ISO_IR 109";
+
+      case Encoding_Latin4:
+        return "ISO_IR 110";
+
+      case Encoding_Latin5:
+        return "ISO_IR 148";
+
+      case Encoding_Cyrillic:
+        return "ISO_IR 144";
+
+      case Encoding_Arabic:
+        return "ISO_IR 127";
+
+      case Encoding_Greek:
+        return "ISO_IR 126";
+
+      case Encoding_Hebrew:
+        return "ISO_IR 138";
+
+      case Encoding_Japanese:
+        return "ISO_IR 13";
+
+      case Encoding_Chinese:
+        return "GB18030";
+
+      case Encoding_Thai:
+        return "ISO_IR 166";
+
+      default:
+        throw OrthancException(ErrorCode_ParameterOutOfRange);
+    }
+  }
 }
--- a/Core/Enumerations.h	Fri Aug 21 15:01:21 2015 +0200
+++ b/Core/Enumerations.h	Fri Aug 21 17:29:16 2015 +0200
@@ -386,4 +386,6 @@
   ResourceType GetParentResourceType(ResourceType type);
 
   DicomModule GetModule(ResourceType type);
+
+  const char* GetDicomSpecificCharacterSet(Encoding encoding);
 }
--- a/Core/Toolbox.cpp	Fri Aug 21 15:01:21 2015 +0200
+++ b/Core/Toolbox.cpp	Fri Aug 21 17:29:16 2015 +0200
@@ -1335,56 +1335,5 @@
     return static_cast<int>(getpid());
 #endif
   }
-
-
-  const char* Toolbox::GetDicomSpecificCharacterSet(Encoding encoding)
-  {
-    // http://www.dabsoft.ch/dicom/3/C.12.1.1.2/
-    switch (encoding)
-    {
-      case Encoding_Utf8:
-      case Encoding_Ascii:
-        return "ISO_IR 192";
-
-      case Encoding_Latin1:
-        return "ISO_IR 100";
-
-      case Encoding_Latin2:
-        return "ISO_IR 101";
-
-      case Encoding_Latin3:
-        return "ISO_IR 109";
-
-      case Encoding_Latin4:
-        return "ISO_IR 110";
-
-      case Encoding_Latin5:
-        return "ISO_IR 148";
-
-      case Encoding_Cyrillic:
-        return "ISO_IR 144";
-
-      case Encoding_Arabic:
-        return "ISO_IR 127";
-
-      case Encoding_Greek:
-        return "ISO_IR 126";
-
-      case Encoding_Hebrew:
-        return "ISO_IR 138";
-
-      case Encoding_Japanese:
-        return "ISO_IR 13";
-
-      case Encoding_Chinese:
-        return "GB18030";
-
-      case Encoding_Thai:
-        return "ISO_IR 166";
-
-      default:
-        throw OrthancException(ErrorCode_ParameterOutOfRange);
-    }
-  }
 }
 
--- a/Core/Toolbox.h	Fri Aug 21 15:01:21 2015 +0200
+++ b/Core/Toolbox.h	Fri Aug 21 17:29:16 2015 +0200
@@ -178,7 +178,5 @@
                     const std::string& prefix);
 
     int GetProcessId();
-
-    const char* GetDicomSpecificCharacterSet(Encoding encoding);
   }
 }
--- a/OrthancServer/OrthancRestApi/OrthancRestAnonymizeModify.cpp	Fri Aug 21 15:01:21 2015 +0200
+++ b/OrthancServer/OrthancRestApi/OrthancRestAnonymizeModify.cpp	Fri Aug 21 17:29:16 2015 +0200
@@ -488,6 +488,54 @@
   }
 
 
+  static bool InjectTags(ParsedDicomFile& dicom,
+                         const Json::Value& tags)
+  {
+    if (tags.type() != Json::objectValue)
+    {
+      LOG(ERROR) << "Bad syntax to specify the tags";
+      return false;
+    }
+
+    // Inject the user-specified tags
+    Json::Value::Members members = tags.getMemberNames();
+    for (size_t i = 0; i < members.size(); i++)
+    {
+      const std::string& name = members[i];
+      if (tags[name].type() != Json::stringValue)
+      {
+        LOG(ERROR) << "Only string values are supported when creating DICOM instances";
+        return false;
+      }
+
+      std::string value = tags[name].asString();
+
+      DicomTag tag = FromDcmtkBridge::ParseTag(name);
+      if (tag != DICOM_TAG_SPECIFIC_CHARACTER_SET)
+      {
+        if (tag != DICOM_TAG_PATIENT_ID &&
+            dicom.HasTag(tag))
+        {
+          LOG(ERROR) << "Trying to override a value inherited from a parent module";
+          return false;
+        }
+
+        if (tag == DICOM_TAG_PIXEL_DATA)
+        {
+          LOG(ERROR) << "Use \"Content\" to inject an image into a new DICOM instance";
+          return false;
+        }
+        else
+        {
+          dicom.Replace(tag, Toolbox::ConvertFromUtf8(value, dicom.GetEncoding()));
+        }
+      }
+    }
+
+    return true;
+  }
+
+
   static void CreateSeries(RestApiPostCall& call,
                            ParsedDicomFile& base /* in */,
                            const Json::Value& content)
@@ -503,14 +551,38 @@
 
     for (Json::ArrayIndex i = 0; i < content.size(); i++)
     {
-      if (content[i].type() != Json::stringValue)
+      std::auto_ptr<ParsedDicomFile> dicom(base.Clone());
+      const Json::Value* payload = NULL;
+
+      if (content[i].type() == Json::stringValue)
+      {
+        payload = &content[i];
+      }
+      else if (content[i].type() == Json::objectValue)
+      {
+        if (!content[i].isMember("Content"))
+        {
+          LOG(ERROR) << "No payload is present for one instance in the series";
+          return;
+        }
+
+        payload = &content[i]["Content"];
+
+        if (content[i].isMember("Tags") &&
+            !InjectTags(*dicom, content[i]["Tags"]))
+        {
+          return;          
+        }
+      }
+
+      if (payload == NULL ||
+          payload->type() != Json::stringValue)
       {
         LOG(ERROR) << "The payload of the DICOM instance must be specified according to Data URI scheme";
         return;
       }
 
-      std::auto_ptr<ParsedDicomFile> dicom(base.Clone());
-      dicom->EmbedContent(content[i].asString());
+      dicom->EmbedContent(payload->asString());
       dicom->Replace(DICOM_TAG_INSTANCE_NUMBER, boost::lexical_cast<std::string>(i + 1));
       dicom->Replace(DICOM_TAG_IMAGE_INDEX, boost::lexical_cast<std::string>(i + 1));
 
@@ -541,25 +613,28 @@
       return;
     }
 
-    Encoding encoding;
+    ParsedDicomFile dicom;
 
-    if (request["Tags"].isMember("SpecificCharacterSet"))
     {
-      const char* tmp = request["Tags"]["SpecificCharacterSet"].asCString();
-      if (!GetDicomEncoding(encoding, tmp))
+      Encoding encoding;
+
+      if (request["Tags"].isMember("SpecificCharacterSet"))
       {
-        LOG(ERROR) << "Unknown specific character set: " << tmp;
-        return;
+        const char* tmp = request["Tags"]["SpecificCharacterSet"].asCString();
+        if (!GetDicomEncoding(encoding, tmp))
+        {
+          LOG(ERROR) << "Unknown specific character set: " << tmp;
+          return;
+        }
       }
+      else
+      {
+        std::string tmp = Configuration::GetGlobalStringParameter("DefaultEncoding", "Latin1");
+        encoding = StringToEncoding(tmp.c_str());
+      }
+
+      dicom.SetEncoding(encoding);
     }
-    else
-    {
-      std::string tmp = Configuration::GetGlobalStringParameter("DefaultEncoding", "Latin1");
-      encoding = StringToEncoding(tmp.c_str());
-    }
-
-    ParsedDicomFile dicom;
-    dicom.SetEncoding(encoding);
 
     ResourceType parentType = ResourceType_Instance;
 
@@ -596,6 +671,27 @@
         context.ReadJson(siblingTags, siblingInstances.front());
       }
 
+
+      // Choose the same encoding as the parent resource
+      {
+        static const char* SPECIFIC_CHARACTER_SET = "0008,0005";
+
+        if (siblingTags.isMember(SPECIFIC_CHARACTER_SET))
+        {
+          Encoding encoding;
+          if (!siblingTags[SPECIFIC_CHARACTER_SET].isMember("Value") ||
+              siblingTags[SPECIFIC_CHARACTER_SET]["Value"].type() != Json::stringValue ||
+              !GetDicomEncoding(encoding, siblingTags[SPECIFIC_CHARACTER_SET]["Value"].asCString()))
+          {
+            LOG(ERROR) << "Unable to get the encoding of the parent resource";
+            return;
+          }
+
+          dicom.SetEncoding(encoding);
+        }
+      }
+
+
       // Retrieve the tags for all the parent modules
       typedef std::set<DicomTag> ModuleTags;
       ModuleTags moduleTags;
@@ -635,13 +731,13 @@
           else if (tag["Type"] == "String")
           {
             std::string value = tag["Value"].asString();
-            dicom.Replace(*it, Toolbox::ConvertFromUtf8(value, encoding));
+            dicom.Replace(*it, Toolbox::ConvertFromUtf8(value, dicom.GetEncoding()));
           }
         }
       }
     }
 
-
+    
     // Inject time-related information
     std::string date, time;
     Toolbox::GetNowDicom(date, time);
@@ -668,39 +764,11 @@
     }
 
 
-    // Inject the user-specified tags
-    Json::Value::Members members = request["Tags"].getMemberNames();
-    for (size_t i = 0; i < members.size(); i++)
+    if (!InjectTags(dicom, request["Tags"]))
     {
-      const std::string& name = members[i];
-      if (request["Tags"][name].type() != Json::stringValue)
-      {
-        LOG(ERROR) << "Only string values are supported when creating DICOM instances";
-        return;
-      }
-
-      std::string value = request["Tags"][name].asString();
+      return;  // Error
+    }
 
-      DicomTag tag = FromDcmtkBridge::ParseTag(name);
-      if (tag != DICOM_TAG_SPECIFIC_CHARACTER_SET)
-      {
-        if (dicom.HasTag(tag))
-        {
-          LOG(ERROR) << "Trying to override a value inherited from a parent module";
-          return;
-        }
-
-        if (tag == DICOM_TAG_PIXEL_DATA)
-        {
-          LOG(ERROR) << "Use \"Content\" to inject an image into a new DICOM instance";
-          return;
-        }
-        else
-        {
-          dicom.Replace(tag, Toolbox::ConvertFromUtf8(value, encoding));
-        }
-      }
-    }
 
     // Inject the content (either an image, or a PDF file)
     if (request.isMember("Content"))
@@ -716,7 +784,7 @@
       {
         if (content.size() > 0)
         {
-          // Let's create a series
+          // Let's create a series instead of a single instance
           CreateSeries(call, dicom, content);
           return;
         }
--- a/OrthancServer/ParsedDicomFile.cpp	Fri Aug 21 15:01:21 2015 +0200
+++ b/OrthancServer/ParsedDicomFile.cpp	Fri Aug 21 17:29:16 2015 +0200
@@ -1357,7 +1357,9 @@
       return;
     }
 
-    std::string s = Toolbox::GetDicomSpecificCharacterSet(encoding);
+    pimpl_->encoding_ = encoding;
+
+    std::string s = GetDicomSpecificCharacterSet(encoding);
     Replace(DICOM_TAG_SPECIFIC_CHARACTER_SET, s, DicomReplaceMode_InsertIfAbsent);
   }