changeset 79:abdde1dfb3eb

use sdk 0.9.4
author Sebastien Jodogne <s.jodogne@gmail.com>
date Fri, 25 Sep 2015 12:32:37 +0200
parents d6da56f86e5a
children 83496e713a8e
files CMakeLists.txt Orthanc/Core/Toolbox.cpp Orthanc/Core/Toolbox.h Orthanc/Plugins/Samples/Common/ExportedSymbols.list Orthanc/Resources/CMake/Compiler.cmake Plugin/Cache/CacheScheduler.cpp Plugin/JpegWriter.cpp Plugin/JpegWriter.h Plugin/ParsedDicomImage.cpp Plugin/ParsedDicomImage.h Plugin/Plugin.cpp Plugin/SeriesInformationAdapter.cpp Plugin/ViewerToolbox.cpp Plugin/ViewerToolbox.h Resources/SyncOrthancFolder.py UnitTestsSources/UnitTestsMain.cpp
diffstat 16 files changed, 218 insertions(+), 485 deletions(-) [+]
line wrap: on
line diff
--- a/CMakeLists.txt	Fri Sep 25 11:29:17 2015 +0200
+++ b/CMakeLists.txt	Fri Sep 25 12:32:37 2015 +0200
@@ -32,7 +32,6 @@
 set(USE_SYSTEM_GDCM ON CACHE BOOL "Use the system version of Grassroot DICOM (GDCM)")
 set(USE_SYSTEM_GOOGLE_TEST ON CACHE BOOL "Use the system version of Google Test")
 set(USE_SYSTEM_JSONCPP ON CACHE BOOL "Use the system version of JsonCpp")
-set(USE_SYSTEM_ZLIB ON CACHE BOOL "Use the system version of zlib")
 set(USE_SYSTEM_SQLITE ON CACHE BOOL "Use the system version of SQLite")
 set(USE_SYSTEM_ORTHANC_SDK ON CACHE BOOL "Use the system version of the Orthanc plugin SDK")
 
@@ -116,13 +115,8 @@
   list(APPEND AUTOGENERATED_SOURCES  ${AUTOGENERATED_DIR}/Version.rc)
 endif()
 
-if (CMAKE_COMPILER_IS_GNUCXX)
-  SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--version-script=${CMAKE_SOURCE_DIR}/Orthanc/Plugins/Samples/Common/VersionScript.map -Wl,--no-undefined")
-endif()
-
 if (APPLE)
   SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -framework CoreFoundation")
