Mercurial > hg > orthanc
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(¶ms, 0, sizeof(params)); + params.image = image; + params.resultPixelFormat = ⌖ + + 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(¶ms, 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(¶ms, 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(¶ms, 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(¶ms, 0, sizeof(params)); + params.resultBuffer = ⌖ + params.image = image; + + if (context->InvokeService(context, _OrthancPluginService_GetImageBuffer, ¶ms) < 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(¶ms, 0, sizeof(params)); + params.target = ⌖ + params.data = data; + params.size = size; + params.format = format; + + if (context->InvokeService(context, _OrthancPluginService_UncompressImage, ¶ms) < 0) + { + return NULL; + } + else + { + return target; + } + } + + + + ORTHANC_PLUGIN_INLINE void OrthancPluginFreeImage( + OrthancPluginContext* context, + OrthancPluginImage* image) + { + _OrthancPluginGetImageInfo params; + memset(¶ms, 0, sizeof(params)); + params.image = image; + + context->InvokeService(context, _OrthancPluginService_FreeImage, ¶ms); + } + + + + + 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(¶ms, 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, ¶ms); + } + + + 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(¶ms, 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, ¶ms); + } + + + #ifdef __cplusplus } #endif