1 /* 2 * 3 * Copyright (C) 2003-2019, OFFIS e.V. 4 * All rights reserved. See COPYRIGHT file for details. 5 * 6 * This software and supporting documentation were developed by 7 * 8 * OFFIS e.V. 9 * R&D Division Health 10 * Escherweg 2 11 * D-26121 Oldenburg, Germany 12 * 13 * 14 * Module: dcmdata 15 * 16 * Author: Michael Onken 17 * 18 * Purpose: Class for modifying DICOM files 19 * 20 */ 21 22 #ifndef MDFDSMAN_H 23 #define MDFDSMAN_H 24 25 #include "dcmtk/config/osconfig.h" // make sure OS specific configuration is included first 26 27 #include "dcmtk/ofstd/ofcond.h" 28 #include "dcmtk/dcmdata/dctagkey.h" 29 #include "dcmtk/dcmdata/dcxfer.h" 30 #include "dcmtk/ofstd/ofcmdln.h" 31 32 33 // forward declarations 34 class DcmDataset; 35 class DcmFileFormat; 36 class DcmElement; 37 38 39 /** This class encapsulates data structures and operations for modifying 40 * DICOM files. Therefore it allows the process of load->modify->save to 41 * provide this service. 42 */ 43 class MdfDatasetManager 44 { 45 public: 46 47 /** Constructor, initializes member-variables 48 */ 49 MdfDatasetManager(); 50 51 /** Destructor 52 */ 53 ~MdfDatasetManager(); 54 55 /** Loads a file into dataset manager 56 * @param file_name file to be loaded 57 @param readMode read file with or without metaheader. Default=autodetect 58 @param xfer try to read with this transfer syntax. Default=autodetect 59 @param createIfNecessary If true, the file is created if it does not exist 60 * @return returns EC_Normal if everything is OK, else an error 61 */ 62 OFCondition loadFile(const char *file_name, 63 const E_FileReadMode readMode = ERM_autoDetect, 64 const E_TransferSyntax xfer = EXS_Unknown, 65 const OFBool createIfNecessary = OFFalse); 66 67 /** Modifies/Inserts a path (with a specific value if desired). 68 * @param tag_path path to item/element 69 * @param value denotes new value of tag 70 * @param only_modify if true, only existing tags are processed. If false, 71 * any not existing tag is inserted 72 * @param update_metaheader updates metaheader UIDs, if related UIDs in 73 * dataset are changed (default=true) 74 * @param ignore_missing_tags if true, tags that could not be found 75 * while modifying (only_modify must be true) 76 * are handled as non-errors 77 * @param no_reservation_checks if true, any missing private reservation 78 * tags are ignored when inserting private 79 * tags. Only makes sense w/o only_modify 80 * @return returns EC_Normal if everything is OK, else an error 81 */ 82 OFCondition modifyOrInsertPath(OFString tag_path, 83 const OFString &value, 84 const OFBool only_modify, 85 const OFBool update_metaheader = OFTrue, 86 const OFBool ignore_missing_tags = OFFalse, 87 const OFBool no_reservation_checks = OFFalse); 88 89 /** Modifies/Inserts a path with a specific value read from file 90 * @param tag_path path to item/element 91 * @param filename name of the file from which the value should be read 92 * @param only_modify if true, only existing tags are processed. If false, 93 * any not existing tag is inserted 94 * @param update_metaheader updates metaheader UIDs, if related UIDs in 95 * dataset are changed (default=true) 96 * @param ignore_missing_tags if true, tags that could not be found 97 * while modifying (only_modify must be true) 98 * are handled as non-errors 99 * @param no_reservation_checks if true, any missing private reservation 100 * tags are ignored when inserting private 101 * tags. Only makes sense w/o only_modify 102 * @return returns EC_Normal if everything is OK, else an error 103 */ 104 OFCondition modifyOrInsertFromFile(OFString tag_path, 105 const OFString &filename, 106 const OFBool only_modify, 107 const OFBool update_metaheader = OFTrue, 108 const OFBool ignore_missing_tags = OFFalse, 109 const OFBool no_reservation_checks = OFFalse); 110 111 /** Modifies all matching tags in dataset to a new value 112 * @param tag_path denotes, which tag to modify 113 * @param value denotes new value of tag 114 * @param update_metaheader if true, metaheader UIDs are updated, 115 * if related dataset UIDs are changed, (default=true) 116 * @param count returns the number of tags that were affected 117 * @param ignore_missing_tags if true, tags that could not be found 118 * while modifying are handled as non-errors 119 * @return returns EC_Normal if everything is OK, else an error 120 */ 121 OFCondition modifyAllTags(OFString tag_path, 122 const OFString &value, 123 const OFBool update_metaheader, 124 int &count, 125 const OFBool ignore_missing_tags = OFFalse); 126 127 /** Deletes tag in dataset 128 * @param tag_path holds complete path to tag 129 * @param all_tags if true, tag is deleted at all levels of dataset, 130 * else only 1st level is accessed 131 * @param ignore_missing_tags if true, tags that could not be found 132 * while modifying are handled as non-errors 133 * @return returns EC_Normal if everything is OK, else an error 134 */ 135 OFCondition deleteTag(OFString tag_path, 136 const OFBool all_tags, 137 const OFBool ignore_missing_tags); 138 139 /** Deletes all private data from file,\ i.e. all tags having 140 * odd group numbers. 141 * @return EC_Normal, if deletion was successful; error code otherwise 142 */ 143 OFCondition deletePrivateData(); 144 145 /** Inserts new Study, Series or SOP Instance UID. If SOP Instance 146 * UID is generated, the related tag in the metaheader is deleted, too 147 * so that the new UID is also applied there when saving to disk later. 148 * @param uidKey [in] The Instance UID to insert (study, series or sop 149 * instance UID key permitted). 150 * @return EC_Normal, if insertion was successful, error otherwise 151 */ 152 OFCondition generateAndInsertUID(const DcmTagKey &uidKey); 153 154 /** Saves current dataset back to a file. Caution: After saving 155 * MdfDatasetManager keeps working on old filename. 156 * @param file_name filename to save to 157 * @param opt_xfer transfer syntax to save to (EXS_Unknown: don't change) 158 * @param opt_enctype write with explicit or implicit length encoding 159 * @param opt_glenc option to set group length calculation mode 160 * @param opt_padenc sets padding option 161 * @param opt_filepad pad file to a multiple of this options value 162 * @param opt_itempad pad item to a multiple of this options value 163 * @param opt_dataset if true, write only dataset, else write fileformat 164 * @return returns EC_Normal if everything is OK, else an error 165 */ 166 OFCondition saveFile(const char *file_name, 167 E_TransferSyntax opt_xfer = EXS_Unknown, 168 E_EncodingType opt_enctype = EET_UndefinedLength, 169 E_GrpLenEncoding opt_glenc = EGL_recalcGL, 170 E_PaddingEncoding opt_padenc = EPD_noChange, 171 OFCmdUnsignedInt opt_filepad = 0, 172 OFCmdUnsignedInt opt_itempad = 0, 173 OFBool opt_dataset = OFFalse); 174 175 /** Saves current dataset back to file using original filename and original 176 * parameters like transfer syntax, padding etc. 177 * @return returns EC_Normal if everything is OK, else an error 178 */ 179 OFCondition saveFile(); 180 181 /** Returns the dataset that this MdfDatasetManager handles. 182 * You should use the returned object with care to avoid side effects with 183 * other class methods that modify this object, too. 184 * @return returns the dataset, this MdfDatasetManager manages and NULL, if 185 * no dataset is loaded 186 */ 187 DcmDataset* getDataset(); 188 189 190 /** Returns the DcmFileFormat that this MdfDatasetManager handles. 191 * You should use the returned object with care to avoid side-effects with 192 * other class methods that modify this object, too. 193 * @return returns the DcmFileFormat, this MdfDatasetManager manages and 194 * NULL, if no file is loaded 195 */ 196 DcmFileFormat* getFileFormat(); 197 198 /** Returns filename of the file that is currently loaded. 199 * @return returns filename and "" if no file is loaded. 200 */ 201 OFString getFilename() const; 202 203 /** Sets whether attributes with VR of UN should be modified or 204 * left alone. 205 * @param modifyUNValues [in] If set, UN values will be modified (default) 206 */ 207 void setModifyUNValues(OFBool modifyUNValues); 208 209 protected: 210 211 /** modifies element to a specific value 212 * @param elem element that should be changed 213 * @param value the value, the element should be changed to 214 * @return OFCondition, which returns an error code if an error occurs 215 */ 216 OFCondition startModify(DcmElement *elem, 217 const OFString &value); 218 219 /** If key is the tag for SOPInstanceUID or SOPClassUID, then this function 220 * removes the related MediaStorage UIDs from the metaheader. The 221 * metaheader is then updated "automagically" when the file is saved back to 222 * disk. 223 * @param key tag to examine 224 */ 225 void deleteRelatedMetaheaderTag(const DcmTagKey &key); 226 227 /** Returns true, if given tag key can be found in dictionary 228 * @param search_key tag to lookup 229 * @return OFTrue if tag could be found, else OFFalse 230 */ 231 OFBool isTagInDictionary(const DcmTagKey &search_key); 232 233 private: 234 235 /// name of file that is currently loaded 236 OFString current_file; 237 238 /// will hold file to modify 239 DcmFileFormat *dfile; 240 241 /// will hold the dataset that should be modified 242 DcmDataset *dset; 243 244 /// if enabled, no value modifications on attributes having VR of UN 245 /// are not executed 246 OFBool ignore_un_modifies; 247 248 /** private undefined assignment operator 249 */ 250 MdfDatasetManager &operator=(const MdfDatasetManager &); 251 252 /** private undefined copy constructor 253 */ 254 MdfDatasetManager(const MdfDatasetManager &); 255 }; 256 257 #endif // MDFDSMAN_H 258