changeset 518:58841db7b64e laaw

mainline to laaw integration
author Sebastien Jodogne <s.jodogne@gmail.com>
date Fri, 19 Jul 2013 16:14:18 +0200
parents 49a1228d6fe7 (diff) 5bb96a6100c0 (current diff)
children cd7d4842851c
files
diffstat 31 files changed, 983 insertions(+), 140 deletions(-) [+]
line wrap: on
line diff
--- a/CMakeLists.txt	Fri Jul 19 16:11:13 2013 +0200
+++ b/CMakeLists.txt	Fri Jul 19 16:14:18 2013 +0200
@@ -7,6 +7,11 @@
   -DORTHANC_VERSION="mainline"
   )
 
+
+#####################################################################
+## CMake parameters tunable at the command line
+#####################################################################
+
 # Parameters of the build
 SET(STATIC_BUILD ON CACHE BOOL "Static build of the third-party libraries (necessary for Windows)")
 SET(STANDALONE_BUILD ON CACHE BOOL "Standalone build (all the resources are embedded, necessary for releases)")
@@ -41,6 +46,15 @@
 include(${CMAKE_SOURCE_DIR}/Resources/CMake/DownloadPackage.cmake)
 include(${CMAKE_SOURCE_DIR}/Resources/CMake/Compiler.cmake)
 
+set(ORTHANC_ROOT ${CMAKE_SOURCE_DIR})
+
+
+
+
+#####################################################################
+## Inclusion of third-party dependencies
+#####################################################################
+
 # Configuration of the standalone builds
 if (${CMAKE_CROSSCOMPILING})
   # Cross-compilation implies the standalone build
@@ -78,6 +92,11 @@
 include(${CMAKE_SOURCE_DIR}/Resources/CMake/LuaConfiguration.cmake)
 
 
+
+#####################################################################
+## Autogeneration of files
+#####################################################################
+
 # Prepare the embedded files
 set(EMBEDDED_FILES
   PREPARE_DATABASE ${CMAKE_CURRENT_SOURCE_DIR}/OrthancServer/PrepareDatabase.sql
@@ -105,11 +124,17 @@
 
 
 
-# The main instructions to build the Orthanc binaries
+#####################################################################
+## Build the core of Orthanc
+#####################################################################
+
+add_library(OpenSSL STATIC ${OPENSSL_SOURCES})
+
 add_library(CoreLibrary
   STATIC
   ${AUTOGENERATED_SOURCES}
   ${THIRD_PARTY_SOURCES}
+  ${CURL_SOURCES}
 
   Core/Cache/MemoryCache.cpp
   Core/ChunkedBuffer.cpp
@@ -166,6 +191,10 @@
 
 
 if(NOT ONLY_CORE_LIBRARY)
+  #####################################################################
+  ## Build the Orthanc server
+  #####################################################################
+
   add_library(ServerLibrary
     STATIC
     ${DCMTK_SOURCES}
@@ -194,14 +223,18 @@
     OrthancServer/main.cpp
     )
 
-  target_link_libraries(Orthanc ServerLibrary CoreLibrary)
+  target_link_libraries(Orthanc ServerLibrary CoreLibrary OpenSSL)
 
   install(
     TARGETS Orthanc
     RUNTIME DESTINATION bin
     )
 
-  # Build the unit tests if required
+
+  #####################################################################
+  ## Build the unit tests if required
+  #####################################################################
+
   if (BUILD_UNIT_TESTS)
     add_definitions(-DORTHANC_BUILD_UNIT_TESTS=1)
     include(${CMAKE_SOURCE_DIR}/Resources/CMake/GoogleTestConfiguration.cmake)
@@ -219,12 +252,75 @@
       UnitTests/Lua.cpp
       UnitTests/main.cpp
       )
-    target_link_libraries(UnitTests ServerLibrary CoreLibrary)
+    target_link_libraries(UnitTests ServerLibrary CoreLibrary OpenSSL)
   endif()
 endif()
 
 
-# Generate the Doxygen documentation if Doxygen is present
+#####################################################################
+## Create the standalone DLL containing the Orthanc Client API
+#####################################################################
+
+# include_directories(${ORTHANC_ROOT}/OrthancCppClient/Package/Laaw)
+
+# if (${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
+#   if (${CMAKE_SIZEOF_VOID_P} EQUAL 4)
+#     set(ORTHANC_CPP_CLIENT_DEF ${ORTHANC_ROOT}/OrthancCppClient/Package/Build/Windows32.def)
+#   elseif (${CMAKE_SIZEOF_VOID_P} EQUAL 8)
+#     set(ORTHANC_CPP_CLIENT_DEF ${ORTHANC_ROOT}/OrthancCppClient/Package/Build/Windows64.def)
+#   else()
+#     message(FATAL_ERROR "Support your platform here")
+#   endif()
+# endif()
+
+# add_library(OrthancCppClient SHARED
+#   ${ORTHANC_ROOT}/Core/OrthancException.cpp
+#   ${ORTHANC_ROOT}/Core/Enumerations.cpp
+#   ${ORTHANC_ROOT}/Core/Toolbox.cpp
+#   ${ORTHANC_ROOT}/Core/HttpClient.cpp
+#   ${ORTHANC_ROOT}/Core/MultiThreading/ArrayFilledByThreads.cpp
+#   ${ORTHANC_ROOT}/Core/MultiThreading/ThreadedCommandProcessor.cpp
+#   ${ORTHANC_ROOT}/Core/MultiThreading/SharedMessageQueue.cpp
+#   ${ORTHANC_ROOT}/Core/FileFormats/PngReader.cpp
+#   ${ORTHANC_ROOT}/OrthancCppClient/OrthancConnection.cpp
+#   ${ORTHANC_ROOT}/OrthancCppClient/Series.cpp
+#   ${ORTHANC_ROOT}/OrthancCppClient/Study.cpp
+#   ${ORTHANC_ROOT}/OrthancCppClient/Instance.cpp
+#   ${ORTHANC_ROOT}/OrthancCppClient/Patient.cpp
+#   ${ORTHANC_ROOT}/OrthancCppClient/Package/SharedLibrary.cpp
+#   ${ORTHANC_ROOT}/Resources/sha1/sha1.cpp
+#   ${ORTHANC_ROOT}/Resources/md5/md5.c
+#   ${ORTHANC_ROOT}/Resources/base64/base64.cpp
+#   ${ORTHANC_CPP_CLIENT_DEF}
+#   ${THIRD_PARTY_SOURCES}
+#   ${OPENSSL_SOURCES}
+#   ${CURL_SOURCES}
+#   )
+
+# if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
+#   set_target_properties(OrthancCppClient
+#     PROPERTIES LINK_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--no-undefined -Wl,--version-script=${ORTHANC_ROOT}/OrthancCppClient/Package/Laaw/VersionScript.map"
+#     )
+#   target_link_libraries(OrthancCppClient pthread)
+# elseif (${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
+#   if (${CMAKE_COMPILER_IS_GNUCXX})
+#     set_target_properties(OrthancCppClient
+#       PROPERTIES LINK_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--allow-multiple-definition -static-libgcc -static-libstdc++"
+#       )
+#     target_link_libraries(OrthancCppClient ws2_32)
+#   else()
+#     message(FATAL_ERROR "Support Visual Studio here")
+#   endif()
+# else()
+#   message(FATAL_ERROR "Support your platform here")
+# endif()
+
+
+
+#####################################################################
+## Generate the documentation if Doxygen is present
+#####################################################################
+
 find_package(Doxygen)
 if (DOXYGEN_FOUND)
   configure_file(
--- a/Core/Enumerations.h	Fri Jul 19 16:11:13 2013 +0200
+++ b/Core/Enumerations.h	Fri Jul 19 16:14:18 2013 +0200
@@ -32,6 +32,8 @@
 
 #pragma once
 
+#include "../OrthancCppClient/Package/Laaw/laaw.h"
+
 namespace Orthanc
 {
   enum Endianness
@@ -67,7 +69,7 @@
     ErrorCode_FullStorage
   };
 
-  enum PixelFormat
+  enum LAAW_API PixelFormat
   {
     PixelFormat_RGB24,
     PixelFormat_Grayscale8,
@@ -75,7 +77,7 @@
     PixelFormat_SignedGrayscale16
   };
 
-  enum ImageExtractionMode
+  enum LAAW_API ImageExtractionMode
   {
     ImageExtractionMode_Preview,
     ImageExtractionMode_UInt8,
--- a/OrthancCppClient/Instance.cpp	Fri Jul 19 16:11:13 2013 +0200
+++ b/OrthancCppClient/Instance.cpp	Fri Jul 19 16:14:18 2013 +0200
@@ -33,7 +33,6 @@
 #include "Instance.h"
 
 #include "OrthancConnection.h"
-#include "../Core/OrthancException.h"
 
 #include <boost/lexical_cast.hpp>
 
@@ -63,16 +62,16 @@
           break;
           
         default:
-          throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented);
+          throw OrthancClientException(Orthanc::ErrorCode_NotImplemented);
       }
 
       Orthanc::HttpClient client(connection_.GetHttpClient());
-      client.SetUrl(connection_.GetOrthancUrl() +  "/instances/" + id_ + "/" + suffix);
+      client.SetUrl(std::string(connection_.GetOrthancUrl()) +  "/instances/" + id_ + "/" + suffix);
       std::string png;
 
       if (!client.Apply(png))
       {
-        throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented);
+        throw OrthancClientException(Orthanc::ErrorCode_NotImplemented);
       }
      
       reader_.reset(new Orthanc::PngReader);
