# HG changeset patch # User Sebastien Jodogne # Date 1717516245 -7200 # Node ID f048683aa619e48eee9e3f970da3eb56217825cc # Parent 9d27024a431ff1fc1ea836c9796df7173715bb31 added "?whole" option to "/instances/{id}/tags" to access tags stored after pixel data diff -r 9d27024a431f -r f048683aa619 NEWS --- a/NEWS Fri May 31 19:10:57 2024 +0200 +++ b/NEWS Tue Jun 04 17:50:45 2024 +0200 @@ -12,7 +12,8 @@ e.g. after you have updated the 'ExtraMainDicomTags' for this level. * The "requestedTags" GET argument was deprecated in favor of "requested-tags". * Fixed broken /instances/../tags route after the calling - /studies/../reconstruct when changing the "IngestTranscoding". + /studies/../reconstruct when changing the "IngestTranscoding". +* Added "?whole" option to "/instances/{id}/tags" to access tags stored after pixel data. Plugins ------- diff -r 9d27024a431f -r f048683aa619 OrthancServer/Sources/OrthancRestApi/OrthancRestResources.cpp --- a/OrthancServer/Sources/OrthancRestApi/OrthancRestResources.cpp Fri May 31 19:10:57 2024 +0200 +++ b/OrthancServer/Sources/OrthancRestApi/OrthancRestResources.cpp Tue Jun 04 17:50:45 2024 +0200 @@ -60,6 +60,7 @@ static const char* const IGNORE_LENGTH = "ignore-length"; static const char* const RECONSTRUCT_FILES = "ReconstructFiles"; static const char* const LIMIT_TO_THIS_LEVEL_MAIN_DICOM_TAGS = "LimitToThisLevelMainDicomTags"; +static const char* const ARG_WHOLE = "whole"; namespace Orthanc @@ -486,7 +487,8 @@ template - static void GetInstanceTagsInternal(RestApiGetCall& call) + static void GetInstanceTagsInternal(RestApiGetCall& call, + bool whole) { ServerContext& context = OrthancRestApi::GetContext(call); @@ -494,56 +496,90 @@ std::set ignoreTagLength; ParseSetOfTags(ignoreTagLength, call, IGNORE_LENGTH); - - if (format != DicomToJsonFormat_Full || - !ignoreTagLength.empty()) + + if (whole) { - Json::Value full; - context.ReadDicomAsJson(full, publicId, ignoreTagLength); - AnswerDicomAsJson(call, full, format); + // This is new in Orthanc 1.12.4. Reference: + // https://discourse.orthanc-server.org/t/private-tags-with-group-7fe0-are-not-provided-via-rest-api/4744 + const DicomToJsonFlags flags = static_cast(DicomToJsonFlags_Default & ~DicomToJsonFlags_StopAfterPixelData); + + Json::Value answer; + + { + ServerContext::DicomCacheLocker locker(OrthancRestApi::GetContext(call), publicId); + locker.GetDicom().DatasetToJson(answer, format, flags, + ORTHANC_MAXIMUM_TAG_LENGTH, ignoreTagLength); + } + + call.GetOutput().AnswerJson(answer); } else { - // This path allows one to avoid the JSON decoding if no - // simplification is asked, and if no "ignore-length" argument - // is present - Json::Value full; - context.ReadDicomAsJson(full, publicId); - call.GetOutput().AnswerJson(full); + if (format != DicomToJsonFormat_Full || + !ignoreTagLength.empty()) + { + Json::Value full; + context.ReadDicomAsJson(full, publicId, ignoreTagLength); + AnswerDicomAsJson(call, full, format); + } + else + { + // This path allows one to avoid the JSON decoding if no + // simplification is asked, and if no "ignore-length" argument + // is present + Json::Value full; + context.ReadDicomAsJson(full, publicId); + call.GetOutput().AnswerJson(full); + } } } + static void DocumentGetInstanceTags(RestApiGetCall& call) + { + call.GetDocumentation() + .SetTag("Instances") + .SetUriArgument("id", "Orthanc identifier of the DICOM instance of interest") + .SetHttpGetArgument( + IGNORE_LENGTH, RestApiCallDocumentation::Type_JsonListOfStrings, + "Also include the DICOM tags that are provided in this list, even if their associated value is long", false) + .SetHttpGetArgument( + ARG_WHOLE, RestApiCallDocumentation::Type_Boolean, "Whether to read the whole DICOM file from the " + "storage area (new in Orthanc 1.12.4). If set to \"false\" (default value), the DICOM file is read " + "until the pixel data tag (7fe0,0010) to optimize access to storage. Setting the option " + "to \"true\" provides access to the DICOM tags stored after the pixel data tag.", false) + .AddAnswerType(MimeType_Json, "JSON object containing the DICOM tags and their associated value"); + } + + static void GetInstanceTags(RestApiGetCall& call) { if (call.IsDocumentation()) { OrthancRestApi::DocumentDicomFormat(call, DicomToJsonFormat_Full); + DocumentGetInstanceTags(call); call.GetDocumentation() - .SetTag("Instances") .SetSummary("Get DICOM tags") .SetDescription("Get the DICOM tags in the specified format. By default, the `full` format is used, which " "combines hexadecimal tags with human-readable description.") - .SetUriArgument("id", "Orthanc identifier of the DICOM instance of interest") - .SetHttpGetArgument(IGNORE_LENGTH, RestApiCallDocumentation::Type_JsonListOfStrings, - "Also include the DICOM tags that are provided in this list, even if their associated value is long", false) - .AddAnswerType(MimeType_Json, "JSON object containing the DICOM tags and their associated value") .SetTruncatedJsonHttpGetSample("https://orthanc.uclouvain.be/demo/instances/7c92ce8e-bbf67ed2-ffa3b8c1-a3b35d94-7ff3ae26/tags", 10); return; } + const bool whole = call.GetBooleanArgument(ARG_WHOLE, false); + switch (OrthancRestApi::GetDicomFormat(call, DicomToJsonFormat_Full)) { case DicomToJsonFormat_Human: - GetInstanceTagsInternal(call); + GetInstanceTagsInternal(call, whole); break; case DicomToJsonFormat_Short: - GetInstanceTagsInternal(call); + GetInstanceTagsInternal(call, whole); break; case DicomToJsonFormat_Full: - GetInstanceTagsInternal(call); + GetInstanceTagsInternal(call, whole); break; default: @@ -556,20 +592,16 @@ { if (call.IsDocumentation()) { + DocumentGetInstanceTags(call); call.GetDocumentation() - .SetTag("Instances") .SetSummary("Get human-readable tags") .SetDescription("Get the DICOM tags in human-readable format (same as the `/instances/{id}/tags?simplify` route)") - .SetUriArgument("id", "Orthanc identifier of the DICOM instance of interest") - .SetHttpGetArgument(IGNORE_LENGTH, RestApiCallDocumentation::Type_JsonListOfStrings, - "Also include the DICOM tags that are provided in this list, even if their associated value is long", false) - .AddAnswerType(MimeType_Json, "JSON object containing the DICOM tags and their associated value") .SetTruncatedJsonHttpGetSample("https://orthanc.uclouvain.be/demo/instances/7c92ce8e-bbf67ed2-ffa3b8c1-a3b35d94-7ff3ae26/simplified-tags", 10); return; } else { - GetInstanceTagsInternal(call); + GetInstanceTagsInternal(call, call.GetBooleanArgument(ARG_WHOLE, false)); } }