-  SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -framework CoreFoundation")
 endif()
 
 add_definitions(
@@ -134,22 +128,16 @@
 set(CORE_SOURCES
   ${BOOST_SOURCES}
   ${SQLITE_SOURCES}
-  ${LIBJPEG_SOURCES}
-  ${ZLIB_SOURCES}
-  ${LIBPNG_SOURCES}
   ${JSONCPP_SOURCES}
 
   # Sources inherited from Orthanc core
   ${CMAKE_SOURCE_DIR}/Orthanc/Core/ChunkedBuffer.cpp
   ${CMAKE_SOURCE_DIR}/Orthanc/Core/Enumerations.cpp
   ${CMAKE_SOURCE_DIR}/Orthanc/Core/FileStorage/FilesystemStorage.cpp
-  ${CMAKE_SOURCE_DIR}/Orthanc/Core/ImageFormats/ImageAccessor.cpp
-  ${CMAKE_SOURCE_DIR}/Orthanc/Core/ImageFormats/ImageBuffer.cpp
-  ${CMAKE_SOURCE_DIR}/Orthanc/Core/ImageFormats/ImageProcessing.cpp
-  ${CMAKE_SOURCE_DIR}/Orthanc/Core/ImageFormats/PngReader.cpp
-  ${CMAKE_SOURCE_DIR}/Orthanc/Core/ImageFormats/PngWriter.cpp
+  ${CMAKE_SOURCE_DIR}/Orthanc/Core/Images/ImageAccessor.cpp
+  ${CMAKE_SOURCE_DIR}/Orthanc/Core/Images/ImageBuffer.cpp
+  ${CMAKE_SOURCE_DIR}/Orthanc/Core/Images/ImageProcessing.cpp
   ${CMAKE_SOURCE_DIR}/Orthanc/Core/MultiThreading/SharedMessageQueue.cpp
-  ${CMAKE_SOURCE_DIR}/Orthanc/Core/OrthancException.cpp
   ${CMAKE_SOURCE_DIR}/Orthanc/Core/SQLite/Connection.cpp
   ${CMAKE_SOURCE_DIR}/Orthanc/Core/SQLite/FunctionContext.cpp
   ${CMAKE_SOURCE_DIR}/Orthanc/Core/SQLite/Statement.cpp
@@ -162,7 +150,6 @@
 
   ${CMAKE_SOURCE_DIR}/Plugin/Cache/CacheManager.cpp
   ${CMAKE_SOURCE_DIR}/Plugin/Cache/CacheScheduler.cpp
-  ${CMAKE_SOURCE_DIR}/Plugin/JpegWriter.cpp
   ${CMAKE_SOURCE_DIR}/Plugin/ViewerToolbox.cpp
   ${CMAKE_SOURCE_DIR}/Plugin/SeriesVolumeSorter.cpp
   ${CMAKE_SOURCE_DIR}/Plugin/ViewerPrefetchPolicy.cpp
--- a/Orthanc/Core/Toolbox.cpp	Fri Sep 25 11:29:17 2015 +0200
+++ b/Orthanc/Core/Toolbox.cpp	Fri Sep 25 12:32:37 2015 +0200
@@ -527,6 +527,29 @@
   {
     result = base64_decode(data);
   }
+
+
+#  if BOOST_HAS_REGEX == 1
+  void Toolbox::DecodeDataUriScheme(std::string& mime,
+                                    std::string& content,
+                                    const std::string& source)
+  {
+    boost::regex pattern("data:([^;]+);base64,([a-zA-Z0-9=+/]*)",
+                         boost::regex::icase /* case insensitive search */);
+
+    boost::cmatch what;
+    if (regex_match(source.c_str(), what, pattern))
+    {
+      mime = what[1];
+      DecodeBase64(content, what[2]);
+    }
+    else
+    {
+      throw OrthancException(ErrorCode_BadFileFormat);
+    }
+  }
+#  endif
+
 #endif
 
 
@@ -1009,28 +1032,6 @@
   }
 
 
-#if BOOST_HAS_REGEX == 1
-  void Toolbox::DecodeDataUriScheme(std::string& mime,
-                                    std::string& content,
-                                    const std::string& source)
-  {
-    boost::regex pattern("data:([^;]+);base64,([a-zA-Z0-9=+/]*)",
-                         boost::regex::icase /* case insensitive search */);
-
-    boost::cmatch what;
-    if (regex_match(source.c_str(), what, pattern))
-    {
-      mime = what[1];
-      DecodeBase64(content, what[2]);
-    }
-    else
-    {
-      throw OrthancException(ErrorCode_BadFileFormat);
-    }
-  }
-#endif
-
-
   void Toolbox::MakeDirectory(const std::string& path)
   {
     if (boost::filesystem::exists(path))
--- a/Orthanc/Core/Toolbox.h	Fri Sep 25 11:29:17 2015 +0200
+++ b/Orthanc/Core/Toolbox.h	Fri Sep 25 12:32:37 2015 +0200
@@ -117,6 +117,12 @@
 
     void EncodeBase64(std::string& result, 
                       const std::string& data);
+
+#  if BOOST_HAS_REGEX == 1
+    void DecodeDataUriScheme(std::string& mime,
+                             std::string& content,
+                             const std::string& source);
+#  endif
 #endif
 
     std::string GetPathToExecutable();
@@ -153,12 +159,6 @@
                         const std::string& source,
                         char separator);
 
-#if BOOST_HAS_REGEX == 1
-    void DecodeDataUriScheme(std::string& mime,
-                             std::string& content,
-                             const std::string& source);
-#endif
-
     void MakeDirectory(const std::string& path);
 
     bool IsExistingFile(const std::string& path);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Orthanc/Plugins/Samples/Common/ExportedSymbols.list	Fri Sep 25 12:32:37 2015 +0200
@@ -0,0 +1,7 @@
+# This is the list of the symbols that must be exported by Orthanc
+# plugins, if targeting OS X
+
+_OrthancPluginInitialize
+_OrthancPluginFinalize
+_OrthancPluginGetName
+_OrthancPluginGetVersion
--- a/Orthanc/Resources/CMake/Compiler.cmake	Fri Sep 25 11:29:17 2015 +0200
+++ b/Orthanc/Resources/CMake/Compiler.cmake	Fri Sep 25 12:32:37 2015 +0200
@@ -50,7 +50,7 @@
     ${CMAKE_SYSTEM_NAME} STREQUAL "kFreeBSD" OR
     ${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD")
   set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,--no-undefined")
-  set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--no-undefined -Wl,--version-script=${CMAKE_SOURCE_DIR}/Plugins/Samples/Common/VersionScript.map")
+  set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--no-undefined -Wl,--version-script=${ORTHANC_ROOT}/Plugins/Samples/Common/VersionScript.map")
 
   # Remove the "-rdynamic" option
   # http://www.mail-archive.com/cmake@cmake.org/msg08837.html
@@ -108,7 +108,7 @@
   endif()
 
 elseif (${CMAKE_SYSTEM_NAME} STREQUAL "Darwin")
-  SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -exported_symbols_list ${CMAKE_SOURCE_DIR}/Plugins/Samples/Common/ExportedSymbols.list")
+  SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -exported_symbols_list ${ORTHANC_ROOT}/Plugins/Samples/Common/ExportedSymbols.list")
 
   add_definitions(
     -D_XOPEN_SOURCE=1
--- a/Plugin/Cache/CacheScheduler.cpp	Fri Sep 25 11:29:17 2015 +0200
+++ b/Plugin/Cache/CacheScheduler.cpp	Fri Sep 25 12:32:37 2015 +0200
@@ -265,7 +265,8 @@
     BundleSchedulers::iterator it = bundles_.find(bundleIndex);
     if (it == bundles_.end())
     {
-      throw Orthanc::OrthancException("No factory associated with this bundle");
+      // No factory associated with this bundle
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
     }
 
     return *(it->second);
--- a/Plugin/JpegWriter.cpp	Fri Sep 25 11:29:17 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,246 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2015 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 Affero General Public License
- * as published by the Free Software Foundation, either version 3 of
- * the License, or (at your option) any later version.
- *
- * 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
- * Affero General Public License for more details.
- * 
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- **/
-
-
-#include "JpegWriter.h"
-
-#include "../Orthanc/Core/OrthancException.h"
-
-#include <jpeglib.h>
-#include <setjmp.h>
-#include <stdio.h>
-#include <vector>
-#include <string.h>
-#include <stdlib.h>
-
-namespace OrthancPlugins
-{
-  namespace
-  {
-    class ErrorManager 
-    {
-    private:
-      struct jpeg_error_mgr pub;  /* "public" fields */
-      jmp_buf setjmp_buffer;      /* for return to caller */
-      std::string message;
-
-      static void OutputMessage(j_common_ptr cinfo)
-      {
-        char message[JMSG_LENGTH_MAX];
-        (*cinfo->err->format_message) (cinfo, message);
-
-        ErrorManager* that = reinterpret_cast<ErrorManager*>(cinfo->err);
-        that->message = std::string(message);
-      }
-
-
-      static void ErrorExit(j_common_ptr cinfo)
-      {
-        (*cinfo->err->output_message) (cinfo);
-
-        ErrorManager* that = reinterpret_cast<ErrorManager*>(cinfo->err);
-        longjmp(that->setjmp_buffer, 1);
-      }
-      
-
-    public:
-      ErrorManager()
-      {
-        memset(&pub, 0, sizeof(struct jpeg_error_mgr));
-        memset(&setjmp_buffer, 0, sizeof(jmp_buf));
-
-        jpeg_std_error(&pub);
-        pub.error_exit = ErrorExit;
-        pub.output_message = OutputMessage;
-      }
-
-      struct jpeg_error_mgr* GetPublic()
-      {
-        return &pub;
-      }
-
-      jmp_buf& GetJumpBuffer()
-      {
-        return setjmp_buffer;
-      }
-
-      const std::string& GetMessage() const
-      {
-        return message;
-      }
-    };
-  }
-
-
-  static void GetLines(std::vector<uint8_t*>& lines,
-                       unsigned int height,
-                       unsigned int pitch,
-                       Orthanc::PixelFormat format,
-                       const void* buffer)
-  {
-    if (format != Orthanc::PixelFormat_Grayscale8 &&
-        format != Orthanc::PixelFormat_RGB24)
-    {
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
-    }
-
-    lines.resize(height);
-
-    uint8_t* base = const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(buffer));
-    for (unsigned int y = 0; y < height; y++)
-    {
-      lines[y] = base + static_cast<intptr_t>(y) * static_cast<intptr_t>(pitch);
-    }
-  }
-
-
-  static void Compress(struct jpeg_compress_struct& cinfo,
-                       std::vector<uint8_t*>& lines,
-                       unsigned int width,
-                       unsigned int height,
-                       Orthanc::PixelFormat format,
-                       int quality)
-  {
-    cinfo.image_width = width;
-    cinfo.image_height = height;
-
-    switch (format)
-    {
-      case Orthanc::PixelFormat_Grayscale8:
-        cinfo.input_components = 1;
-        cinfo.in_color_space = JCS_GRAYSCALE;
-        break;
-
-      case Orthanc::PixelFormat_RGB24:
-        cinfo.input_components = 3;
-        cinfo.in_color_space = JCS_RGB;
-        break;
-
-      default:
-        throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
-    }
-
-    jpeg_set_defaults(&cinfo);
-    jpeg_set_quality(&cinfo, quality, TRUE);
-    jpeg_start_compress(&cinfo, TRUE);
-    jpeg_write_scanlines(&cinfo, &lines[0], height);
-    jpeg_finish_compress(&cinfo);
-    jpeg_destroy_compress(&cinfo);
-  }
-                       
-
-  void JpegWriter::SetQuality(uint8_t quality)
-  {
-    if (quality <= 0 || quality > 100)
-    {
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
-    }
-
-    quality_ = quality;
-  }
-
-
-  void JpegWriter::WriteToFile(const char* filename,
-                               unsigned int width,
-                               unsigned int height,
-                               unsigned int pitch,
-                               Orthanc::PixelFormat format,
-                               const void* buffer)
-  {
-    FILE* fp = fopen(filename, "wb");
-    if (fp == NULL)
-    {
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_FullStorage);
-    }
-
-    std::vector<uint8_t*> lines;
-    GetLines(lines, height, pitch, format, buffer);
-
-    struct jpeg_compress_struct cinfo;
-    memset(&cinfo, 0, sizeof(struct jpeg_compress_struct));
-
-    ErrorManager jerr;
-    cinfo.err = jerr.GetPublic();
-
-    if (setjmp(jerr.GetJumpBuffer())) 
-    {
-      /* If we get here, the JPEG code has signaled an error.
-       * We need to clean up the JPEG object, close the input file, and return.
-       */
-      jpeg_destroy_compress(&cinfo);
-      fclose(fp);
-      throw Orthanc::OrthancException("Error during JPEG encoding: " + jerr.GetMessage());
-    }
-
-    // Do not allocate data on the stack below this line!
-
-    jpeg_create_compress(&cinfo);
-    jpeg_stdio_dest(&cinfo, fp);
-    Compress(cinfo, lines, width, height, format, quality_);
-
-    // Everything went fine, "setjmp()" didn't get called
-
-    fclose(fp);
-  }
-
-
-  void JpegWriter::WriteToMemory(std::string& jpeg,
-                                 unsigned int width,
-                                 unsigned int height,
-                                 unsigned int pitch,
-                                 Orthanc::PixelFormat format,
-                                 const void* buffer)
-  {
-    std::vector<uint8_t*> lines;
-    GetLines(lines, height, pitch, format, buffer);
-
-    struct jpeg_compress_struct cinfo;
-    memset(&cinfo, 0, sizeof(struct jpeg_compress_struct));
-
-    ErrorManager jerr;
-
-    unsigned char* data = NULL;
-    unsigned long size;
-
-    if (setjmp(jerr.GetJumpBuffer())) 
-    {
-      jpeg_destroy_compress(&cinfo);
-
-      if (data != NULL)
-      {
-        free(data);
-      }
-
-      throw Orthanc::OrthancException("Error during JPEG encoding: " + jerr.GetMessage());
-    }
-
-    // Do not allocate data on the stack below this line!
-
-    jpeg_create_compress(&cinfo);
-    cinfo.err = jerr.GetPublic();
-    jpeg_mem_dest(&cinfo, &data, &size);
-
-    Compress(cinfo, lines, width, height, format, quality_);
-
-    // Everything went fine, "setjmp()" didn't get called
-
-    jpeg.assign(reinterpret_cast<const char*>(data), size);
-    free(data);
-  }
-}
--- a/Plugin/JpegWriter.h	Fri Sep 25 11:29:17 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2015 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 Affero General Public License
- * as published by the Free Software Foundation, either version 3 of
- * the License, or (at your option) any later version.
- *
- * 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
- * Affero General Public License for more details.
- * 
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- **/
-
-
-#pragma once
-
-#include "../Orthanc/Core/ImageFormats/ImageAccessor.h"
-
-#include <string>
-#include <stdint.h>
-
-namespace OrthancPlugins
-{
-  class JpegWriter
-  {
-  private:
-    int  quality_;
-
-  public:
-    JpegWriter() : quality_(90)
-    {
-    }
-
-    void SetQuality(uint8_t quality);
-
-    uint8_t GetQuality() const
-    {
-      return quality_;
-    }
-
-    void WriteToFile(const char* filename,
-                     unsigned int width,
-                     unsigned int height,
-                     unsigned int pitch,
-                     Orthanc::PixelFormat format,
-                     const void* buffer);
-
-    void WriteToMemory(std::string& jpeg,
-                       unsigned int width,
-                       unsigned int height,
-                       unsigned int pitch,
-                       Orthanc::PixelFormat format,
-                       const void* buffer);
-
-    void WriteToFile(const char* filename,
-                     const Orthanc::ImageAccessor& accessor)
-    {
-      WriteToFile(filename, accessor.GetWidth(), accessor.GetHeight(),
-                  accessor.GetPitch(), accessor.GetFormat(), accessor.GetConstBuffer());
-    }
-
-    void WriteToMemory(std::string& jpeg,
-                       const Orthanc::ImageAccessor& accessor)
-    {
-      WriteToMemory(jpeg, accessor.GetWidth(), accessor.GetHeight(),
-                    accessor.GetPitch(), accessor.GetFormat(), accessor.GetConstBuffer());
-    }
-  };
-}
--- a/Plugin/ParsedDicomImage.cpp	Fri Sep 25 11:29:17 2015 +0200
+++ b/Plugin/ParsedDicomImage.cpp	Fri Sep 25 12:32:37 2015 +0200
@@ -22,10 +22,8 @@
 
 #include "../Orthanc/Core/OrthancException.h"
 #include "../Orthanc/Core/Toolbox.h"
-#include "../Orthanc/Core/ImageFormats/ImageProcessing.h"
-#include "../Orthanc/Core/ImageFormats/ImageBuffer.h"
-#include "../Orthanc/Core/ImageFormats/PngReader.h"
-#include "JpegWriter.h"
+#include "../Orthanc/Core/Images/ImageProcessing.h"
+#include "../Orthanc/Core/Images/ImageBuffer.h"
 #include "ViewerToolbox.h"
 
 #include <gdcmImageReader.h>
@@ -48,8 +46,7 @@
     std::auto_ptr<gdcm::ImageChangePhotometricInterpretation> photometric_;
     std::auto_ptr<gdcm::ImageChangePlanarConfiguration> interleaved_;
     std::string decoded_;
-    Orthanc::PngReader png_;
-    bool insidePng_;
+    std::auto_ptr<ImageReader> png_;
     bool isDecoded_;
 
     bool DecodeUsingGdcm()
@@ -151,8 +148,7 @@
       {
         try
         {
-          png_.ReadFromMemory(png);
-          insidePng_ = true;
+          png_.reset(new ImageReader(context_, png, OrthancPluginImageFormat_Png));
           return true;
         }
         catch (Orthanc::OrthancException&)
@@ -198,12 +194,17 @@
           const std::string& instanceId) : 
       context_(context),
       instanceId_(instanceId),
-      insidePng_(false),
       isDecoded_(false)
     {
     }
 
 
+    OrthancPluginContext* GetContext()
+    {
+      return context_;
+    }
+
+
     const gdcm::DataSet& GetDataSet() const
     {
       return reader_.GetFile().GetDataSet();
@@ -235,7 +236,8 @@
       reader_.SetStream(stream);
       if (!reader_.Read())
       {
-        throw Orthanc::OrthancException("GDCM cannot extract an image from this DICOM instance");
+        OrthancPluginLogError(context_, "GDCM cannot extract an image from this DICOM instance");
+        throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageFormat);
       }
     }
 