@@ -81,34 +80,34 @@
   }
 
   Instance::Instance(const OrthancConnection& connection,
-                     const std::string& id) :
+                     const char* id) :
     connection_(connection),
     id_(id),
     mode_(Orthanc::ImageExtractionMode_Int16)
   {
     Orthanc::HttpClient client(connection_.GetHttpClient());
             
-    client.SetUrl(connection_.GetOrthancUrl() + "/instances/" + id_ + "/simplified-tags");
+    client.SetUrl(std::string(connection_.GetOrthancUrl()) + "/instances/" + id_ + "/simplified-tags");
     Json::Value v;
     if (!client.Apply(tags_))
     {
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_NetworkProtocol);
+      throw OrthancClientException(Orthanc::ErrorCode_NetworkProtocol);
     }
   }
 
-  std::string Instance::GetTagAsString(const char* tag)
+  const char* Instance::GetTagAsString(const char* tag) const
   {
     if (tags_.isMember(tag))
     {
-      return tags_[tag].asString();
+      return tags_[tag].asCString();
     }
     else
     {
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_InexistentItem);
+      throw OrthancClientException(Orthanc::ErrorCode_InexistentItem);
     }
   }
 
-  float Instance::GetTagAsFloat(const char* tag)
+  float Instance::GetTagAsFloat(const char* tag) const
   {
     std::string value = GetTagAsString(tag);
 
@@ -118,11 +117,11 @@
     }
     catch (boost::bad_lexical_cast)
     {
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat);
+      throw OrthancClientException(Orthanc::ErrorCode_BadFileFormat);
     }
   }
 
-  int Instance::GetTagAsInt(const char* tag)
+  int Instance::GetTagAsInt(const char* tag) const
   {
     std::string value = GetTagAsString(tag);
 
@@ -132,7 +131,7 @@
     }
     catch (boost::bad_lexical_cast)
     {
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat);
+      throw OrthancClientException(Orthanc::ErrorCode_BadFileFormat);
     }
   }
 
@@ -218,7 +217,7 @@
     catch (boost::bad_lexical_cast)
     {
       // Unable to parse the Image Orientation Patient.
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat);
+      throw OrthancClientException(Orthanc::ErrorCode_BadFileFormat);
     }
   }
 }
--- a/OrthancCppClient/Instance.h	Fri Jul 19 16:11:13 2013 +0200
+++ b/OrthancCppClient/Instance.h	Fri Jul 19 16:14:18 2013 +0200
@@ -35,6 +35,7 @@
 #include <string>
 #include <json/value.h>
 
+#include "OrthancClientException.h"
 #include "../Core/IDynamicObject.h"
 #include "../Core/FileFormats/PngReader.h"
 
@@ -42,7 +43,7 @@
 {
   class OrthancConnection;
 
-  class Instance : public Orthanc::IDynamicObject
+  class LAAW_API Instance : public Orthanc::IDynamicObject
   {
   private:
     const OrthancConnection& connection_;
@@ -55,11 +56,11 @@
 
   public:
     Instance(const OrthancConnection& connection,
-             const std::string& id);
+             const char* id);
 
-    const std::string& GetId() const
+    const char* GetId() const
     {
-      return id_;
+      return id_.c_str();
     }
 
     void SetImageExtractionMode(Orthanc::ImageExtractionMode mode);
@@ -69,27 +70,27 @@
       return mode_;
     }
 
-    std::string GetTagAsString(const char* tag);
+    const char* GetTagAsString(const char* tag) const;
 
-    float GetTagAsFloat(const char* tag);
+    float GetTagAsFloat(const char* tag) const;
 
-    int GetTagAsInt(const char* tag);
+    int32_t GetTagAsInt(const char* tag) const;
 
-    unsigned int GetWidth();
+    uint32_t GetWidth();
 
-    unsigned int GetHeight();
+    uint32_t GetHeight();
 
-    unsigned int GetPitch();
+    uint32_t GetPitch();
 
     Orthanc::PixelFormat GetPixelFormat();
 
     const void* GetBuffer();
 
-    const void* GetBuffer(unsigned int y);
+    const void* GetBuffer(uint32_t y);
 
     void DiscardImage();
 
