changeset 1834:b1a6f49b21dd

GDCM decoder sample
author Sebastien Jodogne <s.jodogne@gmail.com>
date Fri, 27 Nov 2015 12:53:32 +0100
parents 47d032c48818
children 323dd6402933
files Plugins/Samples/GdcmDecoder/CMakeLists.txt Plugins/Samples/GdcmDecoder/GdcmDecoderCache.cpp Plugins/Samples/GdcmDecoder/GdcmDecoderCache.h Plugins/Samples/GdcmDecoder/GdcmImageDecoder.cpp Plugins/Samples/GdcmDecoder/GdcmImageDecoder.h Plugins/Samples/GdcmDecoder/OrthancImageWrapper.cpp Plugins/Samples/GdcmDecoder/OrthancImageWrapper.h Plugins/Samples/GdcmDecoder/Plugin.cpp
diffstat 8 files changed, 783 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Samples/GdcmDecoder/CMakeLists.txt	Fri Nov 27 12:53:32 2015 +0100
@@ -0,0 +1,32 @@
+cmake_minimum_required(VERSION 2.8)
+
+project(GdcmDecoder)
+
+SET(GDCM_DECODER_VERSION "0.0" CACHE STRING "Version of the plugin")
+SET(STATIC_BUILD OFF CACHE BOOL "Static build of the third-party libraries (necessary for Windows)")
+SET(ALLOW_DOWNLOADS OFF CACHE BOOL "Allow CMake to download packages")
+SET(USE_SYSTEM_BOOST ON CACHE BOOL "Use the system version of boost")
+
+set(SAMPLES_ROOT ${CMAKE_SOURCE_DIR}/..)
+include(${SAMPLES_ROOT}/Common/OrthancPlugins.cmake)
+include(${ORTHANC_ROOT}/Resources/CMake/BoostConfiguration.cmake)
+
+find_package(GDCM REQUIRED)
+if (GDCM_FOUND)
+  include(${GDCM_USE_FILE})
+  set(GDCM_LIBRARIES gdcmCommon gdcmMSFF)
+else(GDCM_FOUND)
+  message(FATAL_ERROR "Cannot find GDCM, did you set GDCM_DIR?")
+endif(GDCM_FOUND)
+
+add_definitions(-DGDCM_DECODER_VERSION="${GDCM_DECODER_VERSION}")
+
+add_library(GdcmDecoder SHARED
+  ${BOOST_SOURCES}
+  GdcmDecoderCache.cpp
+  GdcmImageDecoder.cpp
+  OrthancImageWrapper.cpp
+  Plugin.cpp
+  )
+
+target_link_libraries(GdcmDecoder ${GDCM_LIBRARIES})
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Samples/GdcmDecoder/GdcmDecoderCache.cpp	Fri Nov 27 12:53:32 2015 +0100
@@ -0,0 +1,98 @@
+/**
+ * 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 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
+ * 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 "GdcmDecoderCache.h"
+
+#include "OrthancImageWrapper.h"
+
+namespace OrthancPlugins
+{
+  std::string GdcmDecoderCache::ComputeMd5(OrthancPluginContext* context,
+                                           const void* dicom,
+                                           size_t size)
+  {
+    std::string result;
+
+    char* md5 = OrthancPluginComputeMd5(context, dicom, size);
+
+    if (md5 == NULL)
+    {
+      throw std::runtime_error("Cannot compute MD5 hash");
+    }
+
+    bool ok = false;
+    try
+    {
+      result.assign(md5);
+      ok = true;
+    }
+    catch (...)
+    {
+    }
+
+    OrthancPluginFreeString(context, md5);
+
+    if (!ok)
+    {
+      throw std::runtime_error("Not enough memory");
+    }
+    else
+    {    
+      return result;
+    }
+  }
+
+
+  OrthancPluginImage* GdcmDecoderCache::Decode(OrthancPluginContext* context,
+                                               const void* dicom,
+                                               const uint32_t size,
+                                               uint32_t frameIndex)
+  {
+    std::string md5 = ComputeMd5(context, dicom, size);
+
+    // First check whether the previously decoded image is the same
+    // as this one
+    {
+      boost::mutex::scoped_lock lock(mutex_);
+
+      if (decoder_.get() != NULL &&
+          size_ == size &&
+          md5_ == md5)
+      {
+        // This is the same image: Reuse the previous decoding
+        return decoder_->Decode(context, frameIndex);
+      }
+    }
+
+    // This is not the same image
+    std::auto_ptr<GdcmImageDecoder> decoder(new GdcmImageDecoder(dicom, size));
+    OrthancImageWrapper image(context, decoder->Decode(context, frameIndex));
+
+    {
+      // Cache the newly created decoder for further use
+      boost::mutex::scoped_lock lock(mutex_);
+      decoder_ = decoder;
+      size_ = size;
+      md5_ = md5;
+    }
+
+    return image.Release();
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Samples/GdcmDecoder/GdcmDecoderCache.h	Fri Nov 27 12:53:32 2015 +0100
@@ -0,0 +1,52 @@
+/**
+ * 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 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
+ * 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 "GdcmImageDecoder.h"
+
+#include <boost/thread.hpp>
+
+
+namespace OrthancPlugins
+{
+  class GdcmDecoderCache : public boost::noncopyable
+  {
+  private:
+    boost::mutex   mutex_;
+    std::auto_ptr<OrthancPlugins::GdcmImageDecoder>  decoder_;
+    size_t       size_;
+    std::string  md5_;
+
+    static std::string ComputeMd5(OrthancPluginContext* context,
+                                  const void* dicom,
+                                  size_t size);
+
+  public:
+    GdcmDecoderCache() : size_(0)
+    {
+    }
+
+    OrthancPluginImage* Decode(OrthancPluginContext* context,
+                               const void* dicom,
+                               const uint32_t size,
+                               uint32_t frameIndex);
+  };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Samples/GdcmDecoder/GdcmImageDecoder.cpp	Fri Nov 27 12:53:32 2015 +0100
@@ -0,0 +1,300 @@
+/**
+ * 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 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
+ * 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 "GdcmImageDecoder.h"
+
+#include "OrthancImageWrapper.h"
+
+#include <gdcmImageReader.h>
+#include <gdcmImageApplyLookupTable.h>
+#include <gdcmImageChangePlanarConfiguration.h>
+#include <gdcmImageChangePhotometricInterpretation.h>
+#include <stdexcept>
+#include <boost/iostreams/stream.hpp>
+#include <boost/iostreams/device/array.hpp>
+
+
+namespace OrthancPlugins
+{
+  struct GdcmImageDecoder::PImpl
+  {
+    const void*           dicom_;
+    size_t                size_;
+
+    gdcm::ImageReader reader_;
+    std::auto_ptr<gdcm::ImageApplyLookupTable> lut_;
+    std::auto_ptr<gdcm::ImageChangePhotometricInterpretation> photometric_;
+    std::auto_ptr<gdcm::ImageChangePlanarConfiguration> interleaved_;
+    std::string decoded_;
+
+    PImpl(const void* dicom,
+          size_t size) :
+      dicom_(dicom),
+      size_(size)
+    {
+    }
+
+
+    const gdcm::DataSet& GetDataSet() const
+    {
+      return reader_.GetFile().GetDataSet();
+    }
+
+
+    const gdcm::Image& GetImage() const
+    {
+      if (interleaved_.get() != NULL)
+      {
+        return interleaved_->GetOutput();
+      }
+
+      if (lut_.get() != NULL)
+      {
+        return lut_->GetOutput();
+      }
+
+      if (photometric_.get() != NULL)
+      {
+        return photometric_->GetOutput();
+      }
+
+      return reader_.GetImage();
+    }
+
+
+    void Decode()
+    {
+      // Change photometric interpretation or apply LUT, if required
+      {
+        const gdcm::Image& image = GetImage();
+        if (image.GetPixelFormat().GetSamplesPerPixel() == 1 &&
+            image.GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::PALETTE_COLOR)
+        {
+          lut_.reset(new gdcm::ImageApplyLookupTable());
+          lut_->SetInput(image);
+          if (!lut_->Apply())
+          {
+            throw std::runtime_error( "GDCM cannot apply the lookup table");
+          }
+        }
+        else if (image.GetPixelFormat().GetSamplesPerPixel() == 1)
+        {
+          if (image.GetPhotometricInterpretation() != gdcm::PhotometricInterpretation::MONOCHROME1 &&
+              image.GetPhotometricInterpretation() != gdcm::PhotometricInterpretation::MONOCHROME2)
+          {
+            photometric_.reset(new gdcm::ImageChangePhotometricInterpretation());
+            photometric_->SetInput(image);
+            photometric_->SetPhotometricInterpretation(gdcm::PhotometricInterpretation::MONOCHROME2);
+            if (!photometric_->Change() ||
+                GetImage().GetPhotometricInterpretation() != gdcm::PhotometricInterpretation::MONOCHROME2)
+            {
+              throw std::runtime_error("GDCM cannot change the photometric interpretation");
+            }
+          }      
+        }
+        else 
+        {
+          if (image.GetPixelFormat().GetSamplesPerPixel() == 3 &&
+              image.GetPhotometricInterpretation() != gdcm::PhotometricInterpretation::RGB)
+          {
+            photometric_.reset(new gdcm::ImageChangePhotometricInterpretation());
+            photometric_->SetInput(image);
+            photometric_->SetPhotometricInterpretation(gdcm::PhotometricInterpretation::RGB);
+            if (!photometric_->Change() ||
+                GetImage().GetPhotometricInterpretation() != gdcm::PhotometricInterpretation::RGB)
+            {
+              throw std::runtime_error("GDCM cannot change the photometric interpretation");
+            }
+          }
+        }
+      }
+
+      // Possibly convert planar configuration to interleaved
+      {
+        const gdcm::Image& image = GetImage();
+        if (image.GetPlanarConfiguration() != 0 && 
+            image.GetPixelFormat().GetSamplesPerPixel() != 1)
+        {
+          interleaved_.reset(new gdcm::ImageChangePlanarConfiguration());
+          interleaved_->SetInput(image);
+          if (!interleaved_->Change() ||
+              GetImage().GetPlanarConfiguration() != 0)
+          {
+            throw std::runtime_error("GDCM cannot change the planar configuration to interleaved");
+          }
+        }
+      }
+    }
+  };
+
+  GdcmImageDecoder::GdcmImageDecoder(const void* dicom,
+                                     size_t size) :
+    pimpl_(new PImpl(dicom, size))
+  {
+    // Setup a stream to the memory buffer
+    using namespace boost::iostreams;
+    basic_array_source<char> source(reinterpret_cast<const char*>(dicom), size);
+    stream<basic_array_source<char> > stream(source);
+
+    // Parse the DICOM instance using GDCM
+    pimpl_->reader_.SetStream(stream);
+    if (!pimpl_->reader_.Read())
+    {
+      throw std::runtime_error("Bad file format");
+    }
+
+    pimpl_->Decode();
+  }
+
+
+  OrthancPluginPixelFormat GdcmImageDecoder::GetFormat() const
+  {
+    const gdcm::Image& image = pimpl_->GetImage();
+
+    if (image.GetPixelFormat().GetSamplesPerPixel() == 1 &&
+        (image.GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::MONOCHROME1 ||
+         image.GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::MONOCHROME2))
+    {
+      switch (image.GetPixelFormat())
+      {
+        case gdcm::PixelFormat::UINT16:
+          return OrthancPluginPixelFormat_Grayscale16;
+
+        case gdcm::PixelFormat::INT16:
+          return OrthancPluginPixelFormat_SignedGrayscale16;
+
+        case gdcm::PixelFormat::UINT8:
+          return OrthancPluginPixelFormat_Grayscale8;
+
+        default:
+          throw std::runtime_error("Unsupported pixel format");
+      }
+    }
+    else if (image.GetPixelFormat().GetSamplesPerPixel() == 3 &&
+             image.GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::RGB)
+    {
+      switch (image.GetPixelFormat())
+      {
+        case gdcm::PixelFormat::UINT8:
+          return OrthancPluginPixelFormat_RGB24;
+
+        default:
+          break;
+      }      
+    }
+
+    throw std::runtime_error("Unsupported pixel format");
+  }
+
+
+  unsigned int GdcmImageDecoder::GetWidth() const
+  {
+    return pimpl_->GetImage().GetColumns();
+  }
+
+
+  unsigned int GdcmImageDecoder::GetHeight() const
+  {
+    return pimpl_->GetImage().GetRows();
+  }
+
+  
+  unsigned int GdcmImageDecoder::GetFramesCount() const
+  {
+    return pimpl_->GetImage().GetDimension(2);
+  }
+
+
+  size_t GdcmImageDecoder::GetBytesPerPixel(OrthancPluginPixelFormat format)
+  {
+    switch (format)
+    {
+      case OrthancPluginPixelFormat_Grayscale8:
+        return 1;
+
+      case OrthancPluginPixelFormat_Grayscale16:
+      case OrthancPluginPixelFormat_SignedGrayscale16:
+        return 2;
+
+      case OrthancPluginPixelFormat_RGB24:
+        return 3;
+
+      default:
+        throw std::runtime_error("Unsupport pixel format");
+    }
+  }
+
+
+  OrthancPluginImage* GdcmImageDecoder::Decode(OrthancPluginContext* context,
+                                               unsigned int frameIndex) const
+  {
+    unsigned int frames = GetFramesCount();
+    unsigned int width = GetWidth();
+    unsigned int height = GetHeight();
+    OrthancPluginPixelFormat format = GetFormat();
+    size_t bpp = GetBytesPerPixel(format);
+
+    if (frameIndex >= frames)
+    {
+      throw std::runtime_error("Inexistent frame index");
+    }
+
+    std::string& decoded = pimpl_->decoded_;
+    OrthancImageWrapper target(context, format, width, height);
+
+    if (width == 0 ||
+        height == 0)
+    {
+      return target.Release();
+    }
+
+    if (decoded.empty())
+    {
+      decoded.resize(pimpl_->GetImage().GetBufferLength());
+      pimpl_->GetImage().GetBuffer(&decoded[0]);
+    }
+
+    const void* sourceBuffer = &decoded[0];
+
+    if (target.GetPitch() == bpp * width &&
+        frames == 1)
+    {
+      assert(decoded.size() == target.GetPitch() * target.GetHeight());      
+      memcpy(target.GetBuffer(), sourceBuffer, decoded.size());
+    }
+    else 
+    {
+      size_t targetPitch = target.GetPitch();
+      size_t sourcePitch = width * bpp;
+
+      const char* a = &decoded[sourcePitch * height * frameIndex];
+      char* b = target.GetBuffer();
+
+      for (uint32_t y = 0; y < height; y++)
+      {
+        memcpy(b, a, sourcePitch);
+        a += sourcePitch;
+        b += targetPitch;
+      }
+    }
+
+    return target.Release();
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Samples/GdcmDecoder/GdcmImageDecoder.h	Fri Nov 27 12:53:32 2015 +0100
@@ -0,0 +1,53 @@
+/**
+ * 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 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
+ * 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 <orthanc/OrthancCPlugin.h>
+#include <stdint.h>
+#include <boost/noncopyable.hpp>
+#include <boost/shared_ptr.hpp>
+
+namespace OrthancPlugins
+{
+  class GdcmImageDecoder : public boost::noncopyable
+  {
+  private:
+    struct PImpl;
+    boost::shared_ptr<PImpl> pimpl_;
+  
+  public:
+    GdcmImageDecoder(const void* dicom,
+                     size_t size);
+
+    OrthancPluginPixelFormat GetFormat() const;
+
+    unsigned int GetWidth() const;
+
+    unsigned int GetHeight() const;
+
+    unsigned int GetFramesCount() const;
+
+    static size_t GetBytesPerPixel(OrthancPluginPixelFormat format);
+
+    OrthancPluginImage* Decode(OrthancPluginContext* context,
+                               unsigned int frameIndex) const;
+  };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Samples/GdcmDecoder/OrthancImageWrapper.cpp	Fri Nov 27 12:53:32 2015 +0100
@@ -0,0 +1,86 @@
+/**
+ * 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 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
+ * 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 "OrthancImageWrapper.h"
+
+#include <stdexcept>
+
+namespace OrthancPlugins
+{
+  OrthancImageWrapper::OrthancImageWrapper(OrthancPluginContext* context,
+                                           OrthancPluginPixelFormat format,
+                                           uint32_t width,
+                                           uint32_t height) :
+    context_(context)
+  {
+    image_ = OrthancPluginCreateImage(context_, format, width, height);
+    if (image_ == NULL)
+    {
+      throw std::runtime_error("Cannot create an image");
+    }
+  }
+
+
+  OrthancImageWrapper::~OrthancImageWrapper()
+  {
+    if (image_ != NULL)
+    {
+      OrthancPluginFreeImage(context_, image_);
+    }
+  }
+
+
+  OrthancPluginImage* OrthancImageWrapper::Release()
+  {
+    OrthancPluginImage* tmp = image_;
+    image_ = NULL;
+    return tmp;
+  }
+
+
+  uint32_t OrthancImageWrapper::GetWidth()
+  {
+    return OrthancPluginGetImageWidth(context_, image_);
+  }
+
+
+  uint32_t OrthancImageWrapper::GetHeight()
+  {
+    return OrthancPluginGetImageHeight(context_, image_);
+  }
+
+
+  uint32_t OrthancImageWrapper::GetPitch()
+  {
+    return OrthancPluginGetImagePitch(context_, image_);
+  }
+
+
+  OrthancPluginPixelFormat OrthancImageWrapper::GetFormat()
+  {
+    return OrthancPluginGetImagePixelFormat(context_, image_);
+  }
+
+
+  char* OrthancImageWrapper::GetBuffer()
+  {
+    return reinterpret_cast<char*>(OrthancPluginGetImageBuffer(context_, image_));
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Samples/GdcmDecoder/OrthancImageWrapper.h	Fri Nov 27 12:53:32 2015 +0100
@@ -0,0 +1,61 @@
+/**
+ * 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 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
+ * 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 <orthanc/OrthancCPlugin.h>
+
+namespace OrthancPlugins
+{
+  class OrthancImageWrapper
+  {
+  private:
+    OrthancPluginContext*  context_;
+    OrthancPluginImage*    image_;
+
+  public:
+    OrthancImageWrapper(OrthancPluginContext* context,
+                        OrthancPluginPixelFormat format,
+                        uint32_t width,
+                        uint32_t height);
+
+    // Takes the ownership
+    OrthancImageWrapper(OrthancPluginContext* context,
+                        OrthancPluginImage* image) :
+      context_(context),
+      image_(image)
+    {
+    }
+
+    ~OrthancImageWrapper();
+
+    OrthancPluginImage* Release();
+
+    uint32_t GetWidth();
+
+    uint32_t GetHeight();
+
+    uint32_t GetPitch();
+
+    OrthancPluginPixelFormat GetFormat();
+
+    char* GetBuffer();
+  };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Samples/GdcmDecoder/Plugin.cpp	Fri Nov 27 12:53:32 2015 +0100
@@ -0,0 +1,101 @@
+/**
+ * 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 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
+ * 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 "GdcmDecoderCache.h"
+
+#include <orthanc/OrthancCPlugin.h>
+
+static OrthancPluginContext* context_ = NULL;
+static OrthancPlugins::GdcmDecoderCache  cache_;
+
+
+static OrthancPluginErrorCode DecodeImageCallback(OrthancPluginImage** target,
+                                                  const void* dicom,
+                                                  const uint32_t size,
+                                                  uint32_t frameIndex)
+{
+  try
+  {
+#if 0
+    // Do not use the cache
+    OrthancPlugins::GdcmImageDecoder decoder(dicom, size);
+    *target = decoder.Decode(context_, frameIndex);
+#else
+    *target = cache_.Decode(context_, dicom, size, frameIndex);
+#endif
+
+    return OrthancPluginErrorCode_Success;
+  }
+  catch (std::runtime_error& e)
+  {
+    *target = NULL;
+
+    std::string s = "Cannot decode image using GDCM: " + std::string(e.what());
+    OrthancPluginLogError(context_, s.c_str());
+    return OrthancPluginErrorCode_Plugin;
+  }
+}
+
+
+
+extern "C"
+{
+  ORTHANC_PLUGINS_API int32_t OrthancPluginInitialize(OrthancPluginContext* context)
+  {
+    context_ = context;
+    OrthancPluginLogWarning(context_, "Initializing the advanced decoder of medical images using GDCM");
+
+
+    /* Check the version of the Orthanc core */
+    if (OrthancPluginCheckVersion(context_) == 0)
+    {
+      char info[1024];
+      sprintf(info, "Your version of Orthanc (%s) must be above %d.%d.%d to run this plugin",
+              context_->orthancVersion,
+              ORTHANC_PLUGINS_MINIMAL_MAJOR_NUMBER,
+              ORTHANC_PLUGINS_MINIMAL_MINOR_NUMBER,
+              ORTHANC_PLUGINS_MINIMAL_REVISION_NUMBER);
+      OrthancPluginLogError(context_, info);
+      return -1;
+    }
+
+    OrthancPluginSetDescription(context_, "Advanced decoder of medical images using GDCM.");
+    OrthancPluginRegisterDecodeImageCallback(context_, DecodeImageCallback);
+
+    return 0;
+  }
+
+
+  ORTHANC_PLUGINS_API void OrthancPluginFinalize()
+  {
+  }
+
+
+  ORTHANC_PLUGINS_API const char* OrthancPluginGetName()
+  {
+    return "gdcm-decoder";
+  }
+
+
+  ORTHANC_PLUGINS_API const char* OrthancPluginGetVersion()
+  {
+    return GDCM_DECODER_VERSION;
+  }
+}