changeset 88:e009c43f4dbb

switch between the media types
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 09 Dec 2015 11:30:05 +0100
parents 8effbfc4cf28
children 4667d4235791
files Plugin/Dicom.h Plugin/WadoRs.cpp
diffstat 2 files changed, 185 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/Plugin/Dicom.h	Wed Dec 09 10:13:39 2015 +0100
+++ b/Plugin/Dicom.h	Wed Dec 09 11:30:05 2015 +0100
@@ -44,6 +44,7 @@
   static const gdcm::Tag DICOM_TAG_REFERENCED_SOP_SEQUENCE(0x0008, 0x1199);
   static const gdcm::Tag DICOM_TAG_ACCESSION_NUMBER(0x0008, 0x0050);
   static const gdcm::Tag DICOM_TAG_SPECIFIC_CHARACTER_SET(0x0008, 0x0005);
+  static const gdcm::Tag DICOM_TAG_PIXEL_DATA(0x7fe0, 0x0010);
 
   class ParsedDicomFile
   {
--- a/Plugin/WadoRs.cpp	Wed Dec 09 10:13:39 2015 +0100
+++ b/Plugin/WadoRs.cpp	Wed Dec 09 11:30:05 2015 +0100
@@ -635,19 +635,200 @@
 
 
 
+static bool Test(const gdcm::DataSet& dicom)
+{
+  if (!dicom.FindDataElement(OrthancPlugins::DICOM_TAG_PIXEL_DATA))
+  {
+    return OrthancPluginErrorCode_IncompatibleImageFormat;
+  }
+
+  const gdcm::DataElement& pixelData = dicom.GetDataElement(OrthancPlugins::DICOM_TAG_PIXEL_DATA);
+  const gdcm::SequenceOfFragments* fragments = pixelData.GetSequenceOfFragments();
+
+  if (fragments == NULL)
+  {
+    printf("Single-frame image\n");
+    printf("%d\n", pixelData.GetByteValue()->GetLength());
+  }
+  else
+  {
+    printf("Multi-frame image (%d fragments)\n", fragments->GetNumberOfFragments());
+
+    for (gdcm::SequenceOfFragments::SizeType i = 0; i < fragments->GetNumberOfFragments(); i++)
+    {
+      printf("%d: %d\n", i, fragments->GetFragment(i).GetByteValue()->GetLength());
+    }
+  }
+
+  return true;
+}
+
+
+static void TokenizeAndNormalize(std::vector<std::string>& tokens,
+                                 const std::string& source,
+                                 char separator)
+{
+  Orthanc::Toolbox::TokenizeString(tokens, source, separator);
+
+  for (size_t i = 0; i < tokens.size(); i++)
+  {
+    tokens[i] = Orthanc::Toolbox::StripSpaces(tokens[i]);
+    Orthanc::Toolbox::ToLowerCase(tokens[i]);
+  }
+}
+
+
+
+static gdcm::TransferSyntax GetTransferSyntax(const OrthancPluginHttpRequest* request)
+{
+  for (uint32_t i = 0; i < request->headersCount; i++)
+  {
+    std::string key(request->headersKeys[i]);
+    Orthanc::Toolbox::ToLowerCase(key);
+
+    if (key == "accept")
+    {
+      std::vector<std::string> tokens;
+      TokenizeAndNormalize(tokens, request->headersValues[i], ';');
+
+      if (tokens.size() < 0 ||
+          tokens[0] != "multipart/related")
+      {
+        throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
+      }
+
+      std::string type("application/octet-stream");
+      std::string transferSyntax;
+      
+      for (size_t j = 1; j < tokens.size(); j++)
+      {
+        std::vector<std::string> parsed;
+        TokenizeAndNormalize(parsed, tokens[j], '=');
+
+        if (parsed.size() != 2)
+        {
+          throw Orthanc::OrthancException(Orthanc::ErrorCode_BadRequest);
+        }
+
+        if (parsed[0] == "type")
+        {
+          type = parsed[1];
+        }
+
+        if (parsed[0] == "transfer-syntax")
+        {
+          transferSyntax = parsed[1];
+        }
+      }
+
+      if (type == "application/octet-stream")
+      {
+        if (transferSyntax.empty())
+        {
+          return gdcm::TransferSyntax(gdcm::TransferSyntax::ImplicitVRLittleEndian);
+        }
+        else
+        {
+          std::string s = ("DICOMweb RetrieveFrames: Cannot specify a transfer syntax (" + 
+                           transferSyntax + ") for default Little Endian uncompressed pixel data");
+          OrthancPluginLogError(context_, s.c_str());
+          throw Orthanc::OrthancException(Orthanc::ErrorCode_BadRequest);
+        }
+      }
+      else
+      {
+        // http://dicom.nema.org/medical/dicom/current/output/html/part18.html#table_6.5-1
+        if (type == "image/dicom+jpeg" && transferSyntax == "1.2.840.10008.1.2.4.50")
+        {
+          return gdcm::TransferSyntax::JPEGBaselineProcess1;
+        }
+        else if (type == "image/dicom+jpeg" && transferSyntax == "1.2.840.10008.1.2.4.51")
+        {
+          return gdcm::TransferSyntax::JPEGExtendedProcess2_4;
+        }
+        else if (type == "image/dicom+jpeg" && transferSyntax == "1.2.840.10008.1.2.4.57")
+        {
+          return gdcm::TransferSyntax::JPEGLosslessProcess14;
+        }
+        else if (type == "image/dicom+jpeg" && (transferSyntax.empty() ||
+                                                transferSyntax == "1.2.840.10008.1.2.4.70"))
+        {
+          return gdcm::TransferSyntax::JPEGLosslessProcess14_1;
+        }
+        else if (type == "image/dicom+rle" && (transferSyntax.empty() ||
+                                               transferSyntax == "1.2.840.10008.1.2.5"))
+        {
+          return gdcm::TransferSyntax::RLELossless;
+        }
+        else if (type == "image/dicom+jpeg-ls" && (transferSyntax.empty() ||
+                                                   transferSyntax == "1.2.840.10008.1.2.4.80"))
+        {
+          return gdcm::TransferSyntax::JPEGLSLossless;
+        }
+        else if (type == "image/dicom+jpeg-ls" && transferSyntax == "1.2.840.10008.1.2.4.81")
+        {
+          return gdcm::TransferSyntax::JPEGLSNearLossless;
+        }
+        else if (type == "image/dicom+jp2" && (transferSyntax.empty() ||
+                                               transferSyntax == "1.2.840.10008.1.2.4.90"))
+        {
+          return gdcm::TransferSyntax::JPEG2000Lossless;
+        }
+        else if (type == "image/dicom+jp2" && transferSyntax == "1.2.840.10008.1.2.4.91")
+        {
+          return gdcm::TransferSyntax::JPEG2000;
+        }
+        else if (type == "image/dicom+jpx" && (transferSyntax.empty() ||
+                                               transferSyntax == "1.2.840.10008.1.2.4.92"))
+        {
+          return gdcm::TransferSyntax::JPEG2000Part2Lossless;
+        }
+        else if (type == "image/dicom+jpx" && transferSyntax == "1.2.840.10008.1.2.4.93")
+        {
+          return gdcm::TransferSyntax::JPEG2000Part2;
+        }
+        else
+        {
+          std::string s = ("DICOMweb RetrieveFrames: Transfer syntax \"" + 
+                           transferSyntax + "\" is incompatible with media type \"" + type + "\"");
+          OrthancPluginLogError(context_, s.c_str());
+          throw Orthanc::OrthancException(Orthanc::ErrorCode_BadRequest);
+        }
+      }
+    }
+  }
+
+  // By default, DICOMweb expectes Little Endian uncompressed pixel data
+  return gdcm::TransferSyntax::ImplicitVRLittleEndian;
+}
+
 
 OrthancPluginErrorCode RetrieveFrames(OrthancPluginRestOutput* output,
                                       const char* url,
                                       const OrthancPluginHttpRequest* request)
 {
+  // storescu -xs localhost 4242 ~/Subversion/orthanc-tests/Database/Multiframe.dcm 
+
   // curl http://localhost:8042/dicom-web/studies/1.3.51.0.1.1.192.168.29.133.1681753.1681732/series/1.3.12.2.1107.5.2.33.37097.2012041612474981424569674.0.0.0/instances/1.3.12.2.1107.5.2.33.37097.2012041612485517294169680/frames/0
+  // curl http://localhost:8042/dicom-web/studies/1.3.46.670589.7.5.8.80001255161.20000323.151537.1/series/1.3.46.670589.7.5.7.80001255161.20000323.151537.1/instances/1.3.46.670589.7.5.1.981501.20000323.16172540.1.1.13/frames/0
+ 
 
   // http://gdcm.sourceforge.net/html/CompressLossyJPEG_8cs-example.html
 
+  printf("T: %s\n", GetTransferSyntax(request).GetString());
+
+
   std::string uri, content;
   if (LocateInstance(output, uri, request) &&
       OrthancPlugins::RestApiGetString(content, context_, uri + "/file"))
   {
+    {
+      OrthancPlugins::ParsedDicomFile dicom(content);
+      Test(dicom.GetDataSet());
+      //return OrthancPluginErrorCode_Success;
+    }
+
+
     printf("RetrieveFrames: [%s] [%s]\n", uri.c_str(), request->groups[3]);
 
     gdcm::ImageChangeTransferSyntax change;
@@ -679,9 +860,11 @@
     writer.SetStream(ss);
     printf("Write: %d\n", writer.Write());
 
-    gdcm::ImageReader reader2;
+    gdcm::Reader reader2;
     reader2.SetStream(ss);
     printf("Read: %d\n", reader2.Read());
+
+    Test(reader2.GetFile().GetDataSet());
   }    
 
   return OrthancPluginErrorCode_Success;