@@ -247,10 +249,10 @@
         return false;
       }
 
-      if (insidePng_)
+      if (png_.get() != NULL)
       {
         // The image was decoded using Orthanc's built-in REST API
-        accessor = png_;
+        accessor = png_->GetAccessor();
         return true;
       }
 
@@ -527,10 +529,7 @@
     result["sizeInBytes"] = converted.GetSize();
 
     std::string z;
-    if (!CompressUsingDeflate(z, converted.GetConstBuffer(), converted.GetSize(), compressionLevel))
-    {
-      return false;
-    }
+    CompressUsingDeflate(z, pimpl_->GetContext(), converted.GetConstBuffer(), converted.GetSize());
 
     result["Orthanc"]["PixelData"] = base64_encode(z);  
 
@@ -597,9 +596,8 @@
     result["sizeInBytes"] = converted.GetSize();
 
     std::string jpeg;
-    OrthancPlugins::JpegWriter writer;
-    writer.SetQuality(quality);
-    writer.WriteToMemory(jpeg, converted);
+    WriteJpegToMemory(jpeg, pimpl_->GetContext(), converted, quality);
+
     result["Orthanc"]["PixelData"] = base64_encode(jpeg);  
     return true;
   }
--- a/Plugin/ParsedDicomImage.h	Fri Sep 25 11:29:17 2015 +0200
+++ b/Plugin/ParsedDicomImage.h	Fri Sep 25 12:32:37 2015 +0200
@@ -20,7 +20,7 @@
 
 #pragma once
 
