comparison OrthancServer/Sources/OrthancRestApi/OrthancRestResources.cpp @ 5647:f048683aa619

added "?whole" option to "/instances/{id}/tags" to access tags stored after pixel data
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 04 Jun 2024 17:50:45 +0200
parents f7adfb22e20e
children 65a509cac161
comparison
equal deleted inserted replaced
5646:9d27024a431f 5647:f048683aa619
58 static const std::string CHECK_REVISIONS = "CheckRevisions"; 58 static const std::string CHECK_REVISIONS = "CheckRevisions";
59 59
60 static const char* const IGNORE_LENGTH = "ignore-length"; 60 static const char* const IGNORE_LENGTH = "ignore-length";
61 static const char* const RECONSTRUCT_FILES = "ReconstructFiles"; 61 static const char* const RECONSTRUCT_FILES = "ReconstructFiles";
62 static const char* const LIMIT_TO_THIS_LEVEL_MAIN_DICOM_TAGS = "LimitToThisLevelMainDicomTags"; 62 static const char* const LIMIT_TO_THIS_LEVEL_MAIN_DICOM_TAGS = "LimitToThisLevelMainDicomTags";
63 static const char* const ARG_WHOLE = "whole";
63 64
64 65
65 namespace Orthanc 66 namespace Orthanc
66 { 67 {
67 static std::string GetDocumentationSampleResource(ResourceType type) 68 static std::string GetDocumentationSampleResource(ResourceType type)
484 call.GetOutput().AnswerBuffer("{}", MimeType_Json); 485 call.GetOutput().AnswerBuffer("{}", MimeType_Json);
485 } 486 }
486 487
487 488
488 template <DicomToJsonFormat format> 489 template <DicomToJsonFormat format>
489 static void GetInstanceTagsInternal(RestApiGetCall& call) 490 static void GetInstanceTagsInternal(RestApiGetCall& call,
491 bool whole)
490 { 492 {
491 ServerContext& context = OrthancRestApi::GetContext(call); 493 ServerContext& context = OrthancRestApi::GetContext(call);
492 494
493 std::string publicId = call.GetUriComponent("id", ""); 495 std::string publicId = call.GetUriComponent("id", "");
494 496
495 std::set<DicomTag> ignoreTagLength; 497 std::set<DicomTag> ignoreTagLength;
496 ParseSetOfTags(ignoreTagLength, call, IGNORE_LENGTH); 498 ParseSetOfTags(ignoreTagLength, call, IGNORE_LENGTH);
497 499
498 if (format != DicomToJsonFormat_Full || 500 if (whole)
499 !ignoreTagLength.empty()) 501 {
500 { 502 // This is new in Orthanc 1.12.4. Reference:
501 Json::Value full; 503 // https://discourse.orthanc-server.org/t/private-tags-with-group-7fe0-are-not-provided-via-rest-api/4744
502 context.ReadDicomAsJson(full, publicId, ignoreTagLength); 504 const DicomToJsonFlags flags = static_cast<DicomToJsonFlags>(DicomToJsonFlags_Default & ~DicomToJsonFlags_StopAfterPixelData);
503 AnswerDicomAsJson(call, full, format); 505
506 Json::Value answer;
507
508 {
509 ServerContext::DicomCacheLocker locker(OrthancRestApi::GetContext(call), publicId);
510 locker.GetDicom().DatasetToJson(answer, format, flags,
511 ORTHANC_MAXIMUM_TAG_LENGTH, ignoreTagLength);
512 }
513
514 call.GetOutput().AnswerJson(answer);
504 } 515 }
505 else 516 else
506 { 517 {
507 // This path allows one to avoid the JSON decoding if no 518 if (format != DicomToJsonFormat_Full ||
508 // simplification is asked, and if no "ignore-length" argument 519 !ignoreTagLength.empty())
509 // is present 520 {
510 Json::Value full; 521 Json::Value full;
511 context.ReadDicomAsJson(full, publicId); 522 context.ReadDicomAsJson(full, publicId, ignoreTagLength);
512 call.GetOutput().AnswerJson(full); 523 AnswerDicomAsJson(call, full, format);
513 } 524 }
525 else
526 {
527 // This path allows one to avoid the JSON decoding if no
528 // simplification is asked, and if no "ignore-length" argument
529 // is present
530 Json::Value full;
531 context.ReadDicomAsJson(full, publicId);
532 call.GetOutput().AnswerJson(full);
533 }
534 }
535 }
536
537
538 static void DocumentGetInstanceTags(RestApiGetCall& call)
539 {
540 call.GetDocumentation()
541 .SetTag("Instances")
542 .SetUriArgument("id", "Orthanc identifier of the DICOM instance of interest")
543 .SetHttpGetArgument(
544 IGNORE_LENGTH, RestApiCallDocumentation::Type_JsonListOfStrings,
545 "Also include the DICOM tags that are provided in this list, even if their associated value is long", false)
546 .SetHttpGetArgument(
547 ARG_WHOLE, RestApiCallDocumentation::Type_Boolean, "Whether to read the whole DICOM file from the "
548 "storage area (new in Orthanc 1.12.4). If set to \"false\" (default value), the DICOM file is read "
549 "until the pixel data tag (7fe0,0010) to optimize access to storage. Setting the option "
550 "to \"true\" provides access to the DICOM tags stored after the pixel data tag.", false)
551 .AddAnswerType(MimeType_Json, "JSON object containing the DICOM tags and their associated value");
514 } 552 }
515 553
516 554
517 static void GetInstanceTags(RestApiGetCall& call) 555 static void GetInstanceTags(RestApiGetCall& call)
518 { 556 {
519 if (call.IsDocumentation()) 557 if (call.IsDocumentation())
520 { 558 {
521 OrthancRestApi::DocumentDicomFormat(call, DicomToJsonFormat_Full); 559 OrthancRestApi::DocumentDicomFormat(call, DicomToJsonFormat_Full);
522 call.GetDocumentation() 560 DocumentGetInstanceTags(call);
523 .SetTag("Instances") 561 call.GetDocumentation()
524 .SetSummary("Get DICOM tags") 562 .SetSummary("Get DICOM tags")
525 .SetDescription("Get the DICOM tags in the specified format. By default, the `full` format is used, which " 563 .SetDescription("Get the DICOM tags in the specified format. By default, the `full` format is used, which "
526 "combines hexadecimal tags with human-readable description.") 564 "combines hexadecimal tags with human-readable description.")
527 .SetUriArgument("id", "Orthanc identifier of the DICOM instance of interest")
528 .SetHttpGetArgument(IGNORE_LENGTH, RestApiCallDocumentation::Type_JsonListOfStrings,
529 "Also include the DICOM tags that are provided in this list, even if their associated value is long", false)
530 .AddAnswerType(MimeType_Json, "JSON object containing the DICOM tags and their associated value")
531 .SetTruncatedJsonHttpGetSample("https://orthanc.uclouvain.be/demo/instances/7c92ce8e-bbf67ed2-ffa3b8c1-a3b35d94-7ff3ae26/tags", 10); 565 .SetTruncatedJsonHttpGetSample("https://orthanc.uclouvain.be/demo/instances/7c92ce8e-bbf67ed2-ffa3b8c1-a3b35d94-7ff3ae26/tags", 10);
532 return; 566 return;
533 } 567 }
534 568
569 const bool whole = call.GetBooleanArgument(ARG_WHOLE, false);
570
535 switch (OrthancRestApi::GetDicomFormat(call, DicomToJsonFormat_Full)) 571 switch (OrthancRestApi::GetDicomFormat(call, DicomToJsonFormat_Full))
536 { 572 {
537 case DicomToJsonFormat_Human: 573 case DicomToJsonFormat_Human:
538 GetInstanceTagsInternal<DicomToJsonFormat_Human>(call); 574 GetInstanceTagsInternal<DicomToJsonFormat_Human>(call, whole);
539 break; 575 break;
540 576
541 case DicomToJsonFormat_Short: 577 case DicomToJsonFormat_Short:
542 GetInstanceTagsInternal<DicomToJsonFormat_Short>(call); 578 GetInstanceTagsInternal<DicomToJsonFormat_Short>(call, whole);
543 break; 579 break;
544 580
545 case DicomToJsonFormat_Full: 581 case DicomToJsonFormat_Full:
546 GetInstanceTagsInternal<DicomToJsonFormat_Full>(call); 582 GetInstanceTagsInternal<DicomToJsonFormat_Full>(call, whole);
547 break; 583 break;
548 584
549 default: 585 default:
550 throw OrthancException(ErrorCode_InternalError); 586 throw OrthancException(ErrorCode_InternalError);
551 } 587 }
554 590
555 static void GetInstanceSimplifiedTags(RestApiGetCall& call) 591 static void GetInstanceSimplifiedTags(RestApiGetCall& call)
556 { 592 {
557 if (call.IsDocumentation()) 593 if (call.IsDocumentation())
558 { 594 {
559 call.GetDocumentation() 595 DocumentGetInstanceTags(call);
560 .SetTag("Instances") 596 call.GetDocumentation()
561 .SetSummary("Get human-readable tags") 597 .SetSummary("Get human-readable tags")
562 .SetDescription("Get the DICOM tags in human-readable format (same as the `/instances/{id}/tags?simplify` route)") 598 .SetDescription("Get the DICOM tags in human-readable format (same as the `/instances/{id}/tags?simplify` route)")
563 .SetUriArgument("id", "Orthanc identifier of the DICOM instance of interest")
564 .SetHttpGetArgument(IGNORE_LENGTH, RestApiCallDocumentation::Type_JsonListOfStrings,
565 "Also include the DICOM tags that are provided in this list, even if their associated value is long", false)
566 .AddAnswerType(MimeType_Json, "JSON object containing the DICOM tags and their associated value")
567 .SetTruncatedJsonHttpGetSample("https://orthanc.uclouvain.be/demo/instances/7c92ce8e-bbf67ed2-ffa3b8c1-a3b35d94-7ff3ae26/simplified-tags", 10); 599 .SetTruncatedJsonHttpGetSample("https://orthanc.uclouvain.be/demo/instances/7c92ce8e-bbf67ed2-ffa3b8c1-a3b35d94-7ff3ae26/simplified-tags", 10);
568 return; 600 return;
569 } 601 }
570 else 602 else
571 { 603 {
572 GetInstanceTagsInternal<DicomToJsonFormat_Human>(call); 604 GetInstanceTagsInternal<DicomToJsonFormat_Human>(call, call.GetBooleanArgument(ARG_WHOLE, false));
573 } 605 }
574 } 606 }
575 607
576 608
577 static void ListFrames(RestApiGetCall& call) 609 static void ListFrames(RestApiGetCall& call)