comparison OrthancServer/Sources/OrthancRestApi/OrthancRestResources.cpp @ 4406:4cb9f66a1c7c

documenting generation of images
author Sebastien Jodogne <s.jodogne@gmail.com>
date Thu, 24 Dec 2020 17:32:19 +0100
parents 5466f336b09f
children 2412601cd24b
comparison
equal deleted inserted replaced
4405:5466f336b09f 4406:4cb9f66a1c7c
662 const DicomMap& dicom) = 0; 662 const DicomMap& dicom) = 0;
663 663
664 virtual bool RequiresDicomTags() const = 0; 664 virtual bool RequiresDicomTags() const = 0;
665 665
666 static void Apply(RestApiGetCall& call, 666 static void Apply(RestApiGetCall& call,
667 IDecodedFrameHandler& handler) 667 IDecodedFrameHandler& handler,
668 { 668 ImageExtractionMode mode /* for generation of documentation */,
669 bool isRendered /* for generation of documentation */)
670 {
671 if (call.IsDocumentation())
672 {
673 std::string m;
674 if (!isRendered)
675 {
676 switch (mode)
677 {
678 case ImageExtractionMode_Preview:
679 m = "preview";
680 break;
681 case ImageExtractionMode_UInt8:
682 m = "uint8";
683 break;
684 case ImageExtractionMode_UInt16:
685 m = "uint16";
686 break;
687 case ImageExtractionMode_Int16:
688 m = "int16";
689 break;
690 default:
691 throw OrthancException(ErrorCode_ParameterOutOfRange);
692 }
693 }
694
695 std::string description;
696 std::string verb = (isRendered ? "Render" : "Decode");
697
698 if (call.HasUriComponent("frame"))
699 {
700 description = verb + " one frame of interest from the given DICOM instance.";
701 call.GetDocumentation()
702 .SetSummary(verb + " a frame" + (m.empty() ? "" : " (" + m + ")"))
703 .SetUriArgument("frame", RestApiCallDocumentation::Type_Number, "Index of the frame (starts at `0`)");
704 }
705 else
706 {
707 description = verb + " the first frame of the given DICOM instance.";
708 call.GetDocumentation()
709 .SetSummary(verb + " an image" + (m.empty() ? "" : " (" + m + ")"));
710 }
711
712 if (isRendered)
713 {
714 description += (" This function takes scaling into account (`RescaleSlope` and `RescaleIntercept` tags), "
715 "as well as the default windowing stored in the DICOM file (`WindowCenter` and `WindowWidth`tags), "
716 "and can be used to resize the resulting image. Color images are not affected by windowing.");
717 call.GetDocumentation()
718 .SetHttpGetArgument("window-center",RestApiCallDocumentation::Type_Number, "Windowing center", false)
719 .SetHttpGetArgument("window-width",RestApiCallDocumentation::Type_Number, "Windowing width", false)
720 .SetHttpGetArgument("width",RestApiCallDocumentation::Type_Number, "Width of the resized image", false)
721 .SetHttpGetArgument("height",RestApiCallDocumentation::Type_Number, "Height of the resized image", false)
722 .SetHttpGetArgument("smooth",RestApiCallDocumentation::Type_Boolean, "Whether to smooth image on resize", false);
723 }
724 else
725 {
726 switch (mode)
727 {
728 case ImageExtractionMode_Preview:
729 description += " The full dynamic range of grayscale images is rescaled to the [0,255] range.";
730 break;
731 case ImageExtractionMode_UInt8:
732 description += " Pixels of grayscale images are truncated to the [0,255] range.";
733 break;
734 case ImageExtractionMode_UInt16:
735 description += " Pixels of grayscale images are truncated to the [0,65535] range.";
736 break;
737 case ImageExtractionMode_Int16:
738 description += (" Pixels of grayscale images are truncated to the [-32768,32767] range. "
739 "Negative values must be interpreted according to two's complement.");
740 break;
741 default:
742 throw OrthancException(ErrorCode_ParameterOutOfRange);
743 }
744 }
745
746 call.GetDocumentation()
747 .SetTag("Instances")
748 .SetUriArgument("id", "Orthanc identifier of the DICOM instance of interest")
749 .SetHttpGetArgument("quality", RestApiCallDocumentation::Type_Number, "Quality for JPEG images (between 1 and 100, defaults to 90)", false)
750 .SetHttpHeader("Accept", "Format of the resulting image. Can be `image/png` (default), `image/jpeg` or `image/x-portable-arbitrarymap`")
751 .AddAnswerType(MimeType_Png, "PNG image")
752 .AddAnswerType(MimeType_Jpeg, "JPEG image")
753 .AddAnswerType(MimeType_Pam, "PAM image (Portable Arbitrary Map)")
754 .SetDescription(description);
755
756 return;
757 }
758
669 ServerContext& context = OrthancRestApi::GetContext(call); 759 ServerContext& context = OrthancRestApi::GetContext(call);
670 760
671 std::string frameId = call.GetUriComponent("frame", "0"); 761 std::string frameId = call.GetUriComponent("frame", "0");
672 762
673 unsigned int frame; 763 unsigned int frame;
1058 static void GetImage(RestApiGetCall& call) 1148 static void GetImage(RestApiGetCall& call)
1059 { 1149 {
1060 Semaphore::Locker locker(throttlingSemaphore_); 1150 Semaphore::Locker locker(throttlingSemaphore_);
1061 1151
1062 GetImageHandler handler(mode); 1152 GetImageHandler handler(mode);
1063 IDecodedFrameHandler::Apply(call, handler); 1153 IDecodedFrameHandler::Apply(call, handler, mode, false /* not rendered */);
1064 } 1154 }
1065 1155
1066 1156
1067 static void GetRenderedFrame(RestApiGetCall& call) 1157 static void GetRenderedFrame(RestApiGetCall& call)
1068 { 1158 {
1069 Semaphore::Locker locker(throttlingSemaphore_); 1159 Semaphore::Locker locker(throttlingSemaphore_);
1070 1160
1071 RenderedFrameHandler handler; 1161 RenderedFrameHandler handler;
1072 IDecodedFrameHandler::Apply(call, handler); 1162 IDecodedFrameHandler::Apply(call, handler, ImageExtractionMode_Preview /* arbitrary value */, true);
1073 } 1163 }
1074 1164
1075 1165
1076 static void GetMatlabImage(RestApiGetCall& call) 1166 static void GetMatlabImage(RestApiGetCall& call)
1077 { 1167 {