/*========================================================================= Program: GDCM (Grassroots DICOM). A DICOM library Copyright (c) 2006-2011 Mathieu Malaterre All rights reserved. See Copyright.txt or http://gdcm.sourceforge.net/Copyright.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 notice for more information. =========================================================================*/ #include "gdcmReader.h" #include "gdcmImage.h" #include "gdcmImageWriter.h" #include "gdcmDataElement.h" #include "gdcmPrivateTag.h" #include "gdcmUIDGenerator.h" #include #include #include #include /* * This example will extract the Movie from the private group of * GEMS_Ultrasound_MovieGroup_001 See Attribute * (7fe1,60,GEMS_Ultrasound_MovieGroup_001) * * The output file will be stored in `outvid.dcm` as * MultiframeGrayscaleByteSecondaryCaptureImageStorage */ using namespace gdcm; static bool processgroup(Item & item3, std::string const & outfilename) { // Item &item3 = sqi3->GetItem(1); DataSet &subds3 = item3.GetNestedDataSet(); const PrivateTag tseq6(0x7fe1,0x26,"GEMS_Ultrasound_MovieGroup_001"); if( !subds3.FindDataElement( tseq6 ) ) return 1; const DataElement& seq6 = subds3.GetDataElement( tseq6 ); SmartPointer sqi6 = seq6.GetValueAsSQ(); size_t ni6= sqi6->GetNumberOfItems(); assert( sqi6->GetNumberOfItems() >= 1 ); const PrivateTag tseq7(0x7fe1,0x86,"GEMS_Ultrasound_MovieGroup_001"); int dimx = 0, dimy = 0; for( size_t i6 = 1; i6 <= ni6; ++i6 ) { Item &item6 = sqi6->GetItem(i6); DataSet &subds6 = item6.GetNestedDataSet(); if( subds6.FindDataElement( tseq7 ) ) { Element el; el.SetFromDataElement( subds6.GetDataElement( tseq7 ) ); dimx = el.GetValue(0); dimy = el.GetValue(1); std::cout << "Dims= " << dimx << " " << dimy << std::endl; } } const PrivateTag tseq3(0x7fe1,0x36,"GEMS_Ultrasound_MovieGroup_001"); if( !subds3.FindDataElement( tseq3 ) ) return 1; const DataElement& seq3 = subds3.GetDataElement( tseq3 ); // std::cout << seq3 << std::endl; SmartPointer sqi4 = seq3.GetValueAsSQ(); size_t ni4= sqi4->GetNumberOfItems(); assert( sqi4->GetNumberOfItems() >= 1 ); const PrivateTag tseq8(0x7fe1,0x37,"GEMS_Ultrasound_MovieGroup_001"); const PrivateTag tseq4(0x7fe1,0x43,"GEMS_Ultrasound_MovieGroup_001"); const PrivateTag tseq5(0x7fe1,0x60,"GEMS_Ultrasound_MovieGroup_001"); std::vector imbuffer; int dimz = 0; for( size_t i4 = 1; i4 <= ni4; ++i4 ) { Item &item4 = sqi4->GetItem(i4); DataSet &subds4 = item4.GetNestedDataSet(); if( !subds4.FindDataElement( tseq8 ) ) return 1; const DataElement& de8 = subds4.GetDataElement( tseq8 ); Element ldimz; ldimz.SetFromDataElement( de8 ); std::cout << "ldimz: " << ldimz.GetValue() << std::endl; dimz += ldimz.GetValue(); if( !subds4.FindDataElement( tseq4 ) ) return 1; const DataElement& seq4 = subds4.GetDataElement( tseq4 ); if( !subds4.FindDataElement( tseq5 ) ) return 1; const DataElement& seq5 = subds4.GetDataElement( tseq5 ); // std::cout << seq4 << std::endl; // std::cout << seq5 << std::endl; const ByteValue *bv4 = seq4.GetByteValue(); (void)bv4; Element el0; el0.SetFromDataElement( seq4 ); std::cout << "TimeStamp (" << el0.GetLength() << "): "; // Seems like the 3D volumes is split into chunks of max 100 frames... assert( ldimz.GetValue() == el0.GetLength() ); for( unsigned long i = 0; i < el0.GetLength(); ++i ) { if(i) std::cout << ","; std::cout << el0.GetValue(i); } std::cout << std::endl; #if 0 { std::ofstream out( "/tmp/mo4", std::ios::binary ); out.write( bv4->GetPointer(), bv4->GetLength()); out.close(); } #endif const ByteValue *bv5 = seq5.GetByteValue(); #if 0 { std::ofstream out( "/tmp/mo5", std::ios::binary ); out.write( bv5->GetPointer(), bv5->GetLength()); out.close(); } #endif std::cout << bv5->GetLength() << std::endl; imbuffer.insert( imbuffer.begin(), bv5->GetPointer(), bv5->GetPointer() + bv5->GetLength() ); } DataElement fakedata; fakedata.SetByteValue( &imbuffer[0], (uint32_t)imbuffer.size() ); gdcm::SmartPointer im = new gdcm::Image; im->SetNumberOfDimensions( 3 ); im->SetDimension(0, dimx ); im->SetDimension(1, dimy ); im->SetDimension(2, dimz ); size_t l1 = imbuffer.size(); (void)l1; size_t l2 = im->GetBufferLength(); (void)l2; assert( im->GetBufferLength() == imbuffer.size() ); im->SetPhotometricInterpretation( gdcm::PhotometricInterpretation::MONOCHROME2 ); im->SetDataElement( fakedata ); gdcm::ImageWriter w; w.SetImage( *im ); DataSet &dataset = w.GetFile().GetDataSet(); gdcm::UIDGenerator uid; gdcm::DataElement de( Tag(0x8,0x18) ); // SOP Instance UID de.SetVR( VR::UI ); const char *u = uid.Generate(); de.SetByteValue( u, (uint32_t)strlen(u) ); //ds.Insert( de ); dataset.Replace( de ); de.SetTag( Tag(0x8,0x16) ); // SOP Class UID de.SetVR( VR::UI ); gdcm::MediaStorage ms( gdcm::MediaStorage::MultiframeGrayscaleByteSecondaryCaptureImageStorage ); de.SetByteValue( ms.GetString(), (uint32_t)strlen(ms.GetString())); dataset.Replace( de ); // replace ! w.SetFileName( outfilename.c_str() ); if( !w.Write() ) { return false; } return true; } int main(int argc, char *argv[]) { if( argc < 2 ) return 1; const char *filename = argv[1]; gdcm::Reader reader; reader.SetFileName( filename ); reader.Read(); gdcm::File &file = reader.GetFile(); gdcm::DataSet &ds = file.GetDataSet(); const PrivateTag tseq(0x7fe1,0x1,"GEMS_Ultrasound_MovieGroup_001"); if( !ds.FindDataElement( tseq ) ) return 1; const DataElement& seq = ds.GetDataElement( tseq ); SmartPointer sqi = seq.GetValueAsSQ(); assert( sqi->GetNumberOfItems() == 1 ); Item &item = sqi->GetItem(1); DataSet &subds = item.GetNestedDataSet(); const PrivateTag tseq1(0x7fe1,0x10,"GEMS_Ultrasound_MovieGroup_001"); if( !subds.FindDataElement( tseq1 ) ) return 1; const DataElement& seq1 = subds.GetDataElement( tseq1 ); SmartPointer sqi2 = seq1.GetValueAsSQ(); assert( sqi2->GetNumberOfItems() == 1 ); //int n = sqi2->GetNumberOfItems(); int index = 1; Item &item2 = sqi2->GetItem(index); DataSet &subds2 = item2.GetNestedDataSet(); const PrivateTag tseq2(0x7fe1,0x20,"GEMS_Ultrasound_MovieGroup_001"); if( !subds2.FindDataElement( tseq2 ) ) return 1; const DataElement& seq2 = subds2.GetDataElement( tseq2 ); // std::cout << seq2 << std::endl; SmartPointer sqi3 = seq2.GetValueAsSQ(); size_t ni3 = sqi3->GetNumberOfItems(); (void)ni3; assert( sqi3->GetNumberOfItems() >= 1 ); std::cout << "#Groups = " << sqi3->GetNumberOfItems() << std::endl; for( SequenceOfItems::SizeType i = 1; i <= sqi3->GetNumberOfItems(); ++i) { Item &item3 = sqi3->GetItem(i); std::ostringstream os; os << "outvid"; os << i; os << ".dcm"; processgroup(item3, os.str()); } return 0; }