diff Framework/Volumes/VolumeReslicer.cpp @ 183:98da3a8d4820 wasm

SubvoxelReader
author Sebastien Jodogne <s.jodogne@gmail.com>
date Thu, 15 Mar 2018 15:19:24 +0100
parents 4da803580da9
children 9523ce4f44cc
line wrap: on
line diff
--- a/Framework/Volumes/VolumeReslicer.cpp	Thu Mar 15 12:12:01 2018 +0100
+++ b/Framework/Volumes/VolumeReslicer.cpp	Thu Mar 15 15:19:24 2018 +0100
@@ -1,6 +1,7 @@
 #include "VolumeReslicer.h"
 
 #include "../Toolbox/GeometryToolbox.h"
+#include "../Toolbox/SubvoxelReader.h"
 
 #include <Core/Images/ImageTraits.h>
 #include <Core/Logging.h>
@@ -116,286 +117,6 @@
     };
 
 
-
-    class VoxelReaderBase : public boost::noncopyable
-    {
-    private:
-      const Orthanc::ImageAccessor&  image_;
-      unsigned int                   width_;
-      unsigned int                   height_;
-      unsigned int                   depth_;
-      float                          widthFloat_;
-      float                          heightFloat_;
-      float                          depthFloat_;
-
-    public:
-      VoxelReaderBase(const ImageBuffer3D& image) :
-        image_(image.GetInternalImage()),
-        width_(image.GetWidth()),
-        height_(image.GetHeight()),
-        depth_(image.GetDepth()),
-        widthFloat_(static_cast<float>(image.GetWidth())),
-        heightFloat_(static_cast<float>(image.GetHeight())),
-        depthFloat_(static_cast<float>(image.GetDepth()))
-      {
-      }
-
-      const Orthanc::ImageAccessor& GetImage() const
-      {
-        return image_;
-      }
-
-      const unsigned int GetImageWidth() const
-      {
-        return width_;
-      }
-
-      const unsigned int GetImageHeight() const
-      {
-        return height_;
-      }
-
-      const unsigned int GetImageDepth() const
-      {
-        return depth_;
-      }
-
-      bool GetNearestCoordinates(unsigned int& imageX,
-                                 unsigned int& imageY,
-                                 unsigned int& imageZ,
-                                 float& fractionalX,
-                                 float& fractionalY,
-                                 float& fractionalZ,
-                                 float volumeX,
-                                 float volumeY,
-                                 float volumeZ) const
-      {
-        if (volumeX >= 0 &&
-            volumeY >= 0 &&
-            volumeZ >= 0)
-        {
-          const float x = volumeX * widthFloat_;
-          const float y = volumeY * heightFloat_;
-          const float z = volumeZ * depthFloat_;
-          
-          imageX = static_cast<unsigned int>(std::floor(x));
-          imageY = static_cast<unsigned int>(std::floor(y));
-          imageZ = static_cast<unsigned int>(std::floor(z));
-
-          if (imageX < width_ &&
-              imageY < height_ &&
-              imageZ < depth_)
-          {
-            fractionalX = x - static_cast<float>(imageX);
-            fractionalY = y - static_cast<float>(imageY);
-            fractionalZ = z - static_cast<float>(imageZ);
-            return true;
-          }
-          else
-          {
-            return false;
-          }
-        }
-        else
-        {
-          return false;
-        }
-      }
-    };
-
-
-    template <Orthanc::PixelFormat InputFormat,
-              ImageInterpolation Interpolation>
-    class VoxelReader;
-
-    
-    template <Orthanc::PixelFormat InputFormat>
-    class VoxelReader<InputFormat, ImageInterpolation_Nearest> :
-      public VoxelReaderBase
-    {
-    public:
-      typedef typename Orthanc::PixelTraits<InputFormat>::PixelType   InputPixelType;
-
-      VoxelReader(const ImageBuffer3D& image) :
-        VoxelReaderBase(image)
-      {
-      }
-
-      ORTHANC_FORCE_INLINE
-      float GetFloatValue(float volumeX,
-                          float volumeY,
-                          float volumeZ) const
-      {
-        InputPixelType value;
-        GetValue(value, volumeX, volumeY, volumeZ);
-        return static_cast<float>(value);
-      }
-
-      ORTHANC_FORCE_INLINE
-      void GetValue(InputPixelType& target,
-                    float volumeX,
-                    float volumeY,
-                    float volumeZ) const
-      {
-        unsigned int imageX, imageY, imageZ;
-        float fractionalX, fractionalY, fractionalZ;  // unused
-
-        if (GetNearestCoordinates(imageX, imageY, imageZ,
-                                  fractionalX, fractionalY, fractionalZ,
-                                  volumeX, volumeY, volumeZ))
-        {
-          Orthanc::ImageTraits<InputFormat>::GetPixel(target, GetImage(), imageX, 
-                                                      imageY + imageZ * GetImageHeight());
-        }
-        else
-        {
-          target = std::numeric_limits<InputPixelType>::min();
-        }
-      }
-    };
-    
-    
-    template <Orthanc::PixelFormat InputFormat>
-    class VoxelReader<InputFormat, ImageInterpolation_Bilinear> :
-      public VoxelReaderBase
-    {
-    private:
-      float outOfVolume_;
-      
-    public:
-      VoxelReader(const ImageBuffer3D& image) :
-        VoxelReaderBase(image)
-      {
-        typedef typename Orthanc::PixelTraits<InputFormat>::PixelType Pixel;
-        outOfVolume_ = static_cast<float>(std::numeric_limits<Pixel>::min());
-      }
-
-      void SampleVoxels(float& f00,
-                        float& f01,
-                        float& f10,
-                        float& f11,
-                        unsigned int imageX,
-                        unsigned int imageY,
-                        unsigned int imageZ) const
-      {
-        f00 = Orthanc::ImageTraits<InputFormat>::GetFloatPixel
-          (GetImage(), imageX, imageY + imageZ * GetImageHeight());
-
-        if (imageX + 1 < GetImageWidth())
-        {
-          f01 = Orthanc::ImageTraits<InputFormat>::GetFloatPixel
-            (GetImage(), imageX + 1, imageY + imageZ * GetImageHeight());
-        }
-        else
-        {
-          f01 = f00;
-        }
-
-        if (imageY + 1 < GetImageWidth())
-        {
-          f10 = Orthanc::ImageTraits<InputFormat>::GetFloatPixel
-            (GetImage(), imageX, imageY + 1 + imageZ * GetImageHeight());
-        }
-        else
-        {
-          f10 = f00;
-        }
-
-        if (imageX + 1 < GetImageWidth() &&
-            imageY + 1 < GetImageHeight())
-        {
-          f11 = Orthanc::ImageTraits<InputFormat>::GetFloatPixel
-            (GetImage(), imageX + 1, imageY + 1 + imageZ * GetImageHeight());
-        }
-        else
-        {
-          f11 = f00;
-        }
-      }
-
-      float GetOutOfVolume() const
-      {
-        return outOfVolume_;
-      }
-      
-      float GetFloatValue(float volumeX,
-                          float volumeY,
-                          float volumeZ) const
-      {
-        unsigned int imageX, imageY, imageZ;
-        float fractionalX, fractionalY, fractionalZ;
-
-        if (GetNearestCoordinates(imageX, imageY, imageZ,
-                                  fractionalX, fractionalY, fractionalZ,
-                                  volumeX, volumeY, volumeZ))
-        {
-          float f00, f01, f10, f11;
-          SampleVoxels(f00, f01, f10, f11, imageX, imageY, imageZ);
-          return GeometryToolbox::ComputeBilinearInterpolationUnitSquare
-            (fractionalX, fractionalY, f00, f01, f10, f11);
-        }
-        else
-        {
-          return outOfVolume_;
-        }
-      }
-    };
-
-
-    template <Orthanc::PixelFormat InputFormat>
-    class VoxelReader<InputFormat, ImageInterpolation_Trilinear> :
-      public VoxelReaderBase
-    {
-    private:
-      typedef VoxelReader<InputFormat, ImageInterpolation_Bilinear>  Bilinear;
-
-      Bilinear      bilinear_;
-      unsigned int  imageDepth_;
-
-    public:
-      VoxelReader(const ImageBuffer3D& image) :
-        VoxelReaderBase(image),
-        bilinear_(image),
-        imageDepth_(image.GetDepth())
-      {
-      }
-
-      float GetFloatValue(float volumeX,
-                          float volumeY,
-                          float volumeZ) const
-      {
-        unsigned int imageX, imageY, imageZ;
-        float fractionalX, fractionalY, fractionalZ;
-
-        if (GetNearestCoordinates(imageX, imageY, imageZ,
-                                  fractionalX, fractionalY, fractionalZ,
-                                  volumeX, volumeY, volumeZ))
-        {
-          float f000, f001, f010, f011;
-          bilinear_.SampleVoxels(f000, f001, f010, f011, imageX, imageY, imageZ);
-
-          if (imageZ + 1 < imageDepth_)
-          {
-            float f100, f101, f110, f111;
-            bilinear_.SampleVoxels(f100, f101, f110, f111, imageX, imageY, imageZ + 1);
-            return GeometryToolbox::ComputeTrilinearInterpolationUnitSquare
-              (fractionalX, fractionalY, fractionalZ,
-               f000, f001, f010, f011, f100, f101, f110, f111);
-          }
-          else
-          {
-            return GeometryToolbox::ComputeBilinearInterpolationUnitSquare
-              (fractionalX, fractionalY, f000, f001, f010, f011);
-          }
-        }
-        else
-        {
-          return bilinear_.GetOutOfVolume();
-        }
-      }
-    };
-
-
     template <typename VoxelReader,
               typename PixelWriter,
               TransferFunction Function>
