@@ -62,6 +62,162 @@ int ignoreerrors = 0;
6262
6363namespace cleanup
6464{
65+ // {"1.3.46.670589.11.0.0.12.2" ,"Philips Private MR Series Data Storage"},
66+ enum {
67+ TYPE_FLOAT = 0 , // float
68+ TYPE_INT32 = 1 , // int32
69+ TYPE_STRING = 2 , // 80 bytes string (+1)
70+ TYPE_UINT32 = 4 , // uint32
71+ };
72+
73+ template <typename T>
74+ void printvaluet (std::istream & is, uint32_t numels)
75+ {
76+ T buffer;
77+ for ( uint32_t i = 0 ; i < numels; ++i )
78+ {
79+ if ( i ) std::cout << " \\ " ;
80+ is.read ( (char *)&buffer, sizeof (T) );
81+ std::cout << buffer;
82+ }
83+ }
84+
85+ void printvalue (std::istream &is, uint32_t type, uint32_t numels, uint32_t pos)
86+ {
87+ assert ( numels > 0 );
88+ std::streampos start = is.tellg ();
89+ is.seekg ( pos );
90+ std::cout << " [" ;
91+ typedef char (string81)[81 ]; // 80'th byte == 0
92+ assert ( sizeof ( string81 ) == 81 );
93+ switch ( type )
94+ {
95+ case TYPE_FLOAT :
96+ printvaluet<float >(is, numels);
97+ break ;
98+ case TYPE_INT32 :
99+ printvaluet<int32_t >(is, numels);
100+ break ;
101+ case TYPE_STRING :
102+ printvaluet<string81>(is, numels);
103+ break ;
104+ case TYPE_UINT32 :
105+ printvaluet<uint32_t >(is, numels);
106+ break ;
107+ default :
108+ assert ( 0 );
109+ }
110+ std::cout << " ]" ;
111+ std::cout << " # " << numels;
112+ is.seekg ( start );
113+ }
114+
115+ struct PDFElement
116+ {
117+ const char *getname () const { return name; }
118+ uint32_t gettype () const { return getvalue (0 ); }
119+ uint32_t getnumelems () const { return getvalue (1 ); }
120+ uint32_t getdummy () const { return getvalue (2 ); }
121+ uint32_t getoffset () const { return getvalue (3 ); }
122+ private:
123+ char name[50 ];
124+ // type , numel and offset needs to be read starting from the end
125+ // the data in between name and those value can contains garbage stuff
126+ uint32_t getvalue (int n) const {
127+ uint32_t val = 0 ;
128+ memcpy ( (char *)&val, name + 50 - 16 + n * 4 , sizeof ( val ) );
129+ return val;
130+ }
131+ };
132+
133+ void printbinary (std::istream &is, PDFElement const & pdfel )
134+ {
135+ const char *bufferref = pdfel.getname ();
136+ std::cout << " " << bufferref << " " ;
137+ uint32_t type = pdfel.gettype ();
138+ uint32_t numels = pdfel.getnumelems ();
139+ uint32_t dummy = pdfel.getdummy ();
140+ assert ( dummy == 0 );
141+ uint32_t offset = pdfel.getoffset ();
142+ uint32_t pos = offset + is.tellg () - 4 ;
143+ printvalue (is, type, numels, pos);
144+ }
145+
146+ void ProcessSDSData ( std::istream & is )
147+ {
148+ // havent been able to figure out what was the begin meant for
149+ is.seekg ( 0x20 - 8 );
150+ uint32_t version = 0 ;
151+ is.read ( (char *)&version, sizeof (version) );
152+ assert ( version == 8 );
153+ uint32_t numel = 0 ;
154+ is.read ( (char *)&numel, sizeof (numel) );
155+ for ( uint32_t el = 0 ; el < numel; ++el )
156+ {
157+ PDFElement pdfel;
158+ assert ( sizeof (pdfel) == 50 );
159+ is.read ( (char *)&pdfel, 50 );
160+ if ( *pdfel.getname () )
161+ {
162+ printbinary ( is, pdfel );
163+ std::cout << std::endl;
164+ }
165+ }
166+
167+ }
168+ // PMS MR Series Data Storage
169+ int DumpPMS_MRSDS (const gdcm::DataSet & ds)
170+ {
171+ const gdcm::PrivateTag tdata (0x2005 ,0x32 ," Philips MR Imaging DD 002" );
172+ if ( !ds.FindDataElement ( tdata ) ) return 1 ;
173+ const gdcm::DataElement &data = ds.GetDataElement ( tdata );
174+ gdcm::SmartPointer<gdcm::SequenceOfItems> sqi = data.GetValueAsSQ ();
175+ if ( !sqi ) return 1 ;
176+ std::cout << " PMS Dumping info from tag " << tdata << std::endl;
177+ gdcm::SequenceOfItems::ConstIterator it = sqi->Begin ();
178+ for ( ; it != sqi->End (); ++it )
179+ {
180+ const gdcm::Item & item = *it;
181+ const gdcm::DataSet & nestedds = item.GetNestedDataSet ();
182+ const gdcm::PrivateTag tprotocoldataname (0x2005 ,0x37 ," Philips MR Imaging DD 002" );
183+ const gdcm::DataElement & protocoldataname = nestedds.GetDataElement ( tprotocoldataname );
184+ const gdcm::ByteValue *bv1 = protocoldataname.GetByteValue ();
185+ const gdcm::PrivateTag tprotocoldatatype (0x2005 ,0x39 ," Philips MR Imaging DD 002" );
186+ const gdcm::DataElement & protocoldatatype = nestedds.GetDataElement ( tprotocoldatatype );
187+ const gdcm::ByteValue *bv2 = protocoldatatype.GetByteValue ();
188+ const gdcm::PrivateTag tprotocoldatablock (0x2005 ,0x44 ," Philips MR Imaging DD 002" );
189+ const gdcm::DataElement & protocoldatablock = nestedds.GetDataElement ( tprotocoldatablock );
190+ const gdcm::ByteValue *bv3 = protocoldatablock.GetByteValue ();
191+ const gdcm::PrivateTag tprotocoldatabool (0x2005 ,0x47 ," Philips MR Imaging DD 002" );
192+ const gdcm::DataElement & protocoldatabool = nestedds.GetDataElement ( tprotocoldatabool );
193+ const gdcm::ByteValue *bv4 = protocoldatabool.GetByteValue ();
194+ std::string s1;
195+ if ( bv1 )
196+ {
197+ s1 = std::string ( bv1->GetPointer (), bv1->GetLength () );
198+ }
199+ std::string s2;
200+ if ( bv2 )
201+ {
202+ s2 = std::string ( bv2->GetPointer (), bv2->GetLength () );
203+ }
204+ std::string s3;
205+ if ( bv3 )
206+ {
207+ s3 = std::string ( bv3->GetPointer (), bv3->GetLength () );
208+ }
209+ std::string s4;
210+ if ( bv4 )
211+ {
212+ s4 = std::string ( bv4->GetPointer (), bv4->GetLength () );
213+ }
214+ std::istringstream is ( s3 );
215+ std::cout << " PMS/Item name: [" << s1 << " /" << s2 << " /" << s4 << " ]" << std::endl;
216+ ProcessSDSData ( is );
217+ }
218+ return 0 ;
219+ }
220+
65221// VEPRO
66222/*
67223[VIMDATA2]
@@ -465,6 +621,24 @@ int PrintVEPRO(const std::string & filename, bool verbose)
465621 return ret;
466622}
467623
624+ int PrintSDS (const std::string & filename, bool verbose)
625+ {
626+ (void )verbose;
627+ gdcm::Reader reader;
628+ reader.SetFileName ( filename.c_str () );
629+ if ( !reader.Read () )
630+ {
631+ std::cerr << " Failed to read: " << filename << std::endl;
632+ return 1 ;
633+ }
634+
635+ const gdcm::DataSet& ds = reader.GetFile ().GetDataSet ();
636+ int ret = cleanup::DumpPMS_MRSDS ( ds );
637+
638+ return ret;
639+ }
640+
641+
468642int PrintPDB (const std::string & filename, bool verbose)
469643{
470644 (void )verbose;
@@ -614,6 +788,7 @@ void PrintHelp()
614788 std::cout << " -P --pdb print GEMS Protocol Data Block (0025,1b,GEMS_SERS_01)." << std::endl;
615789 std::cout << " --elscint print ELSCINT Protocol Information (01f7,26,ELSCINT1)." << std::endl;
616790 std::cout << " --vepro print VEPRO Protocol Information (0055,20,VEPRO VIM 5.0 DATA)." << std::endl;
791+ std::cout << " --sds print Philips MR Series Data Storage (1.3.46.670589.11.0.0.12.2) Information (2005,32,Philips MR Imaging DD 002)." << std::endl;
617792 std::cout << " -A --asn1 print encapsulated ASN1 structure >(0400,0520)." << std::endl;
618793 std::cout << " --map-uid-names map UID to names." << std::endl;
619794 std::cout << " General Options:" << std::endl;
@@ -641,6 +816,7 @@ int main (int argc, char *argv[])
641816 int printpdb = 0 ;
642817 int printelscint = 0 ;
643818 int printvepro = 0 ;
819+ int printsds = 0 ; // MR Series Data Storage
644820 int verbose = 0 ;
645821 int warning = 0 ;
646822 int debug = 0 ;
@@ -681,6 +857,7 @@ int main (int argc, char *argv[])
681857 {" map-uid-names" , 0 , &mapuidnames, 1 },
682858 {" elscint" , 0 , &printelscint, 1 },
683859 {" vepro" , 0 , &printvepro, 1 },
860+ {" sds" , 0 , &printsds, 1 },
684861 {0 , 0 , 0 , 0 } // required
685862 };
686863 static const char short_options[] = " i:xrpdcCPAVWDEhvI" ;
@@ -878,6 +1055,10 @@ int main (int argc, char *argv[])
8781055 {
8791056 res += PrintVEPRO (*it, verbose!= 0 );
8801057 }
1058+ else if ( printsds )
1059+ {
1060+ res += PrintSDS (*it, verbose!= 0 );
1061+ }
8811062 else if ( printelscint )
8821063 {
8831064 res += PrintELSCINT (*it, verbose!= 0 );
@@ -917,6 +1098,10 @@ int main (int argc, char *argv[])
9171098 {
9181099 res += PrintVEPRO (filename, verbose!= 0 );
9191100 }
1101+ else if ( printsds )
1102+ {
1103+ res += PrintSDS (filename, verbose!= 0 );
1104+ }
9201105 else if ( printelscint )
9211106 {
9221107 res += PrintELSCINT (filename, verbose!= 0 );
0 commit comments