1 /*=========================================================================
4 Module: $RCSfile: exExtractCSATag.cxx,v $
6 Date: $Date: 2007/09/11 12:56:11 $
7 Version: $Revision: 1.2 $
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 "gdcmDocEntry.h"
23 #include "gdcmDataEntry.h"
24 #include "gdcmSeqEntry.h"
25 #include "gdcmSQItem.h"
32 static const char *lookupTable1[] = {
35 "TransmitterCalibration",
36 "PhaseGradientAmplitude",
37 "ReadoutGradientAmplitude",
38 "SelectionGradientAmplitude",
41 "RfPowerErrorIndicator",
46 "Operation_mode_flag",
53 "Stim_max_ges_norm_online",
57 "CoilTuningReflection",
63 "RepresentativeImage",
64 "PositivePCSDirections",
68 "SliceArrayConcatenations",
80 static const char *lookupTable2[] = {
83 "EchoPartitionPosition",
85 "Actual3DImaPartNumber",
90 "ProtocolSliceNumber",
94 "SliceMeasurementDuration",
96 "AcquisitionMatrixText",
97 "MeasuredFourierLines",
98 "FlowEncodingDirection",
100 "PhaseEncodingDirectionPositive",
101 "NumberOfImagesInMosaic",
102 "DiffusionGradientDirection",
105 "DiffusionDirectionality",
122 "ImagePositionPatient",
123 "ImageOrientationPatient",
127 "SpectrumTextRegionLabel",
130 "Comp_ManualAdjusted",
132 "Comp_AdjustedParam",
135 "FlowEncodingDirectionString",
136 "RepetitionTimeEffective",
140 static const char *lookupTable3[] = {
143 "ReferencedImageSequence",
144 "PatientOrientation",
154 "MagneticFieldStrength",
155 "NumberOfPhaseEncodingSteps",
158 "PercentPhaseFieldOfView",
163 "PhaseEncodingDirection",
165 "VariableFlipAngleFlag",
171 "ImagePositionPatient",
172 "ImageOrientationPatient",
175 "EchoColumnPosition",
176 "EchoPartitionPosition",
177 "Actual3DImaPartNumber",
179 "ProtocolSliceNumber",
184 "SourceImageSequence",
186 "SliceMeasurementDuration",
188 "AcquisitionMatrixText",
189 "MeasuredFourierLines",
190 "CsiGridshiftVector",
195 * What if SIEMENS decide to add another entry in this table, all the offsets are completely off ...
196 * Also we do not respect the ordering anymore.
197 * TODO: Need to check if elements always comes in the same order
199 unsigned int GetLookupCSAIndex(const char *csa_name, const char **lookuptable = lookupTable1)
201 const char **p = lookuptable;
202 while( *p && strcmp(*p, csa_name) != 0 )
206 assert( strcmp(*p, csa_name) == 0 );
207 return p - lookuptable + 1; // Start at 1 to avoid being on the 0000 position
210 // Looks like there is mapping in between syngodt and vr...
230 static equ mapping[] = {
249 bool check_mapping(uint32_t syngodt, const char *vr)
251 static const unsigned int max = sizeof(mapping) / sizeof(equ);
253 const equ *p = mapping;
254 assert( syngodt <= mapping[max-1].syngodt );
255 while(p->syngodt < syngodt )
259 assert( p->syngodt == syngodt ); // or else need to update mapping
260 const char* lvr = p->vr;
261 int check = strcmp(vr, lvr) == 0;
266 uint32_t readCSAHeader(std::istream &is)
271 std::cout << dummy << std::endl;
272 if( strcmp( dummy, "SV10" ) )
274 std::cerr << "Either not a SV10 header or filled with 0..." << std::endl;
279 if( strcmp( dummy, "\4\3\2\1" ) )
281 std::cerr << "Either not a SV10 header or filled with 0..." << std::endl;
284 std::cout << dummy << std::endl;
286 is.read((char*)&n, sizeof(n));
287 std::cout << n << std::endl;
289 is.read((char*)&unused, sizeof(unused));
290 std::cout << unused << std::endl;
291 assert( unused == 77 ); // 'M' character...
296 DataEntry *readCSAElement(std::istream &is)
299 name[64] = 0; // security
300 //std::cout << "Pos 0x" << std::hex << is.tellg() << std::dec << std::endl;
302 std::cout << "Name=" << name << std::endl;
303 unsigned int element = GetLookupCSAIndex(name,lookupTable2);
305 is.read((char*)&vm, sizeof(vm));
306 std::cout << "vm=" << vm << std::endl;
309 assert( vr[2] == vr[3] && vr[2] == 0 );
310 std::cout << "vr=" << vr << std::endl;
312 DataEntry *de = DataEntry::New(0x0029, element, vr);
315 is.read((char*)&syngodt, sizeof(syngodt));
316 check_mapping(syngodt, vr);
318 std::cout << "syngodt=" << syngodt << std::endl;
320 is.read((char*)&nitems, sizeof(nitems));
321 std::cout << "nitems=" << nitems<< std::endl;
323 is.read((char*)&xx, sizeof(xx));
324 //std::cout << "xx=" << xx<< std::endl;
325 assert( xx == 77 || xx == 205 );
326 for( uint32_t j = 0; j < nitems; ++j)
329 is.read((char*)&item_xx, 4*sizeof(uint32_t));
330 std::cout << "item_xx=" << item_xx[0] << " " << item_xx[1] << " " << item_xx[2] << " " << item_xx[3] << std::endl;
331 //std::cout << "0x" << std::hex << is.tellg() << std::dec << std::endl;
332 assert( item_xx[2] == 77 || item_xx[2] == 205 );
333 uint32_t len = item_xx[1]; // 2nd element
334 std::cout << "len=" << len << std::endl;
335 assert( item_xx[0] == item_xx[1] && item_xx[1] == item_xx[3] );
336 char *val = new char[len+1];
337 val[len] = 0; // security
339 // WARNING vr does not means anything AFAIK, simply print the value as if it was IS/DS or LO (ASCII)
340 std::cout << "val=" << val << std::endl;
342 de->SetString( std::string(val,len) );
345 uint32_t dummy_len = (4 - len % 4) % 4;
346 is.read(dummy, dummy_len );
347 for(uint32_t d= 0; d < dummy_len; ++d)
349 // I think dummy should always be 0
352 std::cout << "dummy=" << (int)dummy[d] << std::endl;
361 int convertCSA(std::istream &is, File *f)
363 f->RemoveEntry( f->GetDataEntry(0X0029,0x1010) );
365 SeqEntry *sq = SeqEntry::New(0x0029,0x1010);
366 SQItem *sqi = SQItem::New(1);
367 // DataEntry *e_0008_1150 = DataEntry::New(0x0008, 0x1150, "UI");
368 // e_0008_1150->SetString( "coucou" );
369 // sqi->AddEntry(e_0008_1150);
370 // e_0008_1150->Delete();
372 // DataEntry *e_0008_1155 = DataEntry::New(0x0008, 0x1155, "UI");
373 // e_0008_1155->SetString( "mathieu" );
374 // sqi->AddEntry(e_0008_1155);
375 // e_0008_1155->Delete();
379 uint32_t n = readCSAHeader(is);
381 for(uint32_t i = 0; i < n; ++i)
383 DataEntry *de = readCSAElement(is);
388 sq->AddSQItem(sqi,1);
390 //sq->Print( std::cout );
393 f->Print( std::cout );
395 gdcm::FileHelper *fh = gdcm::FileHelper::New(f);
396 fh->SetWriteTypeToDcmExplVR();
397 fh->Write("/tmp/csa2.dcm");
401 } // end namespace gdcm
403 int main(int argc, char *argv[])
409 std::cerr << "Usage :" << argv[0] << " input.dcm group element outputfile" << std::endl;
410 std::cerr << " Ex: " << argv[0] << " /tmp/bla.dcm 0029 2110 /tmp/out.raw" << std::endl;
413 std::string fileName = argv[1];
415 std::cout << fileName << std::endl;
416 // ============================================================
417 // Read the input image.
418 // ============================================================
420 f = gdcm::File::New( );
422 //f->SetLoadMode(gdcm::LD_NOSEQ | gdcm::LD_NOSHADOW);
423 f->SetFileName( fileName );
424 f->SetMaxSizeLoadEntry(0xffff);
425 bool res = f->Load();
427 if( gdcm::Debug::GetDebugFlag())
429 std::cout << "---------------------------------------------" << std::endl;
431 std::cout << "---------------------------------------------" << std::endl;
434 std::cerr << "Sorry, " << fileName << " not a gdcm-readable "
435 << "DICOM / ACR File"
440 std::cout << " ... is readable " << std::endl;
442 // Find the dicom tag, and extract the string
443 uint16_t group, elem;
444 std::istringstream convert;
445 convert.str( argv[2] );
446 convert >> std::hex >> group;
447 convert.clear(); //important
448 convert.str( argv[3] );
449 convert >> std::hex >> elem;
450 std::cout << "Extracting tag: (0x" << std::hex << std::setw(4) << std::setfill('0')
451 << group << ",0x" << std::setw(4) << std::setfill('0') << elem << ")" << std::endl;
452 std::string dicom_tag_value = f->GetEntryString(group, elem);
453 if (dicom_tag_value == gdcm::GDCM_UNFOUND)
455 gdcm::DictEntry *dictEntry = f->GetPubDict()->GetEntry( group, elem);
456 std::cerr << "Image doesn't contain any tag: " << dictEntry->GetName() << std::endl;
461 gdcm::DocEntry *dicom_tag_doc = f->GetDocEntry(group, elem);
462 gdcm::DataEntry *dicom_tag = dynamic_cast<gdcm::DataEntry *>(dicom_tag_doc);
465 std::cerr << "Sorry DataEntry only please" << std::endl;
470 // Write out the data as a file:
471 std::ofstream o(argv[4]);
474 std::cerr << "Problem opening file: " << argv[4] << std::endl;
478 o.write((char*)dicom_tag->GetBinArea(), dicom_tag->GetLength());
481 std::istringstream is;
482 is.str( std::string( (char*)dicom_tag->GetBinArea(), dicom_tag->GetLength()) );
484 gdcm::convertCSA(is, f);