-#include "../Orthanc/Core/ImageFormats/ImageAccessor.h"
+#include "../Orthanc/Core/Images/ImageAccessor.h"
 
 #include <orthanc/OrthancCPlugin.h>
 #include <stdint.h>
--- a/Plugin/Plugin.cpp	Fri Sep 25 11:29:17 2015 +0200
+++ b/Plugin/Plugin.cpp	Fri Sep 25 12:32:37 2015 +0200
@@ -84,7 +84,6 @@
       if (obj.get() != NULL)
       {
         const std::string& instanceId = dynamic_cast<DynamicString&>(*obj).GetValue();
-        printf("[%s]\n", instanceId.c_str());
 
         // On the reception of a new instance, precompute its spatial position
         cache->GetScheduler().Prefetch(OrthancPlugins::CacheBundle_InstanceInformation, instanceId);
--- a/Plugin/SeriesInformationAdapter.cpp	Fri Sep 25 11:29:17 2015 +0200
+++ b/Plugin/SeriesInformationAdapter.cpp	Fri Sep 25 12:32:37 2015 +0200
@@ -61,7 +61,8 @@
 
       if (!cache_.Access(tmp, CacheBundle_InstanceInformation, instanceId))
       {
-        throw Orthanc::OrthancException("The cache is corrupted. Delete it to reconstruct it.");
+        OrthancPluginLogError(context_, "The cache is corrupted. Delete it to reconstruct it.");
+        throw Orthanc::OrthancException(Orthanc::ErrorCode_CorruptedFile);
       }
 
       InstanceInformation instance(tmp);
--- a/Plugin/ViewerToolbox.cpp	Fri Sep 25 11:29:17 2015 +0200
+++ b/Plugin/ViewerToolbox.cpp	Fri Sep 25 12:32:37 2015 +0200
@@ -24,7 +24,6 @@
 #include "../Orthanc/Core/Toolbox.h"
 
 #include <json/reader.h>
-#include <zlib.h>
 #include <stdexcept>
 #include <boost/lexical_cast.hpp>
 #include <sys/stat.h>
@@ -51,7 +50,7 @@
       catch (std::bad_alloc&)
       {
         OrthancPluginFreeMemoryBuffer(context, &answer);
-        throw Orthanc::OrthancException("Not enough memory");
+        throw Orthanc::OrthancException(Orthanc::ErrorCode_NotEnoughMemory);
       }
     }
 
