Mercurial > hg > orthanc
diff OrthancFramework/Sources/DicomFormat/DicomStreamReader.h @ 4220:92a21efa5c96
reorganization of DicomStreamReader
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Wed, 30 Sep 2020 15:33:47 +0200 |
parents | |
children | e4c0218b6b23 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancFramework/Sources/DicomFormat/DicomStreamReader.h Wed Sep 30 15:33:47 2020 +0200 @@ -0,0 +1,129 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2020 Osimis S.A., Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include "DicomTag.h" +#include "StreamBlockReader.h" + +namespace Orthanc +{ + /** + * This class parses a stream containing a DICOM instance. It does + * *not* support the visit of sequences (it only works at the first + * level of the hierarchy), and as a consequence, it doesn't give + * access to the pixel data of compressed transfer syntaxes. + **/ + class DicomStreamReader : public boost::noncopyable + { + public: + class IVisitor : public boost::noncopyable + { + public: + virtual ~IVisitor() + { + } + + // The data from this function will always be Little Endian (as + // specified by the DICOM standard) + virtual void VisitMetaHeaderTag(const DicomTag& tag, + const ValueRepresentation& vr, + const std::string& value) = 0; + + virtual void VisitTransferSyntax(DicomTransferSyntax transferSyntax) = 0; + + // Return "false" to stop processing + virtual bool VisitDatasetTag(const DicomTag& tag, + const ValueRepresentation& vr, + const std::string& value, + bool isLittleEndian) = 0; + }; + + private: + enum State + { + State_Preamble, + State_MetaHeader, + State_DatasetTag, + State_SequenceExplicitLength, + State_SequenceExplicitValue, + State_DatasetExplicitLength, + State_DatasetValue, + State_Done + }; + + StreamBlockReader reader_; + State state_; + DicomTransferSyntax transferSyntax_; + DicomTag previousTag_; + DicomTag danglingTag_; // Root-level tag + ValueRepresentation danglingVR_; + unsigned int sequenceDepth_; + + bool IsLittleEndian() const; + + void HandlePreamble(IVisitor& visitor, + const std::string& block); + + void HandleMetaHeader(IVisitor& visitor, + const std::string& block); + + void HandleDatasetTag(const std::string& block, + const DicomTag& untilTag); + + void HandleDatasetExplicitLength(uint32_t length); + + void HandleDatasetExplicitLength(const std::string& block); + + void HandleSequenceExplicitLength(const std::string& block); + + void HandleSequenceExplicitValue(); + + void HandleDatasetValue(IVisitor& visitor, + const std::string& block); + + public: + DicomStreamReader(std::istream& stream); + + /** + * Consume all the available bytes from the input stream, until + * end-of-stream is reached or the current tag is ">= untilTag". + * This method can be invoked several times, as more bytes are + * available from the input stream. To check if the DICOM stream + * is fully parsed until the goal tag, call "IsDone()". + **/ + void Consume(IVisitor& visitor, + const DicomTag& untilTag); + + void Consume(IVisitor& visitor); + + bool IsDone() const + { + return (state_ == State_Done); + } + + uint64_t GetProcessedBytes() const + { + return reader_.GetProcessedBytes(); + } + }; +}