ctkDICOMDataset.h 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  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.commontk.org/LICENSE
  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 __ctkDICOMDataset_h
  15. #define __ctkDICOMDataset_h
  16. #include "ctkDICOMCoreExport.h"
  17. #include "ctkDICOMPersonName.h"
  18. #ifndef WIN32
  19. #define HAVE_CONFIG_H
  20. #endif
  21. #include <dcdatset.h> // DCMTK DcmDataset
  22. #include <QtCore>
  23. class DcmDataDictionary;
  24. class ctkDICOMDatasetPrivate;
  25. /**
  26. \brief Base class for DICOM objects and interface with DICOM toolkit DCMTK.
  27. This class serves as the base class for all DICOM objects (patient, study, series, image).
  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. Basically it offers a lot of convenience methods for subclasses to read and write DICOM attributes
  31. using Qt types. It is the subclasses responsibility to use the correct data types as defined in DICOM.
  32. \note ONLY the Get.. methods should be used to access the internal dataset.
  33. When reading string type attributes (LO, LT, PN, SH, ST, UT), we consider the "specific character set"
  34. tag and decode the stored string using the correct encoding (using Qt methods). This allows to
  35. display e.g. person names written in arabic, hebrew, greek, russian, etc. letters.
  36. \warning Right now, asian phonetic strings cause problems. We have to learn the concept.
  37. \warning Helpers for writing DICOM attributes are not yet implemented. Implementation is straightforward though and can be done when necessary.
  38. \warning DateTime objects ignore the timezone at the moment. This is however of secondary importance.
  39. A subclass could possibly want to store the internal DcmDataset.
  40. For this purpose, the internal DcmDataset is serialized into a memory buffer using DcmDataset::write(..). This buffer
  41. is stored in a base64 encoded string. For deserialization we decode the string and use DcmDataset::read(..).
  42. */
  43. class CTK_DICOM_CORE_EXPORT ctkDICOMDataset : public DcmDataset
  44. {
  45. public:
  46. typedef QObject Superclass;
  47. ctkDICOMDataset();
  48. virtual ~ctkDICOMDataset();
  49. /**
  50. \brief For initialization from a DcmDataset in a constructor / assignment.
  51. This method should be overwritten by all derived classes. It should
  52. be called from the constructor or assignment operators when the class
  53. should copy information from a DcmDataset object.
  54. \warning Derived classes must call PDICOMDataset::InitializeFromDataset(...) to correctly copy encoding information.
  55. */
  56. virtual void InitializeFromDataset(DcmDataset* dataset);
  57. /**
  58. \brief Store a string representation of the object to a database field.
  59. The internal DcmDataset is serialized into a memory buffer using DcmDataset::write(..).
  60. To store the memory buffer in a simple string database field, we convert it to a base64 encoded string.
  61. Doing so prevents errors from encoding conversions that could be made by QString or the database etc.
  62. */
  63. void Serialize();
  64. /**
  65. \brief Restore the object from a string representation in a database field.
  66. The database stored string is base64 decoded into a memory buffer. Then
  67. the internal DcmDataset is created using DcmDataset::read(..).
  68. */
  69. void Deserialize();
  70. /**
  71. \brief To be called from InitializeData, flags status as dirty.
  72. This is to allow data to be read as late as possible. All the
  73. Get/SetElement... methods ensure initialization, which checks this flag.
  74. */
  75. void MarkForInitialization();
  76. /**
  77. \brief Called by all Get/Set methods to initialize DcmDataSet if needed.
  78. */
  79. void EnsureDcmDataSetIsInitialized() const;
  80. /**
  81. \brief Find element in dataset and copy it into internal DcmDataset
  82. Attribute types 1, 1C, 2, 2C, 3 as defined in DICOM can be encoded as
  83. hex values 0x1, 0x1C, 0x2, 0x2C, 0x3.
  84. Conditional attributes are considered MUST attributes. The calling
  85. function shall test the conditions before calling CopyElement
  86. (since conditions might be complex).
  87. */
  88. bool CopyElement( DcmDataset* dataset, const DcmTagKey& tag, int type );
  89. /**
  90. \brief creates a QString from the OFString, respecting the "specific character set" of the Dataset.
  91. This method checks if the dataset has an attribute "specific character set".
  92. If so, all attributes of types Long String (LO), Long Text (LT), Person Name (PN), Short String (SH),
  93. Short Text (ST), Unlimited Text (UT) should be interpreted as encoded with a special set.
  94. See implementation for details.
  95. */
  96. QString Decode(const DcmTag& tag, const OFString& raw) const;
  97. /**
  98. \brief creates an OFString from the QtString
  99. \warning The method currently assumes that the encoding of the passed string if latin1 and converts
  100. it accordingly. The passed DICOM tag is not yet evaluated to determine the actual encoding type.
  101. */
  102. OFString Encode(const DcmTag& tag, const QString& qstring) const;
  103. /**
  104. \brief A const-correct version of DcmDataset::findAndGetElement.
  105. */
  106. OFCondition findAndGetElement(const DcmTag& tag, DcmElement*& element, const OFBool searchIntoSub=OFFalse) const; // DCMTK is not const-correct
  107. /**
  108. \brief A const-correct version of DcmDataset::findAndGetOFString.
  109. */
  110. OFCondition findAndGetOFString(const DcmTag& tag, OFString& value, const unsigned long pos = 0, const OFBool searchIntoSub=OFFalse) const; // DCMTK is not const-correct
  111. static bool CheckCondition(const OFCondition&);
  112. /**
  113. \brief Get-methods for for all subtypes of DcmByteString
  114. */
  115. QString GetAllElementValuesAsString( const DcmTag& tag ) const;
  116. QString GetElementAsString( const DcmTag& tag, unsigned long pos = 0 ) const;
  117. QStringList GetElementAsStringList( const DcmTag& tag ) const;
  118. QPersonName GetElementAsPersonName( const DcmTag& tag, unsigned long pos = 0 ) const;
  119. QPersonNameList GetElementAsPersonNameList( const DcmTag& tag ) const;
  120. QDate GetElementAsDate( const DcmTag& tag, unsigned long pos = 0 ) const;
  121. QTime GetElementAsTime( const DcmTag& tag, unsigned long pos = 0 ) const;
  122. double GetElementAsDouble( const DcmTag& tag, unsigned long pos = 0 ) const; // type DS
  123. long GetElementAsInteger( const DcmTag& tag, unsigned long pos = 0 ) const; // type IS
  124. int GetElementAsSignedShort( const DcmTag& tag, unsigned long pos = 0 ) const; // type SS
  125. int GetElementAsUnsignedShort( const DcmTag& tag, unsigned long pos = 0 ) const; // type US
  126. /**
  127. \warning IGNORES TIME ZONE at the moment!
  128. */
  129. QDateTime GetElementAsDateTime( const DcmTag& tag, unsigned long pos = 0 ) const;
  130. /**
  131. \brief Set-methods for for all subtypes of DcmByteString
  132. */
  133. bool SetElementAsString( const DcmTag& tag, QString string );
  134. bool SetElementAsStringList( const DcmTag& tag, QStringList stringList ); //> Currently not implemented
  135. bool SetElementAsPersonName( const DcmTag& tag, QPersonName personName );
  136. bool SetElementAsPersonNameList( const DcmTag& tag, QPersonNameList personNameList ); //> Currently not implemented
  137. bool SetElementAsDate( const DcmTag& tag, QDate date );
  138. bool SetElementAsTime( const DcmTag& tag, QTime time );
  139. bool SetElementAsDateTime( const DcmTag& tag, QDateTime dateTime );
  140. bool SetElementAsInteger( const DcmTag& tag, long value, unsigned long pos = 0 ); // type IS
  141. bool SetElementAsSignedShort( const DcmTag& tag, int value, unsigned long pos = 0 ); // type SS
  142. bool SetElementAsUnsignedShort( const DcmTag& tag, int value, unsigned long pos = 0 ); // type US
  143. /**
  144. \brief Get a human-readable version of patient position enumerations used e.g. in DICOM series.
  145. */
  146. static QString TranslateDefinedTermPatientPosition( const QString& dt );
  147. /**
  148. \brief Get a human-readable version of modality enumerations used e.g. in DICOM series.
  149. */
  150. static QString TranslateDefinedTermModality( const QString& dt );
  151. /**
  152. \brief Nicely formatted (group,element) version of a tag
  153. */
  154. static QString TagKey( const DcmTag& tag );
  155. /**
  156. \brief Description (name) of the tag
  157. */
  158. static QString TagDescription( const DcmTag& tag );
  159. /**
  160. \brief Value Representation
  161. */
  162. static QString TagVR( const DcmTag& tag );
  163. protected:
  164. /**
  165. \brief Callback for retrieving a serialized version of this class
  166. You can override this method in a subclass to retrieve a serialized
  167. version of the object from some storage mechanism, eg a database
  168. */
  169. virtual QString GetStoredSerialization();
  170. /**
  171. \brief Callback for storing a serialized version of this class
  172. You can override this method in a subclass to store a serialized
  173. version of the object to some storage mechanism, eg a database
  174. */
  175. virtual void SetStoredSerialization(QString serializedDataset);
  176. QScopedPointer<ctkDICOMDatasetPrivate> d_ptr;
  177. private:
  178. Q_DECLARE_PRIVATE(ctkDICOMDataset);
  179. };
  180. #endif