changeset 1598:c6b50b803387

primitives for image encoding/decoding in plugins
author Sebastien Jodogne <s.jodogne@gmail.com>
date Mon, 31 Aug 2015 17:37:54 +0200
parents 415dfd1d1c61
children dd1f9e81f891
files NEWS Plugins/Engine/OrthancPlugins.cpp Plugins/Engine/OrthancPlugins.h Plugins/Include/orthanc/OrthancCPlugin.h
diffstat 4 files changed, 428 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/NEWS	Fri Aug 28 13:47:23 2015 +0200
+++ b/NEWS	Mon Aug 31 17:37:54 2015 +0200
@@ -20,6 +20,7 @@
 Plugins
 -------
 
+* New functions to compress/uncompress images using PNG and JPEG
 * New function "OrthancPluginBufferCompression()" to (un)compress memory buffers
 * New function "OrthancPluginReadFile()" to read files from the filesystem
 * New function "OrthancPluginWriteFile()" to write files to the filesystem
--- a/Plugins/Engine/OrthancPlugins.cpp	Fri Aug 28 13:47:23 2015 +0200
+++ b/Plugins/Engine/OrthancPlugins.cpp	Mon Aug 31 17:37:54 2015 +0200
@@ -43,6 +43,8 @@
 #include "../../OrthancServer/ServerToolbox.h"
 #include "../../Core/Compression/ZlibCompressor.h"
 #include "../../Core/Compression/GzipCompressor.h"
+#include "../../Core/ImageFormats/PngReader.h"
+#include "../../Core/ImageFormats/PngWriter.h"
 
 #include <boost/regex.hpp> 
 
@@ -110,6 +112,56 @@
   }
 
 
+  static OrthancPluginPixelFormat Convert(PixelFormat format)
+  {
+    switch (format)
+    {
+      case PixelFormat_Grayscale16:
+        return OrthancPluginPixelFormat_Grayscale16;
+
+      case PixelFormat_Grayscale8:
+        return OrthancPluginPixelFormat_Grayscale8;
+
+      case PixelFormat_RGB24:
+        return OrthancPluginPixelFormat_RGB24;
+
+      case PixelFormat_RGBA32:
+        return OrthancPluginPixelFormat_RGBA32;
+
+      case PixelFormat_SignedGrayscale16:
+        return OrthancPluginPixelFormat_SignedGrayscale16;
+
+      default:
+        throw OrthancException(ErrorCode_ParameterOutOfRange);
+    }
+  }
+
+
+  static PixelFormat Convert(OrthancPluginPixelFormat format)
+  {
+    switch (format)
+    {
+      case OrthancPluginPixelFormat_Grayscale16:
+        return PixelFormat_Grayscale16;
+
+      case OrthancPluginPixelFormat_Grayscale8:
+        return PixelFormat_Grayscale8;
+
+      case OrthancPluginPixelFormat_RGB24:
+        return PixelFormat_RGB24;
+
+      case OrthancPluginPixelFormat_RGBA32:
+        return PixelFormat_RGBA32;
+
+      case OrthancPluginPixelFormat_SignedGrayscale16:
+        return PixelFormat_SignedGrayscale16;
+
+      default:
+        throw OrthancException(ErrorCode_ParameterOutOfRange);
+    }
+  }
+
+
 
   struct OrthancPlugins::PImpl
   {
@@ -226,6 +278,7 @@
         sizeof(int32_t) != sizeof(OrthancPluginContentType) ||
         sizeof(int32_t) != sizeof(OrthancPluginResourceType) ||
         sizeof(int32_t) != sizeof(OrthancPluginChangeType) ||
+        sizeof(int32_t) != sizeof(OrthancPluginImageFormat) ||
         sizeof(int32_t) != sizeof(OrthancPluginCompressionType) ||
         sizeof(int32_t) != sizeof(_OrthancPluginDatabaseAnswerType))
     {
@@ -993,6 +1046,55 @@
   }
 
 
