changeset 39:9ee7e2f5f1a3

sync
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 21 Dec 2016 14:19:38 +0100
parents bfce0add15f2
children 7207a407bcd8
files Framework/Widgets/TestCairoWidget.cpp Resources/CMake/CairoConfiguration.cmake Resources/CMake/PixmanConfiguration.cmake Resources/Graveyard/Toolbox/DicomDataset.cpp Resources/Graveyard/Toolbox/DicomDataset.h Resources/Orthanc/Core/SystemToolbox.cpp Resources/Orthanc/Core/SystemToolbox.h Resources/Orthanc/Core/Toolbox.cpp Resources/Orthanc/Core/Toolbox.h Resources/Orthanc/Core/WebServiceParameters.cpp Resources/Orthanc/Plugins/Samples/Common/DicomPath.cpp Resources/Orthanc/Plugins/Samples/Common/DicomPath.h Resources/Orthanc/Resources/CMake/BoostConfiguration.cmake
diffstat 13 files changed, 507 insertions(+), 48 deletions(-) [+]
line wrap: on
line diff
--- a/Framework/Widgets/TestCairoWidget.cpp	Mon Dec 19 12:55:14 2016 +0100
+++ b/Framework/Widgets/TestCairoWidget.cpp	Wed Dec 21 14:19:38 2016 +0100
@@ -32,7 +32,7 @@
 
 #include "TestCairoWidget.h"
 
-#include "../../Resources/Orthanc/Core/Toolbox.h"
+#include "../../Resources/Orthanc/Core/SystemToolbox.h"
 
 #include <stdio.h>
 
@@ -51,7 +51,7 @@
 
       NotifyChange();
 
-      Orthanc::Toolbox::USleep(25000);
+      Orthanc::SystemToolbox::USleep(25000);
     }
 
 
--- a/Resources/CMake/CairoConfiguration.cmake	Mon Dec 19 12:55:14 2016 +0100
+++ b/Resources/CMake/CairoConfiguration.cmake	Wed Dec 21 14:19:38 2016 +0100
@@ -193,6 +193,10 @@
     # Disable vectorized instructions when targeting archicture-independent PNaCl
     set(CAIRO_DEFINITIONS "${CAIRO_DEFINITIONS};HAVE_STDINT_H=1;CAIRO_HAS_PTHREAD=1;HAVE_UINT64_T=1")
 
+  elseif (${CMAKE_SYSTEM_NAME} STREQUAL "Emscripten")
+    # Disable vectorized instructions and threading if targeting asm.js
+    set(CAIRO_DEFINITIONS "${CAIRO_DEFINITIONS};HAVE_STDINT_H=1;CAIRO_HAS_PTHREAD=0;CAIRO_NO_MUTEX=1;HAVE_UINT64_T=1")
+
   elseif (CMAKE_COMPILER_IS_GNUCXX OR
       CMAKE_SYSTEM_NAME STREQUAL "Darwin")
 
--- a/Resources/CMake/PixmanConfiguration.cmake	Mon Dec 19 12:55:14 2016 +0100
+++ b/Resources/CMake/PixmanConfiguration.cmake	Wed Dec 21 14:19:38 2016 +0100
@@ -81,7 +81,23 @@
   endif()
 
 
-  if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
+  ##########################
+  ## Portable Google NaCl
+  ##########################
+
+  if (CMAKE_SYSTEM_NAME STREQUAL "PNaCl")
+    # No hardware acceleration
+    set(PIXMAN_DEFINITIONS "${PIXMAN_DEFINITIONS};TLS=__thread")
+
+  elseif (CMAKE_SYSTEM_NAME STREQUAL "Emscripten")
+    ##########################
+    ## Emscripten (asm.js)
+    ##########################
+
+    # No threading support
+    set(PIXMAN_DEFINITIONS "${PIXMAN_DEFINITIONS};PIXMAN_NO_TLS=1;HAVE_GCC_VECTOR_EXTENSIONS")
+
+  elseif (CMAKE_SYSTEM_NAME STREQUAL "Windows")
 
     ##########################
     ## Windows 32 or 64
@@ -183,14 +199,6 @@
       ${PIXMAN_SOURCES_DIR}/pixman/pixman-arm-simd.c
       )
 
