Index: mitk/Core/Code/IO/mitkDicomSeriesReader.txx =================================================================== --- mitk/Core/Code/IO/mitkDicomSeriesReader.txx (revision 24101) +++ mitk/Core/Code/IO/mitkDicomSeriesReader.txx (working copy) @@ -22,27 +22,77 @@ #include +#include +#include + namespace mitk { template void DicomSeriesReader::LoadDicom(const StringContainer &filenames, DataNode &node) { - typedef itk::Image ImageType; + typedef itk::Image ImageType; typedef itk::ImageSeriesReader ReaderType; + /******** Workaround for 4D data ***************/ + gdcm::Sorter sorter; + + sorter.SetSortFunction(DicomSeriesReader::GdcmSortFunction); + sorter.Sort(filenames); + + gdcm::Tag acq_time(0x0008,0x0032); + gdcm::Scanner scanner; + + scanner.AddTag(acq_time); + 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(), acq_time); + unsigned int volume_count = 1u; + + decomposed_filenames.push_back(StringContainer()); + decomposed_filenames.back().push_back(sorter.GetFilenames().front()); + + for (StringContainer::const_iterator f_it = ++sorter.GetFilenames().begin(); f_it != f_end; ++f_it) + { + const char *value = scanner.GetValue(f_it->c_str(), acq_time); + + if (strcmp(act_value, value)) + { + act_value = value; + decomposed_filenames.push_back(StringContainer()); + ++volume_count; + } + + decomposed_filenames.back().push_back(*f_it); + } + /******** End: Workaround for 4D data **********/ + DcmIoType::Pointer io = DcmIoType::New(); typename ReaderType::Pointer reader = ReaderType::New(); - reader->SetFileNames(filenames); reader->SetImageIO(io); reader->ReverseOrderOff(); - reader->Update(); + const std::list::const_iterator df_end = decomposed_filenames.end(); mitk::Image::Pointer image = mitk::Image::New(); + unsigned int act_volume = 1u; - image->InitializeByItk(reader->GetOutput()); - image->SetImportVolume(reader->GetOutput()->GetBufferPointer()); + reader->SetFileNames(decomposed_filenames.front()); + reader->Update(); + image->InitializeByItk(reader->GetOutput(), 1, volume_count); + image->SetImportVolume(reader->GetOutput()->GetBufferPointer(), 0u); + + MITK_INFO << "Volume dimension: [" << image->GetDimension(0) << ", " << image->GetDimension(1) << ", " << image->GetDimension(2) << ", " << image->GetDimension(3) << "]"; + + 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++); + } + node.SetData(image); } Index: mitk/Core/Code/IO/mitkDicomSeriesReader.h =================================================================== --- mitk/Core/Code/IO/mitkDicomSeriesReader.h (revision 24111) +++ mitk/Core/Code/IO/mitkDicomSeriesReader.h (working copy) @@ -27,6 +27,8 @@ #include #endif +#include + namespace mitk { @@ -94,6 +96,12 @@ */ template static void LoadDicom(const StringContainer &filenames, DataNode &node); + + /* + * Auxiliary sort function for Gdcm Dicom sorting. It is used for sorting + * 4D Dicom data. + */ + static bool GdcmSortFunction(const gdcm::DataSet &ds1, const gdcm::DataSet &ds2); }; } Index: mitk/Core/Code/IO/mitkDicomSeriesReader.cpp =================================================================== --- mitk/Core/Code/IO/mitkDicomSeriesReader.cpp (revision 24101) +++ mitk/Core/Code/IO/mitkDicomSeriesReader.cpp (working copy) @@ -19,6 +19,8 @@ #include +#include + namespace mitk { @@ -151,5 +153,27 @@ return name_generator->GetFileNames(series_uid); } +bool DicomSeriesReader::GdcmSortFunction(const gdcm::DataSet &ds1, const gdcm::DataSet &ds2) +{ + gdcm::Attribute<0x0008,0x0032> acq_time1; // Acquisition time + gdcm::Attribute<0x0020,0x0032> image_pos1; // Image Position (Patient) + + acq_time1.Set(ds1); + image_pos1.Set(ds1); + + gdcm::Attribute<0x0008,0x0032> acq_time2; + gdcm::Attribute<0x0020,0x0032> image_pos2; + + acq_time2.Set(ds2); + image_pos2.Set(ds2); + + if (acq_time1 == acq_time2) + { + return image_pos1 < image_pos2; + } + + return acq_time1 < acq_time2; +} + }