+  void OrthancPlugins::UncompressImage(const void* parameters)
+  {
+    const _OrthancPluginUncompressImage& p = reinterpret_cast<const _OrthancPluginUncompressImage&>(parameters);
+
+    switch (p.format)
+    {
+      case OrthancPluginImageFormat_Png:
+      {
+        std::auto_ptr<PngReader> image(new PngReader);
+        image->ReadFromMemory(p.data, p.size);
+        *(p.target) = reinterpret_cast<OrthancPluginImage*>(image.release());
+        return;
+      }
+
+      case OrthancPluginImageFormat_Jpeg:
+        // TODO
+
+      default:
+        throw OrthancException(ErrorCode_ParameterOutOfRange);
+    }
+  }
+
+
+  void OrthancPlugins::CompressImage(const void* parameters)
+  {
+    const _OrthancPluginCompressImage& p = reinterpret_cast<const _OrthancPluginCompressImage&>(parameters);
+
+    std::string compressed;
+
+    switch (p.imageFormat)
+    {
+      case OrthancPluginImageFormat_Png:
+      {
+        PngWriter writer;
+        writer.WriteToMemory(compressed, p.width, p.height, p.pitch, Convert(p.pixelFormat), p.buffer);
+        break;
+      }
+
+      case OrthancPluginImageFormat_Jpeg:
+        // TODO
+
+      default:
+        throw OrthancException(ErrorCode_ParameterOutOfRange);
+    }
+
+    CopyToMemoryBuffer(*p.target, compressed.size() > 0 ? compressed.c_str() : NULL, compressed.size());
+  }
+
+
   bool OrthancPlugins::InvokeService(_OrthancPluginService service,
                                      const void* parameters)
   {
@@ -1297,9 +1399,61 @@
         return true;
       }
 
+      case _OrthancPluginService_GetImagePixelFormat:
+      {
+        const _OrthancPluginGetImageInfo& p = reinterpret_cast<const _OrthancPluginGetImageInfo&>(parameters);
+        *(p.resultPixelFormat) = Convert(reinterpret_cast<const ImageAccessor*>(p.image)->GetFormat());
+        return true;
+      }
+
+      case _OrthancPluginService_GetImageWidth:
+      {
+        const _OrthancPluginGetImageInfo& p = reinterpret_cast<const _OrthancPluginGetImageInfo&>(parameters);
+        *(p.resultUint32) = reinterpret_cast<const ImageAccessor*>(p.image)->GetWidth();
+        return true;
+      }
+
+      case _OrthancPluginService_GetImageHeight:
+      {
+        const _OrthancPluginGetImageInfo& p = reinterpret_cast<const _OrthancPluginGetImageInfo&>(parameters);
+        *(p.resultUint32) = reinterpret_cast<const ImageAccessor*>(p.image)->GetHeight();
+        return true;
+      }
+
+      case _OrthancPluginService_GetImagePitch:
+      {
+        const _OrthancPluginGetImageInfo& p = reinterpret_cast<const _OrthancPluginGetImageInfo&>(parameters);
+        *(p.resultUint32) = reinterpret_cast<const ImageAccessor*>(p.image)->GetPitch();
+        return true;
+      }
+
+      case _OrthancPluginService_GetImageBuffer:
+      {
+        const _OrthancPluginGetImageInfo& p = reinterpret_cast<const _OrthancPluginGetImageInfo&>(parameters);
+        *(p.resultBuffer) = reinterpret_cast<const ImageAccessor*>(p.image)->GetBuffer();
+        return true;
+      }
+
+      case _OrthancPluginService_FreeImage:
+      {
+        const _OrthancPluginGetImageInfo& p = reinterpret_cast<const _OrthancPluginGetImageInfo&>(parameters);
+        delete reinterpret_cast<const ImageAccessor*>(p.image);
+        return true;
+      }
+
+      case _OrthancPluginService_UncompressImage:
+        UncompressImage(parameters);
+        return true;
+
+      case _OrthancPluginService_CompressImage:
+        CompressImage(parameters);
+        return true;
+
       default:
-        // This service is unknown by the Orthanc plugin engine
+      {
+        // This service is unknown to the Orthanc plugin engine
         return false;
+      }
     }
   }
 
--- a/Plugins/Engine/OrthancPlugins.h	Fri Aug 28 13:47:23 2015 +0200
+++ b/Plugins/Engine/OrthancPlugins.h	Mon Aug 31 17:37:54 2015 +0200
@@ -98,6 +98,10 @@
 
     void BufferCompression(const void* parameters);
 
+    void UncompressImage(const void* parameters);
+
+    void CompressImage(const void* parameters);
+
   public:
     OrthancPlugins();
 
--- a/Plugins/Include/orthanc/OrthancCPlugin.h	Fri Aug 28 13:47:23 2015 +0200
+++ b/Plugins/Include/orthanc/OrthancCPlugin.h	Mon Aug 31 17:37:54 2015 +0200
@@ -409,6 +409,16 @@
     _OrthancPluginService_RegisterDatabaseBackend = 5000,
     _OrthancPluginService_DatabaseAnswer = 5001,
 