@@ -424,9 +145,14 @@
                  float volumeY,
                  float volumeZ)
       {
-        typename VoxelReader::InputPixelType image;
-        reader_.GetValue(image, volumeX, volumeY, volumeZ);
-        writer_.SetValue(pixel, image);
+        typename VoxelReader::PixelType value;
+
+        if (!reader_.GetValue(value, volumeX, volumeY, volumeZ))
+        {
+          VoxelReader::Traits::SetMinValue(value);
+        }
+
+        writer_.SetValue(pixel, value);
       }        
     };
 
@@ -438,12 +164,14 @@
     private:
       VoxelReader  reader_;
       PixelWriter  writer_;
+      float        outOfVolume_;
       
     public:
       PixelShader(const ImageBuffer3D& image,
                   float /* scaling */,
                   float /* offset */) :
-        reader_(image)
+        reader_(image),
+        outOfVolume_(static_cast<float>(std::numeric_limits<typename VoxelReader::PixelType>::min()))
       {
       }
       
@@ -453,8 +181,15 @@
                  float volumeY,
                  float volumeZ)
       {
-        writer_.SetFloatValue(pixel, reader_.GetFloatValue(volumeX, volumeY, volumeZ));
-      }        
+        float value;
+
+        if (!reader_.GetFloatValue(value, volumeX, volumeY, volumeZ))
+        {
+          value = outOfVolume_;
+        }
+
+        writer_.SetFloatValue(pixel, value);
+      }
     };
 
     
