# HG changeset patch # User Sebastien Jodogne # Date 1572428906 -3600 # Node ID 8fe89c2ea5930a680947fd8a3d3b6d5d3ebf9cf3 # Parent 1a2d0316e8ec25b28c6b7914de94c307e2064d8d new class: ParsedDicomDir diff -r 1a2d0316e8ec -r 8fe89c2ea593 Core/DicomParsing/ParsedDicomDir.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/DicomParsing/ParsedDicomDir.cpp Wed Oct 30 10:48:26 2019 +0100 @@ -0,0 +1,194 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * 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 General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * In addition, as a special exception, the copyright holders of this + * program give permission to link the code of its release with the + * OpenSSL project's "OpenSSL" library (or with modified versions of it + * that use the same license as the "OpenSSL" library), and distribute + * the linked executables. You must obey the GNU General Public License + * in all respects for all of the code used other than "OpenSSL". If you + * modify file(s) with this exception, you may extend this exception to + * your version of the file(s), but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source files + * in the program, then also delete it here. + * + * 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + **/ + + +#include "../PrecompiledHeaders.h" +#include "ParsedDicomDir.h" + +#include "../OrthancException.h" +#include "ParsedDicomFile.h" +#include "FromDcmtkBridge.h" + +#include + + +namespace Orthanc +{ + void ParsedDicomDir::Clear() + { + for (size_t i = 0; i < content_.size(); i++) + { + assert(content_[i] != NULL); + delete content_[i]; + } + } + + + bool ParsedDicomDir::LookupIndexOfOffset(size_t& target, + unsigned int offset) const + { + if (offset == 0) + { + return false; + } + + OffsetToIndex::const_iterator found = offsetToIndex_.find(offset); + if (found == offsetToIndex_.end()) + { + // Error in the algorithm that computes the offsets + throw OrthancException(ErrorCode_InternalError); + } + else + { + target = found->second; + return true; + } + } + + + ParsedDicomDir::ParsedDicomDir(const std::string content) + { + ParsedDicomFile dicom(content); + + DcmSequenceOfItems* sequence = NULL; + if (dicom.GetDcmtkObject().getDataset() == NULL || + !dicom.GetDcmtkObject().getDataset()->findAndGetSequence(DCM_DirectoryRecordSequence, sequence).good() || + sequence == NULL) + { + throw OrthancException(ErrorCode_BadFileFormat, "Not a DICOMDIR"); + } + + content_.resize(sequence->card()); + nextOffsets_.resize(content_.size()); + lowerOffsets_.resize(content_.size()); + + // Manually reconstruct the list of all the available offsets of + // "DcmItem", as "fStartPosition" is a protected member in DCMTK + // API + std::set availableOffsets; + availableOffsets.insert(0); + + + for (unsigned long i = 0; i < sequence->card(); i++) + { + DcmItem* item = sequence->getItem(i); + if (item == NULL) + { + Clear(); + throw OrthancException(ErrorCode_InternalError); + } + + uint32_t next, lower; + if (!item->findAndGetUint32(DCM_OffsetOfTheNextDirectoryRecord, next).good() || + !item->findAndGetUint32(DCM_OffsetOfReferencedLowerLevelDirectoryEntity, lower).good()) + { + item->writeXML(std::cout); + throw OrthancException(ErrorCode_BadFileFormat, + "Missing offsets in DICOMDIR"); + } + + nextOffsets_[i] = next; + lowerOffsets_[i] = lower; + + std::auto_ptr entry(new DicomMap); + FromDcmtkBridge::ExtractDicomSummary(*entry, *item); + + if (next != 0) + { + availableOffsets.insert(next); + } + + if (lower != 0) + { + availableOffsets.insert(lower); + } + + content_[i] = entry.release(); + } + + if (content_.size() != availableOffsets.size()) + { + throw OrthancException(ErrorCode_BadFileFormat, + "Inconsistent offsets in DICOMDIR"); + } + + unsigned int index = 0; + for (std::set::const_iterator it = availableOffsets.begin(); + it != availableOffsets.end(); ++it) + { + offsetToIndex_[*it] = index; + index ++; + } + } + + + const DicomMap& ParsedDicomDir::GetItem(size_t i) const + { + if (i >= content_.size()) + { + throw OrthancException(ErrorCode_ParameterOutOfRange); + } + else + { + assert(content_[i] != NULL); + return *content_[i]; + } + } + + + bool ParsedDicomDir::LookupNext(size_t& target, + size_t index) const + { + if (index >= nextOffsets_.size()) + { + throw OrthancException(ErrorCode_ParameterOutOfRange); + } + else + { + return LookupIndexOfOffset(target, nextOffsets_[index]); + } + } + + + bool ParsedDicomDir::LookupLower(size_t& target, + size_t index) const + { + if (index >= lowerOffsets_.size()) + { + throw OrthancException(ErrorCode_ParameterOutOfRange); + } + else + { + return LookupIndexOfOffset(target, lowerOffsets_[index]); + } + } +} diff -r 1a2d0316e8ec -r 8fe89c2ea593 Core/DicomParsing/ParsedDicomDir.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/DicomParsing/ParsedDicomDir.h Wed Oct 30 10:48:26 2019 +0100 @@ -0,0 +1,80 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * 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 General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * In addition, as a special exception, the copyright holders of this + * program give permission to link the code of its release with the + * OpenSSL project's "OpenSSL" library (or with modified versions of it + * that use the same license as the "OpenSSL" library), and distribute + * the linked executables. You must obey the GNU General Public License + * in all respects for all of the code used other than "OpenSSL". If you + * modify file(s) with this exception, you may extend this exception to + * your version of the file(s), but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source files + * in the program, then also delete it here. + * + * 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + **/ + + +#pragma once + +#if ORTHANC_ENABLE_DCMTK != 1 +# error The macro ORTHANC_ENABLE_DCMTK must be set to 1 to use this file +#endif + +#include "../DicomFormat/DicomMap.h" + +namespace Orthanc +{ + class ParsedDicomDir : public boost::noncopyable + { + private: + typedef std::map OffsetToIndex; + + std::vector content_; + std::vector nextOffsets_; + std::vector lowerOffsets_; + OffsetToIndex offsetToIndex_; + + void Clear(); + + bool LookupIndexOfOffset(size_t& target, + unsigned int offset) const; + + public: + ParsedDicomDir(const std::string content); + + ~ParsedDicomDir() + { + Clear(); + } + + size_t GetSize() const + { + return content_.size(); + } + + const DicomMap& GetItem(size_t i) const; + + bool LookupNext(size_t& target, + size_t index) const; + + bool LookupLower(size_t& target, + size_t index) const; + }; +} diff -r 1a2d0316e8ec -r 8fe89c2ea593 Resources/CMake/OrthancFrameworkConfiguration.cmake --- a/Resources/CMake/OrthancFrameworkConfiguration.cmake Sat Oct 26 19:37:52 2019 +0200 +++ b/Resources/CMake/OrthancFrameworkConfiguration.cmake Wed Oct 30 10:48:26 2019 +0100 @@ -461,6 +461,7 @@ ${ORTHANC_ROOT}/Core/DicomParsing/DicomModification.cpp ${ORTHANC_ROOT}/Core/DicomParsing/DicomWebJsonVisitor.cpp ${ORTHANC_ROOT}/Core/DicomParsing/FromDcmtkBridge.cpp + ${ORTHANC_ROOT}/Core/DicomParsing/ParsedDicomDir.cpp ${ORTHANC_ROOT}/Core/DicomParsing/ParsedDicomFile.cpp ${ORTHANC_ROOT}/Core/DicomParsing/ToDcmtkBridge.cpp