From: jpr Date: Sun, 28 Aug 2005 17:10:49 +0000 (+0000) Subject: // ------------------------------------------------------------------------ X-Git-Tag: Version1.2.bp~192 X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=commitdiff_plain;h=993bc33a54fcb6097d7f48488911881448c0194d;p=gdcm.git // ------------------------------------------------------------------------ // gdcm mechanisms don't allow user to read an image // whose header contains wrong physical info (say : wrong Row Number ...) // and re-write with a right value. // This program does the job by brutally overwritting the wrong values. // It may be usefull to save a set of images ... // (It dosn't allow to *add* a missing field) // ------------------------------------------------------------------------ "\n PatchHeader :\n ", " Allows aware user to patch an image header, without loading image. ", " Warning : the image(s) is/are overwritten ", " to preserve image(s) integrity, use a copy. ", " WARNING : *NO CHECK* is performed on the new values. ", " Use only if you are sure the original values are wrong ", " *and* your values are right... ", "usage: PatchHeader {filein=inputFileName|dirin=inputDirectoryName} ", " [ { [size=] | [rows=][columns=] } ] [planes=] ", " [bitsallocated=] [bitsstored=] ", " [highbit=] [samplesperpixel=] ", " [pixelrepresentation=] [samplesperpixel=] ", " [ { [noshadowseq] | [noshadow][noseq] } ] [debug] ", " ", " inputFileName : Name of the (single) file user wants to modify ", " inputDirectoryName : user wants to modify *all* the files ", " within the directory ", " size : new (square) size, to owerwrite old (wrong) one ", " or ", " rows : new Rows number, to owerwrite old (wrong) one ", " columns : new Columns number, to owerwrite old (wrong) one ", " planes : new Planes number, ... ", " bitsallocated : new Bits Allocated number, ... ", " bitsstored : new Bits Stored number, ... ", " highbit : new High Bit number, ... ", " samplesperpixel : new Samples Per Pixel, ... ", " pixelrepresentation : new Pixel Representation, ... ", " ", " noshadowseq: user doesn't want to load Private Sequences ", " noshadow : user doesn't want to load Private groups (odd number) ", " noseq : user doesn't want to load Sequences ", " debug : user wants to run the program in 'debug mode' ", --- diff --git a/Example/PatchHeader.cxx b/Example/PatchHeader.cxx new file mode 100644 index 00000000..e1d8dd19 --- /dev/null +++ b/Example/PatchHeader.cxx @@ -0,0 +1,365 @@ +/*========================================================================= + + Program: gdcm + Module: $RCSfile: PatchHeader.cxx,v $ + Language: C++ + Date: $Date: 2005/08/28 17:10:49 $ + Version: $Revision: 1.1 $ + + Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de + l'Image). All rights reserved. See Doc/License.txt or + http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#include "gdcmFile.h" +#include "gdcmFileHelper.h" +#include "gdcmCommon.h" +#include "gdcmDebug.h" +#include "gdcmDirList.h" +#include "gdcmDocEntry.h" +#include "gdcmArgMgr.h" + +#include + +// ------------------------------------------------------------------------ +// gdcm mechanisms don't allow user to read an image +// whose header contains wrong physical info (say : wrong Row Number ...) +// and re-write with a right value. +// This program does the job by brutally overwritting the wrong values. +// It may be usefull to save a set of images ... +// (It dosn't allow to *add* a missing field) +// ------------------------------------------------------------------------ + +// global variables will be seen inside any function. + +gdcm::File *f; +std::fstream *fp; + +uint16_t samplesperpixel; +uint16_t planarconfiguration; +uint16_t size; +uint16_t rows; +uint16_t columns; +uint16_t planes; +uint16_t bitsallocated; +uint16_t bitsstored; +uint16_t highbit; +uint16_t pixelrepresentation; + +bool bsamplesperpixel; +bool bplanarconfiguration; +bool bsize; +bool brows; +bool bcolumns; +bool bplanes; +bool bbitsallocated; +bool bbitsstored; +bool bhighbit; +bool bpixelrepresentation; + +void update() +{ + uint32_t offset; + gdcm::DocEntry *d; + // + // Fields to replace. + // + + // Samples Per Pixel + if (bsamplesperpixel) + { + d = f->GetDocEntry( 0x0028, 0x0002); + if (d) + { + offset = d->GetOffset(); + fp->seekp( offset, std::ios::beg ); + fp->write( (char *)&samplesperpixel, 2 ); + } + } + // Rows + if (brows) + { + d = f->GetDocEntry( 0x0028, 0x0010); + offset = d->GetOffset(); + fp->seekp( offset, std::ios::beg ); + fp->write( (char *)&rows, 2 ); + } + // Columns + if (bcolumns) + { + d = f->GetDocEntry( 0x0028, 0x0011); + offset = d->GetOffset(); + fp->seekp( offset, std::ios::beg ); + fp->write( (char *)&columns, 2 ); + } + // Planes + if (bplanes) + { + d = f->GetDocEntry( 0x0028, 0x0012); + if (d) + { + offset = d->GetOffset(); + fp->seekp( offset, std::ios::beg ); + fp->write( (char *)&planes, 2 ); + } + } + // Bits Allocated + if (bbitsallocated) + { + d = f->GetDocEntry( 0x0028, 0x0100); + offset = d->GetOffset(); + fp->seekp( offset, std::ios::beg ); + fp->write( (char *)&bitsallocated, 2 ); + } + + // Bits Stored + if (bbitsstored) + { + d = f->GetDocEntry( 0x0028, 0x0101); + offset = d->GetOffset(); + fp->seekp( offset, std::ios::beg ); + fp->write( (char *)&bitsstored, 2 ); + } + + // High Bit + if (bhighbit) + { + d = f->GetDocEntry( 0x0028, 0x0102); + offset = d->GetOffset(); + fp->seekp( offset, std::ios::beg ); + fp->write( (char *)&highbit, 2 ); + } + + // Pixel Representation + if (bpixelrepresentation) + { + d = f->GetDocEntry( 0x0028, 0x0103); + offset = d->GetOffset(); + fp->seekp( offset, std::ios::beg ); + fp->write( (char *)&pixelrepresentation, 2 ); + } +} + +int main(int argc, char *argv[]) +{ + START_USAGE(usage) + "\n PatchHeader :\n ", + " Allows aware user to patch an image header, without loading image. ", + " Warning : the image(s) is/are overwritten ", + " to preserve image(s) integrity, use a copy. ", + " WARNING : *NO CHECK* is performed on the new values. ", + " Use only if you are sure the original values are wrong ", + " *and* your values are right... ", + "usage: PatchHeader {filein=inputFileName|dirin=inputDirectoryName} ", + " [ { [size=] | [rows=][columns=] } ] [planes=] ", + " [bitsallocated=] [bitsstored=] ", + " [highbit=] [samplesperpixel=] ", + " [pixelrepresentation=] [samplesperpixel=] ", + " [ { [noshadowseq] | [noshadow][noseq] } ] [debug] ", + " ", + " inputFileName : Name of the (single) file user wants to modify ", + " inputDirectoryName : user wants to modify *all* the files ", + " within the directory ", + " size : new (square) size, to owerwrite old (wrong) one ", + " or ", + " rows : new Rows number, to owerwrite old (wrong) one ", + " columns : new Columns number, to owerwrite old (wrong) one ", + " planes : new Planes number, ... ", + " bitsallocated : new Bits Allocated number, ... ", + " bitsstored : new Bits Stored number, ... ", + " highbit : new High Bit number, ... ", + " samplesperpixel : new Samples Per Pixel, ... ", + " pixelrepresentation : new Pixel Representation, ... ", + " ", + " noshadowseq: user doesn't want to load Private Sequences ", + " noshadow : user doesn't want to load Private groups (odd number) ", + " noseq : user doesn't want to load Sequences ", + " debug : user wants to run the program in 'debug mode' ", + FINISH_USAGE + + // ----- Initialize Arguments Manager ------ + + gdcm::ArgMgr *am = new gdcm::ArgMgr(argc, argv); + + if (am->ArgMgrDefined("usage") || argc == 1) + { + am->ArgMgrUsage(usage); // Display 'usage' + delete am; + return 0; + } + + char *fileName = am->ArgMgrGetString("filein",(char *)0); + char *dirName = am->ArgMgrGetString("dirin",(char *)0); + + if ( (fileName == 0 && dirName == 0) + || + (fileName != 0 && dirName != 0) ) + { + std::cout <ArgMgrDefined("samplesperpixel"); + if ( bsamplesperpixel ) + samplesperpixel = am->ArgMgrWantInt("samplesperpixel",usage); + + planarconfiguration = am->ArgMgrDefined("planarconfiguration"); + if ( bplanarconfiguration ) + planarconfiguration = am->ArgMgrWantInt("planarconfiguration",usage); + + bsize = am->ArgMgrDefined("size"); + brows = am->ArgMgrDefined("rows"); + bcolumns = am->ArgMgrDefined("columns"); + + if (bsize && (brows || bcolumns) ) + { + printf ("Use 'SIZE=...' or 'ROWS=... COLUMNS=...'\n"); + printf ("Not both\n"); + delete am; + return 0; + } + + if ( bsize ) + size = am->ArgMgrWantInt("size",usage); + + if ( brows ) + rows = am->ArgMgrWantInt("rows",usage); + + if ( bcolumns ) + columns = am->ArgMgrWantInt("columns",usage); + + if (bsize) + { + brows = bcolumns = true; + rows = columns = size; + } + bplanes = am->ArgMgrDefined("planes"); + if ( bplanes ) + planes = am->ArgMgrWantInt("planes",usage); + + bbitsallocated = am->ArgMgrDefined("bitsallocated"); + if ( bbitsallocated ) + bitsallocated = am->ArgMgrWantInt("bitsallocated",usage); + + bbitsstored = am->ArgMgrDefined("bitsstored"); + if ( bbitsstored ) + bitsstored = am->ArgMgrWantInt("bitsstored",usage); + + bhighbit = am->ArgMgrDefined("highbit"); + if ( bhighbit ) + highbit = am->ArgMgrWantInt("highbit",usage); + + bpixelrepresentation = am->ArgMgrDefined("pixelrepresentation"); + if ( bpixelrepresentation ) + pixelrepresentation = am->ArgMgrWantInt("pixelrepresentation",usage); + + if (am->ArgMgrDefined("debug")) + gdcm::Debug::DebugOn(); + + int loadMode = 0x00000000; + if ( am->ArgMgrDefined("noshadowseq") ) + loadMode |= NO_SHADOWSEQ; + else + { + if ( am->ArgMgrDefined("noshadow") ) + loadMode |= NO_SHADOW; + if ( am->ArgMgrDefined("noseq") ) + loadMode |= NO_SEQ; + } + + /* if unused Param we give up */ + if ( am->ArgMgrPrintUnusedLabels() ) + { + am->ArgMgrUsage(usage); + delete am; + return 0; + } + + delete am; // ------ we don't need Arguments Manager any longer ------ + + + if ( fileName != 0 ) // ====== Deal with a single file ====== + { + + // + // Parse the input file. + // + + f = new gdcm::File( ); + f->SetLoadMode(loadMode); + f->SetFileName( fileName ); + bool res = f->Load(); + + // gdcm::File::IsReadable() is no usable here, because we deal with + // any kind of gdcm::Readable *document* + // not only gdcm::File (as opposed to gdcm::DicomDir) + if ( !res ) + { + std::cout <close(); + delete fp; + delete f; + return 0; + + } + else // ====== Deal with a (single Patient) Directory ====== + { + std::cout << "dirName [" << dirName << "]" << std::endl; + gdcm::DirList dirList(dirName,1); // gets recursively the file list + gdcm::DirListType fileList = dirList.GetFilenames(); + for( gdcm::DirListType::iterator it = fileList.begin(); + it != fileList.end(); + ++it ) + { + f = new gdcm::File( ); + f->SetLoadMode(loadMode); + f->SetFileName( it->c_str() ); + bool res = f->Load(); + + if ( !res ) + { + delete f; + continue; + } + + // open the file + fp = new std::fstream(it->c_str(), + std::ios::in | std::ios::out | std::ios::binary); + update(); + + + fp->close(); + delete fp; + delete f; + } + } + return 0; +} +