diff Core/DicomFormat/DicomIntegerPixelAccessor.cpp @ 368:80011cd589e6

support of rgb images
author Sebastien Jodogne <s.jodogne@gmail.com>
date Mon, 18 Feb 2013 16:07:28 +0100
parents 760d0f32cb34
children 4632a044746e
line wrap: on
line diff
--- a/Core/DicomFormat/DicomIntegerPixelAccessor.cpp	Thu Feb 07 22:08:59 2013 +0100
+++ b/Core/DicomFormat/DicomIntegerPixelAccessor.cpp	Mon Feb 18 16:07:28 2013 +0100
@@ -40,6 +40,7 @@
 #include <boost/lexical_cast.hpp>
 #include <limits>
 #include <cassert>
+#include <stdio.h>
 
 namespace Orthanc
 {
@@ -50,6 +51,7 @@
   static const DicomTag BITS_STORED(0x0028, 0x0101);
   static const DicomTag HIGH_BIT(0x0028, 0x0102);
   static const DicomTag PIXEL_REPRESENTATION(0x0028, 0x0103);
+  static const DicomTag PLANAR_CONFIGURATION(0x0028, 0x0006);
 
   DicomIntegerPixelAccessor::DicomIntegerPixelAccessor(const DicomMap& values,
                                                        const void* pixelData,
@@ -61,6 +63,7 @@
     unsigned int bitsStored;
     unsigned int highBit;
     unsigned int pixelRepresentation;
+    planarConfiguration_ = 0;
 
     try
     {
@@ -71,11 +74,22 @@
       bitsStored = boost::lexical_cast<unsigned int>(values.GetValue(BITS_STORED).AsString());
       highBit = boost::lexical_cast<unsigned int>(values.GetValue(HIGH_BIT).AsString());
       pixelRepresentation = boost::lexical_cast<unsigned int>(values.GetValue(PIXEL_REPRESENTATION).AsString());
+
+      if (samplesPerPixel_ > 1)
+      {
+        // The "Planar Configuration" is only set when "Samples per Pixels" is greater than 1
+        // https://www.dabsoft.ch/dicom/3/C.7.6.3.1.3/
+        planarConfiguration_ = boost::lexical_cast<unsigned int>(values.GetValue(PLANAR_CONFIGURATION).AsString());
+      }
     }
     catch (boost::bad_lexical_cast)
     {
       throw OrthancException(ErrorCode_NotImplemented);
     }
+    catch (OrthancException)
+    {
+      throw OrthancException(ErrorCode_NotImplemented);
+    }
 
     frame_ = 0;
     try
@@ -94,7 +108,8 @@
 
     if ((bitsAllocated != 8 && bitsAllocated != 16 && 
          bitsAllocated != 24 && bitsAllocated != 32) ||
-        numberOfFrames_ == 0)
+        numberOfFrames_ == 0 ||
+        (planarConfiguration_ != 0 && planarConfiguration_ != 1))
     {
       throw OrthancException(ErrorCode_NotImplemented);
     }
@@ -106,21 +121,23 @@
       throw OrthancException(ErrorCode_NotImplemented);
     }
 
-    if (samplesPerPixel_ != 1)
+    if (samplesPerPixel_ != 1 &&
+        samplesPerPixel_ != 3)
     {
       throw OrthancException(ErrorCode_NotImplemented);
     }
 
-    if (width_ * height_ * bitsAllocated / 8 * numberOfFrames_ > size)
+    bytesPerPixel_ = bitsAllocated / 8;
+    shift_ = highBit + 1 - bitsStored;
+    frameOffset_ = height_ * width_ * bytesPerPixel_ * samplesPerPixel_;
+
+    if (numberOfFrames_ * frameOffset_ > size)
     {
       throw OrthancException(ErrorCode_BadFileFormat);
     }
 
     /*printf("%d %d %d %d %d %d %d %d\n", width_, height_, samplesPerPixel_, bitsAllocated,
-           bitsStored, highBit, pixelRepresentation, numberOfFrames_);*/
-
-    bytesPerPixel_ = bitsAllocated / 8;
-    shift_ = highBit + 1 - bitsStored;
+      bitsStored, highBit, pixelRepresentation, numberOfFrames_);*/
 
     if (pixelRepresentation)
     {
@@ -133,8 +150,25 @@
       signMask_ = 0;
     }
 
-    rowOffset_ = width_ * bytesPerPixel_;
-    frameOffset_ = height_ * width_ * bytesPerPixel_;
+    if (planarConfiguration_ == 0)
+    {
+      /**
+       * The sample values for the first pixel are followed by the
+       * sample values for the second pixel, etc. For RGB images, this
+       * means the order of the pixel values sent shall be R1, G1, B1,
+       * R2, G2, B2, ..., etc.
+       **/
+      rowOffset_ = width_ * bytesPerPixel_ * samplesPerPixel_;
+    }
+    else
+    {
+      /**
+       * Each color plane shall be sent contiguously. For RGB images,
+       * this means the order of the pixel values sent is R1, R2, R3,
+       * ..., G1, G2, G3, ..., B1, B2, B3, etc.
+       **/
+      rowOffset_ = width_ * bytesPerPixel_;
+    }
   }
 
 
@@ -154,22 +188,49 @@
     {
       for (unsigned int x = 0; x < width_; x++)
       {
-        int32_t v = GetValue(x, y);
-        if (v < min)
-          min = v;
-        if (v > max)
-          max = v;
+        for (unsigned int c = 0; c < GetChannelCount(); c++)
+        {
+          int32_t v = GetValue(x, y);
+          if (v < min)
+            min = v;
+          if (v > max)
+            max = v;
+        }
       }
     }
   }
 
 
-  int32_t DicomIntegerPixelAccessor::GetValue(unsigned int x, unsigned int y) const
+  int32_t DicomIntegerPixelAccessor::GetValue(unsigned int x, 
+                                              unsigned int y,
+                                              unsigned int channel) const
   {
-    assert(x < width_ && y < height_);
+    assert(x < width_ && y < height_ && channel < samplesPerPixel_);
     
     const uint8_t* pixel = reinterpret_cast<const uint8_t*>(pixelData_) + 
-      y * rowOffset_ + x * bytesPerPixel_ + frame_ * frameOffset_;
+      y * rowOffset_ + frame_ * frameOffset_;
+
+    // https://www.dabsoft.ch/dicom/3/C.7.6.3.1.3/
+    if (planarConfiguration_ == 0)
+    {
+      /**
+       * The sample values for the first pixel are followed by the
+       * sample values for the second pixel, etc. For RGB images, this
+       * means the order of the pixel values sent shall be R1, G1, B1,
+       * R2, G2, B2, ..., etc.
+       **/
+      pixel += channel * bytesPerPixel_ + x * samplesPerPixel_ * bytesPerPixel_;
+    }
+    else
+    {
+      /**
+       * Each color plane shall be sent contiguously. For RGB images,
+       * this means the order of the pixel values sent is R1, R2, R3,
+       * ..., G1, G2, G3, ..., B1, B2, B3, etc.
+       **/
+      assert(frameOffset_ % samplesPerPixel_ == 0);
+      pixel += channel * frameOffset_ / samplesPerPixel_ + x * bytesPerPixel_;
+    }
 
     int32_t v;
     v = pixel[0];