Mercurial > hg > orthanc-stone
changeset 1882:4e80b8afd0da
numpy in rendering plugin
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Wed, 12 Jan 2022 18:02:24 +0100 |
parents | a05529952510 |
children | fba6e550e0ee |
files | OrthancStone/Sources/Toolbox/AffineTransform2D.cpp RenderingPlugin/Sources/Plugin.cpp |
diffstat | 2 files changed, 109 insertions(+), 6 deletions(-) [+] |
line wrap: on
line diff
--- a/OrthancStone/Sources/Toolbox/AffineTransform2D.cpp Wed Jan 12 10:01:25 2022 +0100 +++ b/OrthancStone/Sources/Toolbox/AffineTransform2D.cpp Wed Jan 12 18:02:24 2022 +0100 @@ -277,12 +277,20 @@ unsigned int width, unsigned int height) { - AffineTransform2D t; - t.matrix_(0, 0) = (flipX ? -1 : 1); - t.matrix_(0, 2) = (flipX ? width : 0); - t.matrix_(1, 1) = (flipY ? -1 : 1); - t.matrix_(1, 2) = (flipY ? height : 0); + if (width == 0 || + height == 0) + { + return AffineTransform2D(); // Identity + } + else + { + AffineTransform2D t; + t.matrix_(0, 0) = (flipX ? -1 : 1); + t.matrix_(0, 2) = (flipX ? width : 0); + t.matrix_(1, 1) = (flipY ? -1 : 1); + t.matrix_(1, 2) = (flipY ? height : 0); - return t; + return t; + } } }
--- a/RenderingPlugin/Sources/Plugin.cpp Wed Jan 12 10:01:25 2022 +0100 +++ b/RenderingPlugin/Sources/Plugin.cpp Wed Jan 12 18:02:24 2022 +0100 @@ -22,10 +22,104 @@ #include "../Resources/Orthanc/Plugins/OrthancPluginCppWrapper.h" +#include "../../OrthancStone/Sources/Toolbox/AffineTransform2D.h" + #include <EmbeddedResources.h> +#include <Images/Image.h> +#include <Images/ImageProcessing.h> +#include <Images/NumpyWriter.h> #include <Logging.h> +#include <boost/math/constants/constants.hpp> + + +static Orthanc::PixelFormat Convert(OrthancPluginPixelFormat format) +{ + switch (format) + { + case OrthancPluginPixelFormat_RGB24: + return Orthanc::PixelFormat_RGB24; + + case OrthancPluginPixelFormat_Grayscale8: + return Orthanc::PixelFormat_Grayscale8; + + case OrthancPluginPixelFormat_Grayscale16: + return Orthanc::PixelFormat_Grayscale16; + + case OrthancPluginPixelFormat_SignedGrayscale16: + return Orthanc::PixelFormat_SignedGrayscale16; + + default: + throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); + } +} + + +static void RenderNumpyFrame(OrthancPluginRestOutput* output, + const char* url, + const OrthancPluginHttpRequest* request) +{ + // TODO: Parameters in GET + // TODO: Rescale slope/intercept + + OrthancPlugins::MemoryBuffer dicom; + dicom.GetDicomInstance(request->groups[0]); + + unsigned int frame = boost::lexical_cast<unsigned int>(request->groups[1]); + + OrthancPlugins::OrthancImage image; + image.DecodeDicomImage(dicom.GetData(), dicom.GetSize(), frame); + + Orthanc::ImageAccessor source; + source.AssignReadOnly(Convert(image.GetPixelFormat()), image.GetWidth(), image.GetHeight(), + image.GetPitch(), image.GetBuffer()); + + double angle = 0; + double scaling = 1; + double offsetX = 0; + double offsetY = 0; + bool flipX = false; + bool flipY = false; + + OrthancStone::AffineTransform2D t; + t = OrthancStone::AffineTransform2D::Combine( + OrthancStone::AffineTransform2D::CreateOffset(static_cast<double>(image.GetWidth()) / 2.0 + offsetX, + static_cast<double>(image.GetHeight()) / 2.0 + offsetY), + OrthancStone::AffineTransform2D::CreateScaling(scaling, scaling), + OrthancStone::AffineTransform2D::CreateRotation(angle / 180.0 * boost::math::constants::pi<double>()), + OrthancStone::AffineTransform2D::CreateOffset(-static_cast<double>(image.GetWidth()) / 2.0, + -static_cast<double>(image.GetHeight()) / 2.0), + OrthancStone::AffineTransform2D::CreateFlip(flipX, flipY, image.GetWidth(), image.GetHeight())); + + std::unique_ptr<Orthanc::ImageAccessor> modified; + + if (source.GetFormat() == Orthanc::PixelFormat_RGB24) + { + LOG(WARNING) << "Bilinear interpolation for color images is not implemented yet"; + + modified.reset(new Orthanc::Image(source.GetFormat(), source.GetWidth(), source.GetHeight(), false)); + t.Apply(*modified, source, OrthancStone::ImageInterpolation_Nearest, true); + } + else + { + Orthanc::Image converted(Orthanc::PixelFormat_Float32, image.GetWidth(), image.GetHeight(), false); + Orthanc::ImageProcessing::Convert(converted, source); + + modified.reset(new Orthanc::Image(converted.GetFormat(), converted.GetWidth(), converted.GetHeight(), false)); + t.Apply(*modified, converted, OrthancStone::ImageInterpolation_Bilinear, true); + } + + assert(modified.get() != NULL); + + std::string answer; + Orthanc::NumpyWriter writer; + Orthanc::IImageWriter::WriteToMemory(writer, answer, *modified); + + OrthancPluginAnswerBuffer(OrthancPlugins::GetGlobalContext(), output, + answer.c_str(), answer.size(), "text/plain"); +} + extern "C" { @@ -54,6 +148,7 @@ try { + OrthancPlugins::RegisterRestCallback<RenderNumpyFrame>("/stone/instances/([^/]+)/frames/([0-9]+)/numpy", true); } catch (...) {