comparison OrthancServer/Sources/OrthancRestApi/OrthancRestResources.cpp @ 4785:61da49321754 openssl-3.x

integration mainline->openssl-3.x
author Sebastien Jodogne <s.jodogne@gmail.com>
date Mon, 30 Aug 2021 22:21:24 +0200
parents 4b721432fa67 3b78ba359db3
children 70d2a97ca8cb
comparison
equal deleted inserted replaced
4760:b2417ac5055a 4785:61da49321754
649 public: 649 public:
650 virtual ~IDecodedFrameHandler() 650 virtual ~IDecodedFrameHandler()
651 { 651 {
652 } 652 }
653 653
654 // "dicom" is non-NULL iff. "RequiresDicomTags() == true"
654 virtual void Handle(RestApiGetCall& call, 655 virtual void Handle(RestApiGetCall& call,
655 std::unique_ptr<ImageAccessor>& decoded, 656 std::unique_ptr<ImageAccessor>& decoded,
656 const DicomMap& dicom) = 0; 657 const ParsedDicomFile* dicom,
658 unsigned int frame) = 0;
657 659
658 virtual bool RequiresDicomTags() const = 0; 660 virtual bool RequiresDicomTags() const = 0;
659 661
660 static void Apply(RestApiGetCall& call, 662 static void Apply(RestApiGetCall& call,
661 IDecodedFrameHandler& handler, 663 IDecodedFrameHandler& handler,
762 catch (boost::bad_lexical_cast&) 764 catch (boost::bad_lexical_cast&)
763 { 765 {
764 return; 766 return;
765 } 767 }
766 768
767 DicomMap dicom;
768 std::unique_ptr<ImageAccessor> decoded; 769 std::unique_ptr<ImageAccessor> decoded;
769 770
770 try 771 try
771 { 772 {
772 std::string publicId = call.GetUriComponent("id", ""); 773 std::string publicId = call.GetUriComponent("id", "");
785 * Retrieve a summary of the DICOM tags, which is 786 * Retrieve a summary of the DICOM tags, which is
786 * necessary to deal with MONOCHROME1 photometric 787 * necessary to deal with MONOCHROME1 photometric
787 * interpretation, and with windowing parameters. 788 * interpretation, and with windowing parameters.
788 **/ 789 **/
789 ServerContext::DicomCacheLocker locker(context, publicId); 790 ServerContext::DicomCacheLocker locker(context, publicId);
790 OrthancConfiguration::DefaultExtractDicomSummary(dicom, locker.GetDicom()); 791 handler.Handle(call, decoded, &locker.GetDicom(), frame);
792 }
793 else
794 {
795 handler.Handle(call, decoded, NULL, frame);
791 } 796 }
792 } 797 }
793 catch (OrthancException& e) 798 catch (OrthancException& e)
794 { 799 {
795 if (e.GetErrorCode() == ErrorCode_ParameterOutOfRange || 800 if (e.GetErrorCode() == ErrorCode_ParameterOutOfRange ||
809 call.GetOutput().Redirect(root + "app/images/unsupported.png"); 814 call.GetOutput().Redirect(root + "app/images/unsupported.png");
810 } 815 }
811 return; 816 return;
812 } 817 }
813 818
814 handler.Handle(call, decoded, dicom);
815 } 819 }
816 820
817 821
818 static void DefaultHandler(RestApiGetCall& call, 822 static void DefaultHandler(RestApiGetCall& call,
819 std::unique_ptr<ImageAccessor>& decoded, 823 std::unique_ptr<ImageAccessor>& decoded,
851 { 855 {
852 } 856 }
853 857
854 virtual void Handle(RestApiGetCall& call, 858 virtual void Handle(RestApiGetCall& call,
855 std::unique_ptr<ImageAccessor>& decoded, 859 std::unique_ptr<ImageAccessor>& decoded,
856 const DicomMap& dicom) ORTHANC_OVERRIDE 860 const ParsedDicomFile* dicom,
861 unsigned int frame) ORTHANC_OVERRIDE
857 { 862 {
858 bool invert = false; 863 bool invert = false;
859 864
860 if (mode_ == ImageExtractionMode_Preview) 865 if (mode_ == ImageExtractionMode_Preview)
861 { 866 {
862 DicomImageInformation info(dicom); 867 if (dicom == NULL)
868 {
869 throw OrthancException(ErrorCode_InternalError);
870 }
871
872 DicomMap tags;
873 OrthancConfiguration::DefaultExtractDicomSummary(tags, *dicom);
874
875 DicomImageInformation info(tags);
863 invert = (info.GetPhotometricInterpretation() == PhotometricInterpretation_Monochrome1); 876 invert = (info.GetPhotometricInterpretation() == PhotometricInterpretation_Monochrome1);
864 } 877 }
865 878
866 DefaultHandler(call, decoded, mode_, invert); 879 DefaultHandler(call, decoded, mode_, invert);
867 } 880 }
874 887
875 888
876 class RenderedFrameHandler : public IDecodedFrameHandler 889 class RenderedFrameHandler : public IDecodedFrameHandler
877 { 890 {
878 private: 891 private:
879 static void GetDicomParameters(bool& invert, 892 static void GetUserArguments(double& windowWidth /* inout */,
880 float& rescaleSlope, 893 double& windowCenter /* inout */,
881 float& rescaleIntercept,
882 float& windowWidth,
883 float& windowCenter,
884 const DicomMap& dicom)
885 {
886 DicomImageInformation info(dicom);
887
888 invert = (info.GetPhotometricInterpretation() == PhotometricInterpretation_Monochrome1);
889
890 rescaleSlope = 1.0f;
891 rescaleIntercept = 0.0f;
892
893 if (dicom.HasTag(Orthanc::DICOM_TAG_RESCALE_SLOPE) &&
894 dicom.HasTag(Orthanc::DICOM_TAG_RESCALE_INTERCEPT))
895 {
896 dicom.ParseFloat(rescaleSlope, Orthanc::DICOM_TAG_RESCALE_SLOPE);
897 dicom.ParseFloat(rescaleIntercept, Orthanc::DICOM_TAG_RESCALE_INTERCEPT);
898 }
899
900 windowWidth = static_cast<float>(1 << info.GetBitsStored()) * rescaleSlope;
901 windowCenter = windowWidth / 2.0f + rescaleIntercept;
902
903 if (dicom.HasTag(Orthanc::DICOM_TAG_WINDOW_CENTER) &&
904 dicom.HasTag(Orthanc::DICOM_TAG_WINDOW_WIDTH))
905 {
906 dicom.ParseFirstFloat(windowCenter, Orthanc::DICOM_TAG_WINDOW_CENTER);
907 dicom.ParseFirstFloat(windowWidth, Orthanc::DICOM_TAG_WINDOW_WIDTH);
908 }
909 }
910
911 static void GetUserArguments(float& windowWidth /* inout */,
912 float& windowCenter /* inout */,
913 unsigned int& argWidth, 894 unsigned int& argWidth,
914 unsigned int& argHeight, 895 unsigned int& argHeight,
915 bool& smooth, 896 bool& smooth,
916 const RestApiGetCall& call) 897 const RestApiGetCall& call)
917 { 898 {
919 static const char* ARG_WINDOW_WIDTH = "window-width"; 900 static const char* ARG_WINDOW_WIDTH = "window-width";
920 static const char* ARG_WIDTH = "width"; 901 static const char* ARG_WIDTH = "width";
921 static const char* ARG_HEIGHT = "height"; 902 static const char* ARG_HEIGHT = "height";
922 static const char* ARG_SMOOTH = "smooth"; 903 static const char* ARG_SMOOTH = "smooth";
923 904
924 if (call.HasArgument(ARG_WINDOW_WIDTH)) 905 if (call.HasArgument(ARG_WINDOW_WIDTH) &&
925 { 906 !SerializationToolbox::ParseDouble(windowWidth, call.GetArgument(ARG_WINDOW_WIDTH, "")))
926 try 907 {
927 { 908 throw OrthancException(ErrorCode_ParameterOutOfRange,
928 windowWidth = boost::lexical_cast<float>(call.GetArgument(ARG_WINDOW_WIDTH, "")); 909 "Bad value for argument: " + std::string(ARG_WINDOW_WIDTH));
929 } 910 }
930 catch (boost::bad_lexical_cast&) 911
931 { 912 if (call.HasArgument(ARG_WINDOW_CENTER) &&
932 throw OrthancException(ErrorCode_ParameterOutOfRange, 913 !SerializationToolbox::ParseDouble(windowCenter, call.GetArgument(ARG_WINDOW_CENTER, "")))
933 "Bad value for argument: " + std::string(ARG_WINDOW_WIDTH)); 914 {
934 } 915 throw OrthancException(ErrorCode_ParameterOutOfRange,
935 } 916 "Bad value for argument: " + std::string(ARG_WINDOW_CENTER));
936
937 if (call.HasArgument(ARG_WINDOW_CENTER))
938 {
939 try
940 {
941 windowCenter = boost::lexical_cast<float>(call.GetArgument(ARG_WINDOW_CENTER, ""));
942 }
943 catch (boost::bad_lexical_cast&)
944 {
945 throw OrthancException(ErrorCode_ParameterOutOfRange,
946 "Bad value for argument: " + std::string(ARG_WINDOW_CENTER));
947 }
948 } 917 }
949 918
950 argWidth = 0; 919 argWidth = 0;
951 argHeight = 0; 920 argHeight = 0;
952 921
1004 973
1005 974
1006 public: 975 public:
1007 virtual void Handle(RestApiGetCall& call, 976 virtual void Handle(RestApiGetCall& call,
1008 std::unique_ptr<ImageAccessor>& decoded, 977 std::unique_ptr<ImageAccessor>& decoded,
1009 const DicomMap& dicom) ORTHANC_OVERRIDE 978 const ParsedDicomFile* dicom,
1010 { 979 unsigned int frame) ORTHANC_OVERRIDE
1011 bool invert; 980 {
1012 float rescaleSlope, rescaleIntercept, windowWidth, windowCenter; 981 if (dicom == NULL)
1013 GetDicomParameters(invert, rescaleSlope, rescaleIntercept, windowWidth, windowCenter, dicom); 982 {
1014 983 throw OrthancException(ErrorCode_InternalError);
984 }
985
986 PhotometricInterpretation photometric;
987 const bool invert = (dicom->LookupPhotometricInterpretation(photometric) &&
988 photometric == PhotometricInterpretation_Monochrome1);
989
990 double rescaleIntercept, rescaleSlope, windowCenter, windowWidth;
991 dicom->GetRescale(rescaleIntercept, rescaleSlope, frame);
992 dicom->GetDefaultWindowing(windowCenter, windowWidth, frame);
993
1015 unsigned int argWidth, argHeight; 994 unsigned int argWidth, argHeight;
1016 bool smooth; 995 bool smooth;
1017 GetUserArguments(windowWidth, windowCenter, argWidth, argHeight, smooth, call); 996 GetUserArguments(windowWidth, windowCenter, argWidth, argHeight, smooth, call);
1018 997
1019 unsigned int targetWidth = decoded->GetWidth(); 998 unsigned int targetWidth = decoded->GetWidth();
1079 if (windowWidth <= 1.0f) 1058 if (windowWidth <= 1.0f)
1080 { 1059 {
1081 windowWidth = 1; 1060 windowWidth = 1;
1082 } 1061 }
1083 1062
1084 if (std::abs(rescaleSlope) <= 0.1f) 1063 if (std::abs(rescaleSlope) <= 0.1)
1085 { 1064 {
1086 rescaleSlope = 0.1f; 1065 rescaleSlope = 0.1;
1087 } 1066 }
1088 1067
1089 const float scaling = 255.0f * rescaleSlope / windowWidth; 1068 const double scaling = 255.0 * rescaleSlope / windowWidth;
1090 const float offset = (rescaleIntercept - windowCenter + windowWidth / 2.0f) / rescaleSlope; 1069 const double offset = (rescaleIntercept - windowCenter + windowWidth / 2.0) / rescaleSlope;
1091 1070
1092 std::unique_ptr<ImageAccessor> rescaled(new Image(PixelFormat_Grayscale8, decoded->GetWidth(), decoded->GetHeight(), false)); 1071 std::unique_ptr<ImageAccessor> rescaled(new Image(PixelFormat_Grayscale8, decoded->GetWidth(), decoded->GetHeight(), false));
1093 ImageProcessing::ShiftScale(*rescaled, converted, offset, scaling, false); 1072 ImageProcessing::ShiftScale(*rescaled, converted, static_cast<float>(offset), static_cast<float>(scaling), false);
1094 1073
1095 if (targetWidth == decoded->GetWidth() && 1074 if (targetWidth == decoded->GetWidth() &&
1096 targetHeight == decoded->GetHeight()) 1075 targetHeight == decoded->GetHeight())
1097 { 1076 {
1098 DefaultHandler(call, rescaled, ImageExtractionMode_UInt8, invert); 1077 DefaultHandler(call, rescaled, ImageExtractionMode_UInt8, invert);