ctkDICOMItem.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. /*=========================================================================
  2. Library: CTK
  3. Copyright (c) Mint Medical GmbH
  4. Licensed under the Apache License, Version 2.0 (the "License");
  5. you may not use this file except in compliance with the License.
  6. You may obtain a copy of the License at
  7. http://www.apache.org/licenses/LICENSE-2.0.txt
  8. Unless required by applicable law or agreed to in writing, software
  9. distributed under the License is distributed on an "AS IS" BASIS,
  10. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. See the License for the specific language governing permissions and
  12. limitations under the License.
  13. =========================================================================*/
  14. #ifndef __ctkDICOMItem_h
  15. #define __ctkDICOMItem_h
  16. #include "ctkDICOMCoreExport.h"
  17. #include "ctkDICOMPersonName.h"
  18. #include <dcmtk/dcmdata/dcdatset.h> // DCMTK DcmDataset
  19. #include <QtCore>
  20. class DcmDataDictionary;
  21. class ctkDICOMItemPrivate;
  22. /// \ingroup DICOM_Core
  23. ///
  24. /// \brief Base class for DICOM objects and interface with DICOM toolkit DCMTK.
  25. ///
  26. /// This class serves as the base class for all DICOM objects (patient, study, series, image).
  27. ///
  28. /// The class is derived from DcmDataset, the data type that is used by the DICOM toolkit when
  29. /// reading an image file or formulating a message request or receiving a message response (e.g. C-FIND).
  30. ///
  31. /// Basically it offers a lot of convenience methods for subclasses to read and write DICOM attributes
  32. /// using Qt types. It is the subclasses responsibility to use the correct data types as defined in DICOM.
  33. ///
  34. /// \note ONLY the Get.. methods should be used to access the internal dataset.
  35. ///
  36. /// When reading string type attributes (LO, LT, PN, SH, ST, UT), we consider the "specific character set"
  37. /// tag and decode the stored string using the correct encoding (using Qt methods). This allows to
  38. /// display e.g. person names written in arabic, hebrew, greek, russian, etc. letters.
  39. ///
  40. /// \warning Right now, asian phonetic strings cause problems. We have to learn the concept.
  41. /// \warning Helpers for writing DICOM attributes are not yet implemented. Implementation is straightforward though and can be done when necessary.
  42. /// \warning DateTime objects ignore the timezone at the moment. This is however of secondary importance.
  43. ///
  44. /// A subclass could possibly want to store the internal DcmDataset.
  45. /// For this purpose, the internal DcmDataset is serialized into a memory buffer using DcmDataset::write(..). This buffer
  46. /// is stored in a base64 encoded string. For deserialization we decode the string and use DcmDataset::read(..).
  47. class ctkDICOMItem;
  48. typedef ctkDICOMItem ctkDICOMItem;
  49. class CTK_DICOM_CORE_EXPORT ctkDICOMItem
  50. {
  51. public:
  52. typedef QObject Superclass;
  53. ///
  54. /// \brief Create an empty object. This has to be initialized by one of
  55. /// the InitializeFrom... methods before it can be used.
  56. ///
  57. /// @param strictErrorHandling If set to false (the default) only critical errors throw exceptions.
  58. ctkDICOMItem(bool strictErrorHandling = false);
  59. virtual ~ctkDICOMItem();
  60. /// \brief For initialization from a DcmDataset in a constructor / assignment.
  61. ///
  62. /// This method should be overwritten by all derived classes. It should
  63. /// be called from the constructor or assignment operators when the class
  64. /// should copy information from a DcmDataset object.
  65. /// \warning Derived classes must call PDICOMDataset::InitializeFromDataset(...) to correctly copy encoding information.
  66. virtual void InitializeFromItem(DcmItem* dataset, bool takeOwnership = false);
  67. ///
  68. /// \brief For initialization from file in a constructor / assignment.
  69. ///
  70. virtual void InitializeFromFile(const QString& filename,
  71. const E_TransferSyntax readXfer = EXS_Unknown,
  72. const E_GrpLenEncoding groupLength = EGL_noChange,
  73. const Uint32 maxReadLength = DCM_MaxReadLength,
  74. const E_FileReadMode readMode = ERM_autoDetect);
  75. /// \brief Save dataset to file
  76. ///
  77. /// \returns true on success.
  78. bool SaveToFile(const QString& filePath) const;
  79. /// \brief Store a string representation of the object to a database field.
  80. ///
  81. /// The internal DcmDataset is serialized into a memory buffer using DcmDataset::write(..).
  82. /// To store the memory buffer in a simple string database field, we convert it to a base64 encoded string.
  83. /// Doing so prevents errors from encoding conversions that could be made by QString or the database etc.
  84. void Serialize();
  85. /// \brief Restore the object from a string representation in a database field.
  86. ///
  87. /// The database stored string is base64 decoded into a memory buffer. Then
  88. /// the internal DcmDataset is created using DcmDataset::read(..).
  89. void Deserialize();
  90. /// \brief To be called from InitializeData, flags status as dirty.
  91. ///
  92. /// This is to allow data to be read as late as possible. All the
  93. /// Get/SetElement... methods ensure initialization, which checks this flag.
  94. void MarkForInitialization();
  95. /// \brief Is this dataset initialized ?
  96. bool IsInitialized() const;
  97. ///
  98. /// \brief Called by all Get/Set methods to initialize DcmDataSet if needed.
  99. ///
  100. void EnsureDcmDataSetIsInitialized() const;
  101. /// \brief Find element in dataset and copy it into internal DcmDataset
  102. ///
  103. /// Attribute types 1, 1C, 2, 2C, 3 as defined in DICOM can be encoded as
  104. /// hex values 0x1, 0x1C, 0x2, 0x2C, 0x3.
  105. ///
  106. /// Conditional attributes are considered MUST attributes. The calling
  107. /// function shall test the conditions before calling CopyElement
  108. /// (since conditions might be complex).
  109. bool CopyElement( DcmDataset* dataset, const DcmTagKey& tag, int type );
  110. /// \brief creates a QString from the OFString, respecting the "specific character set" of the Dataset.
  111. ///
  112. /// This method checks if the dataset has an attribute "specific character set".
  113. /// If so, all attributes of types Long String (LO), Long Text (LT), Person Name (PN), Short String (SH),
  114. /// Short Text (ST), Unlimited Text (UT) should be interpreted as encoded with a special set.
  115. ///
  116. /// See implementation for details.
  117. QString Decode(const DcmTag& tag, const OFString& raw) const;
  118. /// \brief creates an OFString from the QtString
  119. ///
  120. /// \warning The method currently assumes that the encoding of the passed string if latin1 and converts
  121. /// it accordingly. The passed DICOM tag is not yet evaluated to determine the actual encoding type.
  122. OFString Encode(const DcmTag& tag, const QString& qstring) const;
  123. ///
  124. /// \brief A const-correct version of DcmDataset::findAndGetElement.
  125. ///
  126. OFCondition findAndGetElement(const DcmTag& tag, DcmElement*& element, const OFBool searchIntoSub=OFFalse) const; // DCMTK is not const-correct
  127. ///
  128. /// \brief A const-correct version of DcmDataset::findAndGetOFString.
  129. ///
  130. OFCondition findAndGetOFString(const DcmTag& tag, OFString& value, const unsigned long pos = 0, const OFBool searchIntoSub=OFFalse) const; // DCMTK is not const-correct
  131. static bool CheckCondition(const OFCondition&);
  132. ///
  133. /// \brief Get-methods for for all subtypes of DcmByteString
  134. ///
  135. QString GetAllElementValuesAsString( const DcmTag& tag ) const;
  136. QString GetElementAsString( const DcmTag& tag, unsigned long pos = 0 ) const;
  137. QStringList GetElementAsStringList( const DcmTag& tag ) const;
  138. ctkDICOMPersonName GetElementAsPersonName( const DcmTag& tag, unsigned long pos = 0 ) const;
  139. ctkDICOMPersonNameList GetElementAsPersonNameList( const DcmTag& tag ) const;
  140. QDate GetElementAsDate( const DcmTag& tag, unsigned long pos = 0 ) const;
  141. QTime GetElementAsTime( const DcmTag& tag, unsigned long pos = 0 ) const;
  142. double GetElementAsDouble( const DcmTag& tag, unsigned long pos = 0 ) const; // type DS
  143. long GetElementAsInteger( const DcmTag& tag, unsigned long pos = 0 ) const; // type IS
  144. int GetElementAsSignedShort( const DcmTag& tag, unsigned long pos = 0 ) const; // type SS
  145. int GetElementAsUnsignedShort( const DcmTag& tag, unsigned long pos = 0 ) const; // type US
  146. ///
  147. /// \warning IGNORES TIME ZONE at the moment!
  148. ///
  149. QDateTime GetElementAsDateTime( const DcmTag& tag, unsigned long pos = 0 ) const;
  150. ///
  151. /// \brief Set-methods for for all subtypes of DcmByteString
  152. ///
  153. bool SetElementAsString( const DcmTag& tag, QString string );
  154. bool SetElementAsStringList( const DcmTag& tag, QStringList stringList ); //> Currently not implemented
  155. bool SetElementAsPersonName( const DcmTag& tag, ctkDICOMPersonName personName );
  156. bool SetElementAsPersonNameList( const DcmTag& tag, ctkDICOMPersonNameList personNameList ); //> Currently not implemented
  157. bool SetElementAsDate( const DcmTag& tag, QDate date );
  158. bool SetElementAsTime( const DcmTag& tag, QTime time );
  159. bool SetElementAsDateTime( const DcmTag& tag, QDateTime dateTime );
  160. bool SetElementAsInteger( const DcmTag& tag, long value, unsigned long pos = 0 ); // type IS
  161. bool SetElementAsSignedShort( const DcmTag& tag, int value, unsigned long pos = 0 ); // type SS
  162. bool SetElementAsUnsignedShort( const DcmTag& tag, int value, unsigned long pos = 0 ); // type US
  163. /// Some convenience getter
  164. QString GetStudyInstanceUID() const;
  165. QString GetSeriesInstanceUID() const;
  166. QString GetSOPInstanceUID() const;
  167. ///
  168. /// \brief Get a human-readable version of patient position enumerations used e.g. in DICOM series.
  169. ///
  170. static QString TranslateDefinedTermPatientPosition( const QString& dt );
  171. ///
  172. /// \brief Get a human-readable version of modality enumerations used e.g. in DICOM series.
  173. ///
  174. static QString TranslateDefinedTermModality( const QString& dt );
  175. ///
  176. /// \brief Nicely formatted (group,element) version of a tag
  177. ///
  178. static QString TagKey( const DcmTag& tag );
  179. ///
  180. /// \brief Description (name) of the tag
  181. ///
  182. static QString TagDescription( const DcmTag& tag );
  183. ///
  184. /// \brief Value Representation
  185. ///
  186. static QString TagVR( const DcmTag& tag );
  187. protected:
  188. ///
  189. /// \brief Callback for retrieving a serialized version of this class
  190. ///
  191. /// You can override this method in a subclass to retrieve a serialized
  192. /// version of the object from some storage mechanism, eg a database
  193. ///
  194. virtual QString GetStoredSerialization();
  195. ///
  196. /// \brief Callback for storing a serialized version of this class
  197. ///
  198. /// You can override this method in a subclass to store a serialized
  199. /// version of the object to some storage mechanism, eg a database
  200. ///
  201. virtual void SetStoredSerialization(QString serializedDataset);
  202. QScopedPointer<ctkDICOMItemPrivate> d_ptr;
  203. DcmItem& GetDcmItem() const;
  204. private:
  205. Q_DECLARE_PRIVATE(ctkDICOMItem);
  206. };
  207. #endif