comparison Sources/Plugin.cpp @ 50:bf4c4e4e7198 nexus

added route /stl/create-nexus
author Sebastien Jodogne <s.jodogne@gmail.com>
date Fri, 17 May 2024 17:16:07 +0200
parents a70fc4846be1
children 40a093f90be6
comparison
equal deleted inserted replaced
49:0a408a81fb15 50:bf4c4e4e7198
51 #endif 51 #endif
52 52
53 #define ORTHANC_PLUGIN_NAME "stl" 53 #define ORTHANC_PLUGIN_NAME "stl"
54 54
55 55
56 #if ORTHANC_ENABLE_NEXUS == 1
57 static const char* const ORTHANC_STL_PRIVATE_CREATOR = "OrthancSTL";
58 static const char* const ORTHANC_STL_MANUFACTURER = "ORTHANC^STL";
59 static const uint16_t ORTHANC_STL_PRIVATE_GROUP = 0x4205u;
60 static const uint16_t ORTHANC_STL_CREATOR_ELEMENT = 0x0010u;
61 static const uint16_t ORTHANC_STL_NEXUS_ELEMENT = 0x1001u;
62 static const Orthanc::DicomTag DICOM_TAG_CREATOR_VERSION_UID(0x0008, 0x9123);
63 #endif
64
65
56 // Forward declaration 66 // Forward declaration
57 void ReadStaticAsset(std::string& target, 67 void ReadStaticAsset(std::string& target,
58 const std::string& path); 68 const std::string& path);
59 69
60 70
118 } 128 }
119 }; 129 };
120 130
121 131
122 static ResourcesCache cache_; 132 static ResourcesCache cache_;
123 static bool hasCreateDicomStl_;
124 133
125 void ServeFile(OrthancPluginRestOutput* output, 134 void ServeFile(OrthancPluginRestOutput* output,
126 const char* url, 135 const char* url,
127 const OrthancPluginHttpRequest* request) 136 const OrthancPluginHttpRequest* request)
128 { 137 {
876 OrthancPluginSetHttpHeader(context, output, "Content-Type", "application/octet-stream"); 885 OrthancPluginSetHttpHeader(context, output, "Content-Type", "application/octet-stream");
877 886
878 OrthancPluginSendHttpStatus(context, output, 206 /* partial content */, part.c_str(), part.size()); 887 OrthancPluginSendHttpStatus(context, output, 206 /* partial content */, part.c_str(), part.size());
879 } 888 }
880 889
890
891 static const char* GetCreatorVersionUid(const std::string& version)
892 {
893 /**
894 * Each version of the STL plugin must provide a different value for
895 * the CreatorVersionUID (0008,9123) tag. A new UID can be generated
896 * by typing:
897 *
898 * $ python -c 'import pydicom; print(pydicom.uid.generate_uid())'
899 *
900 **/
901
902 if (version == "mainline")
903 {
904 return "1.2.826.0.1.3680043.8.498.90514926286349109728701975613711986292";
905 }
906 else
907 {
908 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
909 }
910 }
911
912
913 void DicomizeNexusModel(OrthancPluginRestOutput* output,
914 const char* url,
915 const OrthancPluginHttpRequest* request)
916 {
917 static const char* KEY_CONTENT = "Content";
918 static const char* KEY_PARENT = "Parent";
919 static const char* KEY_TAGS = "Tags";
920 static const char* KEY_PRIVATE_CREATOR = "PrivateCreator";
921
922 OrthancPluginContext* context = OrthancPlugins::GetGlobalContext();
923
924 if (request->method != OrthancPluginHttpMethod_Post)
925 {
926 OrthancPluginSendMethodNotAllowed(context, output, "POST");
927 return;
928 }
929
930 Json::Value body;
931 if (!Orthanc::Toolbox::ReadJson(body, request->body, request->bodySize) ||
932 body.type() != Json::objectValue ||
933 !body.isMember(KEY_TAGS) ||
934 body[KEY_TAGS].type() != Json::objectValue)
935 {
936 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadRequest);
937 }
938
939 if (!body.isMember(KEY_CONTENT) ||
940 body[KEY_CONTENT].type() != Json::stringValue)
941 {
942 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadRequest,
943 "POST body missing string field \"" + std::string(KEY_CONTENT) + "\"");
944 }
945
946 std::string nexus;
947 Orthanc::Toolbox::DecodeBase64(nexus, body[KEY_CONTENT].asString());
948
949 std::string raw;
950 Orthanc::Toolbox::EncodeDataUriScheme(raw, "application/octet-stream", nexus);
951
952 Json::Value creationBody = Json::objectValue;
953
954 creationBody[KEY_TAGS] = body[KEY_TAGS];
955 creationBody[KEY_TAGS][Orthanc::DICOM_TAG_MANUFACTURER.Format()] = ORTHANC_STL_MANUFACTURER;
956 creationBody[KEY_TAGS][Orthanc::DICOM_TAG_SOP_CLASS_UID.Format()] = "1.2.840.10008.5.1.4.1.1.66";
957 creationBody[KEY_TAGS][Orthanc::DICOM_TAG_MODALITY.Format()] = "OT";
958 creationBody[KEY_TAGS][DICOM_TAG_CREATOR_VERSION_UID.Format()] = GetCreatorVersionUid(ORTHANC_STL_VERSION);
959 creationBody[KEY_TAGS][Orthanc::DicomTag(ORTHANC_STL_PRIVATE_GROUP, ORTHANC_STL_CREATOR_ELEMENT).Format()] = ORTHANC_STL_PRIVATE_CREATOR;
960 creationBody[KEY_TAGS][Orthanc::DicomTag(ORTHANC_STL_PRIVATE_GROUP, ORTHANC_STL_NEXUS_ELEMENT).Format()] = raw;
961 creationBody[KEY_PRIVATE_CREATOR] = ORTHANC_STL_PRIVATE_CREATOR;
962
963 if (body.isMember(KEY_PARENT))
964 {
965 creationBody[KEY_PARENT] = body[KEY_PARENT];
966 }
967
968 std::string bodyString;
969 Orthanc::Toolbox::WriteFastJson(bodyString, creationBody);
970
971 std::string result;
972 if (OrthancPlugins::RestApiPost(result, "/tools/create-dicom",
973 bodyString.empty() ? NULL : bodyString.c_str(),
974 bodyString.size(), false))
975 {
976 OrthancPluginAnswerBuffer(context, output, result.empty() ? NULL : result.c_str(),
977 result.size(), "application/json");
978 }
979 else
980 {
981 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadRequest);
982 }
983 }
984
881 #endif 985 #endif
882 986
883 987
884 extern "C" 988 extern "C"
885 { 989 {
908 Orthanc::Logging::Initialize(context); 1012 Orthanc::Logging::Initialize(context);
909 #endif 1013 #endif
910 1014
911 Orthanc::InitializeFramework("", false); 1015 Orthanc::InitializeFramework("", false);
912 1016
913 hasCreateDicomStl_ = OrthancPlugins::CheckMinimalOrthancVersion(1, 12, 1); 1017 const bool hasCreateDicomStl_ = OrthancPlugins::CheckMinimalOrthancVersion(1, 12, 1);
914 LOG(WARNING) << "Hello!";
915 1018
916 if (!hasCreateDicomStl_) 1019 if (!hasCreateDicomStl_)
917 { 1020 {
918 LOG(WARNING) << "Your version of Orthanc (" << std::string(context->orthancVersion) 1021 LOG(WARNING) << "Your version of Orthanc (" << std::string(context->orthancVersion)
919 << ") is insufficient to create DICOM STL, it should be above 1.12.1"; 1022 << ") is insufficient to create DICOM STL, it should be above 1.12.1";
933 1036
934 #if ORTHANC_ENABLE_NEXUS == 1 1037 #if ORTHANC_ENABLE_NEXUS == 1
935 nexusCache_.SetMaximumSize(512 * 1024 * 1024); // Cache of 512MB for Nexus 1038 nexusCache_.SetMaximumSize(512 * 1024 * 1024); // Cache of 512MB for Nexus
936 OrthancPlugins::RegisterRestCallback<ExtractNexusModel>("/instances/([0-9a-f-]+)/nexus", true); 1039 OrthancPlugins::RegisterRestCallback<ExtractNexusModel>("/instances/([0-9a-f-]+)/nexus", true);
937 OrthancPlugins::RegisterRestCallback<ServeNexusAssets>("/stl/nexus/(.*)", true); 1040 OrthancPlugins::RegisterRestCallback<ServeNexusAssets>("/stl/nexus/(.*)", true);
1041
1042 const bool hasCreateNexus_ = OrthancPlugins::CheckMinimalOrthancVersion(1, 9, 4);
1043
1044 if (hasCreateNexus_)
1045 {
1046 OrthancPlugins::RegisterRestCallback<DicomizeNexusModel>("/stl/create-nexus", true);
1047
1048 if (OrthancPluginRegisterPrivateDictionaryTag(
1049 context, ORTHANC_STL_PRIVATE_GROUP, ORTHANC_STL_CREATOR_ELEMENT, OrthancPluginValueRepresentation_LO,
1050 "PrivateCreator", 1, 1, ORTHANC_STL_PRIVATE_CREATOR) != OrthancPluginErrorCode_Success ||
1051 OrthancPluginRegisterPrivateDictionaryTag(
1052 context, ORTHANC_STL_PRIVATE_GROUP, ORTHANC_STL_NEXUS_ELEMENT, OrthancPluginValueRepresentation_OB,
1053 "NexusData", 1, 1, ORTHANC_STL_PRIVATE_CREATOR) != OrthancPluginErrorCode_Success)
1054 {
1055 LOG(ERROR) << "Cannot register the private DICOM tags for handling Nexus";
1056 }
1057 }
1058 else
1059 {
1060 LOG(WARNING) << "Your version of Orthanc (" << std::string(context->orthancVersion)
1061 << ") is insufficient to create DICOM-ize Nexus models, it should be above 1.9.4";
1062 }
938 #endif 1063 #endif
939 1064
940 OrthancPlugins::OrthancConfiguration globalConfiguration; 1065 OrthancPlugins::OrthancConfiguration globalConfiguration;
941 OrthancPlugins::OrthancConfiguration configuration; 1066 OrthancPlugins::OrthancConfiguration configuration;
942 globalConfiguration.GetSection(configuration, "STL"); 1067 globalConfiguration.GetSection(configuration, "STL");