1 /*=========================================================================
4 Module: $RCSfile: PatchHeader.cxx,v $
6 Date: $Date: 2007/05/23 14:18:04 $
7 Version: $Revision: 1.8 $
9 Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
10 l'Image). All rights reserved. See Doc/License.txt or
11 http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
13 This software is distributed WITHOUT ANY WARRANTY; without even
14 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 PURPOSE. See the above copyright notices for more information.
17 =========================================================================*/
19 #include "gdcmFileHelper.h"
20 #include "gdcmCommon.h"
21 #include "gdcmDebug.h"
22 #include "gdcmDirList.h"
23 #include "gdcmDocEntry.h"
24 #include "gdcmArgMgr.h"
28 // ------------------------------------------------------------------------
29 // gdcm mechanisms don't allow user to read an image
30 // whose header contains wrong physical info (say : wrong Row Number ...)
31 // and re-write with a right value.
32 // This program does the job by brutally overwritting the wrong values.
33 // It may be usefull to save a set of images ...
34 // (It doesn't allow to *add* a missing field)
35 // ------------------------------------------------------------------------
37 // global variables will be seen inside any function.
39 GDCM_NAME_SPACE::File *f;
42 uint16_t samplesperpixel;
43 uint16_t planarconfiguration;
48 uint16_t bitsallocated;
51 uint16_t pixelrepresentation;
54 int bplanarconfiguration;
62 int bpixelrepresentation;
67 GDCM_NAME_SPACE::DocEntry *d;
75 d = f->GetDocEntry( 0x0028, 0x0002);
78 offset = d->GetOffset();
79 fp->seekp( offset, std::ios::beg );
80 fp->write( (char *)&samplesperpixel, 2 );
86 d = f->GetDocEntry( 0x0028, 0x0010);
87 offset = d->GetOffset();
88 fp->seekp( offset, std::ios::beg );
89 fp->write( (char *)&rows, 2 );
94 d = f->GetDocEntry( 0x0028, 0x0011);
95 offset = d->GetOffset();
96 fp->seekp( offset, std::ios::beg );
97 fp->write( (char *)&columns, 2 );
102 d = f->GetDocEntry( 0x0028, 0x0012);
105 offset = d->GetOffset();
106 fp->seekp( offset, std::ios::beg );
107 fp->write( (char *)&planes, 2 );
113 d = f->GetDocEntry( 0x0028, 0x0100);
114 offset = d->GetOffset();
115 fp->seekp( offset, std::ios::beg );
116 fp->write( (char *)&bitsallocated, 2 );
122 d = f->GetDocEntry( 0x0028, 0x0101);
123 offset = d->GetOffset();
124 fp->seekp( offset, std::ios::beg );
125 fp->write( (char *)&bitsstored, 2 );
131 d = f->GetDocEntry( 0x0028, 0x0102);
132 offset = d->GetOffset();
133 fp->seekp( offset, std::ios::beg );
134 fp->write( (char *)&highbit, 2 );
137 // Pixel Representation
138 if (bpixelrepresentation)
140 d = f->GetDocEntry( 0x0028, 0x0103);
141 offset = d->GetOffset();
142 fp->seekp( offset, std::ios::beg );
143 fp->write( (char *)&pixelrepresentation, 2 );
147 int main(int argc, char *argv[])
150 "\n PatchHeader :\n ",
151 " Allows aware user to patch an image header, without loading image. ",
152 " Warning : the image(s) is/are overwritten ",
153 " to preserve image(s) integrity, use a copy. ",
154 " WARNING : *NO CHECK* is performed on the new values. ",
155 " Use only if you are sure the original values are wrong ",
156 " *and* your values are right... ",
157 "usage: PatchHeader {filein=inputFileName|dirin=inputDirectoryName} ",
158 " [ { [size=] | [rows=][columns=] } ] [planes=] ",
159 " [bitsallocated=] [bitsstored=] ",
160 " [highbit=] [samplesperpixel=] ",
161 " [pixelrepresentation=] [samplesperpixel=] ",
162 " [ { [noshadowseq] | [noshadow][noseq] } ] [debug] ",
164 " inputFileName : Name of the (single) file user wants to modify ",
165 " inputDirectoryName : user wants to modify *all* the files ",
166 " within the directory ",
167 " size : new (square) size, to owerwrite old (wrong) one ",
169 " rows : new Rows number, to owerwrite old (wrong) one ",
170 " columns : new Columns number, to owerwrite old (wrong) one ",
171 " planes : new Planes number, ... ",
172 " bitsallocated : new Bits Allocated number, ... ",
173 " bitsstored : new Bits Stored number, ... ",
174 " highbit : new High Bit number, ... ",
175 " samplesperpixel : new Samples Per Pixel, ... ",
176 " pixelrepresentation : new Pixel Representation, ... ",
178 " noshadowseq: user doesn't want to load Private Sequences ",
179 " noshadow : user doesn't want to load Private groups (odd number) ",
180 " noseq : user doesn't want to load Sequences ",
181 " debug : user wants to run the program in 'debug mode' ",
184 // ----- Initialize Arguments Manager ------
186 GDCM_NAME_SPACE::ArgMgr *am = new GDCM_NAME_SPACE::ArgMgr(argc, argv);
188 if (am->ArgMgrDefined("usage") || argc == 1)
190 am->ArgMgrUsage(usage); // Display 'usage'
195 const char *fileName = am->ArgMgrGetString("filein");
196 const char *dirName = am->ArgMgrGetString("dirin");
198 if ( (fileName == 0 && dirName == 0)
200 (fileName != 0 && dirName != 0) )
202 std::cout <<std::endl
203 << "Either 'filein=' or 'dirin=' must be present;"
204 << std::endl << "Not both" << std::endl;
205 am->ArgMgrUsage(usage); // Display 'usage'
210 bsamplesperpixel = am->ArgMgrDefined("samplesperpixel");
211 if ( bsamplesperpixel )
212 samplesperpixel = am->ArgMgrWantInt("samplesperpixel",usage);
214 planarconfiguration = am->ArgMgrDefined("planarconfiguration");
215 if ( bplanarconfiguration )
216 planarconfiguration = am->ArgMgrWantInt("planarconfiguration",usage);
218 bsize = am->ArgMgrDefined("size");
219 brows = am->ArgMgrDefined("rows");
220 bcolumns = am->ArgMgrDefined("columns");
222 if (bsize && (brows || bcolumns) )
224 printf ("Use 'SIZE=...' or 'ROWS=... COLUMNS=...'\n");
225 printf ("Not both\n");
231 size = am->ArgMgrWantInt("size",usage);
234 rows = am->ArgMgrWantInt("rows",usage);
237 columns = am->ArgMgrWantInt("columns",usage);
241 brows = bcolumns = true;
242 rows = columns = size;
244 bplanes = am->ArgMgrDefined("planes");
246 planes = am->ArgMgrWantInt("planes",usage);
248 bbitsallocated = am->ArgMgrDefined("bitsallocated");
249 if ( bbitsallocated )
250 bitsallocated = am->ArgMgrWantInt("bitsallocated",usage);
252 bbitsstored = am->ArgMgrDefined("bitsstored");
254 bitsstored = am->ArgMgrWantInt("bitsstored",usage);
256 bhighbit = am->ArgMgrDefined("highbit");
258 highbit = am->ArgMgrWantInt("highbit",usage);
260 bpixelrepresentation = am->ArgMgrDefined("pixelrepresentation");
261 if ( bpixelrepresentation )
262 pixelrepresentation = am->ArgMgrWantInt("pixelrepresentation",usage);
264 if (am->ArgMgrDefined("debug"))
265 GDCM_NAME_SPACE::Debug::DebugOn();
267 int loadMode = GDCM_NAME_SPACE::LD_ALL;
268 if ( am->ArgMgrDefined("noshadowseq") )
269 loadMode |= GDCM_NAME_SPACE::LD_NOSHADOWSEQ;
272 if ( am->ArgMgrDefined("noshadow") )
273 loadMode |= GDCM_NAME_SPACE::LD_NOSHADOW;
274 if ( am->ArgMgrDefined("noseq") )
275 loadMode |= GDCM_NAME_SPACE::LD_NOSEQ;
278 /* if unused Param we give up */
279 if ( am->ArgMgrPrintUnusedLabels() )
281 am->ArgMgrUsage(usage);
286 delete am; // ------ we don't need Arguments Manager any longer ------
289 if ( fileName != 0 ) // ====== Deal with a single file ======
292 // Parse the input file.
294 f = GDCM_NAME_SPACE::File::New( );
295 f->SetLoadMode(loadMode);
296 f->SetFileName( fileName );
297 bool res = f->Load();
299 // GDCM_NAME_SPACE::File::IsReadable() is no usable here, because we deal with
300 // any kind of GDCM_NAME_SPACE::Readable *document*
301 // not only GDCM_NAME_SPACE::File (as opposed to GDCM_NAME_SPACE::DicomDir)
304 std::cout <<std::endl
305 << "Sorry, " << fileName <<" not a gdcm-readable "
306 << "DICOM / ACR Document"
311 std::cout << fileName << " is readable " << std::endl;
314 // No need to load the pixels in memory.
315 // File will be overwritten
319 fp = new std::fstream(fileName,
320 std::ios::in | std::ios::out | std::ios::binary);
330 else // ====== Deal with a (single Patient) Directory ======
332 std::cout << "dirName [" << dirName << "]" << std::endl;
333 GDCM_NAME_SPACE::DirList dirList(dirName,1); // gets recursively the file list
334 GDCM_NAME_SPACE::DirListType fileList = dirList.GetFilenames();
335 for( GDCM_NAME_SPACE::DirListType::iterator it = fileList.begin();
336 it != fileList.end();
339 f = GDCM_NAME_SPACE::File::New( );
340 f->SetLoadMode(loadMode);
341 f->SetFileName( it->c_str() );
342 bool res = f->Load();
351 fp = new std::fstream(it->c_str(),
352 std::ios::in | std::ios::out | std::ios::binary);