@@ -127,41 +126,35 @@
   }
 
 
-  bool CompressUsingDeflate(std::string& compressed,
+  void CompressUsingDeflate(std::string& compressed,
+                            OrthancPluginContext* context,
                             const void* uncompressed,
-                            size_t uncompressedSize,
-                            uint8_t compressionLevel)
+                            size_t uncompressedSize)
   {
-    if (uncompressedSize == 0)
+    OrthancPluginMemoryBuffer tmp;
+   
+    OrthancPluginErrorCode code = OrthancPluginBufferCompression(
+      context, &tmp, uncompressed, uncompressedSize, 
+      OrthancPluginCompressionType_Zlib, 0 /*compress*/);
+      
+    if (code != OrthancPluginErrorCode_Success)
     {
-      compressed.clear();
-      return true;
+      throw Orthanc::OrthancException(static_cast<Orthanc::ErrorCode>(code));
     }
 
-    uLongf compressedSize = compressBound(uncompressedSize);
-    compressed.resize(compressedSize);
-
-    int error = compress2
-      (reinterpret_cast<uint8_t*>(&compressed[0]),
-       &compressedSize,
-       const_cast<Bytef *>(static_cast<const Bytef *>(uncompressed)), 
-       uncompressedSize,
-       compressionLevel);
+    try
+    {
+      compressed.assign(reinterpret_cast<const char*>(tmp.data), tmp.size);
+    }
+    catch (...)
+    {
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_NotEnoughMemory);
+    }
 
