changeset 3744:accf1b60b108

accessing raw pixel data
author Sebastien Jodogne <s.jodogne@gmail.com>
date Thu, 12 Mar 2020 17:58:34 +0100
parents 33c19a6643e1
children 113a7b994a12
files Core/DicomParsing/Internals/DicomImageDecoder.cpp Core/DicomParsing/Internals/DicomImageDecoder.h UnitTestsSources/FromDcmtkTests.cpp
diffstat 3 files changed, 106 insertions(+), 21 deletions(-) [+]
line wrap: on
line diff
--- a/Core/DicomParsing/Internals/DicomImageDecoder.cpp	Thu Mar 12 16:08:08 2020 +0100
+++ b/Core/DicomParsing/Internals/DicomImageDecoder.cpp	Thu Mar 12 17:58:34 2020 +0100
@@ -34,6 +34,8 @@
 #include "../../PrecompiledHeaders.h"
 #include "DicomImageDecoder.h"
 
+#include "../ParsedDicomFile.h"
+
 
 /*=========================================================================
 
@@ -84,7 +86,6 @@
 #include "../../DicomFormat/DicomIntegerPixelAccessor.h"
 #include "../ToDcmtkBridge.h"
 #include "../FromDcmtkBridge.h"
-#include "../ParsedDicomFile.h"
 
 #if ORTHANC_ENABLE_PNG == 1
 #  include "../../Images/PngWriter.h"
@@ -98,7 +99,6 @@
 #include <boost/lexical_cast.hpp>
 
 #include <dcmtk/dcmdata/dcdeftag.h>
-#include <dcmtk/dcmdata/dcfilefo.h>
 #include <dcmtk/dcmdata/dcrleccd.h>
 #include <dcmtk/dcmdata/dcrlecp.h>
 #include <dcmtk/dcmdata/dcrlerp.h>
@@ -662,7 +662,20 @@
   ImageAccessor* DicomImageDecoder::Decode(ParsedDicomFile& dicom,
                                            unsigned int frame)
   {
-    DcmDataset& dataset = *dicom.GetDcmtkObject().getDataset();
+    if (dicom.GetDcmtkObject().getDataset() == NULL)
+    {
+      throw OrthancException(ErrorCode_InternalError);
+    }
+    else
+    {
+      return Decode(*dicom.GetDcmtkObject().getDataset(), frame);
+    }
+  }
+
+
+  ImageAccessor* DicomImageDecoder::Decode(DcmDataset& dataset,
+                                           unsigned int frame)
+  {
     E_TransferSyntax syntax = dataset.getOriginalXfer();
 
     /**
--- a/Core/DicomParsing/Internals/DicomImageDecoder.h	Thu Mar 12 16:08:08 2020 +0100
+++ b/Core/DicomParsing/Internals/DicomImageDecoder.h	Thu Mar 12 17:58:34 2020 +0100
@@ -34,7 +34,7 @@
 #pragma once
 
 #include "../../Compatibility.h"
-#include "../ParsedDicomFile.h"
+#include "../../Images/ImageAccessor.h"
 
 #include <memory>
 
@@ -62,6 +62,8 @@
 
 namespace Orthanc
 {
+  class ParsedDicomFile;
+  
   class DicomImageDecoder : public boost::noncopyable
   {
   private:
@@ -102,6 +104,9 @@
     static ImageAccessor *Decode(ParsedDicomFile& dicom,
                                  unsigned int frame);
 
+    static ImageAccessor *Decode(DcmDataset& dataset,
+                                 unsigned int frame);
+
     static void ExtractPamImage(std::string& result,
                                 std::unique_ptr<ImageAccessor>& image,
                                 ImageExtractionMode mode,
--- a/UnitTestsSources/FromDcmtkTests.cpp	Thu Mar 12 16:08:08 2020 +0100
+++ b/UnitTestsSources/FromDcmtkTests.cpp	Thu Mar 12 17:58:34 2020 +0100
@@ -1919,6 +1919,11 @@
 
 #include "../Core/DicomFormat/DicomImageInformation.h"
 
+#include <dcmtk/dcmdata/dcostrmb.h>
+#include <dcmtk/dcmdata/dcpixel.h>
+#include <dcmtk/dcmdata/dcpxitem.h>
+
+
 namespace Orthanc
 {
   class IDicomTranscoder : public boost::noncopyable
@@ -1936,13 +1941,13 @@
 
     virtual unsigned int GetFramesCount() = 0;
 
-    virtual IDicomTranscoder* Transcode(std::set<DicomTransferSyntax> syntaxes,
-                                        bool allowNewSopInstanceUid) = 0;
-
     virtual ImageAccessor* DecodeFrame(unsigned int frame) = 0;
 
     virtual void GetCompressedFrame(std::string& target,
                                     unsigned int frame) = 0;
+
+    virtual IDicomTranscoder* Transcode(std::set<DicomTransferSyntax> syntaxes,
+                                        bool allowNewSopInstanceUid) = 0;
   };
 
 
@@ -2012,11 +2017,6 @@
       Setup(FromDcmtkBridge::LoadFromMemoryBuffer(dicom, size));
     }
 
-    DcmtkTranscoder(const ParsedDicomFile& dicom)
-    {
-      Setup(new DcmFileFormat(dicom.GetDcmtkObject()));
-    }
-
     virtual DicomTransferSyntax GetTransferSyntax() ORTHANC_OVERRIDE
     {
       return transferSyntax_;
@@ -2037,20 +2037,83 @@
       return info_->GetNumberOfFrames();
     }
 
-    virtual IDicomTranscoder* Transcode(std::set<DicomTransferSyntax> syntaxes,
-                                        bool allowNewSopInstanceUid) ORTHANC_OVERRIDE
-    {
-      throw OrthancException(ErrorCode_NotImplemented);
-    }
-
     virtual ImageAccessor* DecodeFrame(unsigned int frame) ORTHANC_OVERRIDE
     {
-      throw OrthancException(ErrorCode_NotImplemented);
+      assert(dicom_->getDataset() != NULL);
+      return DicomImageDecoder::Decode(*dicom_->getDataset(), frame);
     }
 
     virtual void GetCompressedFrame(std::string& target,
                                     unsigned int frame) ORTHANC_OVERRIDE
     {
+      assert(dicom_->getDataset() != NULL);
+      DcmDataset& dataset = *dicom_->getDataset();
+      
+      DcmPixelSequence* pixelSequence = FromDcmtkBridge::GetPixelSequence(dataset);
+
+      if (pixelSequence == NULL)
+      {
+        // This is an uncompressed frame
+
+        DcmElement* element = NULL;
+        if (dataset.findAndGetElement(DCM_PixelData, element).good() &&
+            element != NULL)
+        {
+          Uint8* pixelData = NULL;
+        
+          if (element->getUint8Array(pixelData).good() &&
+              pixelData != NULL)
+          {    
+            // TODO => use "pixelData"
+            printf("RAW %d\n", element->getLength());
+          }
+          else
+          {
+            throw OrthancException(ErrorCode_BadFileFormat,
+                                   "Cannot access uncompressed pixel data");
+          }
+        }
+        else
+        {
+          std::string decoded;
+          if (DicomImageDecoder::DecodePsmctRle1(decoded, dataset))
+          {
+            // TODO => use "decoded"
+          }
+          else
+          {
+            throw OrthancException(ErrorCode_BadFileFormat,
+                                   "Cannot access uncompressed pixel data");
+          }
+        }
+      }
+      else
+      {
+        printf("COMPRESSED\n");
+
+        // Check out "djcodecd.cc"
+
+        printf("%d fragments\n", pixelSequence->card());
+
+        // Skip the first fragment, that is the offset table
+        for (unsigned long i = 1; ;i++)
+        {
+          DcmPixelItem *fragment = NULL;
+          if (pixelSequence->getItem(fragment, i).good())
+          {
+            printf("fragment %d %d\n", i, fragment->getLength());
+          }
+          else
+          {
+            break;
+          }
+        }
+      }
+    }
+
+    virtual IDicomTranscoder* Transcode(std::set<DicomTransferSyntax> syntaxes,
+                                        bool allowNewSopInstanceUid) ORTHANC_OVERRIDE
+    {
       throw OrthancException(ErrorCode_NotImplemented);
     }
   };
@@ -2058,7 +2121,6 @@
 
 
 
-#include <dcmtk/dcmdata/dcostrmb.h>
 
 static bool Transcode(std::string& buffer,
                       DcmDataset& dataSet,
@@ -2144,9 +2206,14 @@
 
   Orthanc::DcmtkTranscoder transcoder(s.c_str(), s.size());
 
-  printf("[%s] [%s] [%s] %d\n\n", GetTransferSyntaxUid(transcoder.GetTransferSyntax()),
+  printf("[%s] [%s] [%s] %d\n", GetTransferSyntaxUid(transcoder.GetTransferSyntax()),
          transcoder.GetSopClassUid().c_str(), transcoder.GetSopInstanceUid().c_str(),
          transcoder.GetFramesCount());
+
+  std::string f;
+  transcoder.GetCompressedFrame(f, 0);
+
+  printf("\n");
 }
 
 TEST(Toto, Transcode)