# HG changeset patch # User Sebastien Jodogne # Date 1572530746 -3600 # Node ID b82b74d138304696a4d03e055d95e2624d6b96bb # Parent 79b1b541fe150d9d8a37d52ccc5ec0cc506b672c ParseDicomFileCommand diff -r 79b1b541fe15 -r b82b74d13830 Framework/Oracle/GenericOracleRunner.cpp --- a/Framework/Oracle/GenericOracleRunner.cpp Wed Oct 30 11:56:10 2019 +0100 +++ b/Framework/Oracle/GenericOracleRunner.cpp Thu Oct 31 15:05:46 2019 +0100 @@ -21,6 +21,10 @@ #include "GenericOracleRunner.h" +#if !defined(ORTHANC_ENABLE_DCMTK) +# error The macro ORTHANC_ENABLE_DCMTK must be defined +#endif + #include "CustomOracleCommand.h" #include "GetOrthancImageCommand.h" #include "GetOrthancWebViewerJpegCommand.h" @@ -29,6 +33,11 @@ #include "OrthancRestApiCommand.h" #include "ReadFileCommand.h" +#if ORTHANC_ENABLE_DCMTK == 1 +# include "ParseDicomFileCommand.h" +# include +#endif + #include #include #include @@ -37,6 +46,7 @@ #include + namespace OrthancStone { static void CopyHttpHeaders(Orthanc::HttpClient& client, @@ -182,27 +192,80 @@ } + static std::string GetPath(const std::string& root, + const std::string& file) + { + boost::filesystem::path a(root); + boost::filesystem::path b(file); + + boost::filesystem::path c; + if (b.is_absolute()) + { + c = b; + } + else + { + c = a / b; + } + + LOG(INFO) << "Oracle reading file: " << c.string(); + return c.string(); + } + + static IMessage* Execute(const std::string& root, const ReadFileCommand& command) { - boost::filesystem::path a(root); - boost::filesystem::path b(command.GetPath()); + std::string path = GetPath(root, command.GetPath()); + + std::string content; + Orthanc::SystemToolbox::ReadFile(content, path, true /* log */); + + return new ReadFileCommand::SuccessMessage(command, content); + } + - boost::filesystem::path path; - if (b.is_absolute()) +#if ORTHANC_ENABLE_DCMTK == 1 + static IMessage* Execute(const std::string& root, + const ParseDicomFileCommand& command) + { + std::string path = GetPath(root, command.GetPath()); + + DcmFileFormat f; + bool ok; + + if (command.IsPixelDataIncluded()) { - path = b; + ok = f.loadFile(path.c_str()).good(); } else { - path = a / b; +#if DCMTK_VERSION_NUMBER >= 362 + // NB : We could stop at (0x3007, 0x0000) instead of + // DCM_PixelData, cf. the Orthanc::DICOM_TAG_* constants + + static const DcmTagKey STOP = DCM_PixelData; + //static const DcmTagKey STOP(0x3007, 0x0000); + + ok = f.loadFileUntilTag(path.c_str(), EXS_Unknown, EGL_noChange, + DCM_MaxReadLength, ERM_autoDetect, STOP).good(); +#else + // The primitive "loadFileUntilTag" was introduced in DCMTK 3.6.2 + ok = f.loadFile(path.c_str()).good(); +#endif } - std::string content; - Orthanc::SystemToolbox::ReadFile(content, path.string(), true /* log */); - - return new ReadFileCommand::SuccessMessage(command, content); + if (ok) + { + return new ParseDicomFileCommand::SuccessMessage(command, f); + } + else + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat, + "Cannot parse file: " + path); + } } +#endif IMessage* GenericOracleRunner::Run(IOracleCommand& command) @@ -233,6 +296,14 @@ case IOracleCommand::Type_ReadFile: return Execute(rootDirectory_, dynamic_cast(command)); + case IOracleCommand::Type_ParseDicomFile: +#if ORTHANC_ENABLE_DCMTK == 1 + return Execute(rootDirectory_, dynamic_cast(command)); +#else + throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented, + "DCMTK must be enabled to parse DICOM files"); +#endif + default: throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); } diff -r 79b1b541fe15 -r b82b74d13830 Framework/Oracle/IOracleCommand.h --- a/Framework/Oracle/IOracleCommand.h Wed Oct 30 11:56:10 2019 +0100 +++ b/Framework/Oracle/IOracleCommand.h Thu Oct 31 15:05:46 2019 +0100 @@ -35,6 +35,7 @@ Type_GetOrthancWebViewerJpeg, Type_Http, Type_OrthancRestApi, + Type_ParseDicomFile, Type_ReadFile, Type_Sleep }; diff -r 79b1b541fe15 -r b82b74d13830 Framework/Oracle/ParseDicomFileCommand.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Oracle/ParseDicomFileCommand.cpp Thu Oct 31 15:05:46 2019 +0100 @@ -0,0 +1,32 @@ +/** + * Stone of Orthanc + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2019 Osimis S.A., Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + **/ + + +#include "ParseDicomFileCommand.h" + +namespace OrthancStone +{ + ParseDicomFileCommand::SuccessMessage::SuccessMessage(const ParseDicomFileCommand& command, + DcmFileFormat& content) : + OriginMessage(command) + { + dicom_.reset(new Orthanc::ParsedDicomFile(content)); + } +} diff -r 79b1b541fe15 -r b82b74d13830 Framework/Oracle/ParseDicomFileCommand.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Oracle/ParseDicomFileCommand.h Thu Oct 31 15:05:46 2019 +0100 @@ -0,0 +1,92 @@ +/** + * Stone of Orthanc + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2019 Osimis S.A., Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + **/ + + +#pragma once + +#if !defined(ORTHANC_ENABLE_DCMTK) +# error The macro ORTHANC_ENABLE_DCMTK must be defined +#endif + +#if ORTHANC_ENABLE_DCMTK != 1 +# error Support for DCMTK must be enabled to use ParseDicomFileCommand +#endif + +#include "../Messages/IMessage.h" +#include "OracleCommandWithPayload.h" + +#include + +#include + +namespace OrthancStone +{ + class ParseDicomFileCommand : public OracleCommandWithPayload + { + public: + class SuccessMessage : public OriginMessage + { + ORTHANC_STONE_MESSAGE(__FILE__, __LINE__); + + private: + std::auto_ptr dicom_; + + public: + SuccessMessage(const ParseDicomFileCommand& command, + DcmFileFormat& content); + + const Orthanc::ParsedDicomFile& GetDicom() const + { + return *dicom_; + } + }; + + private: + std::string path_; + bool pixelDataIncluded_; + + public: + ParseDicomFileCommand(const std::string& path) : + path_(path), + pixelDataIncluded_(true) + { + } + + virtual Type GetType() const + { + return Type_ParseDicomFile; + } + + const std::string& GetPath() const + { + return path_; + } + + bool IsPixelDataIncluded() const + { + return pixelDataIncluded_; + } + + void SetPixelDataIncluded(bool included) + { + pixelDataIncluded_ = included; + } + }; +} diff -r 79b1b541fe15 -r b82b74d13830 Resources/CMake/OrthancStoneConfiguration.cmake --- a/Resources/CMake/OrthancStoneConfiguration.cmake Wed Oct 30 11:56:10 2019 +0100 +++ b/Resources/CMake/OrthancStoneConfiguration.cmake Thu Oct 31 15:05:46 2019 +0100 @@ -399,6 +399,12 @@ endif() +if (ENABLE_DCMTK) + list(APPEND ORTHANC_STONE_SOURCES + ${ORTHANC_STONE_ROOT}/Framework/Oracle/ParseDicomFileCommand.cpp + ) +endif() + if (ENABLE_THREADS) list(APPEND ORTHANC_STONE_SOURCES ${ORTHANC_STONE_ROOT}/Framework/Messages/LockingEmitter.cpp