-    void SplitVectorOfFloats(std::vector<float>& target,
-                             const char* tag);
+    LAAW_API_INTERNAL void SplitVectorOfFloats(std::vector<float>& target,
+                                               const char* tag);
   };
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/OrthancCppClient/OrthancClientException.h	Fri Jul 19 16:14:18 2013 +0200
@@ -0,0 +1,58 @@
+/**
+ * Orthanc - A Lightweight, RESTful DICOM Store
+ * Copyright (C) 2012-2013 Medical Physics Department, CHU 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 "../Core/OrthancException.h"
+#include "Package/Laaw/laaw.h"
+
+namespace OrthancClient
+{
+  class OrthancClientException : public ::Laaw::LaawException
+  {
+  public:
+    OrthancClientException(Orthanc::ErrorCode code) :
+      LaawException(Orthanc::OrthancException::GetDescription(code))
+    { 
+    }
+
+    OrthancClientException(const char* message) : 
+      LaawException(message)
+    {    
+    }
+
+    OrthancClientException(const std::string& message) : 
+      LaawException(message)
+    {    
+    }
+  };
+}
--- a/OrthancCppClient/OrthancConnection.cpp	Fri Jul 19 16:11:13 2013 +0200
+++ b/OrthancCppClient/OrthancConnection.cpp	Fri Jul 19 16:14:18 2013 +0200
@@ -32,8 +32,6 @@
 
 #include "OrthancConnection.h"
 
-#include "../Core/OrthancException.h"
-
 namespace OrthancClient
 {
   void OrthancConnection::ReadPatients()
@@ -42,14 +40,15 @@
     Json::Value v;
     if (!client_.Apply(content_))
     {
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_NetworkProtocol);
+      throw OrthancClientException(Orthanc::ErrorCode_NetworkProtocol);
     }
   }
 
   Orthanc::IDynamicObject* OrthancConnection::GetFillerItem(size_t index)
   {
     Json::Value::ArrayIndex tmp = static_cast<Json::Value::ArrayIndex>(index);
-    return new Patient(*this, content_[tmp].asString());
+    std::string id = content_[tmp].asString();
+    return new Patient(*this, id.c_str());
   }
 
   Patient& OrthancConnection::GetPatient(unsigned int index)
@@ -71,6 +70,4 @@
     client_.SetCredentials(username, password);
     ReadPatients();
   }
-
-
 }
--- a/OrthancCppClient/OrthancConnection.h	Fri Jul 19 16:11:13 2013 +0200
+++ b/OrthancCppClient/OrthancConnection.h	Fri Jul 19 16:14:18 2013 +0200
@@ -38,7 +38,7 @@
 
 namespace OrthancClient
 {
-  class OrthancConnection : 
+  class LAAW_API OrthancConnection : 
     public boost::noncopyable,
     private Orthanc::ArrayFilledByThreads::IFiller
   {
@@ -64,12 +64,16 @@
                       const char* username, 
                       const char* password);
 
-    unsigned int GetThreadCount() const
+    virtual ~OrthancConnection()
+    {
+    }
+
+    uint32_t GetThreadCount() const
     {
       return patients_.GetThreadCount();
     }
 
-    void SetThreadCount(unsigned int threadCount)
+    void SetThreadCount(uint32_t threadCount)
     {
       patients_.SetThreadCount(threadCount);
     }
@@ -79,21 +83,21 @@
       patients_.Reload();
     }
 
-    const Orthanc::HttpClient& GetHttpClient() const
+    LAAW_API_INTERNAL const Orthanc::HttpClient& GetHttpClient() const
     {
       return client_;
     }
 
-    const std::string& GetOrthancUrl() const
+    const char* GetOrthancUrl() const
     {
-      return orthancUrl_;
+      return orthancUrl_.c_str();
     }
 
-    unsigned int GetPatientCount()
+    uint32_t GetPatientCount()
     {
       return patients_.GetSize();
     }
 
-    Patient& GetPatient(unsigned int index);
+    Patient& GetPatient(uint32_t index);
   };
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/OrthancCppClient/Package/ConfigurationCpp.json	Fri Jul 19 16:14:18 2013 +0200
@@ -0,0 +1,5 @@
+{
+  "InternalsNamespace" : [ "OrthancClient", "Internals" ],
+  "PublicNamespace" : [ "OrthancClient" ],
+  "ExceptionClassName" : "OrthancClientException"
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/OrthancCppClient/Package/Laaw/VersionScript.map	Fri Jul 19 16:14:18 2013 +0200
@@ -0,0 +1,9 @@
+# This is a version-script
+
+{
+global:
+  LAAW_EXTERNC_*;
+
+local:
+  *;
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/OrthancCppClient/Package/Laaw/laaw-exports.h	Fri Jul 19 16:14:18 2013 +0200
@@ -0,0 +1,85 @@
+/**
+ * Laaw - A Lightweight, Automated API Wrapper
+ * Copyright (C) 2010-2013 Alain Mazy, Benjamin Golinvaux, Sebastien
+ * Jodogne
+ *
+ * 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
+
+/********************************************************************
+ ** Windows target
+ ********************************************************************/
+
+#if defined _WIN32
+
+#include <windows.h>
+
+#if defined(__GNUC__)
+// This is Mingw
+#define LAAW_EXPORT_DLL_API  // The exports are handled by the .DEF file
+#else
+// This is MSVC
+#define LAAW_EXPORT_DLL_API __declspec(dllexport)
+#endif
+
+#ifdef _M_X64
+// 64 bits target
+#define LAAW_CALL_CONVENTION
+#else
+// 32 bits target
+#define LAAW_CALL_CONVENTION  __stdcall  // Use the StdCall in Windows32 (for VB6)
+#endif
+
+
+/********************************************************************
+ ** Linux target
+ ********************************************************************/
+
+#elif defined(__linux)
+
+// Try the gcc visibility support
+// http://gcc.gnu.org/wiki/Visibility
+#if ((__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4))
+#define LAAW_EXPORT_DLL_API  __attribute__ ((visibility("default")))
+#define LAAW_CALL_CONVENTION
+#else
+#error No support for visibility in your version of GCC
+#endif
+
+
+/********************************************************************
+ ** Max OS X target
+ ********************************************************************/
+
+#else
+
+#define LAAW_EXPORT_DLL_API  __attribute__ ((visibility("default")))
+#define LAAW_CALL_CONVENTION
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/OrthancCppClient/Package/Laaw/laaw.h	Fri Jul 19 16:14:18 2013 +0200
@@ -0,0 +1,89 @@
+/**
+ * Laaw - A Lightweight, Automated API Wrapper
+ * Copyright (C) 2010-2013 Alain Mazy, Benjamin Golinvaux, Sebastien
+ * Jodogne
+ *
+ * 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 "laaw-exports.h"
+#include <stddef.h>
+#include <string>
+
+#if (LAAW_PARSING == 1)
+
+#define LAAW_API   __attribute__((deprecated("")))
+#define LAAW_API_INTERNAL  __attribute__((deprecated("")))
+#define LAAW_API_OVERLOAD(name)  __attribute__((deprecated("")))
+#define LAAW_API_PROPERTY  __attribute__((deprecated("")))
+#define LAAW_API_STATIC_CLASS  __attribute__((deprecated("")))
+#define LAAW_API_CUSTOM(name, value)  __attribute__((deprecated("")))
+
+#else
+
+#define LAAW_API
+#define LAAW_API_INTERNAL
+#define LAAW_API_OVERLOAD(name)
+#define LAAW_API_PROPERTY
+#define LAAW_API_STATIC_CLASS
+#define LAAW_API_CUSTOM(name, value)
+
+#endif
+
+
+namespace Laaw
+{
+  /**
+   * This is the base class from which all the public exceptions in
+   * the SDK should derive.
+   **/
+  class LaawException
+  {
+  private:
+    std::string what_;
+
+  public:
+    LaawException()
+    {
+    }
+
+    LaawException(const std::string& what) : what_(what)
+    {
+    }
+
+    LaawException(const char* what) : what_(what)
+    {
+    }
+
+    virtual const char* What() const
+    {
+      return what_.c_str();
+    }
+  };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/OrthancCppClient/Package/OrthancCppClient.cmake	Fri Jul 19 16:14:18 2013 +0200
@@ -0,0 +1,62 @@
+include_directories(${ORTHANC_ROOT}/OrthancCppClient/Package/Laaw)
+
+set(STATIC_BUILD ON)
+include(${ORTHANC_ROOT}/Resources/CMake/DownloadPackage.cmake)
+include(${ORTHANC_ROOT}/Resources/CMake/JsonCppConfiguration.cmake)
+include(${ORTHANC_ROOT}/Resources/CMake/LibCurlConfiguration.cmake)
+include(${ORTHANC_ROOT}/Resources/CMake/LibPngConfiguration.cmake)
+include(${ORTHANC_ROOT}/Resources/CMake/BoostConfiguration.cmake)
+include(${ORTHANC_ROOT}/Resources/CMake/ZlibConfiguration.cmake)
+
+if (${CMAKE_COMPILER_IS_GNUCXX})
+  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -pedantic -Wno-implicit-function-declaration")  # --std=c99 makes libcurl not to compile
+  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -pedantic -Wno-long-long -Wno-variadic-macros")
+  set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--as-needed")
+  set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--no-undefined")
+elseif (${MSVC})
+  add_definitions(-D_CRT_SECURE_NO_WARNINGS=1)  
+endif()
+
+if (${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
+  if (${CMAKE_SIZEOF_VOID_P} EQUAL 4)
+    set(WINDOWS_DEF ${ORTHANC_ROOT}/OrthancCppClient/Package/Build/Windows32.def)
+  elseif (${CMAKE_SIZEOF_VOID_P} EQUAL 8)
+    set(WINDOWS_DEF ${ORTHANC_ROOT}/OrthancCppClient/Package/Build/Windows64.def)
+  else()
+    message(FATAL_ERROR "Support your platform here")
+  endif()
+endif()
+
+add_library(OrthancCppClient SHARED
+  ${THIRD_PARTY_SOURCES}
+  ${ORTHANC_ROOT}/Core/OrthancException.cpp
+  ${ORTHANC_ROOT}/Core/Enumerations.cpp
+  ${ORTHANC_ROOT}/Core/Toolbox.cpp
+  ${ORTHANC_ROOT}/Core/HttpClient.cpp
+  ${ORTHANC_ROOT}/Core/MultiThreading/ArrayFilledByThreads.cpp
+  ${ORTHANC_ROOT}/Core/MultiThreading/ThreadedCommandProcessor.cpp
+  ${ORTHANC_ROOT}/Core/MultiThreading/SharedMessageQueue.cpp
+  ${ORTHANC_ROOT}/Core/FileFormats/PngReader.cpp
+  ${ORTHANC_ROOT}/OrthancCppClient/OrthancConnection.cpp
+  ${ORTHANC_ROOT}/OrthancCppClient/Series.cpp
+  ${ORTHANC_ROOT}/OrthancCppClient/Study.cpp
+  ${ORTHANC_ROOT}/OrthancCppClient/Instance.cpp
+  ${ORTHANC_ROOT}/OrthancCppClient/Patient.cpp
+  ${ORTHANC_ROOT}/OrthancCppClient/Package/SharedLibrary.cpp
+  ${ORTHANC_ROOT}/Resources/sha1/sha1.cpp
+  ${ORTHANC_ROOT}/Resources/md5/md5.c
+  ${ORTHANC_ROOT}/Resources/base64/base64.cpp
+  ${WINDOWS_DEF}
+  )
+
+if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
+  set_target_properties(OrthancCppClient
+    PROPERTIES LINK_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--no-undefined -Wl,--version-script=${ORTHANC_ROOT}/OrthancCppClient/Package/Laaw/VersionScript.map"
+    )
+  target_link_libraries(OrthancCppClient pthread)
+else()
+  set_target_properties(OrthancCppClient
+    PROPERTIES LINK_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--allow-multiple-definition -static-libgcc -static-libstdc++"
+    )
+  target_link_libraries(OrthancCppClient ws2_32)
+endif()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/OrthancCppClient/Package/Product.json	Fri Jul 19 16:14:18 2013 +0200
@@ -0,0 +1,8 @@
+{
+  "Product" : "OrthancClient",
+  "Description" : "Native client to the REST API of Orthanc",
+  "Company" : "CHU of Liege",
+  "Copyright" : "(c) 2012-2013 CHU of Liege",
+  "Legal" : "Licensing information is available on https://code.google.com/p/orthanc/",
+  "Version" : "1.0.1"
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/OrthancCppClient/Package/SharedLibrary.cpp	Fri Jul 19 16:14:18 2013 +0200
@@ -0,0 +1,23 @@
+#include "../../Core/HttpClient.h"
+#include "../OrthancConnection.h"
+
+
+class SharedLibrarySingleton
+{
+public:
+  SharedLibrarySingleton()
+  {
+    Orthanc::HttpClient::GlobalInitialize();
+  }
+
+  ~SharedLibrarySingleton()
+  {
+    Orthanc::HttpClient::GlobalFinalize();
+  }
+};
+
+
+static SharedLibrarySingleton  singleton_;
+
+
+#include "Build/ExternC.cpp"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/OrthancCppClient/Package/Test.sh	Fri Jul 19 16:14:18 2013 +0200
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+mkdir -p Build
+LAAW_ROOT=~/Subversion/Jomago/Src/Labo/Laaw
+
+${LAAW_ROOT}/Parser/Build/LaawParser.exe Build/CodeModelRaw.json ../OrthancConnection.h -I`pwd`/../../s/jsoncpp-src-0.6.0-rc2/include -fms-extensions && \
+    python ${LAAW_ROOT}/Generators/CodeModelPostProcessing.py Build/CodeModel.json Build/CodeModelRaw.json Product.json && \
+    python ${LAAW_ROOT}/Generators/GenerateWrapperCpp.py Build/OrthancClient.h Build/CodeModel.json Product.json ConfigurationCpp.json && \
+    python ${LAAW_ROOT}/Generators/GenerateExternC.py Build/ExternC.cpp Build/CodeModel.json Product.json && \
+    python ${LAAW_ROOT}/Generators/GenerateWindows32Def.py Build/Windows32.def Build/CodeModel.json && \
+    python ${LAAW_ROOT}/Generators/GenerateWindows64Def.py Build/Windows64.def Build/CodeModel.json
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/OrthancCppClient/Package/Test/Basic/Build.sh	Fri Jul 19 16:14:18 2013 +0200
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+rm -rf i w32 w64
+mkdir i
+mkdir w32
+mkdir w64
+
+cd i && cmake .. && cd .. && \
+    cd w32 && cmake .. -DCMAKE_TOOLCHAIN_FILE=../../../../Resources/MinGWToolchain.cmake && cd .. && \
+    cd w64 && cmake .. -DCMAKE_TOOLCHAIN_FILE=../../../../Resources/MinGW64Toolchain.cmake && cd ..
+
+make -C i -j12
+make -C w32 -j12
+make -C w64 -j12
+
+nm -C -D --defined-only i/libOrthancCppClient.so 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/OrthancCppClient/Package/Test/Basic/CMakeLists.txt	Fri Jul 19 16:14:18 2013 +0200
@@ -0,0 +1,14 @@
+cmake_minimum_required(VERSION 2.8)
+
+project(OrthancCppClientTest)
+
+set(ORTHANC_ROOT ${CMAKE_SOURCE_DIR}/../../../..)
+include(../../OrthancCppClient.cmake)
+
+add_executable(Test main.cpp)
+
+if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
+  target_link_libraries(Test dl)
+else()
+  set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libgcc -static-libstdc++")
+endif()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/OrthancCppClient/Package/Test/Basic/main.cpp	Fri Jul 19 16:14:18 2013 +0200
@@ -0,0 +1,75 @@
+/**
+ * Orthanc - A Lightweight, RESTful DICOM Store
+ * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege,
+ * Belgium
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ **/
+
+
+#include <iostream>
+
+#include "../../Build/OrthancClient.h"
+
+int main()
+{
+  try
+  {
+#ifdef _WIN32
+    OrthancClient::Initialize("libOrthancCppClient.dll");
+#else
+    OrthancClient::Initialize("libOrthancCppClient.so");
+#endif
+
+    // Display the content of the local Orthanc instance
+    OrthancClient::OrthancConnection orthanc("http://localhost:8042");
+
+    for (unsigned int i = 0; i < orthanc.GetPatientCount(); i++)
+    {
+      OrthancClient::Patient patient = orthanc.GetPatient(i);
+      std::cout << "Patient: " << patient.GetId() << std::endl;
+
+      for (unsigned int j = 0; j < patient.GetStudyCount(); j++)
+      {
+        OrthancClient::Study study = patient.GetStudy(j);
+        std::cout << "  Study: " << study.GetId() << std::endl;
+
+        for (unsigned int k = 0; k < study.GetSeriesCount(); k++)
+        {
+          OrthancClient::Series series = study.GetSeries(k);
+          std::cout << "    Series: " << series.GetId() << std::endl;
+
+          for (unsigned int l = 0; l < series.GetInstanceCount(); l++)
+          {
+            std::cout << "      Instance: " << series.GetInstance(l).GetId() << std::endl;
+          }
+        }
+      }
+    }
+
+    return 0;
+  }
+  catch (OrthancClient::OrthancClientException e)
+  {
+    std::cerr << "EXCEPTION: [" << e.What() << "]" << std::endl;
+    return -1;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/OrthancCppClient/Package/Test/Vtk/CMakeLists.txt	Fri Jul 19 16:14:18 2013 +0200
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8)
+
+project(OrthancCppClientTest)
+
+set(ORTHANC_ROOT ${CMAKE_SOURCE_DIR}/../../../..)
+include(../../OrthancCppClient.cmake)
+
+find_package(VTK REQUIRED)
+include(${VTK_USE_FILE})
+
+add_executable(Test
+  main.cpp
+  )
+
+if(VTK_LIBRARIES)
+  target_link_libraries(Test ${VTK_LIBRARIES})
+else()
+  target_link_libraries(Test vtkHybrid vtkVolumeRendering)
+endif()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/OrthancCppClient/Package/Test/Vtk/main.cpp	Fri Jul 19 16:14:18 2013 +0200
@@ -0,0 +1,179 @@
+/**
+ * Orthanc - A Lightweight, RESTful DICOM Store
+ * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege,
+ * Belgium
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ **/
+
+
+#include <iostream>
+
+#include <vtkRenderWindow.h>
+#include <vtkImageData.h>
+#include <vtkPiecewiseFunction.h>
+#include <vtkFixedPointVolumeRayCastMapper.h>
+#include <vtkColorTransferFunction.h>
+#include <vtkVolumeProperty.h>
+#include <vtkRenderWindowInteractor.h>
+#include <vtkRenderer.h>
+#include <vtkSmartPointer.h>
+#include <vtkOpenGLRenderer.h>
+#include <vtkInteractorStyleTrackballCamera.h>
+
+#include "../../Build/OrthancClient.h"
+
+
+void Display(OrthancClient::Series& series)
+{
+  /**
+   * Load the 3D image from Orthanc into VTK.
+   **/
+
+  vtkSmartPointer<vtkImageData> image = vtkSmartPointer<vtkImageData>::New();
+  image->SetDimensions(series.GetWidth(), series.GetHeight(), series.GetInstanceCount());
+  image->SetScalarType(VTK_SHORT);
+  image->AllocateScalars();
+
+  if (series.GetWidth() != 0 &&
+      series.GetHeight() != 0 && 
+      series.GetInstanceCount() != 0)
+  {
+    series.Load3DImage(image->GetScalarPointer(0, 0, 0), Orthanc::PixelFormat_SignedGrayscale16,
+                       2 * series.GetWidth(), 2 * series.GetHeight() * series.GetWidth());
+  }
+
+  image->SetSpacing(series.GetVoxelSizeX(), 
+                    series.GetVoxelSizeY(), 
+                    series.GetVoxelSizeZ());
+
+
+  /**
+   * The following code is based on the VTK sample for MIP
+   * http://www.vtk.org/Wiki/VTK/Examples/Cxx/VolumeRendering/MinIntensityRendering
+   **/
+
+  // Create a transfer function mapping scalar value to opacity
+  double range[2];
+  image->GetScalarRange(range);
+
+  vtkSmartPointer<vtkPiecewiseFunction> opacityTransfer = 
+    vtkSmartPointer<vtkPiecewiseFunction>::New();
+  opacityTransfer->AddSegment(range[0], 0.0, range[1], 1.0);
+ 
+  vtkSmartPointer<vtkColorTransferFunction> colorTransfer = 
+    vtkSmartPointer<vtkColorTransferFunction>::New();
+  colorTransfer->AddRGBPoint(0, 1.0, 1.0, 1.0);
+  colorTransfer->AddRGBPoint(range[1], 1.0, 1.0, 1.0);
+ 
+  vtkSmartPointer<vtkVolumeProperty> property = 
+    vtkSmartPointer<vtkVolumeProperty>::New();
+  property->SetScalarOpacity(opacityTransfer);
+  property->SetColor(colorTransfer);
+  property->SetInterpolationTypeToLinear();
+
+  // Create a Maximum Intensity Projection rendering
+  vtkSmartPointer<vtkFixedPointVolumeRayCastMapper> mapper = 
+    vtkSmartPointer<vtkFixedPointVolumeRayCastMapper>::New();
+  mapper->SetBlendModeToMaximumIntensity();
+  mapper->SetInput(image);
+
+  vtkSmartPointer<vtkVolume> volume = vtkSmartPointer<vtkVolume>::New();
+  volume->SetMapper(mapper);
+  volume->SetProperty(property);
+  
+  vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkOpenGLRenderer>::New();
+  renderer->AddViewProp(volume);
+  renderer->SetBackground(0.1, 0.2, 0.3); // Background color dark blue
+
+  vtkSmartPointer<vtkInteractorStyleTrackballCamera> style = 
+    vtkSmartPointer<vtkInteractorStyleTrackballCamera>::New();
+ 
+  vtkSmartPointer<vtkRenderWindow> window = vtkSmartPointer<vtkRenderWindow>::New();
+  window->AddRenderer(renderer); 
+
+  vtkSmartPointer<vtkRenderWindowInteractor> interactor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
+  interactor->SetRenderWindow(window);
+  interactor->SetInteractorStyle(style);
+  interactor->Start();
+}
+
+
+int main()
+{
+  try
+  {
+    OrthancClient::Initialize("libOrthancCppClient.so");
+
+    // Use the commented code below if you know the identifier of a
+    // series that corresponds to a 3D image.
+
+    /*
+      {
+      OrthancClient::OrthancConnection orthanc("http://localhost:8042");
+      OrthancClient::Series series(orthanc, "c1c4cb95-05e3bd11-8da9f5bb-87278f71-0b2b43f5");
+      Display(series);
+      return 0;
+      }
+    */
+
+
+    // Try and find a 3D image inside the local store
+    OrthancClient::OrthancConnection orthanc("http://localhost:8042");
+
+    for (unsigned int i = 0; i < orthanc.GetPatientCount(); i++)
+    {
+      OrthancClient::Patient patient = orthanc.GetPatient(i);
+      std::cout << "Patient: " << patient.GetId() << std::endl;
+
+      for (unsigned int j = 0; j < patient.GetStudyCount(); j++)
+      {
+        OrthancClient::Study study = patient.GetStudy(j);
+        std::cout << "  Study: " << study.GetId() << std::endl;
+
+        for (unsigned int k = 0; k < study.GetSeriesCount(); k++)
+        {
+          OrthancClient::Series series = study.GetSeries(k);
+          std::cout << "    Series: " << series.GetId() << std::endl;
+
+          if (series.Is3DImage())
+          {
+            Display(series);
+            return 0;
+          }
+          else
+          {
+            std::cout << "      => Not a 3D image..." << std::endl;
+          }
+        }
+      }
+    }
+
+    std::cout << "Unable to find a 3D image in the local Orthanc store" << std::endl;
+
+    return 0;
+  }
+  catch (OrthancClient::OrthancClientException e)
+  {
+    std::cerr << "EXCEPTION: [" << e.What() << "]" << std::endl;
+    return -1;
+  }
+}
--- a/OrthancCppClient/Patient.cpp	Fri Jul 19 16:11:13 2013 +0200
+++ b/OrthancCppClient/Patient.cpp	Fri Jul 19 16:14:18 2013 +0200
@@ -33,29 +33,30 @@
 #include "Patient.h"
 
 #include "OrthancConnection.h"
-#include "../Core/OrthancException.h"
 
 namespace OrthancClient
 {
   void Patient::ReadPatient()
   {
     Orthanc::HttpClient client(connection_.GetHttpClient());
-    client.SetUrl(connection_.GetOrthancUrl() + "/patients/" + id_);
+    client.SetUrl(std::string(connection_.GetOrthancUrl()) + "/patients/" + id_);
+
     Json::Value v;
     if (!client.Apply(patient_))
     {
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_NetworkProtocol);
+      throw OrthancClientException(Orthanc::ErrorCode_NetworkProtocol);
     }
   }
 
   Orthanc::IDynamicObject* Patient::GetFillerItem(size_t index)
   {
     Json::Value::ArrayIndex tmp = static_cast<Json::Value::ArrayIndex>(index);
-    return new Study(connection_, patient_["Studies"][tmp].asString());
+    std::string id = patient_["Studies"][tmp].asString();
+    return new Study(connection_, id.c_str());
   }
 
   Patient::Patient(const OrthancConnection& connection,
-                   const std::string& id) :
+                   const char* id) :
     connection_(connection),
     id_(id),
     studies_(*this)
@@ -64,11 +65,11 @@
     ReadPatient();
   }
 
-  std::string Patient::GetMainDicomTag(const char* tag, const char* defaultValue) const
+  const char* Patient::GetMainDicomTag(const char* tag, const char* defaultValue) const
   {
     if (patient_["MainDicomTags"].isMember(tag))
     {
-      return patient_["MainDicomTags"][tag].asString();
+      return patient_["MainDicomTags"][tag].asCString();
     }
     else
     {
--- a/OrthancCppClient/Patient.h	Fri Jul 19 16:11:13 2013 +0200
+++ b/OrthancCppClient/Patient.h	Fri Jul 19 16:14:18 2013 +0200
@@ -36,7 +36,7 @@
 
 namespace OrthancClient
 {
-  class Patient : 
+  class LAAW_API Patient : 
     public Orthanc::IDynamicObject, 
     private Orthanc::ArrayFilledByThreads::IFiller
   {
@@ -57,29 +57,29 @@
 
   public:
     Patient(const OrthancConnection& connection,
-            const std::string& id);
+            const char* id);
 
     void Reload()
     {
       studies_.Reload();
     }
 
-    unsigned int GetStudyCount()
+    uint32_t GetStudyCount()
     {
       return studies_.GetSize();
     }
 
-    Study& GetStudy(unsigned int index)
+    Study& GetStudy(uint32_t index)
     {
       return dynamic_cast<Study&>(studies_.GetItem(index));
     }
 
-    const std::string& GetId() const
+    const char* GetId() const
     {
-      return id_;
+      return id_.c_str();
     }
 
-    std::string GetMainDicomTag(const char* tag, 
+    const char* GetMainDicomTag(const char* tag, 
                                 const char* defaultValue) const;
   };
 }
--- a/OrthancCppClient/Series.cpp	Fri Jul 19 16:11:13 2013 +0200
+++ b/OrthancCppClient/Series.cpp	Fri Jul 19 16:14:18 2013 +0200
@@ -33,7 +33,6 @@
 #include "Series.h"
 
 #include "OrthancConnection.h"
-#include "../Core/OrthancException.h"
 
 #include <set>
 #include <boost/lexical_cast.hpp>
@@ -61,7 +60,7 @@
 
         if (cosines.size() != 6)
         {
-          throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat);
+          throw OrthancClientException(Orthanc::ErrorCode_BadFileFormat);
         }
 
         normal_[0] = cosines[1] * cosines[5] - cosines[2] * cosines[4];
@@ -79,7 +78,7 @@
         instance.SplitVectorOfFloats(ipp, "ImagePositionPatient");
         if (ipp.size() != 3)
         {
-          throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat);
+          throw OrthancClientException(Orthanc::ErrorCode_BadFileFormat);
         }
 
         float dist = 0;
@@ -144,7 +143,7 @@
           }
           else
           {
-            throw OrthancException(ErrorCode_NotImplemented);
+            throw OrthancClientException(ErrorCode_NotImplemented);
           }
         }
 
