# HG changeset patch # User Sebastien Jodogne # Date 1642006944 -3600 # Node ID 4e80b8afd0dae5241bbe15e373e380b1cab2f12b # Parent a05529952510c50cf0ff42ec16bcc2850542567e numpy in rendering plugin diff -r a05529952510 -r 4e80b8afd0da OrthancStone/Sources/Toolbox/AffineTransform2D.cpp --- 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; + } } } diff -r a05529952510 -r 4e80b8afd0da RenderingPlugin/Sources/Plugin.cpp --- 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 +#include +#include +#include #include +#include + + +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(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(image.GetWidth()) / 2.0 + offsetX, + static_cast(image.GetHeight()) / 2.0 + offsetY), + OrthancStone::AffineTransform2D::CreateScaling(scaling, scaling), + OrthancStone::AffineTransform2D::CreateRotation(angle / 180.0 * boost::math::constants::pi()), + OrthancStone::AffineTransform2D::CreateOffset(-static_cast(image.GetWidth()) / 2.0, + -static_cast(image.GetHeight()) / 2.0), + OrthancStone::AffineTransform2D::CreateFlip(flipX, flipY, image.GetWidth(), image.GetHeight())); + + std::unique_ptr 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("/stone/instances/([^/]+)/frames/([0-9]+)/numpy", true); } catch (...) {