Mercurial > hg > orthanc
changeset 6792:323f93009cc8
added DicomDataSource::ReadUntilPixelData()
| author | Sebastien Jodogne <s.jodogne@gmail.com> |
|---|---|
| date | Sun, 17 May 2026 18:54:12 +0200 |
| parents | ebd42c3fb06a |
| children | 4514943d9239 |
| files | OrthancFramework/Sources/DataSource/StorageAreaDataSource.cpp OrthancFramework/Sources/DataSource/StorageAreaDataSource.h OrthancFramework/UnitTestsSources/JobsTests.cpp |
| diffstat | 3 files changed, 116 insertions(+), 20 deletions(-) [+] |
line wrap: on
line diff
--- a/OrthancFramework/Sources/DataSource/StorageAreaDataSource.cpp Sun May 17 18:10:27 2026 +0200 +++ b/OrthancFramework/Sources/DataSource/StorageAreaDataSource.cpp Sun May 17 18:54:12 2026 +0200 @@ -88,6 +88,12 @@ { throw OrthancException(ErrorCode_ParameterOutOfRange); } + + uint64_t size = end - start; + if (static_cast<uint64_t>(static_cast<size_t>(size)) != size) + { + throw OrthancException(ErrorCode_NotEnoughMemory); // For 32bit architectures + } } Value* Read(IPluginStorageArea& area) const @@ -190,6 +196,15 @@ bool uncompress, bool checkMD5) { + if (attachment.GetCompressionType() == CompressionType_None) + { + if (attachment.GetCompressedMD5() != attachment.GetUncompressedMD5() || + attachment.GetCompressedSize() != attachment.GetUncompressedSize()) + { + throw OrthancException(ErrorCode_CorruptedFile); + } + } + std::unique_ptr<StorageAreaDataSource::Range> range(ReadRange(reader, attachment.GetUuid(), attachment.GetContentType(), @@ -249,4 +264,29 @@ return range.release(); } } + + + StorageAreaDataSource::Range* StorageAreaDataSource::ReadBeginning(DataSourceReader& reader, + const FileInfo& attachment, + size_t untilPosition) + { + if (attachment.GetCompressionType() != CompressionType_None) + { + throw OrthancException(ErrorCode_BadParameterType); + } + + if (attachment.GetCompressedMD5() != attachment.GetUncompressedMD5() || + attachment.GetCompressedSize() != attachment.GetUncompressedSize()) + { + throw OrthancException(ErrorCode_CorruptedFile); + } + + if (untilPosition > attachment.GetUncompressedSize()) + { + throw OrthancException(ErrorCode_ParameterOutOfRange); + } + + return ReadRange(reader, attachment.GetUuid(), attachment.GetContentType(), + 0, untilPosition, attachment.GetCustomData()); + } }
--- a/OrthancFramework/Sources/DataSource/StorageAreaDataSource.h Sun May 17 18:10:27 2026 +0200 +++ b/OrthancFramework/Sources/DataSource/StorageAreaDataSource.h Sun May 17 18:54:12 2026 +0200 @@ -84,5 +84,9 @@ const FileInfo& attachment, bool uncompress, bool checkMD5); + + static Range* ReadBeginning(DataSourceReader& reader, + const FileInfo& attachment, + size_t untilPosition); }; }
--- a/OrthancFramework/UnitTestsSources/JobsTests.cpp Sun May 17 18:10:27 2026 +0200 +++ b/OrthancFramework/UnitTestsSources/JobsTests.cpp Sun May 17 18:54:12 2026 +0200 @@ -1921,25 +1921,25 @@ boost::shared_ptr<DataSourceReader> storageAreaReader_; bool checkMD5_; - class Identifier : public IDataIdentifier + class BaseIdentifier : public IDataIdentifier + { + public: + virtual StorageAreaDataSource::Range* ReadRange(DataSourceReader& reader) const = 0; + }; + + class WholeIdentifier : public BaseIdentifier { private: FileInfo attachment_; public: - explicit Identifier(const FileInfo& attachment) : + explicit WholeIdentifier(const FileInfo& attachment) : attachment_(attachment) { } - const FileInfo& GetAttachment() const - { - return attachment_; - } - virtual bool GetCacheKey(std::string& key) const ORTHANC_OVERRIDE { - // TODO - Support "read until pixel data" key = (attachment_.GetUuid() + "|" + boost::lexical_cast<std::string>(attachment_.GetContentType())); return true; @@ -1947,12 +1947,54 @@ virtual bool EstimateValueSize(size_t& target) const ORTHANC_OVERRIDE { - // TODO - Support "read until pixel data" target = attachment_.GetUncompressedSize(); return true; } + + virtual StorageAreaDataSource::Range* ReadRange(DataSourceReader& reader) const ORTHANC_OVERRIDE + { + return StorageAreaDataSource::ReadAttachment(reader, attachment_, true /* uncompress */, true /* check MD5 */); + } }; + + class BeginningIdentifier : public BaseIdentifier + { + private: + FileInfo attachment_; + bool hasPixelDataOffset_; + size_t pixelDataOffset_; + + public: + BeginningIdentifier(const FileInfo& attachment, + size_t pixelDataOffset) : + attachment_(attachment), + hasPixelDataOffset_(true), + pixelDataOffset_(pixelDataOffset) + { + } + + virtual bool GetCacheKey(std::string& key) const ORTHANC_OVERRIDE + { + key = (attachment_.GetUuid() + "|" + + boost::lexical_cast<std::string>(attachment_.GetContentType()) + "|" + + boost::lexical_cast<std::string>(pixelDataOffset_)); + return true; + } + + virtual bool EstimateValueSize(size_t& target) const ORTHANC_OVERRIDE + { + target = pixelDataOffset_; + return true; + } + + virtual StorageAreaDataSource::Range* ReadRange(DataSourceReader& reader) const ORTHANC_OVERRIDE + { + return StorageAreaDataSource::ReadBeginning(reader, attachment_, pixelDataOffset_); + } + }; + + class Value : public IDynamicObject { private: @@ -2000,12 +2042,19 @@ virtual IDynamicObject* Load(const IDataIdentifier& obj) ORTHANC_OVERRIDE { - const Identifier& id = dynamic_cast<const Identifier&>(obj); + const BaseIdentifier& id = dynamic_cast<const BaseIdentifier&>(obj); + + std::unique_ptr<StorageAreaDataSource::Range> range(id.ReadRange(*storageAreaReader_)); - std::unique_ptr<StorageAreaDataSource::Range> range( - StorageAreaDataSource::ReadAttachment(*storageAreaReader_, id.GetAttachment(), true /* uncompress */, true /* check MD5 */)); + // Sanity check + size_t size; + if (!obj.EstimateValueSize(size) || + size != range->GetSize()) + { + throw OrthancException(ErrorCode_InternalError); + } - return new Value(new ParsedDicomFile(range->GetData(), range->GetSize()), id.GetAttachment().GetUncompressedSize()); + return new Value(new ParsedDicomFile(range->GetData(), range->GetSize()), range->GetSize()); } virtual size_t GetValueSize(const IDynamicObject& obj) const ORTHANC_OVERRIDE @@ -2037,16 +2086,19 @@ } }; - static Dicom* ReadDicom(DataSourceReader& reader, + static Dicom* ReadWhole(DataSourceReader& reader, const FileInfo& attachment) { - if (attachment.GetCompressionType() == CompressionType_None && - attachment.GetCompressedMD5() != attachment.GetUncompressedMD5()) - { - throw OrthancException(ErrorCode_CorruptedFile); - } + std::unique_ptr<IDataIdentifier> id(new WholeIdentifier(attachment)); + boost::shared_ptr<IDynamicObject> value = reader.ReadSingle(id.release()); + return new Dicom(value); + } - std::unique_ptr<IDataIdentifier> id(new Identifier(attachment)); + static Dicom* ReadUntilPixelData(DataSourceReader& reader, + const FileInfo& attachment, + size_t pixelDataOffset) + { + std::unique_ptr<IDataIdentifier> id(new BeginningIdentifier(attachment, pixelDataOffset)); boost::shared_ptr<IDynamicObject> value = reader.ReadSingle(id.release()); return new Dicom(value); }
