Mercurial > hg > orthanc-dicomweb
changeset 252:13b8e4c3c5bd
DicomWebFormatter::HttpWriter
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Tue, 26 Feb 2019 17:05:30 +0100 |
parents | 768634772ad7 |
children | 172ddccbbc1a |
files | Plugin/DicomWebFormatter.cpp Plugin/DicomWebFormatter.h Plugin/QidoRs.cpp Plugin/WadoRs.cpp |
diffstat | 4 files changed, 136 insertions(+), 61 deletions(-) [+] |
line wrap: on
line diff
--- a/Plugin/DicomWebFormatter.cpp Tue Feb 26 16:37:30 2019 +0100 +++ b/Plugin/DicomWebFormatter.cpp Tue Feb 26 17:05:30 2019 +0100 @@ -45,24 +45,40 @@ uint16_t tagElement, OrthancPluginValueRepresentation vr) { - std::string uri = GetSingleton().bulkRoot_; + const DicomWebFormatter& that = GetSingleton(); - for (size_t i = 0; i < levelDepth; i++) + switch (that.mode_) { - uri += ("/" + FormatTag(levelTagGroup[i], levelTagElement[i]) + "/" + - boost::lexical_cast<std::string>(levelIndex[i] + 1)); - } + case OrthancPluginDicomWebBinaryMode_Ignore: + case OrthancPluginDicomWebBinaryMode_InlineBinary: + setter(node, that.mode_, NULL); + break; + + case OrthancPluginDicomWebBinaryMode_BulkDataUri: + { + std::string uri = GetSingleton().bulkRoot_; + + for (size_t i = 0; i < levelDepth; i++) + { + uri += ("/" + FormatTag(levelTagGroup[i], levelTagElement[i]) + "/" + + boost::lexical_cast<std::string>(levelIndex[i] + 1)); + } - uri += "/" + FormatTag(tagGroup, tagElement); + uri += "/" + FormatTag(tagGroup, tagElement); - setter(node, OrthancPluginDicomWebBinaryMode_BulkDataUri, uri.c_str()); + setter(node, that.mode_, uri.c_str()); + break; + } + } } - DicomWebFormatter::Locker::Locker(const std::string& bulkRoot) : + DicomWebFormatter::Locker::Locker(OrthancPluginDicomWebBinaryMode mode, + const std::string& bulkRoot) : that_(GetSingleton()), lock_(that_.mutex_) { + that_.mode_ = mode; that_.bulkRoot_ = bulkRoot; } @@ -86,4 +102,73 @@ s.ToString(target); } + + + DicomWebFormatter::HttpWriter::HttpWriter(OrthancPluginRestOutput* output, + bool isXml) : + context_(OrthancPlugins::GetGlobalContext()), + output_(output), + isXml_(isXml), + first_(true) + { + if (context_ == NULL || + output_ == NULL) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); + } + + if (isXml_) + { + OrthancPluginStartMultipartAnswer(context_, output_, "related", "application/dicom+xml"); + } + else + { + jsonBuffer_.AddChunk("["); + } + } + + + void DicomWebFormatter::HttpWriter::AddRawDicom(const void* dicom, + size_t size, + OrthancPluginDicomWebBinaryMode mode, + const std::string& bulkRoot) + { + if (!first_ && + !isXml_) + { + jsonBuffer_.AddChunk(","); + } + + first_ = false; + + std::string item; + + { + // TODO - Avoid a global mutex => Need to change Orthanc SDK + OrthancPlugins::DicomWebFormatter::Locker locker(mode, bulkRoot); + locker.Apply(item, context_, dicom, size, isXml_); + } + + if (isXml_) + { + OrthancPluginSendMultipartItem(context_, output_, item.c_str(), item.size()); + } + else + { + jsonBuffer_.AddChunk(item); + } + } + + + void DicomWebFormatter::HttpWriter::Send() + { + if (!isXml_) + { + jsonBuffer_.AddChunk("]"); + + std::string answer; + jsonBuffer_.Flatten(answer); + OrthancPluginAnswerBuffer(context_, output_, answer.c_str(), answer.size(), "application/dicom+json"); + } + } }
--- a/Plugin/DicomWebFormatter.h Tue Feb 26 16:37:30 2019 +0100 +++ b/Plugin/DicomWebFormatter.h Tue Feb 26 17:05:30 2019 +0100 @@ -21,6 +21,8 @@ #pragma once +#include <Core/ChunkedBuffer.h> + #include <orthanc/OrthancCPlugin.h> #include <boost/noncopyable.hpp> @@ -32,8 +34,9 @@ class DicomWebFormatter : public boost::noncopyable { private: - boost::mutex mutex_; - std::string bulkRoot_; + boost::mutex mutex_; + OrthancPluginDicomWebBinaryMode mode_; + std::string bulkRoot_; static DicomWebFormatter& GetSingleton() { @@ -59,7 +62,8 @@ boost::mutex::scoped_lock lock_; public: - Locker(const std::string& bulkRoot); + Locker(OrthancPluginDicomWebBinaryMode mode, + const std::string& bulkRoot); void Apply(std::string& target, OrthancPluginContext* context, @@ -67,5 +71,26 @@ size_t size, bool xml); }; + + class HttpWriter : public boost::noncopyable + { + private: + OrthancPluginContext* context_; + OrthancPluginRestOutput* output_; + bool isXml_; + bool first_; + Orthanc::ChunkedBuffer jsonBuffer_; + + public: + HttpWriter(OrthancPluginRestOutput* output, + bool isXml); + + void AddRawDicom(const void* dicom, + size_t size, + OrthancPluginDicomWebBinaryMode mode, + const std::string& bulkRoot); + + void Send(); + }; }; }
--- a/Plugin/QidoRs.cpp Tue Feb 26 16:37:30 2019 +0100 +++ b/Plugin/QidoRs.cpp Tue Feb 26 17:05:30 2019 +0100 @@ -302,11 +302,10 @@ if (OrthancPlugins::RestApiGet(series, "/studies/" + resource + "/series?expand", false) && OrthancPlugins::RestApiGet(instances, "/studies/" + resource + "/instances", false)) { - // Number of Study Related Series - target[Orthanc::DicomTag(0x0020, 0x1206)] = boost::lexical_cast<std::string>(series.size()); - - // Number of Study Related Instances - target[Orthanc::DicomTag(0x0020, 0x1208)] = boost::lexical_cast<std::string>(instances.size()); + target[Orthanc::DICOM_TAG_NUMBER_OF_STUDY_RELATED_SERIES] = + boost::lexical_cast<std::string>(series.size()); + target[Orthanc::DICOM_TAG_NUMBER_OF_STUDY_RELATED_INSTANCES] = + boost::lexical_cast<std::string>(instances.size()); // Collect the Modality of all the child series std::set<std::string> modalities; @@ -331,13 +330,13 @@ s += *it; } - target[Orthanc::DicomTag(0x0008, 0x0061)] = s; // Modalities in Study + target[Orthanc::DICOM_TAG_MODALITIES_IN_STUDY] = s; } else { - target[Orthanc::DicomTag(0x0008, 0x0061)] = ""; // Modalities in Study - target[Orthanc::DicomTag(0x0020, 0x1206)] = "0"; // Number of Study Related Series - target[Orthanc::DicomTag(0x0020, 0x1208)] = "0"; // Number of Study Related Instances + target[Orthanc::DICOM_TAG_MODALITIES_IN_STUDY] = ""; + target[Orthanc::DICOM_TAG_NUMBER_OF_STUDY_RELATED_SERIES] = "0"; + target[Orthanc::DICOM_TAG_NUMBER_OF_STUDY_RELATED_INSTANCES] = "0"; } break; @@ -349,11 +348,12 @@ if (OrthancPlugins::RestApiGet(instances, "/series/" + resource + "/instances", false)) { // Number of Series Related Instances - target[Orthanc::DicomTag(0x0020, 0x1209)] = boost::lexical_cast<std::string>(instances.size()); + target[Orthanc::DICOM_TAG_NUMBER_OF_SERIES_RELATED_INSTANCES] = + boost::lexical_cast<std::string>(instances.size()); } else { - target[Orthanc::DicomTag(0x0020, 0x1209)] = "0"; // Number of Series Related Instances + target[Orthanc::DICOM_TAG_NUMBER_OF_SERIES_RELATED_INSTANCES] = "0"; } break;
--- a/Plugin/WadoRs.cpp Tue Feb 26 16:37:30 2019 +0100 +++ b/Plugin/WadoRs.cpp Tue Feb 26 17:05:30 2019 +0100 @@ -310,15 +310,7 @@ const std::string wadoBase = OrthancPlugins::Configuration::GetBaseUrl(request); - // For JSON - Orthanc::ChunkedBuffer buffer; - buffer.AddChunk("["); - bool first = true; - - if (isXml) - { - OrthancPluginStartMultipartAnswer(context, output, "related", "application/dicom+xml"); - } + OrthancPlugins::DicomWebFormatter::HttpWriter writer(output, isXml); for (std::list<std::string>::const_iterator it = instances.begin(); it != instances.end(); ++it) @@ -334,40 +326,13 @@ OrthancPlugins::MemoryBuffer dicom; if (dicom.RestApiGet("/instances/" + *it + "/file", false)) { - std::string item; - - { - // TODO - Avoid a global mutex - OrthancPlugins::DicomWebFormatter::Locker locker(bulkRoot); - locker.Apply(item, context, dicom.GetData(), dicom.GetSize(), isXml); - } - - if (isXml) - { - OrthancPluginSendMultipartItem(context, output, item.c_str(), item.size()); - } - else - { - if (!first) - { - buffer.AddChunk(","); - first = false; - } - - buffer.AddChunk(item); - } + writer.AddRawDicom(dicom.GetData(), dicom.GetSize(), + OrthancPluginDicomWebBinaryMode_BulkDataUri, bulkRoot); } } } - if (!isXml) - { - buffer.AddChunk("]"); - - std::string answer; - buffer.Flatten(answer); - OrthancPluginAnswerBuffer(context, output, answer.c_str(), answer.size(), "application/dicom+json"); - } + writer.Send(); }