changeset 989:8566ba2d4b3a plugins

integration mainline->plugins
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 01 Jul 2014 16:54:34 +0200
parents 0bfdfc0c6b9b (current diff) 9ea31f012561 (diff)
children af014624dac1
files NEWS
diffstat 8 files changed, 198 insertions(+), 121 deletions(-) [+]
line wrap: on
line diff
--- a/NEWS	Tue Jul 01 15:22:14 2014 +0200
+++ b/NEWS	Tue Jul 01 16:54:34 2014 +0200
@@ -1,13 +1,21 @@
 Pending changes in the mainline
 ===============================
 
+Major changes
+-------------
+
 * Introduction of the Orthanc Plugin SDK
 * Official support of OS X (Darwin)
+
+Minor changes
+-------------
+
 * Extraction of tags for the patient/study/series/instance DICOM modules
 * Extraction of the tags shared by all the instances of a patient/study/series
 * Options to limit the number of results for an incoming C-FIND query
 * Support of kFreeBSD
 * Several code refactorings
+* Fix OrthancCppClient::GetVoxelSizeZ()
 
 
 Version 0.7.6 (2014/06/11)
--- a/OrthancCppClient/Series.cpp	Tue Jul 01 15:22:14 2014 +0200
+++ b/OrthancCppClient/Series.cpp	Tue Jul 01 16:54:34 2014 +0200
@@ -53,11 +53,12 @@
         /**
          * Compute the slice normal from Image Orientation Patient.
          * http://nipy.sourceforge.net/nibabel/dicom/dicom_orientation.html#dicom-z-from-slice
+         * http://dicomiseasy.blogspot.be/2013/06/getting-oriented-using-image-plane.html
          * http://www.itk.org/pipermail/insight-users/2003-September/004762.html
          **/
 
         std::vector<float> cosines;
