# HG changeset patch # User Sebastien Jodogne # Date 1608827539 -3600 # Node ID 4cb9f66a1c7ce2a62a95a3bb496c8b49b7ce82eb # Parent 5466f336b09f1b8e6bed507d1774b0bcfd9ff0d6 documenting generation of images diff -r 5466f336b09f -r 4cb9f66a1c7c OrthancFramework/Sources/RestApi/RestApi.cpp --- a/OrthancFramework/Sources/RestApi/RestApi.cpp Thu Dec 24 09:37:30 2020 +0100 +++ b/OrthancFramework/Sources/RestApi/RestApi.cpp Thu Dec 24 17:32:19 2020 +0100 @@ -161,18 +161,21 @@ throw OrthancException(ErrorCode_InternalError); } - std::set uriArguments; + std::set uriArgumentsNames; + HttpToolbox::Arguments uriArguments; for (HttpToolbox::Arguments::const_iterator it = components.begin(); it != components.end(); ++it) { assert(it->second.empty()); - uriArguments.insert(it->first.c_str()); + uriArgumentsNames.insert(it->first.c_str()); + uriArguments[it->first] = ""; } if (hasTrailing) { - uriArguments.insert("..."); + uriArgumentsNames.insert("..."); + uriArguments["..."] = ""; } if (resource.HasHandler(HttpMethod_Get)) @@ -184,8 +187,7 @@ RestApiOutput o3(o2, HttpMethod_Get); RestApiGetCall call(o3, restApi_, RequestOrigin_Documentation, "" /* remote IP */, "" /* username */, HttpToolbox::Arguments() /* HTTP headers */, - HttpToolbox::Arguments() /* URI components */, - UriComponents() /* trailing */, + uriArguments, UriComponents() /* trailing */, uri, HttpToolbox::Arguments() /* GET arguments */); bool ok = false; @@ -194,7 +196,7 @@ try { ok = (resource.Handle(call) && - call.GetDocumentation().FormatOpenApi(v, uriArguments)); + call.GetDocumentation().FormatOpenApi(v, uriArgumentsNames)); } catch (OrthancException&) { @@ -223,8 +225,8 @@ RestApiOutput o3(o2, HttpMethod_Post); RestApiPostCall call(o3, restApi_, RequestOrigin_Documentation, "" /* remote IP */, "" /* username */, HttpToolbox::Arguments() /* HTTP headers */, - HttpToolbox::Arguments() /* URI components */, - UriComponents() /* trailing */, uri, NULL /* body */, 0 /* body size */); + uriArguments, UriComponents() /* trailing */, + uri, NULL /* body */, 0 /* body size */); bool ok = false; Json::Value v; @@ -232,7 +234,7 @@ try { ok = (resource.Handle(call) && - call.GetDocumentation().FormatOpenApi(v, uriArguments)); + call.GetDocumentation().FormatOpenApi(v, uriArgumentsNames)); } catch (OrthancException&) { @@ -261,8 +263,7 @@ RestApiOutput o3(o2, HttpMethod_Delete); RestApiDeleteCall call(o3, restApi_, RequestOrigin_Documentation, "" /* remote IP */, "" /* username */, HttpToolbox::Arguments() /* HTTP headers */, - HttpToolbox::Arguments() /* URI components */, - UriComponents() /* trailing */, uri); + uriArguments, UriComponents() /* trailing */, uri); bool ok = false; Json::Value v; @@ -270,7 +271,7 @@ try { ok = (resource.Handle(call) && - call.GetDocumentation().FormatOpenApi(v, uriArguments)); + call.GetDocumentation().FormatOpenApi(v, uriArgumentsNames)); } catch (OrthancException&) { @@ -299,8 +300,8 @@ RestApiOutput o3(o2, HttpMethod_Put); RestApiPutCall call(o3, restApi_, RequestOrigin_Documentation, "" /* remote IP */, "" /* username */, HttpToolbox::Arguments() /* HTTP headers */, - HttpToolbox::Arguments() /* URI components */, - UriComponents() /* trailing */, uri, NULL /* body */, 0 /* body size */); + uriArguments, UriComponents() /* trailing */, uri, + NULL /* body */, 0 /* body size */); bool ok = false; Json::Value v; @@ -308,7 +309,7 @@ try { ok = (resource.Handle(call) && - call.GetDocumentation().FormatOpenApi(v, uriArguments)); + call.GetDocumentation().FormatOpenApi(v, uriArgumentsNames)); } catch (OrthancException&) { @@ -523,8 +524,8 @@ OpenApiVisitor visitor(*this); UriComponents root; - std::set uriArguments; - root_.ExploreAllResources(visitor, root, uriArguments); + std::set uriArgumentsNames; + root_.ExploreAllResources(visitor, root, uriArgumentsNames); target = Json::objectValue; diff -r 5466f336b09f -r 4cb9f66a1c7c OrthancFramework/Sources/RestApi/RestApiCall.h --- a/OrthancFramework/Sources/RestApi/RestApiCall.h Thu Dec 24 09:37:30 2020 +0100 +++ b/OrthancFramework/Sources/RestApi/RestApiCall.h Thu Dec 24 17:32:19 2020 +0100 @@ -92,6 +92,11 @@ return trailing_; } + bool HasUriComponent(const std::string& name) const + { + return (uriComponents_.find(name) != uriComponents_.end()); + } + std::string GetUriComponent(const std::string& name, const std::string& defaultValue) const { diff -r 5466f336b09f -r 4cb9f66a1c7c OrthancServer/Sources/OrthancRestApi/OrthancRestResources.cpp --- a/OrthancServer/Sources/OrthancRestApi/OrthancRestResources.cpp Thu Dec 24 09:37:30 2020 +0100 +++ b/OrthancServer/Sources/OrthancRestApi/OrthancRestResources.cpp Thu Dec 24 17:32:19 2020 +0100 @@ -664,8 +664,98 @@ virtual bool RequiresDicomTags() const = 0; static void Apply(RestApiGetCall& call, - IDecodedFrameHandler& handler) + IDecodedFrameHandler& handler, + ImageExtractionMode mode /* for generation of documentation */, + bool isRendered /* for generation of documentation */) { + if (call.IsDocumentation()) + { + std::string m; + if (!isRendered) + { + switch (mode) + { + case ImageExtractionMode_Preview: + m = "preview"; + break; + case ImageExtractionMode_UInt8: + m = "uint8"; + break; + case ImageExtractionMode_UInt16: + m = "uint16"; + break; + case ImageExtractionMode_Int16: + m = "int16"; + break; + default: + throw OrthancException(ErrorCode_ParameterOutOfRange); + } + } + + std::string description; + std::string verb = (isRendered ? "Render" : "Decode"); + + if (call.HasUriComponent("frame")) + { + description = verb + " one frame of interest from the given DICOM instance."; + call.GetDocumentation() + .SetSummary(verb + " a frame" + (m.empty() ? "" : " (" + m + ")")) + .SetUriArgument("frame", RestApiCallDocumentation::Type_Number, "Index of the frame (starts at `0`)"); + } + else + { + description = verb + " the first frame of the given DICOM instance."; + call.GetDocumentation() + .SetSummary(verb + " an image" + (m.empty() ? "" : " (" + m + ")")); + } + + if (isRendered) + { + description += (" This function takes scaling into account (`RescaleSlope` and `RescaleIntercept` tags), " + "as well as the default windowing stored in the DICOM file (`WindowCenter` and `WindowWidth`tags), " + "and can be used to resize the resulting image. Color images are not affected by windowing."); + call.GetDocumentation() + .SetHttpGetArgument("window-center",RestApiCallDocumentation::Type_Number, "Windowing center", false) + .SetHttpGetArgument("window-width",RestApiCallDocumentation::Type_Number, "Windowing width", false) + .SetHttpGetArgument("width",RestApiCallDocumentation::Type_Number, "Width of the resized image", false) + .SetHttpGetArgument("height",RestApiCallDocumentation::Type_Number, "Height of the resized image", false) + .SetHttpGetArgument("smooth",RestApiCallDocumentation::Type_Boolean, "Whether to smooth image on resize", false); + } + else + { + switch (mode) + { + case ImageExtractionMode_Preview: + description += " The full dynamic range of grayscale images is rescaled to the [0,255] range."; + break; + case ImageExtractionMode_UInt8: + description += " Pixels of grayscale images are truncated to the [0,255] range."; + break; + case ImageExtractionMode_UInt16: + description += " Pixels of grayscale images are truncated to the [0,65535] range."; + break; + case ImageExtractionMode_Int16: + description += (" Pixels of grayscale images are truncated to the [-32768,32767] range. " + "Negative values must be interpreted according to two's complement."); + break; + default: + throw OrthancException(ErrorCode_ParameterOutOfRange); + } + } + + call.GetDocumentation() + .SetTag("Instances") + .SetUriArgument("id", "Orthanc identifier of the DICOM instance of interest") + .SetHttpGetArgument("quality", RestApiCallDocumentation::Type_Number, "Quality for JPEG images (between 1 and 100, defaults to 90)", false) + .SetHttpHeader("Accept", "Format of the resulting image. Can be `image/png` (default), `image/jpeg` or `image/x-portable-arbitrarymap`") + .AddAnswerType(MimeType_Png, "PNG image") + .AddAnswerType(MimeType_Jpeg, "JPEG image") + .AddAnswerType(MimeType_Pam, "PAM image (Portable Arbitrary Map)") + .SetDescription(description); + + return; + } + ServerContext& context = OrthancRestApi::GetContext(call); std::string frameId = call.GetUriComponent("frame", "0"); @@ -1060,7 +1150,7 @@ Semaphore::Locker locker(throttlingSemaphore_); GetImageHandler handler(mode); - IDecodedFrameHandler::Apply(call, handler); + IDecodedFrameHandler::Apply(call, handler, mode, false /* not rendered */); } @@ -1069,7 +1159,7 @@ Semaphore::Locker locker(throttlingSemaphore_); RenderedFrameHandler handler; - IDecodedFrameHandler::Apply(call, handler); + IDecodedFrameHandler::Apply(call, handler, ImageExtractionMode_Preview /* arbitrary value */, true); }