-    ##########################
-    ## Portable Google NaCl
-    ##########################
-
-  elseif (CMAKE_SYSTEM_NAME STREQUAL "PNaCl")
-    # No hardware acceleration
-    set(PIXMAN_DEFINITIONS "${PIXMAN_DEFINITIONS};TLS=__thread")
-
   else()
     message(FATAL_ERROR "Support your platform here")
   endif()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Resources/Graveyard/Toolbox/DicomDataset.cpp	Wed Dec 21 14:19:38 2016 +0100
@@ -0,0 +1,315 @@
+/**
+ * Stone of Orthanc
+ * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
+ * Department, University Hospital of Liege, Belgium
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * In addition, as a special exception, the copyright holders of this
+ * program give permission to link the code of its release with the
+ * OpenSSL project's "OpenSSL" library (or with modified versions of it
+ * that use the same license as the "OpenSSL" library), and distribute
+ * the linked executables. You must obey the GNU General Public License
+ * in all respects for all of the code used other than "OpenSSL". If you
+ * modify file(s) with this exception, you may extend this exception to
+ * your version of the file(s), but you are not obligated to do so. If
+ * you do not wish to do so, delete this exception statement from your
+ * version. If you delete this exception statement from all source files
+ * in the program, then also delete it here.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+
+#include "DicomDataset.h"
+
+#include "../../Resources/Orthanc/Core/OrthancException.h"
+#include "../../Resources/Orthanc/Core/Logging.h"
+#include "../../Resources/Orthanc/Core/Toolbox.h"
+
+#include <boost/lexical_cast.hpp>
+#include <json/value.h>
+#include <json/reader.h>
+
+namespace OrthancStone
+{
+  static uint16_t GetCharValue(char c)
+  {
+    if (c >= '0' && c <= '9')
+      return c - '0';
+    else if (c >= 'a' && c <= 'f')
+      return c - 'a' + 10;
+    else if (c >= 'A' && c <= 'F')
+      return c - 'A' + 10;
+    else
+      return 0;
+  }
+
+
+  static uint16_t GetHexadecimalValue(const char* c)
+  {
+    return ((GetCharValue(c[0]) << 12) + 
+            (GetCharValue(c[1]) << 8) + 
+            (GetCharValue(c[2]) << 4) + 
+            GetCharValue(c[3]));
+  }
+
+
+  static DicomDataset::Tag ParseTag(const std::string& tag)
+  {
+    if (tag.size() == 9 &&
+        isxdigit(tag[0]) &&
+        isxdigit(tag[1]) &&
+        isxdigit(tag[2]) &&
+        isxdigit(tag[3]) &&
+        (tag[4] == '-' || tag[4] == ',') &&
+        isxdigit(tag[5]) &&
+        isxdigit(tag[6]) &&
+        isxdigit(tag[7]) &&
+        isxdigit(tag[8]))        
+    {
+      uint16_t group = GetHexadecimalValue(tag.c_str());
+      uint16_t element = GetHexadecimalValue(tag.c_str() + 5);
+      return std::make_pair(group, element);
+    }
+    else if (tag.size() == 8 &&
+             isxdigit(tag[0]) &&
+             isxdigit(tag[1]) &&
+             isxdigit(tag[2]) &&
+             isxdigit(tag[3]) &&
+             isxdigit(tag[4]) &&
+             isxdigit(tag[5]) &&
+             isxdigit(tag[6]) &&
+             isxdigit(tag[7]))        
+    {
+      uint16_t group = GetHexadecimalValue(tag.c_str());
+      uint16_t element = GetHexadecimalValue(tag.c_str() + 4);
+      return std::make_pair(group, element);
+    }
+    else
+    {
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat);        
+    }
+  }
+
+  void DicomDataset::Parse(const std::string& content)
+  {
+    Json::Value json;
+    Json::Reader reader;
+    if (!reader.parse(content, json))
+    {
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat);        
+    }
+
+    Parse(json);
+  }
+
+
+  void DicomDataset::Parse(const Json::Value& content)
+  {
+    if (content.type() != Json::objectValue)
+    {
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat);        
+    }
+
+    Json::Value::Members members = content.getMemberNames();
+    for (size_t i = 0; i < members.size(); i++)
+    {
+      Tag tag = ParseTag(members[i]);
+
+      const Json::Value& item = content[members[i]];
+
+      if (item.type() != Json::objectValue ||
+          !item.isMember("Type") ||
+          !item.isMember("Value") ||
+          !item.isMember("Name") ||
+          item["Type"].type() != Json::stringValue ||
+          item["Name"].type() != Json::stringValue)
+      {
+        throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat);        
+      }
+
+      if (item["Type"].asString() == "String")
+      {
+        if (item["Value"].type() == Json::stringValue)
+        {
+          values_[tag] = item["Value"].asString();
+        }
+        else
+        {
+          throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat);        
+        }
+      }
+    }
+  }
+
+
+  DicomDataset::DicomDataset(OrthancPlugins::IOrthancConnection& orthanc,
+                             const std::string& instanceId)
+  {
+    std::string content;
+    orthanc.RestApiGet(content, "/instances/" + instanceId + "/tags");
+
+    Parse(content);
+  }
+
+
+  std::string DicomDataset::GetStringValue(const Tag& tag) const
+  {
+    Values::const_iterator it = values_.find(tag);
+
+    if (it == values_.end())
+    {
+      LOG(ERROR) << "Trying to access a DICOM tag that is not set in a DICOM dataset";
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_InexistentItem);
+    }
+    else
+    {
+      return it->second;
+    }
+  }
+
+
+  std::string DicomDataset::GetStringValue(const Tag& tag,
+                                           const std::string& defaultValue) const
+  {
+    Values::const_iterator it = values_.find(tag);
+
+    if (it == values_.end())
+    {
+      return defaultValue;
+    }
+    else
+    {
+      return it->second;
+    }
+  }
+
+
+  float DicomDataset::GetFloatValue(const Tag& tag) const
+  {
+    try 
+    {
+      return boost::lexical_cast<float>(Orthanc::Toolbox::StripSpaces(GetStringValue(tag)));
+    }
+    catch (boost::bad_lexical_cast&)
+    {
+      LOG(ERROR) << "Trying to access a DICOM tag that is not a float";
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat);
+    }
+  }
+
+
+  double DicomDataset::GetDoubleValue(const Tag& tag) const
+  {
+    try 
+    {
+      return boost::lexical_cast<double>(Orthanc::Toolbox::StripSpaces(GetStringValue(tag)));
+    }
+    catch (boost::bad_lexical_cast&)
+    {
+      LOG(ERROR) << "Trying to access a DICOM tag that is not a float";
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat);
+    }
+  }
+
+
+  int DicomDataset::GetIntegerValue(const Tag& tag) const
+  {
+    try 
+    {
+      return boost::lexical_cast<int>(Orthanc::Toolbox::StripSpaces(GetStringValue(tag)));
+    }
+    catch (boost::bad_lexical_cast&)
+    {
+      LOG(ERROR) << "Trying to access a DICOM tag that is not an integer";
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat);
+    }
+  }
+
+
+  unsigned int DicomDataset::GetUnsignedIntegerValue(const Tag& tag) const
+  {
+    int v = GetIntegerValue(tag);
+
+    if (v < 0)
+    {
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat);
+    }
+    else
+    {
+      return static_cast<unsigned int>(v);
+    }
+  }
+
+
+  void DicomDataset::GetVectorValue(Vector& vector, 
+                                    const Tag& tag) const
+  {
+    if (!GeometryToolbox::ParseVector(vector, Orthanc::Toolbox::StripSpaces(GetStringValue(tag))))
+    {
+      LOG(ERROR) << "Trying to access a DICOM tag that is not a vector";
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat);
+    }
+  }
+
+
+  void DicomDataset::GetVectorValue(Vector& vector, 
+                                    const Tag& tag,
+                                    size_t expectedSize) const
+  {
+    GetVectorValue(vector, tag);
+
+    if (vector.size() != expectedSize)
+    {
+      LOG(ERROR) << "A vector in a DICOM tag has a bad size";
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat);
+    }
+  }
+
+
+  void DicomDataset::Print() const
+  {
+    for (Values::const_iterator it = values_.begin(); it != values_.end(); ++it)
+    {
+      printf("%04x,%04x = [%s]\n", it->first.first, it->first.second, it->second.c_str());
+    }
+    printf("\n");
+  }
+
+
+  bool DicomDataset::IsGrayscale() const
+  {
+    std::string photometric = Orthanc::Toolbox::StripSpaces(GetStringValue(DICOM_TAG_PHOTOMETRIC_INTERPRETATION));
+
+    return (photometric == "MONOCHROME1" ||
+            photometric == "MONOCHROME2");
+  }
+
+
+  void DicomDataset::GetPixelSpacing(double& spacingX,
+                                     double& spacingY) const
+  {
+    if (HasTag(DICOM_TAG_PIXEL_SPACING))
+    {
+      Vector spacing;
+      GetVectorValue(spacing, DICOM_TAG_PIXEL_SPACING, 2);
+      spacingX = spacing[0];
+      spacingY = spacing[1];
+    }
+    else
+    {
+      spacingX = 1.0;
+      spacingY = 1.0;
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Resources/Graveyard/Toolbox/DicomDataset.h	Wed Dec 21 14:19:38 2016 +0100
@@ -0,0 +1,121 @@
+/**
+ * Stone of Orthanc
+ * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
+ * Department, University Hospital of Liege, Belgium
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * In addition, as a special exception, the copyright holders of this
+ * program give permission to link the code of its release with the
+ * OpenSSL project's "OpenSSL" library (or with modified versions of it
+ * that use the same license as the "OpenSSL" library), and distribute
+ * the linked executables. You must obey the GNU General Public License
+ * in all respects for all of the code used other than "OpenSSL". If you
+ * modify file(s) with this exception, you may extend this exception to
+ * your version of the file(s), but you are not obligated to do so. If
+ * you do not wish to do so, delete this exception statement from your
+ * version. If you delete this exception statement from all source files
+ * in the program, then also delete it here.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+
+#pragma once
+
+#include "GeometryToolbox.h"
+#include "../../Resources/Orthanc/Plugins/Samples/Common/IOrthancConnection.h"
+
+#include <map>
+#include <stdint.h>
+#include <json/value.h>
+
+namespace OrthancStone
+{
+  // This class is NOT thread-safe
+  // This is a lightweight alternative to Orthanc::DicomMap
+  class DicomDataset : public boost::noncopyable
+  {
+  public:
+    typedef std::pair<uint16_t, uint16_t>  Tag;
+
+  private:
+    typedef std::map<Tag, std::string>  Values;
+
+    Values  values_;
+
+    void Parse(const std::string& content);
+
+    void Parse(const Json::Value& content);
+
+  public:
+    DicomDataset(const std::string& content)
+    {
+      Parse(content);
+    }
+
+    DicomDataset(const Json::Value& content)
+    {
+      Parse(content);
+    }
+
+    DicomDataset(OrthancPlugins::IOrthancConnection& orthanc,
+                 const std::string& instanceId);
+
+    bool HasTag(const Tag& tag) const
+    {
+      return values_.find(tag) != values_.end();
+    }
+
+    std::string GetStringValue(const Tag& tag) const;
+
+    std::string GetStringValue(const Tag& tag,
+                               const std::string& defaultValue) const;
+
+    float GetFloatValue(const Tag& tag) const;
+
+    double GetDoubleValue(const Tag& tag) const;
+
+    int GetIntegerValue(const Tag& tag) const;
+
+    unsigned int GetUnsignedIntegerValue(const Tag& tag) const;
+
+    void GetVectorValue(Vector& vector, 
+                        const Tag& tag,
+                        size_t expectedSize) const;
+
+    void GetVectorValue(Vector& vector, 
+                        const Tag& tag) const;
+
+    void Print() const;
+
+    bool IsGrayscale() const;
+
+    void GetPixelSpacing(double& spacingX,
+                         double& spacingY) const;
+  };
+
+
+  static const DicomDataset::Tag DICOM_TAG_COLUMNS(0x0028, 0x0011);
+  static const DicomDataset::Tag DICOM_TAG_IMAGE_ORIENTATION_PATIENT(0x0020, 0x0037);
+  static const DicomDataset::Tag DICOM_TAG_IMAGE_POSITION_PATIENT(0x0020, 0x0032);
+  static const DicomDataset::Tag DICOM_TAG_NUMBER_OF_FRAMES(0x0028, 0x0008);
+  static const DicomDataset::Tag DICOM_TAG_PIXEL_REPRESENTATION(0x0028, 0x0103);
+  static const DicomDataset::Tag DICOM_TAG_PIXEL_SPACING(0x0028, 0x0030);
+  static const DicomDataset::Tag DICOM_TAG_RESCALE_INTERCEPT(0x0028, 0x1052);
+  static const DicomDataset::Tag DICOM_TAG_RESCALE_SLOPE(0x0028, 0x1053);
+  static const DicomDataset::Tag DICOM_TAG_ROWS(0x0028, 0x0010);
+  static const DicomDataset::Tag DICOM_TAG_SLICE_THICKNESS(0x0018, 0x0050);
+  static const DicomDataset::Tag DICOM_TAG_WINDOW_CENTER(0x0028, 0x1050);
+  static const DicomDataset::Tag DICOM_TAG_WINDOW_WIDTH(0x0028, 0x1051);
+  static const DicomDataset::Tag DICOM_TAG_PHOTOMETRIC_INTERPRETATION(0x0028, 0x0004);
+}
--- a/Resources/Orthanc/Core/SystemToolbox.cpp	Mon Dec 19 12:55:14 2016 +0100
+++ b/Resources/Orthanc/Core/SystemToolbox.cpp	Wed Dec 21 14:19:38 2016 +0100
@@ -123,7 +123,7 @@
     barrierEvent_ = ServerBarrierEvent_Stop;
     while (!(*stopFlag || finish_))
     {
-      Toolbox::USleep(100 * 1000);
+      SystemToolbox::USleep(100 * 1000);
     }
 
 #if defined(_WIN32)
@@ -152,6 +152,18 @@
   }
 
 
+  void SystemToolbox::USleep(uint64_t microSeconds)
+  {
+#if defined(_WIN32)
+    ::Sleep(static_cast<DWORD>(microSeconds / static_cast<uint64_t>(1000)));
+#elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD_kernel__) || defined(__FreeBSD__) || defined(__native_client__)
+    usleep(microSeconds);
+#else
+#error Support your platform here
+#endif
+  }
+
+
   static std::streamsize GetStreamSize(std::istream& f)
   {
     // http://www.cplusplus.com/reference/iostream/istream/tellg/
--- a/Resources/Orthanc/Core/SystemToolbox.h	Mon Dec 19 12:55:14 2016 +0100
+++ b/Resources/Orthanc/Core/SystemToolbox.h	Wed Dec 21 14:19:38 2016 +0100
@@ -50,6 +50,8 @@
 {
   namespace SystemToolbox
   {
+    void USleep(uint64_t microSeconds);
+
     ServerBarrierEvent ServerBarrier(const bool& stopFlag);
 
     ServerBarrierEvent ServerBarrier();
--- a/Resources/Orthanc/Core/Toolbox.cpp	Mon Dec 19 12:55:14 2016 +0100
+++ b/Resources/Orthanc/Core/Toolbox.cpp	Wed Dec 21 14:19:38 2016 +0100
@@ -90,18 +90,6 @@
 
 namespace Orthanc
 {
-  void Toolbox::USleep(uint64_t microSeconds)
-  {
-#if defined(_WIN32)
-    ::Sleep(static_cast<DWORD>(microSeconds / static_cast<uint64_t>(1000)));
-#elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD_kernel__) || defined(__FreeBSD__) || defined(__native_client__)
-    usleep(microSeconds);
-#else
-#error Support your platform here
-#endif
-  }
-
-
   void Toolbox::ToUpperCase(std::string& s)
   {
     std::transform(s.begin(), s.end(), s.begin(), toupper);
--- a/Resources/Orthanc/Core/Toolbox.h	Mon Dec 19 12:55:14 2016 +0100
+++ b/Resources/Orthanc/Core/Toolbox.h	Wed Dec 21 14:19:38 2016 +0100
@@ -78,8 +78,6 @@
 
   namespace Toolbox
   {
-    void USleep(uint64_t microSeconds);
-
     void ToUpperCase(std::string& s);  // Inplace version
 
     void ToLowerCase(std::string& s);  // Inplace version
--- a/Resources/Orthanc/Core/WebServiceParameters.cpp	Mon Dec 19 12:55:14 2016 +0100
+++ b/Resources/Orthanc/Core/WebServiceParameters.cpp	Wed Dec 21 14:19:38 2016 +0100
@@ -34,7 +34,6 @@
 #include "WebServiceParameters.h"
 
 #include "../Core/Logging.h"
-#include "../Core/Toolbox.h"
 #include "../Core/OrthancException.h"
 
 #if ORTHANC_SANDBOXED == 0
--- a/Resources/Orthanc/Plugins/Samples/Common/DicomPath.cpp	Mon Dec 19 12:55:14 2016 +0100
+++ b/Resources/Orthanc/Plugins/Samples/Common/DicomPath.cpp	Wed Dec 21 14:19:38 2016 +0100
@@ -49,20 +49,20 @@
   }
 
 
-  DicomPath::DicomPath(DicomTag sequence,
+  DicomPath::DicomPath(const DicomTag& sequence,
                        size_t index,
-                       DicomTag tag) :
+                       const DicomTag& tag) :
     finalTag_(tag)
   {
     AddToPrefix(sequence, index);
   }
 
 
-  DicomPath::DicomPath(DicomTag sequence1,
+  DicomPath::DicomPath(const DicomTag& sequence1,
                        size_t index1,
-                       DicomTag sequence2,
+                       const DicomTag& sequence2,
                        size_t index2,
-                       DicomTag tag) :
+                       const DicomTag& tag) :
     finalTag_(tag)
   {
     AddToPrefix(sequence1, index1);
@@ -70,13 +70,13 @@
   }
 
 
-  DicomPath::DicomPath(DicomTag sequence1,
+  DicomPath::DicomPath(const DicomTag& sequence1,
                        size_t index1,
-                       DicomTag sequence2,
+                       const DicomTag& sequence2,
                        size_t index2,
-                       DicomTag sequence3,
+                       const DicomTag& sequence3,
                        size_t index3,
-                       DicomTag tag) :
+                       const DicomTag& tag) :
     finalTag_(tag)
   {
     AddToPrefix(sequence1, index1);
--- a/Resources/Orthanc/Plugins/Samples/Common/DicomPath.h	Mon Dec 19 12:55:14 2016 +0100
+++ b/Resources/Orthanc/Plugins/Samples/Common/DicomPath.h	Wed Dec 21 14:19:38 2016 +0100
@@ -50,30 +50,30 @@
     const Prefix& GetPrefixItem(size_t depth) const;
 
   public:
-    DicomPath(DicomTag finalTag) :
+    DicomPath(const DicomTag& finalTag) :
     finalTag_(finalTag)
     {
     }
 
-    DicomPath(DicomTag sequence,
+    DicomPath(const DicomTag& sequence,
               size_t index,
-              DicomTag tag);
+              const DicomTag& tag);
 
-    DicomPath(DicomTag sequence1,
+    DicomPath(const DicomTag& sequence1,
               size_t index1,
-              DicomTag sequence2,
+              const DicomTag& sequence2,
               size_t index2,
-              DicomTag tag);
+              const DicomTag& tag);
 
-    DicomPath(DicomTag sequence1,
+    DicomPath(const DicomTag& sequence1,
               size_t index1,
-              DicomTag sequence2,
+              const DicomTag& sequence2,
               size_t index2,
-              DicomTag sequence3,
+              const DicomTag& sequence3,
               size_t index3,
-              DicomTag tag);
+              const DicomTag& tag);
 
-    void AddToPrefix(DicomTag tag,
+    void AddToPrefix(const DicomTag& tag,
                      size_t position)
     {
       prefix_.push_back(std::make_pair(tag, position));
--- a/Resources/Orthanc/Resources/CMake/BoostConfiguration.cmake	Mon Dec 19 12:55:14 2016 +0100
+++ b/Resources/Orthanc/Resources/CMake/BoostConfiguration.cmake	Wed Dec 21 14:19:38 2016 +0100
@@ -99,6 +99,13 @@
       -DBOOST_LOCALE_NO_POSIX_BACKEND=1
       -DBOOST_LOCALE_NO_STD_BACKEND=1
       )
+
+  elseif (${CMAKE_SYSTEM_NAME} STREQUAL "Emscripten")
+    add_definitions(
+      -DBOOST_LOCALE_NO_POSIX_BACKEND=1
+      -DBOOST_LOCALE_NO_STD_BACKEND=1
+      )
+
   else()
     message(FATAL_ERROR "Support your platform here")
   endif()
@@ -114,10 +121,15 @@
   list(APPEND BOOST_SOURCES
     ${BOOST_REGEX_SOURCES}
     ${BOOST_SOURCES_DIR}/libs/date_time/src/gregorian/greg_month.cpp
-    ${BOOST_SOURCES_DIR}/libs/locale/src/encoding/codepage.cpp
     ${BOOST_SOURCES_DIR}/libs/system/src/error_code.cpp
     )
 
+  if (NOT ${CMAKE_SYSTEM_NAME} STREQUAL "Emscripten")
+    list(APPEND BOOST_SOURCES
+      ${BOOST_SOURCES_DIR}/libs/locale/src/encoding/codepage.cpp
+      )
+  endif()
+
   if (${CMAKE_SYSTEM_NAME} STREQUAL "PNaCl" OR
       ${CMAKE_SYSTEM_NAME} STREQUAL "NaCl32" OR
       ${CMAKE_SYSTEM_NAME} STREQUAL "NaCl64")