+    /* Primitives for handling images */
+    _OrthancPluginService_GetImagePixelFormat = 6000,
+    _OrthancPluginService_GetImageWidth = 6001,
+    _OrthancPluginService_GetImageHeight = 6002,
+    _OrthancPluginService_GetImagePitch = 6003,
+    _OrthancPluginService_GetImageBuffer = 6004,
+    _OrthancPluginService_UncompressImage = 6005,
+    _OrthancPluginService_FreeImage = 6006,
+    _OrthancPluginService_CompressImage = 6007,
+
     _OrthancPluginService_INTERNAL = 0x7fffffff
   } _OrthancPluginService;
 
@@ -469,6 +479,8 @@
      **/
     OrthancPluginPixelFormat_RGBA32 = 5,
 
+    OrthancPluginPixelFormat_Unknown = 6,   /*!< Unknown pixel format */
+
     _OrthancPluginPixelFormat_INTERNAL = 0x7fffffff
   } OrthancPluginPixelFormat;
 
@@ -537,6 +549,15 @@
   } OrthancPluginCompressionType;
 
 
+  typedef enum
+  {
+    OrthancPluginImageFormat_Png = 0,   /*!< Image compressed using PNG */
+    OrthancPluginImageFormat_Jpeg = 1,  /*!< Image compressed using JPEG */
+
+    _OrthancPluginImageFormat_INTERNAL = 0x7fffffff
+  } OrthancPluginImageFormat;
+
+
 
   /**
    * @brief A memory buffer allocated by the core system of Orthanc.
@@ -576,6 +597,13 @@
 
 
   /**
+   * @brief Opaque structure that represents a uncompressed image in memory.
+   **/
+  typedef struct _OrthancPluginImage_t OrthancPluginImage;
+
+
+
+  /**
    * @brief Signature of a callback function that answers to a REST request.
    **/
   typedef int32_t (*OrthancPluginRestCallback) (
@@ -723,7 +751,8 @@
         sizeof(int32_t) != sizeof(OrthancPluginContentType) ||
         sizeof(int32_t) != sizeof(OrthancPluginResourceType) ||
         sizeof(int32_t) != sizeof(OrthancPluginChangeType) ||
-        sizeof(int32_t) != sizeof(OrthancPluginCompressionType))
+        sizeof(int32_t) != sizeof(OrthancPluginCompressionType) ||
+        sizeof(int32_t) != sizeof(OrthancPluginImageFormat))
     {
       /* Mismatch in the size of the enumerations */
       return 0;
@@ -2581,6 +2610,244 @@
   }
 
 