@@ -161,7 +160,7 @@
   {
     if (!Is3DImage())
     {
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented);
+      throw OrthancClientException(Orthanc::ErrorCode_NotImplemented);
     }
   }
 
@@ -174,13 +173,17 @@
         return true;
       }
 
+      Instance& i1 = GetInstance(0);
+
       for (unsigned int i = 0; i < GetInstanceCount(); i++)
       {
-        if (GetInstance(0).GetTagAsString("Columns") != GetInstance(i).GetTagAsString("Columns") ||
-            GetInstance(0).GetTagAsString("Rows") != GetInstance(i).GetTagAsString("Rows") ||
-            GetInstance(0).GetTagAsString("ImageOrientationPatient") != GetInstance(i).GetTagAsString("ImageOrientationPatient") ||
-            GetInstance(0).GetTagAsString("SliceThickness") != GetInstance(i).GetTagAsString("SliceThickness") ||
-            GetInstance(0).GetTagAsString("PixelSpacing") != GetInstance(i).GetTagAsString("PixelSpacing"))
+        Instance& i2 = GetInstance(1);
+
+        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")))
         {
           return false;
         }              
@@ -195,7 +198,7 @@
 
       return l.size() == GetInstanceCount();
     }
-    catch (Orthanc::OrthancException)
+    catch (OrthancClientException)
     {
       return false;
     }
