diff OrthancServer/Internals/DicomImageDecoder.cpp @ 854:ff530685e46a jpeg

fast version of image copy
author Sebastien Jodogne <s.jodogne@gmail.com>
date Fri, 06 Jun 2014 12:35:08 +0200
parents 839be3022203
children ebc41566f742
line wrap: on
line diff
--- a/OrthancServer/Internals/DicomImageDecoder.cpp	Fri Jun 06 11:45:16 2014 +0200
+++ b/OrthancServer/Internals/DicomImageDecoder.cpp	Fri Jun 06 12:35:08 2014 +0200
@@ -78,6 +78,7 @@
 
 
 #include "../../Core/OrthancException.h"
+#include "../../Core/ImageFormats/ImageProcessing.h"
 #include "../../Core/DicomFormat/DicomIntegerPixelAccessor.h"
 #include "../ToDcmtkBridge.h"
 #include "../FromDcmtkBridge.h"
@@ -180,7 +181,7 @@
       return slowAccessor_->GetInformation().GetChannelCount();
     }
 
-    const DicomIntegerPixelAccessor GetAccessor() const
+    const DicomIntegerPixelAccessor& GetAccessor() const
     {
       assert(slowAccessor_.get() != NULL);
       return *slowAccessor_;
@@ -313,67 +314,23 @@
   void DicomImageDecoder::SetupImageBuffer(ImageBuffer& target,
                                            DcmDataset& dataset)
   {
-    OFString value;
-
-    if (!dataset.findAndGetOFString(ToDcmtkBridge::Convert(DICOM_TAG_COLUMNS), value).good())
-    {
-      throw OrthancException(ErrorCode_BadFileFormat);
-    }
-
-    unsigned int width = boost::lexical_cast<unsigned int>(value.c_str());
-
-    if (!dataset.findAndGetOFString(ToDcmtkBridge::Convert(DICOM_TAG_ROWS), value).good())
-    {
-      throw OrthancException(ErrorCode_BadFileFormat);
-    }
-
-    unsigned int height = boost::lexical_cast<unsigned int>(value.c_str());
-
-    if (!dataset.findAndGetOFString(ToDcmtkBridge::Convert(DICOM_TAG_BITS_STORED), value).good())
-    {
-      throw OrthancException(ErrorCode_BadFileFormat);
-    }
-
-    unsigned int bitsStored = boost::lexical_cast<unsigned int>(value.c_str());
-
-    if (!dataset.findAndGetOFString(ToDcmtkBridge::Convert(DICOM_TAG_PIXEL_REPRESENTATION), value).good())
-    {
-      throw OrthancException(ErrorCode_BadFileFormat);
-    }
-
-    bool isSigned = (boost::lexical_cast<unsigned int>(value.c_str()) != 0);
+    DicomMap m;
+    FromDcmtkBridge::Convert(m, dataset);
 
-    unsigned int samplesPerPixel = 1; // By default
-    if (dataset.findAndGetOFString(ToDcmtkBridge::Convert(DICOM_TAG_SAMPLES_PER_PIXEL), value).good())
-    {
-      samplesPerPixel = boost::lexical_cast<unsigned int>(value.c_str());
-    }
-
-    target.SetHeight(height);
-    target.SetWidth(width);
-
-    if (bitsStored == 8 && samplesPerPixel == 1 && !isSigned)
-    {
-      target.SetFormat(PixelFormat_Grayscale8);
-    }
-    else if (bitsStored == 8 && samplesPerPixel == 3 && !isSigned)
+    DicomImageInformation info(m);
+    PixelFormat format;
+    
+    if (!info.ExtractPixelFormat(format))
     {
-      target.SetFormat(PixelFormat_RGB24);
-    }
-    else if (bitsStored >= 9 && bitsStored <= 16 && samplesPerPixel == 1 && !isSigned)
-    {
-      target.SetFormat(PixelFormat_Grayscale16);
-    }
-    else if (bitsStored >= 9 && bitsStored <= 16 && samplesPerPixel == 1 && isSigned)
-    {
-      target.SetFormat(PixelFormat_SignedGrayscale16);
-    }
-    else
-    {
-      LOG(WARNING) << "Unsupported DICOM image: " << bitsStored << "bpp, " 
-      << samplesPerPixel << " channels, " << (isSigned ? "signed" : "unsigned");
+      LOG(WARNING) << "Unsupported DICOM image: " << info.GetBitsStored() 
+                   << "bpp, " << info.GetChannelCount() << " channels, " 
+                   << (info.IsSigned() ? "signed" : "unsigned");
       throw OrthancException(ErrorCode_NotImplemented);
     }
+    
+    target.SetHeight(info.GetHeight());
+    target.SetWidth(info.GetWidth());
+    target.SetFormat(format);
   }
 
 
@@ -455,8 +412,8 @@
 
     SetupImageBuffer(target, dataset);
 
-    if (target.GetWidth() != target.GetWidth() ||
-        target.GetHeight() != target.GetHeight())
+    if (source.GetWidth() != target.GetWidth() ||
+        source.GetHeight() != target.GetHeight())
     {
       throw OrthancException(ErrorCode_InternalError);
     }
@@ -490,30 +447,63 @@
 
 
     /**
+     * If the format of the DICOM buffer is natively supported, use a
+     * direct access to copy its values.
+     **/
+
+    ImageAccessor targetAccessor(target.GetAccessor());
+    const DicomImageInformation& info = source.GetAccessor().GetInformation();
+
+    bool fastVersionSuccess = false;
+    PixelFormat sourceFormat;
+    if (info.ExtractPixelFormat(sourceFormat))
+    {
+      try
+      {
+        ImageAccessor sourceImage;
+        sourceImage.AssignReadOnly(sourceFormat, 
+                                   info.GetWidth(), 
+                                   info.GetHeight(),
+                                   info.GetWidth() * info.GetBytesPerPixel(),
+                                   source.GetAccessor().GetPixelData());                                   
+
+        ImageProcessing::Convert(targetAccessor, sourceImage);
+        ImageProcessing::ShiftRight(targetAccessor, info.GetShift());
+        fastVersionSuccess = true;
+      }
+      catch (OrthancException&)
+      {
+        // Unsupported conversion
+      }
+    }
+
+
+    /**
      * Loop over the DICOM buffer, storing its value into the target
      * image.
      **/
 
-    ImageAccessor accessor(target.GetAccessor());
-
-    switch (target.GetFormat())
+    if (!fastVersionSuccess)
     {
-      case PixelFormat_RGB24:
-      case PixelFormat_RGBA32:
-      case PixelFormat_Grayscale8:
-        CopyPixels<uint8_t>(accessor, source.GetAccessor());
+      switch (target.GetFormat())
+      {
+        case PixelFormat_RGB24:
+        case PixelFormat_RGBA32:
+        case PixelFormat_Grayscale8:
+        CopyPixels<uint8_t>(targetAccessor, source.GetAccessor());
         break;
 
-      case PixelFormat_Grayscale16:
-        CopyPixels<uint16_t>(accessor, source.GetAccessor());
+        case PixelFormat_Grayscale16:
+        CopyPixels<uint16_t>(targetAccessor, source.GetAccessor());
         break;
 
-      case PixelFormat_SignedGrayscale16:
-        CopyPixels<int16_t>(accessor, source.GetAccessor());
+        case PixelFormat_SignedGrayscale16:
+        CopyPixels<int16_t>(targetAccessor, source.GetAccessor());
         break;
 
-      default:
+        default:
         throw OrthancException(ErrorCode_InternalError);
+      }
     }
   }
 
@@ -544,7 +534,7 @@
 
     SetupImageBuffer(target, dataset);
 
-    ImageAccessor accessor(target.GetAccessor());
+    ImageAccessor targetAccessor(target.GetAccessor());
 
     /**
      * The "DJLSLosslessDecoder" and "DJLSNearLosslessDecoder" in DCMTK
@@ -560,8 +550,8 @@
     OFString decompressedColorModel;  // Out
     DJ_RPLossless representationParameter;
     OFCondition c = decoder.decodeFrame(&representationParameter, pixelSequence, &parameters, 
-                                        &dataset, frame, startFragment, accessor.GetBuffer(), 
-                                        accessor.GetSize(), decompressedColorModel);
+                                        &dataset, frame, startFragment, targetAccessor.GetBuffer(), 
+                                        targetAccessor.GetSize(), decompressedColorModel);
 
     if (!c.good())
     {