-    if (error == Z_OK)
-    {
-      compressed.resize(compressedSize);
-      return true;
-    }
-    else
-    {
-      compressed.clear();
-      return false;
-    }
+    OrthancPluginFreeMemoryBuffer(context, &tmp);
   }
 
 
-
   const char* GetMimeType(const std::string& path)
   {
     size_t dot = path.find_last_of('.');
@@ -276,50 +269,116 @@
   }
 
 
-  bool ReadFile(std::string& content,
-                const std::string& path)
+  OrthancPluginPixelFormat Convert(Orthanc::PixelFormat format)
   {
-    struct stat s;
-    if (stat(path.c_str(), &s) != 0 ||
-        !(s.st_mode & S_IFREG))
+    switch (format)
+    {
+      case Orthanc::PixelFormat_Grayscale16:
+        return OrthancPluginPixelFormat_Grayscale16;
+
+      case Orthanc::PixelFormat_Grayscale8:
+        return OrthancPluginPixelFormat_Grayscale8;
+
+      case Orthanc::PixelFormat_RGB24:
+        return OrthancPluginPixelFormat_RGB24;
+
+      case Orthanc::PixelFormat_RGBA32:
+        return OrthancPluginPixelFormat_RGBA32;
+
+      case Orthanc::PixelFormat_SignedGrayscale16:
+        return OrthancPluginPixelFormat_SignedGrayscale16;
+
+      default:
+        throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
+    }
+  }
+
+
+  Orthanc::PixelFormat Convert(OrthancPluginPixelFormat format)
+  {
+    switch (format)
     {
-      // Either the path does not exist, or it is not a regular file
-      return false;
-    }
+      case OrthancPluginPixelFormat_Grayscale16:
+        return Orthanc::PixelFormat_Grayscale16;
+
+      case OrthancPluginPixelFormat_Grayscale8:
+        return Orthanc::PixelFormat_Grayscale8;
+
+      case OrthancPluginPixelFormat_RGB24:
+        return Orthanc::PixelFormat_RGB24;
+
+      case OrthancPluginPixelFormat_RGBA32:
+        return Orthanc::PixelFormat_RGBA32;
+
+      case OrthancPluginPixelFormat_SignedGrayscale16:
+        return Orthanc::PixelFormat_SignedGrayscale16;
 
-    FILE* fp = fopen(path.c_str(), "rb");
-    if (fp == NULL)
+      default:
+        throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
+    }
+  }
+
+
+  void WriteJpegToMemory(std::string& result,
+                         OrthancPluginContext* context,
+                         const Orthanc::ImageAccessor& accessor,
+                         uint8_t quality)
+  {
+    OrthancPluginMemoryBuffer tmp;
+   
+    OrthancPluginErrorCode code = OrthancPluginCompressJpegImage
+      (context, &tmp, Convert(accessor.GetFormat()), 
+       accessor.GetWidth(), accessor.GetHeight(), accessor.GetPitch(),
+       accessor.GetBuffer(), quality);
+
+    if (code != OrthancPluginErrorCode_Success)
     {
-      return false;
+      throw Orthanc::OrthancException(static_cast<Orthanc::ErrorCode>(code));
     }
 
-    long size;
-
-    if (fseek(fp, 0, SEEK_END) == -1 ||
-        (size = ftell(fp)) < 0)
+    try
     {
-      fclose(fp);
-      return false;
+      result.assign(reinterpret_cast<const char*>(tmp.data), tmp.size);
+    }
+    catch (...)
+    {
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_NotEnoughMemory);
     }
 