@@ -205,28 +208,31 @@
   {
     Orthanc::HttpClient client(connection_.GetHttpClient());
 
-    client.SetUrl(connection_.GetOrthancUrl() + "/series/" + id_);
+    client.SetUrl(std::string(connection_.GetOrthancUrl()) + "/series/" + id_);
     Json::Value v;
     if (!client.Apply(series_))
     {
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_NetworkProtocol);
+      throw OrthancClientException(Orthanc::ErrorCode_NetworkProtocol);
     }
   }
 
   Orthanc::IDynamicObject* Series::GetFillerItem(size_t index)
   {
     Json::Value::ArrayIndex tmp = static_cast<Json::Value::ArrayIndex>(index);
-    return new Instance(connection_, series_["Instances"][tmp].asString());
+    std::string id = series_["Instances"][tmp].asString();
+    return new Instance(connection_, id.c_str());
   }
 
   Series::Series(const OrthancConnection& connection,
-                 const std::string& id) :
+                 const char* id) :
     connection_(connection),
     id_(id),
     instances_(*this)
   {
     ReadSeries();
     status_ = Status3DImage_NotTested;
+    url_ = std::string(connection_.GetOrthancUrl()) + "/series/" + id_;
+    isVoxelSizeRead_ = false;
 
     instances_.SetThreadCount(connection.GetThreadCount());
   }
