Index: Algorithms/mitkDataNodeFactory.cpp =================================================================== --- Algorithms/mitkDataNodeFactory.cpp (revision 28567) +++ Algorithms/mitkDataNodeFactory.cpp (working copy) @@ -229,6 +229,25 @@ std::locale l( "C" ); std::cin.imbue(l); + #if GDCM_MAJOR_VERSION >= 2 + if ( DicomSeriesReader::IsPhilips3DDicom(this->GetFileName()) ) + { + MITK_INFO << "it is a Philips3D US Dicom file" << std::endl; + this->ResizeOutputs(1); + DataNode::Pointer node = this->GetOutput(0); + mitk::DicomSeriesReader::StringContainer stringvec; + stringvec.push_back(this->GetFileName()); + if (DicomSeriesReader::LoadDicomSeries(stringvec, *node)) + { + node->SetName(this->GetBaseFileName()); + } + setlocale(LC_NUMERIC, previousCLocale); + std::cin.imbue(previousCppLocale); + return; + + } + #endif + DicomSeriesReader::UidFileNamesMap names_map = DicomSeriesReader::GetSeries(this->GetDirectory(), this->m_UseSeriesDetails, this->m_SeriesRestrictions); const unsigned int size = names_map.size(); @@ -244,7 +263,7 @@ const std::string &uid = n_it->first; DataNode::Pointer node = this->GetOutput(i); - MITK_INFO << "Reading series #" << i << ": " << uid << std::endl; + MITK_INFO << "Readng series #" << i << ": " << uid << std::endl; if (DicomSeriesReader::LoadDicomSeries(n_it->second, *node)) { Index: IO/mitkDicomSeriesReader.cpp =================================================================== --- IO/mitkDicomSeriesReader.cpp (revision 28567) +++ IO/mitkDicomSeriesReader.cpp (working copy) @@ -21,6 +21,8 @@ #if GDCM_MAJOR_VERSION >= 2 #include + #include + #include #endif namespace mitk @@ -108,6 +110,7 @@ return false; } + bool DicomSeriesReader::IsDicom(const std::string &filename) { DcmIoType::Pointer io = DcmIoType::New(); @@ -115,6 +118,31 @@ return io->CanReadFile(filename.c_str()); } +#if GDCM_MAJOR_VERSION >= 2 +bool DicomSeriesReader::IsPhilips3DDicom(const std::string &filename) +{ + DcmIoType::Pointer io = DcmIoType::New(); + + if (io->CanReadFile(filename.c_str())) + { + //Look at header Tag 3001,0010 if it is "Philips3D" + gdcm::PixmapReader reader; + reader.SetFileName(filename.c_str()); + reader.Read(); + gdcm::DataSet &data_set = reader.GetFile().GetDataSet(); + gdcm::StringFilter sf; + sf.SetFile(reader.GetFile()); + + if (data_set.FindDataElement(gdcm::Tag(0x3001, 0x0010)) && + (sf.ToString(gdcm::Tag(0x3001, 0x0010)) == "Philips3D ")) + { + return true; + } + } + return false; +} +#endif + DicomSeriesReader::UidFileNamesMap DicomSeriesReader::GetSeries(const std::string &dir, bool additional_criteria, const StringContainer &restrictions) { DcmFileNamesGeneratorType::Pointer name_generator = DcmFileNamesGeneratorType::New(); Index: IO/mitkDicomSeriesReader.h =================================================================== --- IO/mitkDicomSeriesReader.h (revision 28567) +++ IO/mitkDicomSeriesReader.h (working copy) @@ -71,6 +71,13 @@ static bool IsDicom(const std::string &filename); /** + * Checks if a specific file is a Philips3D Ultrasound DICOM file. + */ + #if GDCM_MAJOR_VERSION >= 2 + static bool IsPhilips3DDicom(const std::string &filename); + #endif + + /** * Find all series in a particular directory. * For each series, an enumeration of the files contained in it is created. * Optionally, more criteria can be used to distinguish between different series, and series Index: IO/mitkDicomSeriesReader.txx =================================================================== --- IO/mitkDicomSeriesReader.txx (revision 28567) +++ IO/mitkDicomSeriesReader.txx (working copy) @@ -21,102 +21,272 @@ #include #include - +//#define GDCM_MAJOR_VERSION 3 #if GDCM_MAJOR_VERSION >= 2 - #include - #include +#include +#include +#include +#include +#include #endif namespace mitk { -template -void DicomSeriesReader::LoadDicom(const StringContainer &filenames, DataNode &node, UpdateCallBackMethod callback) -{ - const char* previousCLocale = setlocale(LC_NUMERIC, NULL); - setlocale(LC_NUMERIC, "C"); - std::locale previousCppLocale( std::cin.getloc() ); - std::locale l( "C" ); - std::cin.imbue(l); - - try + template + void DicomSeriesReader::LoadDicom(const StringContainer &filenames, DataNode &node, UpdateCallBackMethod callback) { - mitk::Image::Pointer image = mitk::Image::New(); - CallbackCommand *command = callback ? new CallbackCommand(callback) : 0; + const char* previousCLocale = setlocale(LC_NUMERIC, NULL); + setlocale(LC_NUMERIC, "C"); + std::locale previousCppLocale( std::cin.getloc() ); + std::locale l( "C" ); + std::cin.imbue(l); + try + { + mitk::Image::Pointer image = mitk::Image::New(); + CallbackCommand *command = callback ? new CallbackCommand(callback) : 0; + #if GDCM_MAJOR_VERSION >= 2 - /******** Workaround for 4D data ***************/ - gdcm::Sorter sorter; + /******** Workaround for Philips 3D+t images ********/ + if ( DicomSeriesReader::IsPhilips3DDicom(filenames.front().c_str()) ) + { + // It is Philips3D! + // Now get PhilipsSpecific Tags + + gdcm::PixmapReader reader; + reader.SetFileName(filenames.front().c_str()); + reader.Read(); + gdcm::DataSet &data_set = reader.GetFile().GetDataSet(); + gdcm::StringFilter sf; + sf.SetFile(reader.GetFile()); + + gdcm::Attribute<0x0028,0x0011> dimTagX; // coloumns || sagittal + gdcm::Attribute<0x3001,0x1001, gdcm::VR::UL, gdcm::VM::VM1> dimTagZ; //I have no idea what is VM1. // (Philips specific) // transversal + gdcm::Attribute<0x0028,0x0010> dimTagY; // rows || coronal + gdcm::Attribute<0x0028,0x0008> dimTagT; + gdcm::Attribute<0x0018,0x602c> spaceTagX; + gdcm::Attribute<0x0018,0x602e> spaceTagY; + gdcm::Attribute<0x3001,0x1003, gdcm::VR::FD, gdcm::VM::VM1> spaceTagZ; // (Philips specific) + gdcm::Attribute<0x0018,0x6024> physicalTagX; + gdcm::Attribute<0x0018,0x6026> physicalTagY; + gdcm::Attribute<0x3001,0x1002, gdcm::VR::US, gdcm::VM::VM1> physicalTagZ; // (Philips specific) - sorter.SetSortFunction(DicomSeriesReader::GdcmSortFunction); - sorter.Sort(filenames); + dimTagX.Set(data_set); + dimTagY.Set(data_set); + dimTagZ.Set(data_set); + dimTagT.Set(data_set); + spaceTagX.Set(data_set); + spaceTagY.Set(data_set); + spaceTagZ.Set(data_set); + physicalTagX.Set(data_set); + physicalTagY.Set(data_set); + physicalTagZ.Set(data_set); - gdcm::Tag tag(0x0020,0x1041); //Slice location - gdcm::Scanner scanner; + unsigned int + dimX = dimTagX.GetValue(), + dimY = dimTagY.GetValue(), + dimZ = dimTagZ.GetValue(), + dimT = dimTagT.GetValue(), + physicalX = physicalTagX.GetValue(), + physicalY = physicalTagY.GetValue(), + physicalZ = physicalTagZ.GetValue(); - scanner.AddTag(tag); - scanner.Scan(sorter.GetFilenames()); + float + spaceX = spaceTagX.GetValue(), + spaceY = spaceTagY.GetValue(), + spaceZ = spaceTagZ.GetValue(); - std::list decomposed_filenames; - const StringContainer::const_iterator f_end = sorter.GetFilenames().end(); - const char *act_value = scanner.GetValue(sorter.GetFilenames().front().c_str(), tag); - unsigned int volume_count = 1u; + // Ok, got all necessary Tags! + // Now read Pixeldata (7fe0,0010) X x Y x Z x T Elements - decomposed_filenames.push_back(StringContainer()); - decomposed_filenames.back().push_back(sorter.GetFilenames().front()); + const gdcm::Pixmap &pixels = reader.GetPixmap(); + gdcm::RAWCodec codec; - for (StringContainer::const_iterator f_it = ++sorter.GetFilenames().begin(); f_it != f_end; ++f_it) - { - const char *value = scanner.GetValue(f_it->c_str(), tag); + codec.SetPhotometricInterpretation(gdcm::PhotometricInterpretation::MONOCHROME2); + codec.SetPixelFormat(pixels.GetPixelFormat()); + codec.SetPlanarConfiguration(0); - if (!strcmp(act_value, value)) + gdcm::DataElement out; + codec.Decode(data_set.GetDataElement(gdcm::Tag(0x7fe0, 0x0010)), out); + + const gdcm::ByteValue *bv = out.GetByteValue(); + const char *new_pixels = bv->GetPointer(); + + // Create MITK Image + Geometry + typedef itk::Image ImageType; + typename ImageType::RegionType myRegion; + typename ImageType::SizeType mySize; + typename ImageType::IndexType myIndex; + typename ImageType::SpacingType mySpacing; + ImageType::Pointer imageItk = ImageType::New(); + + mySpacing[0] = spaceX; + mySpacing[1] = spaceY; + mySpacing[2] = spaceZ; + mySpacing[3] = 1; + myIndex[0] = physicalX; + myIndex[1] = physicalY; + myIndex[2] = physicalZ; + myIndex[3] = 0; + mySize[0] = dimX; + mySize[1] = dimY; + mySize[2] = dimZ; + mySize[3] = dimT; + myRegion.SetSize( mySize); + myRegion.SetIndex( myIndex ); + imageItk->SetSpacing(mySpacing); + imageItk->SetRegions( myRegion); + imageItk->Allocate(); + imageItk->FillBuffer(0); + + typename itk::ImageRegionIterator iterator(imageItk, imageItk->GetLargestPossibleRegion()); + iterator.GoToBegin(); + unsigned long pixCount = 0; + unsigned long planeSize = dimX*dimY; + unsigned long planeCount = 0; + unsigned long timeCount = 0; + unsigned long numberOfSlices = dimZ; + + while (!iterator.IsAtEnd()) + { + unsigned long adressedPixel = + pixCount + + (numberOfSlices-1-planeCount)*planeSize // add offset to adress the first pixel of current plane + + timeCount*numberOfSlices*planeSize; // add time offset + + iterator.Set( new_pixels[ adressedPixel ] ); + pixCount++; + iterator++; + + if (pixCount == planeSize) + { + pixCount = 0; + planeCount++; + } + if (planeCount == numberOfSlices) + { + planeCount = 0; + timeCount++; + } + if (timeCount == dimT) + { + break; + } + } + mitk::CastToMitkImage(imageItk, image); + /* + // this works as well, but then the picture is upside down.. transversal slice[max] should be transversal slice[0] and so on. + while (!iterator.IsAtEnd()) + { + iterator.Set( new_pixels[pixCount] ); + pixCount++; + iterator++; + } + mitk::CastToMitkImage(imageItk, image); + */ + + } + /******** END: Workaround for Phillips 3D+t images ********/ + else { - act_value = value; + /******** Workaround for 4D data ***************/ + gdcm::Sorter sorter; + + sorter.SetSortFunction(DicomSeriesReader::GdcmSortFunction); + sorter.Sort(filenames); + + gdcm::Tag tag(0x0020,0x1041); //Slice location + gdcm::Scanner scanner; + + scanner.AddTag(tag); + scanner.Scan(sorter.GetFilenames()); + + std::list decomposed_filenames; + const StringContainer::const_iterator f_end = sorter.GetFilenames().end(); + const char *act_value = scanner.GetValue(sorter.GetFilenames().front().c_str(), tag); + unsigned int volume_count = 1u; + decomposed_filenames.push_back(StringContainer()); - ++volume_count; - } + decomposed_filenames.back().push_back(sorter.GetFilenames().front()); - decomposed_filenames.back().push_back(*f_it); - } - /******** End: Workaround for 4D data **********/ + for (StringContainer::const_iterator f_it = ++sorter.GetFilenames().begin(); f_it != f_end; ++f_it) + { + const char *value = scanner.GetValue(f_it->c_str(), tag); - if (volume_count > 1) - { - typedef itk::Image ImageType; - typedef itk::ImageSeriesReader ReaderType; + if (!strcmp(act_value, value)) + { + act_value = value; + decomposed_filenames.push_back(StringContainer()); + ++volume_count; + } - DcmIoType::Pointer io = DcmIoType::New(); - typename ReaderType::Pointer reader = ReaderType::New(); + decomposed_filenames.back().push_back(*f_it); + } + /******** End: Workaround for 4D data **********/ - reader->SetImageIO(io); - reader->ReverseOrderOff(); + if (volume_count > 1) + { + typedef itk::Image ImageType; + typedef itk::ImageSeriesReader ReaderType; - if (command) - { - reader->AddObserver(itk::ProgressEvent(), command); - } + DcmIoType::Pointer io = DcmIoType::New(); + typename ReaderType::Pointer reader = ReaderType::New(); - const std::list::const_iterator df_end = decomposed_filenames.end(); - unsigned int act_volume = 1u; + reader->SetImageIO(io); + reader->ReverseOrderOff(); - reader->SetFileNames(decomposed_filenames.front()); - reader->Update(); - image->InitializeByItk(reader->GetOutput(), 1, volume_count); - image->SetImportVolume(reader->GetOutput()->GetBufferPointer(), 0u); + if (command) + { + reader->AddObserver(itk::ProgressEvent(), command); + } - MITK_DEBUG << "Volume dimension: [" << image->GetDimension(0) << ", " << image->GetDimension(1) << ", " << image->GetDimension(2) << ", " << image->GetDimension(3) << "]"; - MITK_DEBUG << "Volume spacing: [" << image->GetGeometry()->GetSpacing()[0] << ", " << image->GetGeometry()->GetSpacing()[1] << ", " << image->GetGeometry()->GetSpacing()[2] << "]"; + const std::list::const_iterator df_end = decomposed_filenames.end(); + unsigned int act_volume = 1u; - for (std::list::iterator df_it = ++decomposed_filenames.begin(); df_it != df_end; ++df_it) - { - reader->SetFileNames(*df_it); - reader->Update(); - image->SetImportVolume(reader->GetOutput()->GetBufferPointer(), act_volume++); + reader->SetFileNames(decomposed_filenames.front()); + reader->Update(); + image->InitializeByItk(reader->GetOutput(), 1, volume_count); + image->SetImportVolume(reader->GetOutput()->GetBufferPointer(), 0u); + + MITK_DEBUG << "Volume dimension: [" << image->GetDimension(0) << ", " << image->GetDimension(1) << ", " << image->GetDimension(2) << ", " << image->GetDimension(3) << "]"; + MITK_DEBUG << "Volume spacing: [" << image->GetGeometry()->GetSpacing()[0] << ", " << image->GetGeometry()->GetSpacing()[1] << ", " << image->GetGeometry()->GetSpacing()[2] << "]"; + + for (std::list::iterator df_it = ++decomposed_filenames.begin(); df_it != df_end; ++df_it) + { + reader->SetFileNames(*df_it); + reader->Update(); + image->SetImportVolume(reader->GetOutput()->GetBufferPointer(), act_volume++); + } + } + else + { + typedef itk::Image ImageType; + typedef itk::ImageSeriesReader ReaderType; + + DcmIoType::Pointer io = DcmIoType::New(); + typename ReaderType::Pointer reader = ReaderType::New(); + + reader->SetImageIO(io); + reader->ReverseOrderOff(); + + if (command) + { + reader->AddObserver(itk::ProgressEvent(), command); + } + + reader->SetFileNames(filenames); + reader->Update(); + image->InitializeByItk(reader->GetOutput()); + image->SetImportVolume(reader->GetOutput()->GetBufferPointer()); + + MITK_DEBUG << "Volume dimension: [" << image->GetDimension(0) << ", " << image->GetDimension(1) << ", " << image->GetDimension(2) << "]"; + MITK_DEBUG << "Volume spacing: [" << image->GetGeometry()->GetSpacing()[0] << ", " << image->GetGeometry()->GetSpacing()[1] << ", " << image->GetGeometry()->GetSpacing()[2] << "]"; + } } - } - else - { + +#else typedef itk::Image ImageType; typedef itk::ImageSeriesReader ReaderType; @@ -138,48 +308,24 @@ MITK_DEBUG << "Volume dimension: [" << image->GetDimension(0) << ", " << image->GetDimension(1) << ", " << image->GetDimension(2) << "]"; MITK_DEBUG << "Volume spacing: [" << image->GetGeometry()->GetSpacing()[0] << ", " << image->GetGeometry()->GetSpacing()[1] << ", " << image->GetGeometry()->GetSpacing()[2] << "]"; - } -#else - typedef itk::Image ImageType; - typedef itk::ImageSeriesReader ReaderType; +#endif - DcmIoType::Pointer io = DcmIoType::New(); - typename ReaderType::Pointer reader = ReaderType::New(); + node.SetData(image); - reader->SetImageIO(io); - reader->ReverseOrderOff(); + setlocale(LC_NUMERIC, previousCLocale); + std::cin.imbue(previousCppLocale); - if (command) + } + catch (std::exception& e) { - reader->AddObserver(itk::ProgressEvent(), command); + setlocale(LC_NUMERIC, previousCLocale); + std::cin.imbue(previousCppLocale); + + throw e; } - - reader->SetFileNames(filenames); - reader->Update(); - image->InitializeByItk(reader->GetOutput()); - image->SetImportVolume(reader->GetOutput()->GetBufferPointer()); - - MITK_DEBUG << "Volume dimension: [" << image->GetDimension(0) << ", " << image->GetDimension(1) << ", " << image->GetDimension(2) << "]"; - MITK_DEBUG << "Volume spacing: [" << image->GetGeometry()->GetSpacing()[0] << ", " << image->GetGeometry()->GetSpacing()[1] << ", " << image->GetGeometry()->GetSpacing()[2] << "]"; - -#endif - - node.SetData(image); - - setlocale(LC_NUMERIC, previousCLocale); - std::cin.imbue(previousCppLocale); - } - catch (std::exception& e) - { - setlocale(LC_NUMERIC, previousCLocale); - std::cin.imbue(previousCppLocale); - throw e; - } } -} - #endif