-    content.resize(size);
-      
-    if (fseek(fp, 0, SEEK_SET) == -1)
+    OrthancPluginFreeMemoryBuffer(context, &tmp);
+  }
+
+
+
+  ImageReader::ImageReader(OrthancPluginContext* context,
+                           const std::string& image,
+                           OrthancPluginImageFormat format) : context_(context)
+  {
+    image_ = OrthancPluginUncompressImage(context_, image.c_str(), image.size(), format);
+
+    if (image_ == NULL)
     {
-      fclose(fp);
-      return false;
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_CorruptedFile);
     }
+  }
 
-    bool ok = true;
 
-    if (size > 0 &&
-        fread(&content[0], size, 1, fp) != 1)
-    {
-      ok = false;
-    }
+  ImageReader::~ImageReader()
+  {
+    OrthancPluginFreeImage(context_, image_);
+  }
+
 
-    fclose(fp);
+  Orthanc::ImageAccessor ImageReader::GetAccessor() const
+  {
+    Orthanc::ImageAccessor accessor;
 
-    return ok;
+    accessor.AssignReadOnly(Convert(OrthancPluginGetImagePixelFormat(context_, image_)),
+                            OrthancPluginGetImageWidth(context_, image_),
+                            OrthancPluginGetImageHeight(context_, image_),
+                            OrthancPluginGetImagePitch(context_, image_),
+                            OrthancPluginGetImageBuffer(context_, image_));
+
+    return accessor;
   }
 }
--- a/Plugin/ViewerToolbox.h	Fri Sep 25 11:29:17 2015 +0200
+++ b/Plugin/ViewerToolbox.h	Fri Sep 25 12:32:37 2015 +0200
@@ -24,6 +24,8 @@
 #include <json/value.h>
 #include <orthanc/OrthancCPlugin.h>
 
+#include "../Orthanc/Core/Images/ImageAccessor.h"
+
 namespace OrthancPlugins
 {
   enum CacheBundle
@@ -45,10 +47,10 @@
                       const std::string& value,
                       unsigned int expectedSize);
 
-  bool CompressUsingDeflate(std::string& compressed,
+  void CompressUsingDeflate(std::string& compressed,
+                            OrthancPluginContext* context,
                             const void* uncompressed,
-                            size_t uncompressedSize,
-                            uint8_t compressionLevel);
+                            size_t uncompressedSize);
 
   const char* GetMimeType(const std::string& path);
 