+
+  typedef struct
+  {
+    const OrthancPluginImage*  image;
+    uint32_t*                  resultUint32;
+    OrthancPluginPixelFormat*  resultPixelFormat;
+    const void**               resultBuffer;
+  } _OrthancPluginGetImageInfo;
+
+
+  ORTHANC_PLUGIN_INLINE OrthancPluginPixelFormat  OrthancPluginGetImagePixelFormat(
+    OrthancPluginContext*      context,
+    const OrthancPluginImage*  image)
+  {
+    OrthancPluginPixelFormat target;
+    
+    _OrthancPluginGetImageInfo params;
+    memset(&params, 0, sizeof(params));
+    params.image = image;
+    params.resultPixelFormat = &target;
+
+    if (context->InvokeService(context, _OrthancPluginService_GetImagePixelFormat, image) < 0)
+    {
+      return OrthancPluginPixelFormat_Unknown;
+    }
+    else
+    {
+      return static_cast<OrthancPluginPixelFormat>(target);
+    }
+  }
+
+
+
+  ORTHANC_PLUGIN_INLINE uint32_t  OrthancPluginGetImageWidth(
+    OrthancPluginContext*      context,
+    const OrthancPluginImage*  image)
+  {
+    uint32_t width;
+    
+    _OrthancPluginGetImageInfo params;
+    memset(&params, 0, sizeof(params));
+    params.image = image;
+    params.resultUint32 = &width;
+
+    if (context->InvokeService(context, _OrthancPluginService_GetImagePixelFormat, image) < 0)
+    {
+      return 0;
+    }
+    else
+    {
+      return width;
+    }
+  }
+
+
+
+  ORTHANC_PLUGIN_INLINE uint32_t  OrthancPluginGetImageHeight(
+    OrthancPluginContext*      context,
+    const OrthancPluginImage*  image)
+  {
+    uint32_t height;
+    
+    _OrthancPluginGetImageInfo params;
+    memset(&params, 0, sizeof(params));
+    params.image = image;
+    params.resultUint32 = &height;
+
+    if (context->InvokeService(context, _OrthancPluginService_GetImagePixelFormat, image) < 0)
+    {
+      return 0;
+    }
+    else
+    {
+      return height;
+    }
+  }
+
+
+
+  ORTHANC_PLUGIN_INLINE uint32_t  OrthancPluginGetImagePitch(
+    OrthancPluginContext*      context,
+    const OrthancPluginImage*  image)
+  {
+    uint32_t pitch;
+    
+    _OrthancPluginGetImageInfo params;
+    memset(&params, 0, sizeof(params));
+    params.image = image;
+    params.resultUint32 = &pitch;
+
+    if (context->InvokeService(context, _OrthancPluginService_GetImagePixelFormat, image) < 0)
+    {
+      return 0;
+    }
+    else
+    {
+      return pitch;
+    }
+  }
+
+
+
+  ORTHANC_PLUGIN_INLINE const void*  OrthancPluginGetImageBuffer(
+    OrthancPluginContext*      context,
+    const OrthancPluginImage*  image)
+  {
+    const void* target = NULL;
+
+    _OrthancPluginGetImageInfo params;
+    memset(&params, 0, sizeof(params));
+    params.resultBuffer = &target;
+    params.image = image;
+
+    if (context->InvokeService(context, _OrthancPluginService_GetImageBuffer, &params) < 0)
+    {
+      return NULL;
+    }
+    else
+    {
+      return target;
+    }
+  }
+
+
+  typedef struct
+  {
+    OrthancPluginImage**       target;
+    const void*                data;
+    uint32_t                   size;
+    OrthancPluginImageFormat   format;
+  } _OrthancPluginUncompressImage;
+
+  ORTHANC_PLUGIN_INLINE OrthancPluginImage *OrthancPluginUncompressImage(
+    OrthancPluginContext*      context,
+    const void*                data,
+    uint32_t                   size,
+    OrthancPluginImageFormat   format)
+  {
+    OrthancPluginImage* target = NULL;
+
+    _OrthancPluginUncompressImage params;
+    memset(&params, 0, sizeof(params));
+    params.target = &target;
+    params.data = data;
+    params.size = size;
+    params.format = format;
+
+    if (context->InvokeService(context, _OrthancPluginService_UncompressImage, &params) < 0)
+    {
+      return NULL;
+    }
+    else
+    {
+      return target;
+    }
+  }
+
+
+
+  ORTHANC_PLUGIN_INLINE void  OrthancPluginFreeImage(
+    OrthancPluginContext* context, 
+    OrthancPluginImage*   image)
+  {
+    _OrthancPluginGetImageInfo params;
+    memset(&params, 0, sizeof(params));
+    params.image = image;
+
+    context->InvokeService(context, _OrthancPluginService_FreeImage, &params);
+  }
+
+
+
+
+  typedef struct
+  {
+    OrthancPluginMemoryBuffer* target;
+    OrthancPluginImageFormat   imageFormat;
+    OrthancPluginPixelFormat   pixelFormat;
+    uint32_t                   width;
+    uint32_t                   height;
+    uint32_t                   pitch;
+    const void*                buffer;
+    uint32_t                   quality;
+  } _OrthancPluginCompressImage;
+
+
+
+  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginCompressPngImage(
+    OrthancPluginContext*         context,
+    OrthancPluginMemoryBuffer*    target,
+    OrthancPluginPixelFormat      pixelFormat,
+    uint32_t                      width,
+    uint32_t                      height,
+    uint32_t                      pitch,
+    const void*                   buffer,
+    uint32_t                      quality)
+  {
+    _OrthancPluginCompressImage params;
+    memset(&params, 0, sizeof(params));
+    params.target = target;
+    params.imageFormat = OrthancPluginImageFormat_Png;
+    params.pixelFormat = pixelFormat;
+    params.width = width;
+    params.height = height;
+    params.pitch = pitch;
+    params.buffer = buffer;
+    params.quality = quality;
+
+    return context->InvokeService(context, _OrthancPluginService_CompressImage, &params);
+  }
+
+
+  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginCompressJpegImage(
+    OrthancPluginContext*         context,
+    OrthancPluginMemoryBuffer*    target,
+    OrthancPluginPixelFormat      pixelFormat,
+    uint32_t                      width,
+    uint32_t                      height,
+    uint32_t                      pitch,
+    const void*                   buffer,
+    uint32_t                      quality)
+  {
+    _OrthancPluginCompressImage params;
+    memset(&params, 0, sizeof(params));
+    params.target = target;
+    params.imageFormat = OrthancPluginImageFormat_Jpeg;
+    params.pixelFormat = pixelFormat;
+    params.width = width;
+    params.height = height;
+    params.pitch = pitch;
+    params.buffer = buffer;
+    params.quality = quality;
+
+    return context->InvokeService(context, _OrthancPluginService_CompressImage, &params);
+  }
+
+
+
 #ifdef  __cplusplus
 }
 #endif