-        someSlice.SplitVectorOfFloats(cosines, "ImageOrientationPatient");
+        someSlice.SplitVectorOfFloats(cosines, "ImageOrientationPatient");  // 0020-0037
 
         if (cosines.size() != 6)
         {
@@ -76,7 +77,7 @@
       float ComputeSliceLocation(Instance& instance) const
       {
         std::vector<float> ipp;
-        instance.SplitVectorOfFloats(ipp, "ImagePositionPatient");
+        instance.SplitVectorOfFloats(ipp, "ImagePositionPatient");  // 0020-0032
         if (ipp.size() != 3)
         {
           throw OrthancClientException(Orthanc::ErrorCode_BadFileFormat);
@@ -129,7 +130,7 @@
 
           if (instance_.GetPixelFormat() == format_)
           {
-            memcpy(p, instance_.GetBuffer(y), 2 * instance_.GetWidth());
+            memcpy(p, instance_.GetBuffer(y), GetBytesPerPixel(instance_.GetPixelFormat()) * instance_.GetWidth());
           }
           else if (instance_.GetPixelFormat() == PixelFormat_Grayscale8 &&
                    format_ == PixelFormat_RGB24)
@@ -212,32 +213,77 @@
     {
       if (GetInstanceCount() == 0)
       {
+        // Empty image, use some default value (should never happen)
+        voxelSizeX_ = 1;
+        voxelSizeY_ = 1;
+        voxelSizeZ_ = 1;
+        sliceThickness_ = 1;
+
         return true;
       }
 
-      Instance& i1 = GetInstance(0);
+      // Choose a reference slice
+      Instance& reference = GetInstance(0);
 
+      // Check that all the child instances share the same 3D parameters
       for (unsigned int i = 0; i < GetInstanceCount(); i++)
       {
         Instance& i2 = GetInstance(i);
 
-        if (std::string(i1.GetTagAsString("Columns")) != std::string(i2.GetTagAsString("Columns")) ||
-            std::string(i1.GetTagAsString("Rows")) != std::string(i2.GetTagAsString("Rows")) ||
-            std::string(i1.GetTagAsString("ImageOrientationPatient")) != std::string(i2.GetTagAsString("ImageOrientationPatient")) ||
-            std::string(i1.GetTagAsString("SliceThickness")) != std::string(i2.GetTagAsString("SliceThickness")) ||
-            std::string(i1.GetTagAsString("PixelSpacing")) != std::string(i2.GetTagAsString("PixelSpacing")))
+        if (std::string(reference.GetTagAsString("Columns")) != std::string(i2.GetTagAsString("Columns")) ||
+            std::string(reference.GetTagAsString("Rows")) != std::string(i2.GetTagAsString("Rows")) ||
+            std::string(reference.GetTagAsString("ImageOrientationPatient")) != std::string(i2.GetTagAsString("ImageOrientationPatient")) ||
+            std::string(reference.GetTagAsString("SliceThickness")) != std::string(i2.GetTagAsString("SliceThickness")) ||
+            std::string(reference.GetTagAsString("PixelSpacing")) != std::string(i2.GetTagAsString("PixelSpacing")))
         {
           return false;
         }              
       }
 
-      SliceLocator locator(GetInstance(0));
+
+      // Extract X/Y voxel size and slice thickness
+      std::string s = GetInstance(0).GetTagAsString("PixelSpacing");  // 0028-0030
+      size_t pos = s.find('\\');
+      assert(pos != std::string::npos);
+      std::string sy = s.substr(0, pos);
+      std::string sx = s.substr(pos + 1);
+
+      try
+      {
+        voxelSizeX_ = boost::lexical_cast<float>(sx);
+        voxelSizeY_ = boost::lexical_cast<float>(sy);
+      }
+      catch (boost::bad_lexical_cast)
+      {
+        throw OrthancClientException(Orthanc::ErrorCode_BadFileFormat);
+      }
+
+      sliceThickness_ = GetInstance(0).GetTagAsFloat("SliceThickness");  // 0018-0050
+
+
+      // Compute the location of each slice to extract the voxel size along Z
+      voxelSizeZ_ = std::numeric_limits<float>::infinity();
+
+      SliceLocator locator(reference);
+      float referenceSliceLocation = locator.ComputeSliceLocation(reference);
+
       std::set<float> l;
       for (unsigned int i = 0; i < GetInstanceCount(); i++)
       {
-        l.insert(locator.ComputeSliceLocation(GetInstance(i)));
+        float location = locator.ComputeSliceLocation(GetInstance(i));
+        float distanceToReferenceSlice = fabs(location - referenceSliceLocation);
+
+        l.insert(location);
+
+        if (distanceToReferenceSlice > std::numeric_limits<float>::epsilon() &&
+            distanceToReferenceSlice < voxelSizeZ_)
+        {
+          voxelSizeZ_ = distanceToReferenceSlice;
+        }
       }
 
+
+      // Make sure that 2 slices do not share the same Z location
       return l.size() == GetInstanceCount();
     }
     catch (OrthancClientException)
@@ -275,10 +321,10 @@
     status_ = Status3DImage_NotTested;
     url_ = std::string(connection_.GetOrthancUrl()) + "/series/" + id_;
 
-    isVoxelSizeRead_ = false;
     voxelSizeX_ = 0;
     voxelSizeY_ = 0;
     voxelSizeZ_ = 0;
+    sliceThickness_ = 0;
 
     instances_.SetThreadCount(connection.GetThreadCount());
   }
@@ -324,46 +370,6 @@
       return GetInstance(0).GetTagAsInt("Rows");
   }
 
-  void Series::LoadVoxelSize()
-  {
-    if (isVoxelSizeRead_)
-    {
-      return;
-    }
-
-    Check3DImage();
-
-    if (GetInstanceCount() == 0)
-    {
-      // Empty image, use some default value
-      voxelSizeX_ = 1;
-      voxelSizeY_ = 1;
-      voxelSizeZ_ = 1;
-    }
-    else
-    {
-      try
-      {
-        std::string s = GetInstance(0).GetTagAsString("PixelSpacing");
-        size_t pos = s.find('\\');
-        assert(pos != std::string::npos);
-        std::string sy = s.substr(0, pos);
-        std::string sx = s.substr(pos + 1);
-
-        voxelSizeX_ = boost::lexical_cast<float>(sx);
-        voxelSizeY_ = boost::lexical_cast<float>(sy);
-        voxelSizeZ_ = GetInstance(0).GetTagAsFloat("SliceThickness");
-      }
-      catch (boost::bad_lexical_cast)
-      {
-        throw OrthancClientException(Orthanc::ErrorCode_NotImplemented);
-      }
-    }
-
-    isVoxelSizeRead_ = true;
-  }
-
-
   const char* Series::GetMainDicomTag(const char* tag, const char* defaultValue) const
   {
     if (series_["MainDicomTags"].isMember(tag))
@@ -486,22 +492,28 @@
 
   float Series::GetVoxelSizeX()
   {
-    LoadVoxelSize();
+    Check3DImage();   // Is3DImageInternal() will compute the voxel sizes
     return voxelSizeX_;
   }
 
   float Series::GetVoxelSizeY()
   {
-    LoadVoxelSize();
+    Check3DImage();   // Is3DImageInternal() will compute the voxel sizes
     return voxelSizeY_;
   }
 
   float Series::GetVoxelSizeZ()
   {
-    LoadVoxelSize();
+    Check3DImage();   // Is3DImageInternal() will compute the voxel sizes
     return voxelSizeZ_;
   }
 
+  float Series::GetSliceThickness()
+  {
+    Check3DImage();   // Is3DImageInternal() will compute the voxel sizes
+    return sliceThickness_;
+  }
+
   void Series::Load3DImage(void* target,
                            Orthanc::PixelFormat format,
                            int64_t lineStride,
--- a/OrthancCppClient/Series.h	Tue Jul 01 15:22:14 2014 +0200
+++ b/OrthancCppClient/Series.h	Tue Jul 01 16:54:34 2014 +0200
@@ -62,11 +62,11 @@
     Orthanc::ArrayFilledByThreads  instances_;
     Status3DImage status_;
 
-    bool isVoxelSizeRead_;
     float voxelSizeX_;
     float voxelSizeY_;
     float voxelSizeZ_;
-  
+    float sliceThickness_;
+
     void Check3DImage();
 
     bool Is3DImageInternal();
@@ -86,8 +86,6 @@
                              size_t stackStride,
                              Orthanc::ThreadedCommandProcessor::IListener* listener);
 
-    void LoadVoxelSize();  
-
   public:
     /**
      * {summary}{Create a connection to some series.}
@@ -189,6 +187,13 @@
      **/
     float GetVoxelSizeZ();
 
+    /**
+     * {summary}{Get the slice thickness.}
+     * {description}{Get the slice thickness. This call is only valid if this series corresponds to a 3D image.}
+     * {returns}{The slice thickness.}
+     **/
+    float GetSliceThickness();
+
     LAAW_API_INTERNAL void Load3DImage(void* target,
                                        Orthanc::PixelFormat format,
                                        int64_t lineStride,
--- a/OrthancCppClient/SharedLibrary/AUTOGENERATED/ExternC.cpp	Tue Jul 01 15:22:14 2014 +0200
+++ b/OrthancCppClient/SharedLibrary/AUTOGENERATED/ExternC.cpp	Tue Jul 01 16:54:34 2014 +0200
@@ -795,6 +795,29 @@
         }
       }
 
+      LAAW_EXPORT_DLL_API char* LAAW_CALL_CONVENTION LAAW_EXTERNC_2be452e7af5bf7dfd8c5021842674497(void* thisObject, float* result)
+      {
+        try
+        {
+          #ifdef LAAW_EXTERNC_START_FUNCTION
+          LAAW_EXTERNC_START_FUNCTION;
+          #endif
+
+          OrthancClient::Series* this_ = static_cast<OrthancClient::Series*>(thisObject);
+*result = this_->GetSliceThickness();
+
+          return NULL;
+        }
+        catch (::Laaw::LaawException& e)
+        {
+          return LAAW_EXTERNC_CopyString(e.What());
+        }
+        catch (...)
+        {
+          return LAAW_EXTERNC_CopyString("...");
+        }
+      }
+
       LAAW_EXPORT_DLL_API char* LAAW_CALL_CONVENTION LAAW_EXTERNC_4dcc7a0fd025efba251ac6e9b701c2c5(void* thisObject, void* arg0, int32_t arg1, int64_t arg2, int64_t arg3)
       {
         try
--- a/OrthancCppClient/SharedLibrary/AUTOGENERATED/OrthancCppClient.h	Tue Jul 01 15:22:14 2014 +0200
+++ b/OrthancCppClient/SharedLibrary/AUTOGENERATED/OrthancCppClient.h	Tue Jul 01 16:54:34 2014 +0200
@@ -203,7 +203,7 @@
   {
   private:
     LAAW_ORTHANC_CLIENT_HANDLE_TYPE  handle_;
-    LAAW_ORTHANC_CLIENT_FUNCTION_TYPE  functionsIndex_[62 + 1];
+    LAAW_ORTHANC_CLIENT_FUNCTION_TYPE  functionsIndex_[63 + 1];
 
 
 
@@ -239,7 +239,7 @@
     void FreeString(char* str)
     {
       typedef void (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (char*);
-      Function function = (Function) GetFunction(62);
+      Function function = (Function) GetFunction(63);
       function(str);
     }
 
@@ -391,7 +391,7 @@
     throw ::OrthancClient::OrthancClientException("Mismatch between the C++ header and the library version");
   }
 
-  functionsIndex_[62] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_FreeString", "4");
+  functionsIndex_[63] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_FreeString", "4");
   functionsIndex_[3] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_557aee7b61817292a0f31269d3c35db7", "8");
   functionsIndex_[4] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_0b8dff0ce67f10954a49b059e348837e", "8");
   functionsIndex_[5] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_e05097c153f676e5a5ee54dcfc78256f", "4");
@@ -423,40 +423,41 @@
   functionsIndex_[30] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_b794f5cd3dad7d7b575dd1fd902afdd0", "8");
   functionsIndex_[31] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_8ee2e50dd9df8f66a3c1766090dd03ab", "8");
   functionsIndex_[32] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_046aed35bbe4751691f4c34cc249a61d", "8");
-  functionsIndex_[33] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_4dcc7a0fd025efba251ac6e9b701c2c5", "28");
-  functionsIndex_[34] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_b2601a161c24ad0a1d3586246f87452c", "32");
+  functionsIndex_[33] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_2be452e7af5bf7dfd8c5021842674497", "8");
+  functionsIndex_[34] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_4dcc7a0fd025efba251ac6e9b701c2c5", "28");
+  functionsIndex_[35] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_b2601a161c24ad0a1d3586246f87452c", "32");
   functionsIndex_[19] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_193599b9e345384fcdfcd47c29c55342", "12");
   functionsIndex_[20] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_7c97f17063a357d38c5fab1136ad12a0", "4");
-  functionsIndex_[37] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_e65b20b7e0170b67544cd6664a4639b7", "4");
-  functionsIndex_[38] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_470e981b0e41f17231ba0ae6f3033321", "8");
-  functionsIndex_[39] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_04cefd138b6ea15ad909858f2a0a8f05", "12");
-  functionsIndex_[40] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_aee5b1f6f0c082f2c3b0986f9f6a18c7", "8");
-  functionsIndex_[41] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_93965682bace75491413e1f0b8d5a654", "16");
-  functionsIndex_[35] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_b01c6003238eb46c8db5dc823d7ca678", "12");
-  functionsIndex_[36] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_0147007fb99bad8cd95a139ec8795376", "4");
-  functionsIndex_[44] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_236ee8b403bc99535a8a4695c0cd45cb", "8");
-  functionsIndex_[45] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_2a437b7aba6bb01e81113835be8f0146", "8");
-  functionsIndex_[46] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_2bcbcb850934ae0bb4c6f0cc940e6cda", "8");
-  functionsIndex_[47] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_8d415c3a78a48e7e61d9fd24e7c79484", "12");
-  functionsIndex_[48] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_70d2f8398bbc63b5f792b69b4ad5fecb", "12");
-  functionsIndex_[49] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_1729a067d902771517388eedd7346b23", "12");
-  functionsIndex_[50] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_72e2aeee66cd3abd8ab7e987321c3745", "8");
-  functionsIndex_[51] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_1ea3df5a1ac1a1a687fe7325adddb6f0", "8");
-  functionsIndex_[52] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_99b4f370e4f532d8b763e2cb49db92f8", "8");
-  functionsIndex_[53] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_c41c742b68617f1c0590577a0a5ebc0c", "8");
-  functionsIndex_[54] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_142dd2feba0fc1d262bbd0baeb441a8b", "8");
-  functionsIndex_[55] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_5f5c9f81a4dff8daa6c359f1d0488fef", "12");
-  functionsIndex_[56] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_9ca979fffd08fa256306d4e68d8b0e91", "8");
-  functionsIndex_[57] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_6f2d77a26edc91c28d89408dbc3c271e", "8");
-  functionsIndex_[58] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_c0f494b80d4ff8b232df7a75baa0700a", "4");
-  functionsIndex_[59] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_d604f44bd5195e082e745e9cbc164f4c", "4");
-  functionsIndex_[60] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_1710299d1c5f3b1f2b7cf3962deebbfd", "8");
-  functionsIndex_[61] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_bb55aaf772ddceaadee36f4e54136bcb", "8");
-  functionsIndex_[42] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_6c5ad02f91b583e29cebd0bd319ce21d", "12");
-  functionsIndex_[43] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_4068241c44a9c1367fe0e57be523f207", "4");
+  functionsIndex_[38] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_e65b20b7e0170b67544cd6664a4639b7", "4");
+  functionsIndex_[39] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_470e981b0e41f17231ba0ae6f3033321", "8");
+  functionsIndex_[40] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_04cefd138b6ea15ad909858f2a0a8f05", "12");
+  functionsIndex_[41] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_aee5b1f6f0c082f2c3b0986f9f6a18c7", "8");
+  functionsIndex_[42] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_93965682bace75491413e1f0b8d5a654", "16");
+  functionsIndex_[36] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_b01c6003238eb46c8db5dc823d7ca678", "12");
+  functionsIndex_[37] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_0147007fb99bad8cd95a139ec8795376", "4");
+  functionsIndex_[45] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_236ee8b403bc99535a8a4695c0cd45cb", "8");
+  functionsIndex_[46] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_2a437b7aba6bb01e81113835be8f0146", "8");
+  functionsIndex_[47] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_2bcbcb850934ae0bb4c6f0cc940e6cda", "8");
+  functionsIndex_[48] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_8d415c3a78a48e7e61d9fd24e7c79484", "12");
+  functionsIndex_[49] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_70d2f8398bbc63b5f792b69b4ad5fecb", "12");
+  functionsIndex_[50] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_1729a067d902771517388eedd7346b23", "12");
+  functionsIndex_[51] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_72e2aeee66cd3abd8ab7e987321c3745", "8");
+  functionsIndex_[52] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_1ea3df5a1ac1a1a687fe7325adddb6f0", "8");
+  functionsIndex_[53] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_99b4f370e4f532d8b763e2cb49db92f8", "8");
+  functionsIndex_[54] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_c41c742b68617f1c0590577a0a5ebc0c", "8");
+  functionsIndex_[55] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_142dd2feba0fc1d262bbd0baeb441a8b", "8");
+  functionsIndex_[56] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_5f5c9f81a4dff8daa6c359f1d0488fef", "12");
+  functionsIndex_[57] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_9ca979fffd08fa256306d4e68d8b0e91", "8");
+  functionsIndex_[58] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_6f2d77a26edc91c28d89408dbc3c271e", "8");
+  functionsIndex_[59] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_c0f494b80d4ff8b232df7a75baa0700a", "4");
+  functionsIndex_[60] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_d604f44bd5195e082e745e9cbc164f4c", "4");
+  functionsIndex_[61] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_1710299d1c5f3b1f2b7cf3962deebbfd", "8");
+  functionsIndex_[62] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_bb55aaf772ddceaadee36f4e54136bcb", "8");
+  functionsIndex_[43] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_6c5ad02f91b583e29cebd0bd319ce21d", "12");
+  functionsIndex_[44] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_4068241c44a9c1367fe0e57be523f207", "4");
   
   /* Check whether the functions were properly loaded */
-  for (unsigned int i = 0; i <= 62; i++)
+  for (unsigned int i = 0; i <= 63; i++)
   {
     if (functionsIndex_[i] == (LAAW_ORTHANC_CLIENT_FUNCTION_TYPE) NULL)
     {
@@ -704,6 +705,7 @@
     inline float GetVoxelSizeX();
     inline float GetVoxelSizeY();
     inline float GetVoxelSizeZ();
+    inline float GetSliceThickness();
     inline void Load3DImage(void* target, ::Orthanc::PixelFormat format, LAAW_INT64 lineStride, LAAW_INT64 stackStride);
     inline void Load3DImage(void* target, ::Orthanc::PixelFormat format, LAAW_INT64 lineStride, LAAW_INT64 stackStride, float progress[]);
   };
@@ -1323,6 +1325,22 @@
     return result_;
   }
   /**
+  * @brief Get the slice thickness.
+  *
+  * Get the slice thickness. This call is only valid if this series corresponds to a 3D image.
+  *
+  * @return The slice thickness.
+  **/
+  inline float Series::GetSliceThickness()
+  {
+    float result_;
+    typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (void*, float*);
+    Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(33);
+    char* error = function(pimpl_, &result_);
+    ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error);
+    return result_;
+  }
+  /**
   * @brief Load the 3D image into a memory buffer.
   *
   * Load the 3D image into a memory buffer. This call is only valid if this series corresponds to a 3D image. The "target" buffer must be wide enough to store all the voxels of the image.
@@ -1335,7 +1353,7 @@
   inline void Series::Load3DImage(void* target, ::Orthanc::PixelFormat format, LAAW_INT64 lineStride, LAAW_INT64 stackStride)
   {
     typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (void*, void*, LAAW_INT32, LAAW_INT64, LAAW_INT64);
-    Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(33);
+    Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(34);
     char* error = function(pimpl_, target, format, lineStride, stackStride);
     ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error);
   }
@@ -1353,7 +1371,7 @@
   inline void Series::Load3DImage(void* target, ::Orthanc::PixelFormat format, LAAW_INT64 lineStride, LAAW_INT64 stackStride, float progress[])
   {
     typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (void*, void*, LAAW_INT32, LAAW_INT64, LAAW_INT64, float*);
-    Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(34);
+    Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(35);
     char* error = function(pimpl_, target, format, lineStride, stackStride, progress);
     ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error);
   }
@@ -1373,7 +1391,7 @@
   {
     isReference_ = false;
     typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (void**, void*, const char*);
-    Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(35);
+    Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(36);
     char* error = function(&pimpl_, connection.pimpl_, id.c_str());
     ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error);
   }
@@ -1387,7 +1405,7 @@
   {
     if (isReference_) return;
     typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (void*);
-    Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(36);
+    Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(37);
     char* error = function(pimpl_);
     error = error;  // Remove warning about unused variable
   }
@@ -1400,7 +1418,7 @@
   inline void Study::Reload()
   {
     typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (void*);
-    Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(37);
+    Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(38);
     char* error = function(pimpl_);
     ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error);
   }
@@ -1415,7 +1433,7 @@
   {
     LAAW_UINT32 result_;
     typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (void*, LAAW_UINT32*);
-    Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(38);
+    Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(39);
     char* error = function(pimpl_, &result_);
     ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error);
     return result_;
@@ -1432,7 +1450,7 @@
   {
     void* result_;
     typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (void*, void**, LAAW_UINT32);
-    Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(39);
+    Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(40);
     char* error = function(pimpl_, &result_, index);
     ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error);
     return ::OrthancClient::Series(result_);
@@ -1448,7 +1466,7 @@
   {
     const char* result_;
     typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (const void*, const char**);
-    Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(40);
+    Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(41);
     char* error = function(pimpl_, &result_);
     ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error);
     return std::string(result_);
@@ -1466,7 +1484,7 @@
   {
     const char* result_;
     typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (const void*, const char**, const char*, const char*);
-    Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(41);
+    Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(42);
     char* error = function(pimpl_, &result_, tag.c_str(), defaultValue.c_str());
     ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error);
     return std::string(result_);
@@ -1487,7 +1505,7 @@
   {
     isReference_ = false;
     typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (void**, void*, const char*);
-    Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(42);
+    Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(43);
     char* error = function(&pimpl_, connection.pimpl_, id.c_str());
     ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error);
   }
@@ -1501,7 +1519,7 @@
   {
     if (isReference_) return;
     typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (void*);
-    Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(43);
+    Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(44);
     char* error = function(pimpl_);
     error = error;  // Remove warning about unused variable
   }
@@ -1516,7 +1534,7 @@
   {
     const char* result_;
     typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (const void*, const char**);
-    Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(44);
+    Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(45);
     char* error = function(pimpl_, &result_);
     ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error);
     return std::string(result_);
@@ -1531,7 +1549,7 @@
   inline void Instance::SetImageExtractionMode(::Orthanc::ImageExtractionMode mode)
   {
     typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (void*, LAAW_INT32);
-    Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(45);
+    Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(46);
     char* error = function(pimpl_, mode);
     ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error);
   }
@@ -1546,7 +1564,7 @@
   {
     LAAW_INT32 result_;
     typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (const void*, LAAW_INT32*);
-    Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(46);
+    Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(47);
     char* error = function(pimpl_, &result_);
     ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error);
     return static_cast< ::Orthanc::ImageExtractionMode >(result_);
@@ -1563,7 +1581,7 @@
   {
     const char* result_;
     typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (const void*, const char**, const char*);
-    Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(47);
+    Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(48);
     char* error = function(pimpl_, &result_, tag.c_str());
     ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error);
     return std::string(result_);
@@ -1580,7 +1598,7 @@
   {
     float result_;
     typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (const void*, float*, const char*);
-    Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(48);
+    Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(49);
     char* error = function(pimpl_, &result_, tag.c_str());
     ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error);
     return result_;
@@ -1597,7 +1615,7 @@
   {
     LAAW_INT32 result_;
     typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (const void*, LAAW_INT32*, const char*);
-    Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(49);
+    Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(50);
     char* error = function(pimpl_, &result_, tag.c_str());
     ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error);
     return result_;
@@ -1613,7 +1631,7 @@
   {
     LAAW_UINT32 result_;
     typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (void*, LAAW_UINT32*);
-    Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(50);
+    Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(51);
     char* error = function(pimpl_, &result_);
     ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error);
     return result_;
@@ -1629,7 +1647,7 @@
   {
     LAAW_UINT32 result_;
     typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (void*, LAAW_UINT32*);
-    Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(51);
+    Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(52);
     char* error = function(pimpl_, &result_);
     ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error);
     return result_;
@@ -1645,7 +1663,7 @@
   {
     LAAW_UINT32 result_;
     typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (void*, LAAW_UINT32*);
-    Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(52);
+    Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(53);
     char* error = function(pimpl_, &result_);
     ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error);
     return result_;
@@ -1661,7 +1679,7 @@
   {
     LAAW_INT32 result_;
     typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (void*, LAAW_INT32*);
-    Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(53);
+    Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(54);
     char* error = function(pimpl_, &result_);
     ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error);
     return static_cast< ::Orthanc::PixelFormat >(result_);
@@ -1677,7 +1695,7 @@
   {
     const void* result_;
     typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (void*, const void**);
-    Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(54);
+    Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(55);
     char* error = function(pimpl_, &result_);
     ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error);
     return reinterpret_cast< const void* >(result_);
@@ -1694,7 +1712,7 @@
   {
     const void* result_;
     typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (void*, const void**, LAAW_UINT32);
-    Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(55);
+    Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(56);
     char* error = function(pimpl_, &result_, y);
     ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error);
     return reinterpret_cast< const void* >(result_);
@@ -1710,7 +1728,7 @@
   {
     LAAW_UINT64 result_;
     typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (void*, LAAW_UINT64*);
-    Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(56);
+    Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(57);
     char* error = function(pimpl_, &result_);
     ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error);
     return result_;
@@ -1726,7 +1744,7 @@
   {
     const void* result_;
     typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (void*, const void**);
-    Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(57);
+    Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(58);
     char* error = function(pimpl_, &result_);
     ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error);
     return reinterpret_cast< const void* >(result_);
@@ -1740,7 +1758,7 @@
   inline void Instance::DiscardImage()
   {
     typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (void*);
-    Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(58);
+    Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(59);
     char* error = function(pimpl_);
     ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error);
   }
@@ -1753,7 +1771,7 @@
   inline void Instance::DiscardDicom()
   {
     typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (void*);
-    Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(59);
+    Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(60);
     char* error = function(pimpl_);
     ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error);
   }
@@ -1767,7 +1785,7 @@
   inline void Instance::LoadTagContent(const ::std::string& path)
   {
     typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (void*, const char*);
-    Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(60);
+    Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(61);
     char* error = function(pimpl_, path.c_str());
     ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error);
   }
@@ -1782,7 +1800,7 @@
   {
     const char* result_;
     typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (const void*, const char**);
-    Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(61);
+    Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(62);
     char* error = function(pimpl_, &result_);
     ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error);
     return std::string(result_);
--- a/OrthancCppClient/SharedLibrary/AUTOGENERATED/Windows32.def	Tue Jul 01 15:22:14 2014 +0200
+++ b/OrthancCppClient/SharedLibrary/AUTOGENERATED/Windows32.def	Tue Jul 01 16:54:34 2014 +0200
@@ -31,6 +31,7 @@
   _LAAW_EXTERNC_b794f5cd3dad7d7b575dd1fd902afdd0@8 = LAAW_EXTERNC_b794f5cd3dad7d7b575dd1fd902afdd0@8
   _LAAW_EXTERNC_8ee2e50dd9df8f66a3c1766090dd03ab@8 = LAAW_EXTERNC_8ee2e50dd9df8f66a3c1766090dd03ab@8
   _LAAW_EXTERNC_046aed35bbe4751691f4c34cc249a61d@8 = LAAW_EXTERNC_046aed35bbe4751691f4c34cc249a61d@8
+  _LAAW_EXTERNC_2be452e7af5bf7dfd8c5021842674497@8 = LAAW_EXTERNC_2be452e7af5bf7dfd8c5021842674497@8
   _LAAW_EXTERNC_4dcc7a0fd025efba251ac6e9b701c2c5@28 = LAAW_EXTERNC_4dcc7a0fd025efba251ac6e9b701c2c5@28
   _LAAW_EXTERNC_b2601a161c24ad0a1d3586246f87452c@32 = LAAW_EXTERNC_b2601a161c24ad0a1d3586246f87452c@32
   _LAAW_EXTERNC_193599b9e345384fcdfcd47c29c55342@12 = LAAW_EXTERNC_193599b9e345384fcdfcd47c29c55342@12
--- a/OrthancCppClient/SharedLibrary/AUTOGENERATED/Windows64.def	Tue Jul 01 15:22:14 2014 +0200
+++ b/OrthancCppClient/SharedLibrary/AUTOGENERATED/Windows64.def	Tue Jul 01 16:54:34 2014 +0200
@@ -31,6 +31,7 @@
   LAAW_EXTERNC_b794f5cd3dad7d7b575dd1fd902afdd0
   LAAW_EXTERNC_8ee2e50dd9df8f66a3c1766090dd03ab
   LAAW_EXTERNC_046aed35bbe4751691f4c34cc249a61d
+  LAAW_EXTERNC_2be452e7af5bf7dfd8c5021842674497
   LAAW_EXTERNC_4dcc7a0fd025efba251ac6e9b701c2c5
   LAAW_EXTERNC_b2601a161c24ad0a1d3586246f87452c
   LAAW_EXTERNC_193599b9e345384fcdfcd47c29c55342
--- a/Resources/Samples/OrthancClient/Basic/main.cpp	Tue Jul 01 15:22:14 2014 +0200
+++ b/Resources/Samples/OrthancClient/Basic/main.cpp	Tue Jul 01 16:54:34 2014 +0200
@@ -54,6 +54,15 @@
           OrthancClient::Series series(study.GetSeries(k));
           std::cout << "    Series: " << series.GetId() << std::endl;
 
+          if (series.Is3DImage())
+          {
+            std::cout << "    This is a 3D image whose voxel size is " 
+                      << series.GetVoxelSizeX() << " x " 
+                      << series.GetVoxelSizeY() << " x " 
+                      << series.GetVoxelSizeZ() << ", and slice thickness is " 
+                      << series.GetSliceThickness() << std::endl;
+          }
+
           for (unsigned int l = 0; l < series.GetInstanceCount(); l++)
           {
             std::cout << "      Instance: " << series.GetInstance(l).GetId() << std::endl;