# HG changeset patch # User am@osimis.io # Date 1550157839 -3600 # Node ID 159a465e27bdd51c927d41f46893faed5cd838f7 # Parent 2f6ecb5037ea346dd1848cab91a77ce802d963f5 reworked RadiographyScene export to export to an Orthanc::Image too diff -r 2f6ecb5037ea -r 159a465e27bd Framework/Radiography/RadiographyMaskLayer.cpp --- a/Framework/Radiography/RadiographyMaskLayer.cpp Thu Feb 14 10:18:02 2019 +0100 +++ b/Framework/Radiography/RadiographyMaskLayer.cpp Thu Feb 14 16:23:59 2019 +0100 @@ -68,6 +68,11 @@ } } + std::string RadiographyMaskLayer::GetInstanceId() const + { + return dicomLayer_.GetInstanceId(); + } + void RadiographyMaskLayer::SetCorner(const MaskPoint& corner, size_t index) { if (index < corners_.size()) diff -r 2f6ecb5037ea -r 159a465e27bd Framework/Radiography/RadiographyMaskLayer.h --- a/Framework/Radiography/RadiographyMaskLayer.h Thu Feb 14 10:18:02 2019 +0100 +++ b/Framework/Radiography/RadiographyMaskLayer.h Thu Feb 14 16:23:59 2019 +0100 @@ -62,10 +62,22 @@ void SetCorners(const std::vector& corners); void SetCorner(const MaskPoint& corner, size_t index); + const std::vector& GetCorners() const + { + return corners_; + } + + float GetForeground() const + { + return foreground_; + } + virtual void Render(Orthanc::ImageAccessor& buffer, const AffineTransform2D& viewTransform, ImageInterpolation interpolation) const; + std::string GetInstanceId() const; + virtual size_t GetControlPointCount() const { return corners_.size(); diff -r 2f6ecb5037ea -r 159a465e27bd Framework/Radiography/RadiographyScene.cpp --- a/Framework/Radiography/RadiographyScene.cpp Thu Feb 14 10:18:02 2019 +0100 +++ b/Framework/Radiography/RadiographyScene.cpp Thu Feb 14 16:23:59 2019 +0100 @@ -539,41 +539,11 @@ } } - - void RadiographyScene::ExportDicom(OrthancApiClient& orthanc, - const Orthanc::DicomMap& dicom, - const std::string& parentOrthancId, - double pixelSpacingX, - double pixelSpacingY, - bool invert, - ImageInterpolation interpolation, - bool usePam) - { - Json::Value createDicomRequestContent; - - ExportToCreateDicomRequest(createDicomRequestContent, dicom, pixelSpacingX, pixelSpacingY, invert, interpolation, usePam); - - if (!parentOrthancId.empty()) - { - createDicomRequestContent["Parent"] = parentOrthancId; - } - - orthanc.PostJsonAsyncExpectJson( - "/tools/create-dicom", createDicomRequestContent, - new Callable - (*this, &RadiographyScene::OnDicomExported), - NULL, NULL); - } - - // Export using PAM is faster than using PNG, but requires Orthanc - // core >= 1.4.3 - void RadiographyScene::ExportToCreateDicomRequest(Json::Value& createDicomRequestContent, - const Orthanc::DicomMap& dicom, - double pixelSpacingX, - double pixelSpacingY, - bool invert, - ImageInterpolation interpolation, - bool usePam) + Orthanc::Image* RadiographyScene::ExportToImage(double pixelSpacingX, + double pixelSpacingY, + ImageInterpolation interpolation, + bool invert, + int64_t maxValue /* for inversion */) { if (pixelSpacingX <= 0 || pixelSpacingY <= 0) @@ -606,9 +576,31 @@ Render(layers, view, interpolation); - Orthanc::Image rendered(Orthanc::PixelFormat_Grayscale16, - layers.GetWidth(), layers.GetHeight(), false); - Orthanc::ImageProcessing::Convert(rendered, layers); + std::auto_ptr rendered(new Orthanc::Image(Orthanc::PixelFormat_Grayscale16, + layers.GetWidth(), layers.GetHeight(), false)); + + Orthanc::ImageProcessing::Convert(*rendered, layers); + if (invert) + Orthanc::ImageProcessing::Invert(*rendered, maxValue); + + return rendered.release(); + } + + + // Export using PAM is faster than using PNG, but requires Orthanc + // core >= 1.4.3 + void RadiographyScene::ExportDicom(OrthancApiClient& orthanc, + const Orthanc::DicomMap& dicom, + const std::string& parentOrthancId, + double pixelSpacingX, + double pixelSpacingY, + bool invert, + ImageInterpolation interpolation, + bool usePam) + { + Json::Value createDicomRequestContent; + + std::auto_ptr rendered(ExportToImage(pixelSpacingX, pixelSpacingY, interpolation)); // note: we don't invert the image in the pixels data because we'll set the PhotometricDisplayMode correctly in the DICOM tags std::string base64; @@ -618,12 +610,12 @@ if (usePam) { Orthanc::PamWriter writer; - writer.WriteToMemory(content, rendered); + writer.WriteToMemory(content, *rendered); } else { Orthanc::PngWriter writer; - writer.WriteToMemory(content, rendered); + writer.WriteToMemory(content, *rendered); } Orthanc::Toolbox::EncodeBase64(base64, content); @@ -680,9 +672,19 @@ createDicomRequestContent["Content"] = ("data:" + std::string(usePam ? Orthanc::MIME_PAM : Orthanc::MIME_PNG) + ";base64," + base64); + + if (!parentOrthancId.empty()) + { + createDicomRequestContent["Parent"] = parentOrthancId; + } + + orthanc.PostJsonAsyncExpectJson( + "/tools/create-dicom", createDicomRequestContent, + new Callable + (*this, &RadiographyScene::OnDicomExported), + NULL, NULL); } - void RadiographyScene::OnDicomExported(const OrthancApiClient::JsonResponseReadyMessage& message) { LOG(INFO) << "DICOM export was successful: " diff -r 2f6ecb5037ea -r 159a465e27bd Framework/Radiography/RadiographyScene.h --- a/Framework/Radiography/RadiographyScene.h Thu Feb 14 10:18:02 2019 +0100 +++ b/Framework/Radiography/RadiographyScene.h Thu Feb 14 16:23:59 2019 +0100 @@ -24,6 +24,7 @@ #include "RadiographyLayer.h" #include "../Toolbox/OrthancApiClient.h" #include "Framework/StoneEnumerations.h" +#include "Core/Images/Image.h" namespace OrthancStone { @@ -203,13 +204,17 @@ ImageInterpolation interpolation, bool usePam); - // temporary version used by VSOL because we need to send the same request at another url - void ExportToCreateDicomRequest(Json::Value& createDicomRequestContent, - const Orthanc::DicomMap& dicom, - double pixelSpacingX, - double pixelSpacingY, - bool invert, - ImageInterpolation interpolation, - bool usePam); + Orthanc::Image* ExportToImage(double pixelSpacingX, + double pixelSpacingY, + ImageInterpolation interpolation) + { + ExportToImage(pixelSpacingX, pixelSpacingY, interpolation, false, 0); + } + + Orthanc::Image* ExportToImage(double pixelSpacingX, + double pixelSpacingY, + ImageInterpolation interpolation, + bool invert, + int64_t maxValue /* for inversion */); }; } diff -r 2f6ecb5037ea -r 159a465e27bd Framework/Radiography/RadiographySceneReader.cpp --- a/Framework/Radiography/RadiographySceneReader.cpp Thu Feb 14 10:18:02 2019 +0100 +++ b/Framework/Radiography/RadiographySceneReader.cpp Thu Feb 14 16:23:59 2019 +0100 @@ -35,6 +35,7 @@ if (version != 1) throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); + RadiographyDicomLayer* dicomLayer = NULL; for(size_t layerIndex = 0; layerIndex < input["layers"].size(); layerIndex++) { const Json::Value& jsonLayer = input["layers"][(int)layerIndex]; @@ -43,7 +44,26 @@ if (jsonLayer["type"].asString() == "dicom") { ReadLayerGeometry(geometry, jsonLayer); - scene_.LoadDicomFrame(orthancApiClient_, jsonLayer["instanceId"].asString(), jsonLayer["frame"].asUInt(), false, &geometry); + dicomLayer = dynamic_cast(&(scene_.LoadDicomFrame(orthancApiClient_, jsonLayer["instanceId"].asString(), jsonLayer["frame"].asUInt(), false, &geometry))); + } + else if (jsonLayer["type"].asString() == "mask") + { + if (dicomLayer == NULL) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); // we always assumed the dicom layer was read before the mask + } + ReadLayerGeometry(geometry, jsonLayer); + + float foreground = jsonLayer["foreground"].asFloat(); + std::vector corners; + for (size_t i = 0; i < jsonLayer["corners"].size(); i++) + { + MaskPoint corner(jsonLayer["corners"][(int)i]["x"].asUInt(), + jsonLayer["corners"][(int)i]["y"].asUInt()); + corners.push_back(corner); + } + + scene_.LoadMask(corners, *dicomLayer, foreground, &geometry); } else if (jsonLayer["type"].asString() == "text") { diff -r 2f6ecb5037ea -r 159a465e27bd Framework/Radiography/RadiographySceneReader.h --- a/Framework/Radiography/RadiographySceneReader.h Thu Feb 14 10:18:02 2019 +0100 +++ b/Framework/Radiography/RadiographySceneReader.h Thu Feb 14 16:23:59 2019 +0100 @@ -24,6 +24,7 @@ #include "RadiographyScene.h" #include "RadiographyAlphaLayer.h" #include "RadiographyDicomLayer.h" +#include "RadiographyMaskLayer.h" #include "RadiographyTextLayer.h" #include #include diff -r 2f6ecb5037ea -r 159a465e27bd Framework/Radiography/RadiographySceneWriter.cpp --- a/Framework/Radiography/RadiographySceneWriter.cpp Thu Feb 14 10:18:02 2019 +0100 +++ b/Framework/Radiography/RadiographySceneWriter.cpp Thu Feb 14 16:23:59 2019 +0100 @@ -57,6 +57,22 @@ output["fontName"] = layer.GetFontName(); } + void RadiographySceneWriter::WriteLayer(Json::Value& output, const RadiographyMaskLayer& layer) + { + output["type"] = "mask"; + output["instanceId"] = layer.GetInstanceId(); // the dicom layer it's being linked to + output["foreground"] = layer.GetForeground(); + output["corners"] = Json::arrayValue; + const std::vector& corners = layer.GetCorners(); + for (size_t i = 0; i < corners.size(); i++) + { + Json::Value corner; + corner["x"] = corners[i].x; + corner["y"] = corners[i].y; + output["corners"].append(corner); + } + } + void RadiographySceneWriter::WriteLayer(Json::Value& output, const RadiographyAlphaLayer& layer) { output["type"] = "alpha"; @@ -128,6 +144,10 @@ { WriteLayer(output, dynamic_cast(layer)); } + else if (dynamic_cast(&layer) != NULL) + { + WriteLayer(output, dynamic_cast(layer)); + } else { throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); diff -r 2f6ecb5037ea -r 159a465e27bd Framework/Radiography/RadiographySceneWriter.h --- a/Framework/Radiography/RadiographySceneWriter.h Thu Feb 14 10:18:02 2019 +0100 +++ b/Framework/Radiography/RadiographySceneWriter.h Thu Feb 14 16:23:59 2019 +0100 @@ -25,6 +25,7 @@ #include "RadiographyAlphaLayer.h" #include "RadiographyDicomLayer.h" #include "RadiographyTextLayer.h" +#include "RadiographyMaskLayer.h" #include namespace OrthancStone @@ -46,5 +47,6 @@ void WriteLayer(Json::Value& output, const RadiographyDicomLayer& layer); void WriteLayer(Json::Value& output, const RadiographyTextLayer& layer); void WriteLayer(Json::Value& output, const RadiographyAlphaLayer& layer); + void WriteLayer(Json::Value& output, const RadiographyMaskLayer& layer); }; }