@@ -252,11 +258,6 @@
     return dynamic_cast<Instance&>(instances_.GetItem(index));
   }
 
-  std::string Series::GetUrl() const
-  {
-    return connection_.GetOrthancUrl() + "/series/" + id_;
-  }
-
   unsigned int Series::GetWidth()
   {
     Check3DImage();
@@ -277,15 +278,21 @@
       return GetInstance(0).GetTagAsInt("Rows");
   }
 
-  void Series::GetVoxelSize(float& sizeX, float& sizeY, float& sizeZ)
+  void Series::LoadVoxelSize()
   {
+    if (isVoxelSizeRead_)
+    {
+      return;
+    }
+
     Check3DImage();
 
     if (GetInstanceCount() == 0)
     {
-      sizeX = 0;
-      sizeY = 0;
-      sizeZ = 0;
+      // Empty image, use some default value
+      voxelSizeX_ = 1;
+      voxelSizeY_ = 1;
+      voxelSizeZ_ = 1;
     }
     else
     {
@@ -297,23 +304,25 @@
         std::string sy = s.substr(0, pos);
         std::string sx = s.substr(pos + 1);
 
-        sizeX = boost::lexical_cast<float>(sx);
-        sizeY = boost::lexical_cast<float>(sy);
-        sizeZ = GetInstance(0).GetTagAsFloat("SliceThickness");
+        voxelSizeX_ = boost::lexical_cast<float>(sx);
+        voxelSizeY_ = boost::lexical_cast<float>(sy);
+        voxelSizeZ_ = GetInstance(0).GetTagAsFloat("SliceThickness");
       }
       catch (boost::bad_lexical_cast)
       {
-        throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented);
+        throw OrthancClientException(Orthanc::ErrorCode_NotImplemented);
       }
     }
