changeset 1950:533ff46e944b

return a single raw frame from DICOM videos
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 05 Apr 2016 11:07:02 +0200
parents d90f737f2dde
children 01de36d949c3
files Core/Endianness.h OrthancServer/Internals/DicomFrameIndex.cpp OrthancServer/Internals/DicomFrameIndex.h OrthancServer/OrthancRestApi/OrthancRestResources.cpp OrthancServer/ParsedDicomFile.cpp OrthancServer/ParsedDicomFile.h
diffstat 6 files changed, 55 insertions(+), 31 deletions(-) [+]
line wrap: on
line diff
--- a/Core/Endianness.h	Tue Apr 05 10:30:17 2016 +0200
+++ b/Core/Endianness.h	Tue Apr 05 11:07:02 2016 +0200
@@ -45,7 +45,7 @@
 /********************************************************************
  ** WINDOWS ARCHITECTURES
  **
- ** On Windows, "host" will always be little-endian ("le").
+ ** On Windows x86, "host" will always be little-endian ("le").
  ********************************************************************/
 
 #if defined(_WIN32)
--- a/OrthancServer/Internals/DicomFrameIndex.cpp	Tue Apr 05 10:30:17 2016 +0200
+++ b/OrthancServer/Internals/DicomFrameIndex.cpp	Tue Apr 05 11:07:02 2016 +0200
@@ -37,6 +37,7 @@
 #include "../../Core/DicomFormat/DicomImageInformation.h"
 #include "../FromDcmtkBridge.h"
 #include "../OrthancInitialization.h"
+#include "../../Core/Endianness.h"
 #include "DicomImageDecoder.h"
 
 #include <boost/lexical_cast.hpp>
@@ -45,16 +46,6 @@
 #include <dcmtk/dcmdata/dcpxitem.h>
 #include <dcmtk/dcmdata/dcpixseq.h>
 
-#if defined(_WIN32)   // Windows machines are always little-endian
-#  define le32toh(x) x
-#elif defined(__APPLE__)
-#  include <libkern/OSByteOrder.h>
-#  define le32toh(x) OSSwapLittleToHostInt32(x)
-#else
-#  include <endian.h>
-#endif
-
-
 namespace Orthanc
 {
   class DicomFrameIndex::FragmentIndex : public DicomFrameIndex::IIndex
@@ -328,9 +319,38 @@
 
 
 
+  bool DicomFrameIndex::IsVideo(const DcmDataset& dataset)
+  {
+    if (dataset.getOriginalXfer() == EXS_MPEG2MainProfileAtMainLevel ||
+        dataset.getOriginalXfer() == EXS_MPEG2MainProfileAtHighLevel)
+    {
+      return true;
+    }        
+
+#if DCMTK_VERSION_NUMBER > 360
+    // New transfer syntaxes introduced in the DICOM standard after DCMTK 3.6.0
+    if (dataset.getOriginalXfer() == EXS_MPEG4HighProfileLevel4 ||
+        dataset.getOriginalXfer() == EXS_MPEG4BDcompatibleHighProfileLevel4 ||
+        dataset.getOriginalXfer() == EXS_MPEG4HighProfileLevel4_2_For2DVideo ||
+        dataset.getOriginalXfer() == EXS_MPEG4HighProfileLevel4_2_For3DVideo ||
+        dataset.getOriginalXfer() == EXS_MPEG4StereoHighProfileLevel4_2)
+    {
+      return true;
+    }        
+#endif
+
+    return false;
+  }
+
 
   unsigned int DicomFrameIndex::GetFramesCount(DcmDataset& dataset)
   {
+    // Assume 1 frame for video transfer syntaxes
+    if (IsVideo(dataset))
+    {
+      return 1;
+    }        
+
     const char* tmp = NULL;
     if (!dataset.findAndGetString(DCM_NumberOfFrames, tmp).good() ||
         tmp == NULL)
--- a/OrthancServer/Internals/DicomFrameIndex.h	Tue Apr 05 10:30:17 2016 +0200
+++ b/OrthancServer/Internals/DicomFrameIndex.h	Tue Apr 05 11:07:02 2016 +0200
@@ -72,6 +72,8 @@
     void GetRawFrame(std::string& frame,
                      unsigned int index) const;
 
+    static bool IsVideo(const DcmDataset& dataset);
+
     static unsigned int GetFramesCount(DcmDataset& dataset);
   };
 }
--- a/OrthancServer/OrthancRestApi/OrthancRestResources.cpp	Tue Apr 05 10:30:17 2016 +0200
+++ b/OrthancServer/OrthancRestApi/OrthancRestResources.cpp	Tue Apr 05 11:07:02 2016 +0200
@@ -236,28 +236,22 @@
   
   static void ListFrames(RestApiGetCall& call)
   {
-    Json::Value instance;
-    if (OrthancRestApi::GetIndex(call).LookupResource(instance, call.GetUriComponent("id", ""), ResourceType_Instance))
-    {
-      unsigned int numberOfFrames = 1;
+    std::string publicId = call.GetUriComponent("id", "");
 
-      try
-      {
-        Json::Value tmp = instance["MainDicomTags"]["NumberOfFrames"];
-        numberOfFrames = boost::lexical_cast<unsigned int>(tmp.asString());
-      }
-      catch (...)
-      {
-      }
-
-      Json::Value result = Json::arrayValue;
-      for (unsigned int i = 0; i < numberOfFrames; i++)
-      {
-        result.append(i);
-      }
-
-      call.GetOutput().AnswerJson(result);
+    unsigned int numberOfFrames;
+      
+    {
+      ServerContext::DicomCacheLocker locker(OrthancRestApi::GetContext(call), publicId);
+      numberOfFrames = locker.GetDicom().GetFramesCount();
     }
+    
+    Json::Value result = Json::arrayValue;
+    for (unsigned int i = 0; i < numberOfFrames; i++)
+    {
+      result.append(i);
+    }
+    
+    call.GetOutput().AnswerJson(result);
   }
 
 
--- a/OrthancServer/ParsedDicomFile.cpp	Tue Apr 05 10:30:17 2016 +0200
+++ b/OrthancServer/ParsedDicomFile.cpp	Tue Apr 05 11:07:02 2016 +0200
@@ -1261,4 +1261,10 @@
   {
     pimpl_->frameIndex_.reset(NULL);
   }
+
+
+  unsigned int ParsedDicomFile::GetFramesCount() const
+  {
+    return DicomFrameIndex::GetFramesCount(*pimpl_->file_->getDataset());
+  }
 }
--- a/OrthancServer/ParsedDicomFile.h	Tue Apr 05 10:30:17 2016 +0200
+++ b/OrthancServer/ParsedDicomFile.h	Tue Apr 05 11:07:02 2016 +0200
@@ -149,6 +149,8 @@
                      std::string& mime,   // OUT
                      unsigned int frameId);  // IN
 
+    unsigned int GetFramesCount() const;
+
     static ParsedDicomFile* CreateFromJson(const Json::Value& value,
                                            DicomFromJsonFlags flags);
   };