@@ -63,6 +65,30 @@
                       const std::string& key,
                       int defaultValue);
 
-  bool ReadFile(std::string& content,
-                const std::string& path);
+
+
+  OrthancPluginPixelFormat Convert(Orthanc::PixelFormat format);
+
+  Orthanc::PixelFormat Convert(OrthancPluginPixelFormat format);
+
+  void WriteJpegToMemory(std::string& result,
+                         OrthancPluginContext* context,
+                         const Orthanc::ImageAccessor& accessor,
+                         uint8_t quality);
+ 
+  class ImageReader
+  {
+  private:
+    OrthancPluginContext* context_;
+    OrthancPluginImage*   image_;
+
+  public:
+    ImageReader(OrthancPluginContext* context,
+                const std::string& image,
+                OrthancPluginImageFormat format);
+
+    ~ImageReader();
+
+    Orthanc::ImageAccessor GetAccessor() const;
+  };
 }
--- a/Resources/SyncOrthancFolder.py	Fri Sep 25 11:29:17 2015 +0200
+++ b/Resources/SyncOrthancFolder.py	Fri Sep 25 12:32:37 2015 +0200
@@ -56,11 +56,8 @@
     'Core/Toolbox.h',
     'Core/Uuid.cpp',
     'Core/Uuid.h',
+    'Plugins/Samples/Common/ExportedSymbols.list',
     'Plugins/Samples/Common/VersionScript.map',
-    'Resources/EmbedResources.py',
-    'Resources/MinGWToolchain.cmake',
-    'Resources/MinGW-W64-Toolchain32.cmake',
-    'Resources/MinGW-W64-Toolchain64.cmake',
     'Resources/CMake/AutoGeneratedCode.cmake',
     'Resources/CMake/BoostConfiguration.cmake',
     'Resources/CMake/Compiler.cmake',
@@ -68,9 +65,13 @@
     'Resources/CMake/GoogleTestConfiguration.cmake',
     'Resources/CMake/JsonCppConfiguration.cmake',
     'Resources/CMake/SQLiteConfiguration.cmake',
-    'Resources/ThirdParty/base64/base64.h',
+    'Resources/EmbedResources.py',
+    'Resources/MinGW-W64-Toolchain32.cmake',
+    'Resources/MinGW-W64-Toolchain64.cmake',
+    'Resources/MinGWToolchain.cmake',
+    'Resources/ThirdParty/VisualStudio/stdint.h',
     'Resources/ThirdParty/base64/base64.cpp',
-    'Resources/ThirdParty/VisualStudio/stdint.h',
+    'Resources/ThirdParty/base64/base64.h',
     'Resources/WindowsResources.py',
     'Resources/WindowsResources.rc',
 ]
--- a/UnitTestsSources/UnitTestsMain.cpp	Fri Sep 25 11:29:17 2015 +0200
+++ b/UnitTestsSources/UnitTestsMain.cpp	Fri Sep 25 12:32:37 2015 +0200
@@ -26,13 +26,10 @@
 
 #include "../Orthanc/Core/OrthancException.h"
 #include "../Orthanc/Core/Toolbox.h"
-#include "../Orthanc/Core/ImageFormats/ImageBuffer.h"
-#include "../Orthanc/Core/ImageFormats/PngWriter.h"
 #include "../Plugin/Cache/CacheManager.h"
 #include "../Plugin/Cache/CacheScheduler.h"
 #include "../Plugin/Cache/ICacheFactory.h"
 #include "../Plugin/Cache/ICacheFactory.h"
-#include "../Plugin/JpegWriter.h"
 
 using namespace OrthancPlugins;
 
@@ -189,29 +186,6 @@
 
 
 
-TEST(JpegWriter, Basic)
-{
-  Orthanc::ImageBuffer img(16, 16, Orthanc::PixelFormat_Grayscale8);
-  Orthanc::ImageAccessor accessor = img.GetAccessor();
-  for (unsigned int y = 0, value = 0; y < img.GetHeight(); y++)
-  {
-    uint8_t* p = reinterpret_cast<uint8_t*>(accessor.GetRow(y));
-    for (unsigned int x = 0; x < img.GetWidth(); x++, p++)
-    {
-      *p = value++;
-    }
-  }
-
-  JpegWriter w;
-  w.WriteToFile("UnitTestsResults/hello.jpg", accessor);
-
-  std::string s;
-  w.WriteToMemory(s, accessor);
-  Orthanc::Toolbox::WriteFile(s, "UnitTestsResults/hello2.jpg");
-}
-
-
-
 int main(int argc, char **argv)
 {
   argc_ = argc;