@@ -467,6 +202,7 @@
       PixelWriter  writer_;
       float        scaling_;
       float        offset_;
+      float        outOfVolume_;
       
     public:
       PixelShader(const ImageBuffer3D& image,
@@ -474,7 +210,8 @@
                   float offset) :
         reader_(image),
         scaling_(scaling),
-        offset_(offset)
+        offset_(offset),
+        outOfVolume_(static_cast<float>(std::numeric_limits<typename VoxelReader::PixelType>::min()))
       {
       }
       
@@ -484,7 +221,18 @@
                  float volumeY,
                  float volumeZ)
       {
-        writer_.SetFloatValue(pixel, scaling_ * reader_.GetFloatValue(volumeX, volumeY, volumeZ) + offset_);
+        float value;
+
+        if (reader_.GetFloatValue(value, volumeX, volumeY, volumeZ))
+        {
+          value = scaling_ * value + offset_;
+        }
+        else
+        {
+          value = outOfVolume_;
+        }
+
+        writer_.SetFloatValue(pixel, value);
       }        
     };
 
@@ -616,13 +364,17 @@
                              float scaling,
                              float offset)
     {
-      typedef VoxelReader<InputFormat, Interpolation>   Reader;
-      typedef PixelWriter<InputFormat, OutputFormat>    Writer;
-      typedef PixelShader<Reader, Writer, Function>     Shader;
+      typedef SubvoxelReader<InputFormat, Interpolation>   Reader;
+      typedef PixelWriter<InputFormat, OutputFormat>       Writer;
+      typedef PixelShader<Reader, Writer, Function>        Shader;
 
       const unsigned int outputWidth = slice.GetWidth();
       const unsigned int outputHeight = slice.GetHeight();
 
+      const float sourceWidth = static_cast<float>(source.GetWidth());
+      const float sourceHeight = static_cast<float>(source.GetHeight());
+      const float sourceDepth = static_cast<float>(source.GetDepth());
+
       Shader shader(source, scaling, offset);
 
       for (unsigned int y = 0; y < outputHeight; y++)
@@ -636,7 +388,11 @@
         {
           float volumeX, volumeY, volumeZ;
           it.GetVolumeCoordinates(volumeX, volumeY, volumeZ);
-          shader.Apply(p, volumeX, volumeY, volumeZ);
+
+          shader.Apply(p, 
+                       volumeX * sourceWidth, 
+                       volumeY * sourceHeight, 
+                       volumeZ * sourceDepth);
           it.Next();
         }
       }