+
+    isVoxelSizeRead_ = true;
   }
 
 
-  std::string Series::GetMainDicomTag(const char* tag, const char* defaultValue) const
+  const char* Series::GetMainDicomTag(const char* tag, const char* defaultValue) const
   {
     if (series_["MainDicomTags"].isMember(tag))
     {
-      return series_["MainDicomTags"][tag].asString();
+      return series_["MainDicomTags"][tag].asCString();
     }
     else
     {
@@ -361,7 +370,7 @@
         break;
 
       default:
-        throw OrthancException(ErrorCode_NotImplemented);
+        throw OrthancClientException(ErrorCode_NotImplemented);
     }
 
 
@@ -372,7 +381,7 @@
     if (lineStride < sx * bytesPerPixel ||
         stackStride < sx * sy * bytesPerPixel)
     {
-      throw OrthancException(ErrorCode_BadRequest);
+      throw OrthancClientException(ErrorCode_BadRequest);
     }
 
     if (sx == 0 || sy == 0 || GetInstanceCount() == 0)
@@ -402,7 +411,7 @@
     if (instances.size() != GetInstanceCount())
     {
       // Several instances have the same Z coordinate
-      throw OrthancException(ErrorCode_NotImplemented);
+      throw OrthancClientException(ErrorCode_NotImplemented);
     }
 
 
@@ -425,8 +434,26 @@
     // Wait for all the stacks to be downloaded
     if (!processor.Join())
     {
-      throw OrthancException(ErrorCode_NetworkProtocol);
+      throw OrthancClientException(ErrorCode_NetworkProtocol);
     }
   }
 
+  float Series::GetVoxelSizeX()
+  {
+    LoadVoxelSize();
+    return voxelSizeX_;
+  }
+
+  float Series::GetVoxelSizeY()
+  {
+    LoadVoxelSize();
+    return voxelSizeY_;
+  }
+
+  float Series::GetVoxelSizeZ()
+  {
+    LoadVoxelSize();
+    return voxelSizeZ_;
+  }
+
 }
--- a/OrthancCppClient/Series.h	Fri Jul 19 16:11:13 2013 +0200
+++ b/OrthancCppClient/Series.h	Fri Jul 19 16:14:18 2013 +0200
@@ -39,7 +39,7 @@
 
 namespace OrthancClient
 {
-  class Series :
+  class LAAW_API Series :
     public Orthanc::IDynamicObject, 
     private Orthanc::ArrayFilledByThreads::IFiller
   {
@@ -52,10 +52,15 @@
     };
 
     const OrthancConnection& connection_;
-    std::string id_;
+    std::string id_, url_;
     Json::Value series_;
     Orthanc::ArrayFilledByThreads  instances_;
     Status3DImage status_;
+
+    bool isVoxelSizeRead_;
+    float voxelSizeX_;
+    float voxelSizeY_;
+    float voxelSizeZ_;
   
     void Check3DImage();
 
@@ -76,9 +81,11 @@
                      size_t stackStride,
                      Orthanc::ThreadedCommandProcessor::IListener* listener);
 
+    void LoadVoxelSize();  
+
   public:
     Series(const OrthancConnection& connection,
-           const std::string& id);
+           const char* id);
 
     void Reload()
     {
@@ -87,39 +94,46 @@
 
     bool Is3DImage();
 
-    unsigned int GetInstanceCount();
-
-    Instance& GetInstance(unsigned int index);
+    uint32_t GetInstanceCount();
+    
+    Instance& GetInstance(uint32_t index);
 
-    const std::string& GetId() const
+    const char* GetId() const
     {
-      return id_;
+      return id_.c_str();
+    }
+
+    const char* GetUrl() const
+    {
+      return url_.c_str();
     }
 
-    std::string GetUrl() const;
+    uint32_t GetWidth();
 
-    unsigned int GetWidth();
+    uint32_t GetHeight();
+
+    float GetVoxelSizeX();
 
-    unsigned int GetHeight();
+    float GetVoxelSizeY();
 
-    void GetVoxelSize(float& sizeX, float& sizeY, float& sizeZ);  
+    float GetVoxelSizeZ();
 
-    std::string GetMainDicomTag(const char* tag, 
+    const char* GetMainDicomTag(const char* tag, 
                                 const char* defaultValue) const;
 
-    void Load3DImage(void* target,
-                     Orthanc::PixelFormat format,
-                     size_t lineStride,
-                     size_t stackStride,
-                     Orthanc::ThreadedCommandProcessor::IListener& listener)
+    LAAW_API_INTERNAL void Load3DImage(void* target,
+                                       Orthanc::PixelFormat format,
+                                       int64_t lineStride,
+                                       int64_t stackStride,
+                                       Orthanc::ThreadedCommandProcessor::IListener& listener)
     {
       Load3DImage(target, format, lineStride, stackStride, &listener);
     }
 
     void Load3DImage(void* target,
                      Orthanc::PixelFormat format,
-                     size_t lineStride,
-                     size_t stackStride)
+                     int64_t lineStride,
+                     int64_t stackStride)
     {
       Load3DImage(target, format, lineStride, stackStride, NULL);
     }
--- a/OrthancCppClient/Study.cpp	Fri Jul 19 16:11:13 2013 +0200
+++ b/OrthancCppClient/Study.cpp	Fri Jul 19 16:14:18 2013 +0200
@@ -33,29 +33,30 @@
 #include "Study.h"
 
 #include "OrthancConnection.h"
-#include "../Core/OrthancException.h"
 
 namespace OrthancClient
 {
   void Study::ReadStudy()
   {
     Orthanc::HttpClient client(connection_.GetHttpClient());
-    client.SetUrl(connection_.GetOrthancUrl() + "/studies/" + id_);
+    client.SetUrl(std::string(connection_.GetOrthancUrl()) + "/studies/" + id_);
+
     Json::Value v;
     if (!client.Apply(study_))
     {
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_NetworkProtocol);
+      throw OrthancClientException(Orthanc::ErrorCode_NetworkProtocol);
     }
   }
 
   Orthanc::IDynamicObject* Study::GetFillerItem(size_t index)
   {
     Json::Value::ArrayIndex tmp = static_cast<Json::Value::ArrayIndex>(index);
-    return new Series(connection_, study_["Series"][tmp].asString());
+    std::string id = study_["Series"][tmp].asString();
+    return new Series(connection_, id.c_str());
   }
 
   Study::Study(const OrthancConnection& connection,
-               const std::string& id) :
+               const char* id) :
     connection_(connection),
     id_(id),
     series_(*this)
@@ -64,11 +65,11 @@
     ReadStudy();
   }
 
