533 lines
23 KiB
C++
533 lines
23 KiB
C++
/*
|
|
*
|
|
* Copyright (C) 1994-2016, OFFIS e.V.
|
|
* All rights reserved. See COPYRIGHT file for details.
|
|
*
|
|
* This software and supporting documentation were developed by
|
|
*
|
|
* OFFIS e.V.
|
|
* R&D Division Health
|
|
* Escherweg 2
|
|
* D-26121 Oldenburg, Germany
|
|
*
|
|
*
|
|
* Module: dcmdata
|
|
*
|
|
* Author: Gerd Ehlers, Andreas Barth
|
|
*
|
|
* Purpose: Interface of class DcmDirectoryRecord
|
|
*
|
|
*/
|
|
|
|
#ifndef DCDIRREC_H
|
|
#define DCDIRREC_H
|
|
|
|
#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */
|
|
|
|
#include "dcmtk/dcmdata/dcitem.h"
|
|
#include "dcmtk/dcmdata/dcsequen.h"
|
|
#include "dcmtk/dcmdata/dcfilefo.h"
|
|
|
|
|
|
/// types of directory records in a DICOMDIR
|
|
typedef enum {
|
|
/// root
|
|
ERT_root = 0,
|
|
/// curve (retired)
|
|
ERT_Curve = 1,
|
|
/// film box (retired)
|
|
ERT_FilmBox = 2,
|
|
/// film session (retired)
|
|
ERT_FilmSession = 3,
|
|
/// image
|
|
ERT_Image = 4,
|
|
/// image box (retired)
|
|
ERT_ImageBox = 5,
|
|
/// interpretation (retired)
|
|
ERT_Interpretation = 6,
|
|
/// modality LUT (retired)
|
|
ERT_ModalityLut = 7,
|
|
/// MRDR (retired)
|
|
ERT_Mrdr = 8,
|
|
/// overlay (retired)
|
|
ERT_Overlay = 9,
|
|
/// patient
|
|
ERT_Patient = 10,
|
|
/// print queue (retired)
|
|
ERT_PrintQueue = 11,
|
|
/// private
|
|
ERT_Private = 12,
|
|
/// results
|
|
ERT_Results = 13,
|
|
/// series
|
|
ERT_Series = 14,
|
|
/// study
|
|
ERT_Study = 15,
|
|
/// study component (retired)
|
|
ERT_StudyComponent = 16,
|
|
/// topic (retired)
|
|
ERT_Topic = 17,
|
|
/// visit (retired)
|
|
ERT_Visit = 18,
|
|
/// VOI LUT (retired)
|
|
ERT_VoiLut = 19,
|
|
/// SR document
|
|
ERT_SRDocument = 20,
|
|
/// presentation state
|
|
ERT_Presentation = 21,
|
|
/// waveform
|
|
ERT_Waveform = 22,
|
|
/// RT dose
|
|
ERT_RTDose = 23,
|
|
/// RT structure set
|
|
ERT_RTStructureSet = 24,
|
|
/// RT plan
|
|
ERT_RTPlan = 25,
|
|
/// RT treatment record
|
|
ERT_RTTreatRecord = 26,
|
|
/// stored print (retired)
|
|
ERT_StoredPrint = 27,
|
|
/// key object selection document
|
|
ERT_KeyObjectDoc = 28,
|
|
/// registration
|
|
ERT_Registration = 29,
|
|
/// fiducial
|
|
ERT_Fiducial = 30,
|
|
/// raw data
|
|
ERT_RawData = 31,
|
|
/// spectroscopy
|
|
ERT_Spectroscopy = 32,
|
|
/// encapsulated document
|
|
ERT_EncapDoc = 33,
|
|
/// value map
|
|
ERT_ValueMap = 34,
|
|
/// hanging protocol
|
|
ERT_HangingProtocol = 35,
|
|
/// stereometric relationships
|
|
ERT_Stereometric = 36,
|
|
/// HL7 structured document
|
|
ERT_HL7StrucDoc = 37,
|
|
/// palette
|
|
ERT_Palette = 38,
|
|
/// surface
|
|
ERT_Surface = 39,
|
|
/// measurement
|
|
ERT_Measurement = 40,
|
|
/// implant
|
|
ERT_Implant = 41,
|
|
/// implant group
|
|
ERT_ImplantGroup = 42,
|
|
/// implant assembly
|
|
ERT_ImplantAssy = 43,
|
|
/// plan
|
|
ERT_Plan = 44,
|
|
/// surface scan
|
|
ERT_SurfaceScan = 45,
|
|
/// tractography
|
|
ERT_Tract = 46,
|
|
/// assessment
|
|
ERT_Assessment = 47
|
|
} E_DirRecType;
|
|
|
|
|
|
class DcmDicomDir;
|
|
|
|
/** a class representing a directory record dataset in a DICOMDIR.
|
|
*/
|
|
class DCMTK_DCMDATA_EXPORT DcmDirectoryRecord : public DcmItem
|
|
{
|
|
|
|
friend class DcmDicomDir;
|
|
|
|
public:
|
|
/// default constructor
|
|
DcmDirectoryRecord();
|
|
|
|
/** constructor
|
|
* @param tag attribute tag
|
|
* @param len length of the attribute value
|
|
*/
|
|
DcmDirectoryRecord(const DcmTag &tag,
|
|
const Uint32 len);
|
|
|
|
/** constructor
|
|
* @param recordType record type
|
|
* @param referencedFileID referenced file ID in DICOM format
|
|
* @param sourceFileName path to referenced file in operating system specific format
|
|
* @param fileFormat fileFormat for sourceFileName, can be NULL
|
|
*/
|
|
DcmDirectoryRecord(const E_DirRecType recordType,
|
|
const char *referencedFileID, // DICOM format with '\\'
|
|
const OFFilename &sourceFileName, // OS format
|
|
DcmFileFormat* fileFormat = NULL);
|
|
|
|
/** constructor
|
|
* @param recordTypeName record type as string
|
|
* @param referencedFileID referenced file ID in DICOM format
|
|
* @param sourceFileName path to referenced file in operating system specific format
|
|
* @param fileFormat fileFormat for sourceFileName, can be NULL
|
|
*/
|
|
DcmDirectoryRecord(const char *recordTypeName,
|
|
const char *referencedFileID, // DICOM format with '\\'
|
|
const OFFilename &sourceFileName, // OS format
|
|
DcmFileFormat* fileFormat = NULL);
|
|
|
|
/** copy constructor
|
|
* @param oldDirRec element to be copied
|
|
*/
|
|
DcmDirectoryRecord(const DcmDirectoryRecord &oldDirRec);
|
|
|
|
/** assignment operator
|
|
* @param obj the directory record to be copied
|
|
*/
|
|
DcmDirectoryRecord &operator=(const DcmDirectoryRecord &obj);
|
|
|
|
/// destructor
|
|
virtual ~DcmDirectoryRecord();
|
|
|
|
/** clone method
|
|
* @return deep copy of this object
|
|
*/
|
|
virtual DcmObject *clone() const
|
|
{
|
|
return new DcmDirectoryRecord(*this);
|
|
}
|
|
|
|
/** Virtual object copying. This method can be used for DcmObject
|
|
* and derived classes to get a deep copy of an object. Internally
|
|
* the assignment operator is called if the given DcmObject parameter
|
|
* is of the same type as "this" object instance. If not, an error
|
|
* is returned. This function permits copying an object by value
|
|
* in a virtual way which therefore is different to just calling the
|
|
* assignment operator of DcmElement which could result in slicing
|
|
* the object.
|
|
* @param rhs - [in] The instance to copy from. Has to be of the same
|
|
* class type as "this" object
|
|
* @return EC_Normal if copying was successful, error otherwise
|
|
*/
|
|
virtual OFCondition copyFrom(const DcmObject& rhs);
|
|
|
|
/** return identifier for this class. Every class derived from this class
|
|
* returns a unique value of type enum DcmEVR for this call. This is used
|
|
* as a "poor man's RTTI" to correctly identify instances derived from
|
|
* this class even on compilers not supporting RTTI.
|
|
* @return type identifier of this class
|
|
*/
|
|
virtual DcmEVR ident() const;
|
|
|
|
/// returns current status flag
|
|
inline OFCondition error() const { return errorFlag; }
|
|
|
|
/** mode specifying whether the SpecificCharacterSet (0008,0005) element should be
|
|
* checked by convertCharacterSet() or not, i.e.\ whether this element might be
|
|
* present on this dataset-level.
|
|
* @return always returns OFTrue, i.e.\ SpecificCharacterSet should be checked
|
|
*/
|
|
virtual OFBool checkForSpecificCharacterSet() const { return OFTrue; }
|
|
|
|
/** convert all element values that are contained in this record and that are
|
|
* affected by SpecificCharacterSet from the given source character set to the given
|
|
* destination character set. The defined terms for a particular character set can
|
|
* be found in the DICOM standard, e.g. "ISO_IR 100" for ISO 8859-1 (Latin 1) or
|
|
* "ISO_IR 192" for Unicode in UTF-8. An empty string denotes the default character
|
|
* repertoire, which is ASCII (7-bit). If multiple values are given for 'fromCharset'
|
|
* (separated by a backslash) code extension techniques are used and escape sequences
|
|
* may be encountered in the source string to switch between the specified character
|
|
* sets.
|
|
* @param fromCharset name of the source character set(s) used for the conversion
|
|
* @param toCharset name of the destination character set used for the conversion.
|
|
* Only a single value is permitted (i.e. no code extensions).
|
|
* @param transliterate mode specifying whether a character that cannot be
|
|
* represented in the destination character encoding is approximated through one
|
|
* or more characters that look similar to the original one
|
|
* @param updateCharset if OFTrue, the SpecificCharacterSet (0008,0005) element is
|
|
* updated, i.e.\ the current value is either replaced or a new element is inserted
|
|
* or the existing element is deleted. If OFFalse the SpecificCharacterSet element
|
|
* remains unchanged.
|
|
* @param discardIllegal mode specifying whether characters that cannot be represented
|
|
* in the destination character encoding will be silently discarded
|
|
* @return status, EC_Normal if successful, an error code otherwise
|
|
*/
|
|
virtual OFCondition convertCharacterSet(const OFString &fromCharset,
|
|
const OFString &toCharset,
|
|
const OFBool transliterate = OFFalse,
|
|
const OFBool updateCharset = OFFalse,
|
|
const OFBool discardIllegal = OFFalse);
|
|
|
|
/** convert all element values that are contained in this record and that are
|
|
* affected by SpecificCharacterSet to the given destination character set. If not
|
|
* disabled, the source character set is determined automatically from the value of
|
|
* the SpecificCharacterSet (0008,0005) element. The defined terms for the
|
|
* destination character set can be found in the DICOM standard, e.g. "ISO_IR 100"
|
|
* for ISO 8859-1 (Latin 1) or "ISO_IR 192" for Unicode in UTF-8. An empty string
|
|
* denotes the default character repertoire, which is ASCII (7-bit).
|
|
* @param toCharset name of the destination character set used for the conversion.
|
|
* Only a single value is permitted (i.e. no code extensions).
|
|
* @param transliterate mode specifying whether a character that cannot be
|
|
* represented in the destination character encoding is approximated through one
|
|
* or more characters that look similar to the original one
|
|
* @param ignoreCharset if OFTrue, the value of SpecificCharacterSet is ignored.
|
|
* Also see checkForSpecificCharacterSet().
|
|
* @param discardIllegal mode specifying whether characters that cannot be represented
|
|
* in the destination character encoding will be silently discarded
|
|
* @return status, EC_Normal if successful, an error code otherwise
|
|
*/
|
|
virtual OFCondition convertCharacterSet(const OFString &toCharset,
|
|
const OFBool transliterate = OFFalse,
|
|
const OFBool ignoreCharset = OFFalse,
|
|
const OFBool discardIllegal = OFFalse);
|
|
|
|
/** convert all element values that are contained in this record and that are
|
|
* affected by SpecificCharacterSet from the currently selected source character
|
|
* set to the currently selected destination character set. Since the Basic
|
|
* Directory IOD, which specifies the structure and content of a DICOMDIR, does not
|
|
* contain the SpecificCharacterSet (0008,0005) element in the main dataset but in
|
|
* each directory record, this method also checks for this element and creates a new
|
|
* character set converter for the contained data elements (if needed).
|
|
* @param converter character set converter to be used to convert the element values
|
|
* @return status, EC_Normal if successful, an error code otherwise
|
|
*/
|
|
virtual OFCondition convertCharacterSet(DcmSpecificCharacterSet &converter);
|
|
|
|
/** print all elements of the item to a stream
|
|
* @param out output stream
|
|
* @param flags optional flag used to customize the output (see DCMTypes::PF_xxx)
|
|
* @param level current level of nested items. Used for indentation.
|
|
* @param pixelFileName not used
|
|
* @param pixelCounter not used
|
|
*/
|
|
virtual void print(STD_NAMESPACE ostream&out,
|
|
const size_t flags = 0,
|
|
const int level = 0,
|
|
const char *pixelFileName = NULL,
|
|
size_t *pixelCounter = NULL);
|
|
|
|
/** This function reads the information of all attributes which
|
|
* are captured in the input stream and captures this information
|
|
* in elementList. Each attribute is represented as an element
|
|
* in this list. If not all information for an attribute could be
|
|
* read from the stream, the function returns EC_StreamNotifyClient.
|
|
* @param inStream The stream which contains the information.
|
|
* @param xfer The transfer syntax which was used to encode
|
|
* the information in inStream.
|
|
* @param glenc Encoding type for group length; specifies
|
|
* what will be done with group length tags.
|
|
* @param maxReadLength Maximum read length for reading an attribute value.
|
|
* @return status, EC_Normal if successful, an error code otherwise
|
|
*/
|
|
virtual OFCondition read(DcmInputStream & inStream,
|
|
const E_TransferSyntax xfer,
|
|
const E_GrpLenEncoding glenc = EGL_noChange,
|
|
const Uint32 maxReadLength = DCM_MaxReadLength);
|
|
|
|
/** write object in XML format
|
|
* @param out output stream to which the XML document is written
|
|
* @param flags optional flag used to customize the output (see DCMTypes::XF_xxx)
|
|
* @return status, EC_Normal if successful, an error code otherwise
|
|
*/
|
|
virtual OFCondition writeXML(STD_NAMESPACE ostream&out,
|
|
const size_t flags = 0);
|
|
|
|
|
|
/** check the currently stored element value
|
|
* @param autocorrect correct value length if OFTrue
|
|
* @return status, EC_Normal if value length is correct, an error code otherwise
|
|
*/
|
|
virtual OFCondition verify(const OFBool autocorrect = OFFalse);
|
|
|
|
/** a complex, stack-based, hierarchical search method. It allows for a search
|
|
* for a DICOM object with a given attribute within a given container,
|
|
* hierarchically, from a starting position identified through a cursor stack.
|
|
* @param xtag the DICOM attribute tag we are searching for
|
|
* @param resultStack depending on the search mode (see below), this parameter
|
|
* either serves as an input and output parameter, or as an output parameter
|
|
* only (the latter being the default). When used as an input parameter,
|
|
* the cursor stack defines the start position for the search within a
|
|
* hierarchical DICOM dataset. Upon successful return, the stack contains
|
|
* the position of the element found, in the form of a pointer to each dataset,
|
|
* sequence, item and element from the main dataset down to the found element.
|
|
* @param mode search mode, controls how the search stack is handled.
|
|
* In the default mode, ESM_fromHere, the stack is ignored on input, and
|
|
* the search starts in the object for which this method is called.
|
|
* In the other modes, the stack is used both as an input and an output
|
|
* parameter and defines the starting point for the search.
|
|
* @param searchIntoSub if true, the search will be performed hierarchically descending
|
|
* into the sequences and items of the dataset. If false, only the current container
|
|
* (sequence or item) will be traversed.
|
|
* @return EC_Normal if found, EC_TagNotFound if not found, an error code is something went wrong.
|
|
*/
|
|
virtual OFCondition search(const DcmTagKey &xtag, // in
|
|
DcmStack &resultStack, // inout
|
|
E_SearchMode mode = ESM_fromHere, // in
|
|
OFBool searchIntoSub = OFTrue); // in
|
|
|
|
/// get record type of this directory record
|
|
virtual E_DirRecType getRecordType();
|
|
|
|
/** if this directory record references an MRDR (multi-reference directory record),
|
|
* return pointer to the MRDR referenced by this object.
|
|
* @return pointer to MRDR referenced by this object or NULL of no MRDR referenced
|
|
*/
|
|
virtual DcmDirectoryRecord* getReferencedMRDR();
|
|
|
|
/** create a reference from this record to an MRDR
|
|
* @param mrdr pointer to MRDR
|
|
* @return EC_Normal upon success, an error code otherwise
|
|
*/
|
|
virtual OFCondition assignToMRDR(DcmDirectoryRecord *mrdr ); // in
|
|
|
|
/** open a DICOM file and make this directory record into a directory
|
|
* record for that DICOM file. The most relevant record keys
|
|
* (SOP Class UID, SOP instance UID, Transfer Syntax UID) are inserted
|
|
* into the directory record.
|
|
* @param referencedFileID referenced file ID in DICOM format
|
|
* @param sourceFileName path to file in operating system specific format
|
|
* @return EC_Normal upon success, an error code otherwise
|
|
*/
|
|
virtual OFCondition assignToSOPFile(const char *referencedFileID,
|
|
const OFFilename &sourceFileName);
|
|
|
|
/// return number of directory records that are child record of this one
|
|
virtual unsigned long cardSub() const;
|
|
|
|
/** insert a child directory record
|
|
* @param dirRec directory record to be inserted. Must be allocated on heap, ownership is
|
|
* transferred to this object
|
|
* @param where index where to insert object
|
|
* @param before flag indicating whether to insert the record before or after the element
|
|
* identified by where
|
|
* @return EC_Normal upon success, an error code otherwise
|
|
*/
|
|
virtual OFCondition insertSub(DcmDirectoryRecord* dirRec,
|
|
unsigned long where = DCM_EndOfListIndex,
|
|
OFBool before = OFFalse);
|
|
|
|
/** insert new directory child record at the current position.
|
|
* The current position is stored internally in the 'lowerLevelList' member variable.
|
|
* @param dirRec new child record to be inserted
|
|
* @param before flag indicating whether to insert the record before (OFFalse) or
|
|
* after (OFTrue) the current position
|
|
* @return status, EC_Normal upon success, an error code otherwise
|
|
*/
|
|
virtual OFCondition insertSubAtCurrentPos(DcmDirectoryRecord *dirRec,
|
|
OFBool before = OFFalse);
|
|
|
|
/** access child directory record. Returns a pointer to the object maintained
|
|
* as a child, not a copy.
|
|
* @param num index, must be < cardSub()
|
|
* @return pointer to child directory record or NULL if not found
|
|
*/
|
|
virtual DcmDirectoryRecord* getSub(const unsigned long num);
|
|
|
|
/** get next directory child record starting at a given record
|
|
* @param dirRec record to start from (goto first record if NULL)
|
|
* @return pointer to next record if successful, NULL otherwise
|
|
*/
|
|
virtual DcmDirectoryRecord* nextSub(const DcmDirectoryRecord *dirRec);
|
|
|
|
/** remove child directory record. If found, the record is not deleted but
|
|
* returned to the caller who is responsible for further management of the
|
|
* DcmDirectoryRecord object.
|
|
* @param num index number of element, must be < cardSub()
|
|
* @return pointer to DcmDirectoryRecord if found, NULL otherwise
|
|
*/
|
|
virtual DcmDirectoryRecord* removeSub(const unsigned long num);
|
|
|
|
/** remove child directory record. If found, the record is not deleted but
|
|
* returned to the caller who is responsible for further management of the
|
|
* DcmDirectoryRecord object.
|
|
* @param dirRec pointer to element to be removed from list
|
|
* @return pointer to element if found, NULL otherwise
|
|
*/
|
|
virtual DcmDirectoryRecord* removeSub(DcmDirectoryRecord *dirRec);
|
|
|
|
/** remove child directory record and delete file referenced by that record, if any
|
|
* @param num index number of element, must be < cardSub()
|
|
* @return status, EC_Normal upon success, an error code otherwise
|
|
*/
|
|
virtual OFCondition deleteSubAndPurgeFile(const unsigned long num);
|
|
|
|
/** remove child directory record and delete file referenced by that record, if any
|
|
* @param dirRec pointer to element to be removed from list
|
|
* @return status, EC_Normal upon success, an error code otherwise
|
|
*/
|
|
virtual OFCondition deleteSubAndPurgeFile(DcmDirectoryRecord *dirRec);
|
|
|
|
/// revert the list of child directory records to default constructed (empty) state
|
|
virtual OFCondition clearSub();
|
|
|
|
/** store the filename from which this directory record was read from
|
|
* @param fname filename, must not be empty
|
|
*/
|
|
virtual void setRecordsOriginFile(const OFFilename &fname);
|
|
|
|
/// get the filename from which this directory record was read from, empty if not set
|
|
virtual const OFFilename &getRecordsOriginFile();
|
|
|
|
/// get the offset in file of this directory record
|
|
Uint32 getFileOffset() const;
|
|
|
|
protected:
|
|
|
|
// side-effect-free conversion routines:
|
|
E_DirRecType recordNameToType(const char *recordTypeName);
|
|
char* buildFileName(const char *origName, char *destName);
|
|
OFCondition checkHierarchy(const E_DirRecType upperRecord,
|
|
const E_DirRecType lowerRecord);
|
|
|
|
// access to data elements within the Directory Records:
|
|
OFCondition setRecordType(E_DirRecType newType);
|
|
E_DirRecType lookForRecordType();
|
|
OFCondition setReferencedFileID( const char *referencedFileID);
|
|
const char* lookForReferencedFileID();
|
|
DcmDirectoryRecord* lookForReferencedMRDR();
|
|
const char* getReferencedFileName(); // local or in MRDR
|
|
OFCondition setRecordInUseFlag(const Uint16 newFlag);
|
|
Uint16 lookForRecordInUseFlag();
|
|
Uint32 setFileOffset(Uint32 position);
|
|
|
|
// access to MRDR data element:
|
|
OFCondition setNumberOfReferences(Uint32 newRefNum);
|
|
Uint32 lookForNumberOfReferences();
|
|
Uint32 increaseRefNum();
|
|
Uint32 decreaseRefNum();
|
|
|
|
// misc:
|
|
/** Load all necessary info for this directory record.
|
|
* @param referencedFileID file ID that is being referenced, may be NULL
|
|
* @param sourceFileName filename for the DICOM file, may be empty (unspecified)
|
|
* @param fileFormat If not NULL, then this should be the result of loading
|
|
* sourceFileName. May only be non-NULL if sourceFileName isn't empty.
|
|
*/
|
|
OFCondition fillElementsAndReadSOP(const char *referencedFileID,
|
|
const OFFilename &sourceFileName,
|
|
DcmFileFormat *fileFormat = NULL);
|
|
OFCondition masterInsertSub(DcmDirectoryRecord *dirRec,
|
|
const unsigned long where = DCM_EndOfListIndex);
|
|
OFCondition purgeReferencedFile();
|
|
|
|
private:
|
|
|
|
/// filename (path) of the file from which this directory record was read
|
|
OFFilename recordsOriginFile;
|
|
|
|
/// list of child directory records, kept in a sequence of items
|
|
DcmSequenceOfItems *lowerLevelList;
|
|
|
|
/// directory record type of this record
|
|
E_DirRecType DirRecordType;
|
|
|
|
/// pointer to multi-referenced directory record (MRDR) if this record refers to one, NULL otherwise
|
|
DcmDirectoryRecord *referencedMRDR;
|
|
|
|
/// number of other directory records referring to this one; used for MRDR records
|
|
Uint32 numberOfReferences;
|
|
|
|
/// byte offset at which the start of this directory record resides in the file from which it was read
|
|
Uint32 offsetInFile;
|
|
|
|
};
|
|
|
|
|
|
#endif // DCDIRREC_H
|