329 lines
11 KiB
C++
329 lines
11 KiB
C++
/**
|
|
* Orthanc - A Lightweight, RESTful DICOM Store
|
|
* Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
|
|
* Department, University Hospital of Liege, Belgium
|
|
* Copyright (C) 2017-2023 Osimis S.A., Belgium
|
|
* Copyright (C) 2024-2025 Orthanc Team SRL, Belgium
|
|
* Copyright (C) 2021-2025 Sebastien Jodogne, ICTEAM UCLouvain, 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 "../OrthancFramework.h"
|
|
|
|
#if !defined(ORTHANC_ENABLE_JPEG)
|
|
# error Macro ORTHANC_ENABLE_JPEG must be defined to use this file
|
|
#endif
|
|
|
|
#if !defined(ORTHANC_ENABLE_PNG)
|
|
# error Macro ORTHANC_ENABLE_PNG must be defined to use this file
|
|
#endif
|
|
|
|
#if !defined(ORTHANC_ENABLE_CIVETWEB)
|
|
# error Macro ORTHANC_ENABLE_CIVETWEB must be defined to use this file
|
|
#endif
|
|
|
|
#if !defined(ORTHANC_ENABLE_MONGOOSE)
|
|
# error Macro ORTHANC_ENABLE_MONGOOSE must be defined to use this file
|
|
#endif
|
|
|
|
#if !defined(ORTHANC_SANDBOXED)
|
|
# error The macro ORTHANC_SANDBOXED must be defined
|
|
#endif
|
|
|
|
#if !defined(ORTHANC_ENABLE_DCMTK)
|
|
# error The macro ORTHANC_ENABLE_DCMTK must be defined
|
|
#endif
|
|
|
|
#if ORTHANC_ENABLE_DCMTK != 1
|
|
# error The macro ORTHANC_ENABLE_DCMTK must be set to 1 to use this file
|
|
#endif
|
|
|
|
#include "ITagVisitor.h"
|
|
#include "../DicomFormat/DicomInstanceHasher.h"
|
|
#include "../DicomFormat/DicomPath.h"
|
|
#include "../Images/ImageAccessor.h"
|
|
#include "../IDynamicObject.h"
|
|
#include "../Toolbox.h"
|
|
|
|
#if ORTHANC_ENABLE_CIVETWEB == 1 || ORTHANC_ENABLE_MONGOOSE == 1
|
|
# include "../RestApi/RestApiOutput.h"
|
|
#endif
|
|
|
|
#include <boost/shared_ptr.hpp>
|
|
|
|
|
|
class DcmDataset;
|
|
class DcmFileFormat;
|
|
|
|
namespace Orthanc
|
|
{
|
|
class ORTHANC_PUBLIC ParsedDicomFile : public IDynamicObject
|
|
{
|
|
private:
|
|
struct PImpl;
|
|
boost::shared_ptr<PImpl> pimpl_;
|
|
|
|
ParsedDicomFile(const ParsedDicomFile& other,
|
|
bool keepSopInstanceUid);
|
|
|
|
void CreateFromDicomMap(const DicomMap& source,
|
|
Encoding defaultEncoding,
|
|
bool permissive,
|
|
const std::string& defaultPrivateCreator,
|
|
const std::map<uint16_t, std::string>& privateCreators);
|
|
|
|
void RemovePrivateTagsInternal(const std::set<DicomTag>* toKeep);
|
|
|
|
void UpdateStorageUid(const DicomTag& tag,
|
|
const std::string& value,
|
|
bool decodeDataUriScheme);
|
|
|
|
void InvalidateCache();
|
|
|
|
bool EmbedContentInternal(const std::string& dataUriScheme);
|
|
|
|
void EncapsulateDocument(MimeType mime,
|
|
const std::string& document);
|
|
|
|
// For internal use only, in order to provide const-correctness on
|
|
// the top of DCMTK API
|
|
DcmFileFormat& GetDcmtkObjectConst() const;
|
|
|
|
void ConfigureTagsForUncompressedImage(unsigned int& bytesPerPixel /* out */,
|
|
const ImageAccessor& accessor);
|
|
|
|
explicit ParsedDicomFile(DcmFileFormat* dicom); // This takes ownership (no clone)
|
|
|
|
#if ORTHANC_BUILDING_FRAMEWORK_LIBRARY == 1
|
|
// Alias for binary compatibility with Orthanc Framework 1.7.2 => don't use it anymore
|
|
void DatasetToJson(Json::Value& target,
|
|
DicomToJsonFormat format,
|
|
DicomToJsonFlags flags,
|
|
unsigned int maxStringLength);
|
|
DcmFileFormat& GetDcmtkObject() const;
|
|
void Apply(ITagVisitor& visitor);
|
|
ParsedDicomFile* Clone(bool keepSopInstanceUid);
|
|
bool LookupTransferSyntax(std::string& result);
|
|
bool LookupTransferSyntax(std::string& result) const;
|
|
bool GetTagValue(std::string& value,
|
|
const DicomTag& tag);
|
|
#endif
|
|
|
|
public:
|
|
explicit ParsedDicomFile(bool createIdentifiers); // Create a minimal DICOM instance
|
|
|
|
ParsedDicomFile(const DicomMap& map,
|
|
Encoding defaultEncoding,
|
|
bool permissive);
|
|
|
|
ParsedDicomFile(const DicomMap& map,
|
|
Encoding defaultEncoding,
|
|
bool permissive,
|
|
const std::string& defaultPrivateCreator,
|
|
const std::map<uint16_t, std::string>& privateCreators);
|
|
|
|
ParsedDicomFile(const void* content,
|
|
size_t size);
|
|
|
|
explicit ParsedDicomFile(const std::string& content);
|
|
|
|
explicit ParsedDicomFile(DcmDataset& dicom); // This clones the DCMTK object
|
|
|
|
explicit ParsedDicomFile(DcmFileFormat& dicom); // This clones the DCMTK object
|
|
|
|
static ParsedDicomFile* AcquireDcmtkObject(DcmFileFormat* dicom);
|
|
|
|
DcmFileFormat& GetDcmtkObject();
|
|
|
|
// The "ParsedDicomFile" object cannot be used after calling this method
|
|
DcmFileFormat* ReleaseDcmtkObject();
|
|
|
|
ParsedDicomFile* Clone(bool keepSopInstanceUid) const;
|
|
|
|
#if ORTHANC_ENABLE_CIVETWEB == 1 || ORTHANC_ENABLE_MONGOOSE == 1
|
|
void SendPathValue(RestApiOutput& output,
|
|
const UriComponents& uri) const;
|
|
|
|
void Answer(RestApiOutput& output) const;
|
|
#endif
|
|
|
|
void Remove(const DicomTag& tag);
|
|
|
|
// Replace the DICOM tag as a NULL/empty value (e.g. for anonymization)
|
|
void Clear(const DicomTag& tag,
|
|
bool onlyIfExists);
|
|
|
|
void Replace(const DicomTag& tag,
|
|
const std::string& utf8Value,
|
|
bool decodeDataUriScheme,
|
|
DicomReplaceMode mode,
|
|
const std::string& privateCreator /* used only for private tags */);
|
|
|
|
void Replace(const DicomTag& tag,
|
|
const Json::Value& value, // Assumed to be encoded with UTF-8
|
|
bool decodeDataUriScheme,
|
|
DicomReplaceMode mode,
|
|
const std::string& privateCreator /* used only for private tags */);
|
|
|
|
void Insert(const DicomTag& tag,
|
|
const Json::Value& value, // Assumed to be encoded with UTF-8
|
|
bool decodeDataUriScheme,
|
|
const std::string& privateCreator /* used only for private tags */);
|
|
|
|
// Cannot be applied to private tags
|
|
void ReplacePlainString(const DicomTag& tag,
|
|
const std::string& utf8Value);
|
|
|
|
// Cannot be applied to private tags
|
|
void SetIfAbsent(const DicomTag& tag,
|
|
const std::string& utf8Value);
|
|
|
|
void RemovePrivateTags();
|
|
|
|
void RemovePrivateTags(const std::set<DicomTag>& toKeep);
|
|
|
|
// WARNING: This function handles the decoding of strings to UTF8
|
|
bool GetTagValue(std::string& value,
|
|
const DicomTag& tag) const;
|
|
|
|
DicomInstanceHasher GetHasher() const;
|
|
|
|
// The "Save" methods are not tagged as "const", as the internal
|
|
// representation might be changed after serialization
|
|
void SaveToMemoryBuffer(std::string& buffer);
|
|
|
|
#if ORTHANC_SANDBOXED == 0
|
|
void SaveToFile(const std::string& path);
|
|
#endif
|
|
|
|
// This method must only be used on the PixelData and EncapsulatedDocument tags
|
|
void EmbedContent(const std::string& dataUriScheme);
|
|
|
|
void EmbedImage(const ImageAccessor& accessor);
|
|
|
|
void EmbedImage(MimeType mime,
|
|
const std::string& content);
|
|
|
|
void EmbedRawPixelData(const std::string& content);
|
|
|
|
Encoding DetectEncoding(bool& hasCodeExtensions) const;
|
|
|
|
// WARNING: This function only sets the encoding, it will not
|
|
// convert the encoding of the tags. Use "ChangeEncoding()" if need be.
|
|
void SetEncoding(Encoding encoding);
|
|
|
|
void DatasetToJson(Json::Value& target,
|
|
DicomToJsonFormat format,
|
|
DicomToJsonFlags flags,
|
|
unsigned int maxStringLength) const;
|
|
|
|
void DatasetToJson(Json::Value& target,
|
|
DicomToJsonFormat format,
|
|
DicomToJsonFlags flags,
|
|
unsigned int maxStringLength,
|
|
const std::set<DicomTag>& ignoreTagLength) const;
|
|
|
|
void HeaderToJson(Json::Value& target,
|
|
DicomToJsonFormat format) const;
|
|
|
|
bool HasTag(const DicomTag& tag) const;
|
|
|
|
bool ExtractPdf(std::string& pdf) const;
|
|
|
|
void GetRawFrame(std::string& target, // OUT
|
|
MimeType& mime, // OUT
|
|
unsigned int frameId) const; // IN
|
|
|
|
unsigned int GetFramesCount() const;
|
|
|
|
static ParsedDicomFile* CreateFromJson(const Json::Value& value,
|
|
DicomFromJsonFlags flags,
|
|
const std::string& privateCreator);
|
|
|
|
void ChangeEncoding(Encoding target);
|
|
|
|
/**
|
|
* The DICOM tags with a string whose size is greater than
|
|
* "maxTagLength", are replaced by a DicomValue whose type is
|
|
* "DicomValue_Null". If "maxTagLength" is zero, all the leaf tags
|
|
* are included, independently of their length.
|
|
**/
|
|
void ExtractDicomSummary(DicomMap& target,
|
|
unsigned int maxTagLength) const;
|
|
|
|
/**
|
|
* This flavor can be used to bypass the "maxTagLength" limitation
|
|
* on a selected set of DICOM tags.
|
|
**/
|
|
void ExtractDicomSummary(DicomMap& target,
|
|
unsigned int maxTagLength,
|
|
const std::set<DicomTag>& ignoreTagLength) const;
|
|
|
|
bool LookupTransferSyntax(DicomTransferSyntax& result) const;
|
|
|
|
bool LookupPhotometricInterpretation(PhotometricInterpretation& result) const;
|
|
|
|
void Apply(ITagVisitor& visitor) const;
|
|
|
|
// Decode the given frame, using the built-in DICOM decoder of Orthanc
|
|
ImageAccessor* DecodeFrame(unsigned int frame) const;
|
|
|
|
void ReplacePath(const DicomPath& path,
|
|
const Json::Value& value, // Assumed to be encoded with UTF-8
|
|
bool decodeDataUriScheme,
|
|
DicomReplaceMode mode,
|
|
const std::string& privateCreator /* used only for private tags */);
|
|
|
|
void RemovePath(const DicomPath& path);
|
|
|
|
void ClearPath(const DicomPath& path,
|
|
bool onlyIfExists);
|
|
|
|
bool LookupSequenceItem(DicomMap& target,
|
|
const DicomPath& path,
|
|
size_t sequenceIndex) const;
|
|
|
|
void GetDefaultWindowing(double& windowCenter,
|
|
double& windowWidth,
|
|
unsigned int frame) const;
|
|
|
|
void GetRescale(double& rescaleIntercept,
|
|
double& rescaleSlope,
|
|
unsigned int frame) const;
|
|
|
|
void ListOverlays(std::set<uint16_t>& groups) const;
|
|
|
|
ImageAccessor* DecodeOverlay(int& originX,
|
|
int& originY,
|
|
uint16_t group) const;
|
|
|
|
ImageAccessor* DecodeAllOverlays(int& originX,
|
|
int& originY) const;
|
|
|
|
void InjectEmptyPixelData(ValueRepresentation vr);
|
|
|
|
// Remove all the tags after pixel data
|
|
void RemoveFromPixelData();
|
|
|
|
ValueRepresentation GuessPixelDataValueRepresentation() const;
|
|
|
|
void EncapsulatePixelData(const std::string& dataUriScheme);
|
|
};
|
|
}
|