-  std::string Study::GetMainDicomTag(const char* tag, const char* defaultValue) const
+  const char* Study::GetMainDicomTag(const char* tag, const char* defaultValue) const
   {
     if (study_["MainDicomTags"].isMember(tag))
     {
-      return study_["MainDicomTags"][tag].asString();
+      return study_["MainDicomTags"][tag].asCString();
     }
     else
     {
--- a/OrthancCppClient/Study.h	Fri Jul 19 16:11:13 2013 +0200
+++ b/OrthancCppClient/Study.h	Fri Jul 19 16:14:18 2013 +0200
@@ -36,7 +36,7 @@
 
 namespace OrthancClient
 {
-  class Study : 
+  class LAAW_API Study : 
     public Orthanc::IDynamicObject, 
     private Orthanc::ArrayFilledByThreads::IFiller
   {
@@ -57,29 +57,29 @@
 
   public:
     Study(const OrthancConnection& connection,
-          const std::string& id);
+          const char* id);
 
     void Reload()
     {
       series_.Reload();
     }
 
-    unsigned int GetSeriesCount()
+    uint32_t GetSeriesCount()
     {
       return series_.GetSize();
     }
 
-    Series& GetSeries(unsigned int index)
+    Series& GetSeries(uint32_t index)
     {
       return dynamic_cast<Series&>(series_.GetItem(index));
     }
 
-    const std::string& GetId() const
+    const char* GetId() const
     {
-      return id_;
+      return id_.c_str();
     }
 
-    std::string GetMainDicomTag(const char* tag, 
+    const char* GetMainDicomTag(const char* tag, 
                                 const char* defaultValue) const;
   };
 }
--- a/Resources/CMake/LibCurlConfiguration.cmake	Fri Jul 19 16:11:13 2013 +0200
+++ b/Resources/CMake/LibCurlConfiguration.cmake	Fri Jul 19 16:14:18 2013 +0200
@@ -9,8 +9,8 @@
   AUX_SOURCE_DIRECTORY(${CURL_SOURCES_DIR}/lib CURL_SOURCES)
   source_group(ThirdParty\\LibCurl REGULAR_EXPRESSION ${CURL_SOURCES_DIR}/.*)
 
-  add_library(Curl STATIC ${CURL_SOURCES})
-  link_libraries(Curl)  
+  #add_library(Curl STATIC ${CURL_SOURCES})
+  #link_libraries(Curl)  
 
   add_definitions(
     -DCURL_STATICLIB=1
--- a/Resources/CMake/OpenSslConfiguration.cmake	Fri Jul 19 16:11:13 2013 +0200
+++ b/Resources/CMake/OpenSslConfiguration.cmake	Fri Jul 19 16:14:18 2013 +0200
@@ -164,6 +164,20 @@
     ${OPENSSL_SOURCES_DIR}/crypto/sha/sha512t.c
     ${OPENSSL_SOURCES_DIR}/crypto/sha/shatest.c
     ${OPENSSL_SOURCES_DIR}/crypto/srp/srptest.c
+
+    ${OPENSSL_SOURCES_DIR}/crypto/bn/divtest.c
+    ${OPENSSL_SOURCES_DIR}/crypto/bn/bnspeed.c
+    ${OPENSSL_SOURCES_DIR}/crypto/des/destest.c
+    ${OPENSSL_SOURCES_DIR}/crypto/dh/p192.c
+    ${OPENSSL_SOURCES_DIR}/crypto/dh/p512.c
+    ${OPENSSL_SOURCES_DIR}/crypto/dh/p1024.c
+    ${OPENSSL_SOURCES_DIR}/crypto/des/rpw.c
+    ${OPENSSL_SOURCES_DIR}/ssl/ssltest.c
+    ${OPENSSL_SOURCES_DIR}/crypto/dsa/dsagen.c
+    ${OPENSSL_SOURCES_DIR}/crypto/dsa/dsatest.c
+    ${OPENSSL_SOURCES_DIR}/crypto/dh/dhtest.c
+    ${OPENSSL_SOURCES_DIR}/crypto/pqueue/pq_test.c
+    ${OPENSSL_SOURCES_DIR}/crypto/des/ncbc_enc.c
     )
 
   #if (${MSVC})
@@ -174,8 +188,8 @@
       "OPENSSL_SYSNAME_WIN32;SO_WIN32;WIN32_LEAN_AND_MEAN;L_ENDIAN")
   endif()
 
-  add_library(OpenSSL STATIC ${OPENSSL_SOURCES})
-  link_libraries(OpenSSL)
+  #add_library(OpenSSL STATIC ${OPENSSL_SOURCES})
+  #link_libraries(OpenSSL)
 
 else()
   include(FindOpenSSL)
--- a/Resources/CMake/ZlibConfiguration.cmake	Fri Jul 19 16:11:13 2013 +0200
+++ b/Resources/CMake/ZlibConfiguration.cmake	Fri Jul 19 16:14:18 2013 +0200
@@ -1,7 +1,7 @@
 # This is the minizip distribution to create ZIP files
 list(APPEND THIRD_PARTY_SOURCES 
-  ${CMAKE_SOURCE_DIR}/Resources/minizip/ioapi.c
-  ${CMAKE_SOURCE_DIR}/Resources/minizip/zip.c
+  ${ORTHANC_ROOT}/Resources/minizip/ioapi.c
+  ${ORTHANC_ROOT}/Resources/minizip/zip.c
   )
 
 if (${STATIC_BUILD})
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Resources/MinGW64Toolchain.cmake	Fri Jul 19 16:14:18 2013 +0200
@@ -0,0 +1,34 @@
+# http://sourceforge.net/apps/trac/mingw-w64/wiki/GeneralUsageInstructions
+
+# the name of the target operating system
+SET(CMAKE_SYSTEM_NAME Windows)
+
+# Detect the prefix of the mingw-w64 compiler
+execute_process(
+  COMMAND uname -p
+  OUTPUT_VARIABLE MINGW64_ARCHITECTURE
+  OUTPUT_STRIP_TRAILING_WHITESPACE
+  )
+
+if (${MINGW64_ARCHITECTURE} STREQUAL "x86_64")
+  set(MINGW64_PREFIX "x86_64")
+else()
+  set(MINGW64_PREFIX "i686")
+endif()
+  
+# which compilers to use for C and C++
+SET(CMAKE_C_COMPILER ${MINGW64_PREFIX}-w64-mingw32-gcc)
+SET(CMAKE_CXX_COMPILER ${MINGW64_PREFIX}-w64-mingw32-g++)
+SET(CMAKE_RC_COMPILER ${MINGW64_PREFIX}-w64-mingw32-windres)
+
+# here is the target environment located
+SET(CMAKE_FIND_ROOT_PATH /usr/i686-w64-mingw32)
+
+# adjust the default behaviour of the FIND_XXX() commands:
+# search headers and libraries in the target environment, search 
+# programs in the host environment
+set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
+set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
+set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
+
+SET(CMAKE_RC_COMPILE_OBJECT "${CMAKE_RC_COMPILER} -O coff -I${CMAKE_CURRENT_SOURCE_DIR} <SOURCE> <OBJECT>")
--- a/Resources/Samples/OrthancCppClient/Vtk/main.cpp	Fri Jul 19 16:11:13 2013 +0200
+++ b/Resources/Samples/OrthancCppClient/Vtk/main.cpp	Fri Jul 19 16:14:18 2013 +0200
@@ -88,9 +88,9 @@
                        2 * series.GetWidth(), 2 * series.GetHeight() * series.GetWidth(), listener);
   }
 
-  float sx, sy, sz;
-  series.GetVoxelSize(sx, sy, sz);
-  image->SetSpacing(sx, sy, sz);
+  image->SetSpacing(series.GetVoxelSizeX(), 
+                    series.GetVoxelSizeY(), 
+                    series.GetVoxelSizeZ());
 
 
   /**