Index: mbi-sb/BundlesQt/org.mitk.gui.qt.dicombrowser/src/internal/QmitkDICOMBrowserView.cpp =================================================================== --- mbi-sb/BundlesQt/org.mitk.gui.qt.dicombrowser/src/internal/QmitkDICOMBrowserView.cpp (revision 28789) +++ mbi-sb/BundlesQt/org.mitk.gui.qt.dicombrowser/src/internal/QmitkDICOMBrowserView.cpp (working copy) @@ -162,7 +162,7 @@ QmitkDICOMBrowserView::ProgressAux::m_LastProgress = 0u; mitk::DicomSeriesReader::StringContainer names = mitk::DicomSeriesReader::GetSeries(dir.toStdString(), series_uid.toStdString()); - mitk::DataNode::Pointer node = mitk::DicomSeriesReader::LoadDicomSeries(names, QmitkDICOMBrowserView::ProgressAux::UpdateProgressBar); + mitk::DataNode::Pointer node = mitk::DicomSeriesReader::LoadDicomSeries(names, true, true, QmitkDICOMBrowserView::ProgressAux::UpdateProgressBar); if (node.IsNull()) { Index: mitk/Core/Code/Algorithms/mitkDataNodeFactory.cpp =================================================================== --- mitk/Core/Code/Algorithms/mitkDataNodeFactory.cpp (revision 28789) +++ mitk/Core/Code/Algorithms/mitkDataNodeFactory.cpp (working copy) @@ -90,7 +90,6 @@ bool mitk::DataNodeFactory::m_TextureInterpolationActive = false; // default value for texture interpolation if nothing is defined in global options (see QmitkMainTemplate.ui.h) mitk::DataNodeFactory::DataNodeFactory() -: m_UseSeriesDetails(true) { m_Serie = false; m_OldProgress = 0; @@ -248,7 +247,7 @@ } #endif - DicomSeriesReader::UidFileNamesMap names_map = DicomSeriesReader::GetSeries(this->GetDirectory(), this->m_UseSeriesDetails, this->m_SeriesRestrictions); + DicomSeriesReader::UidFileNamesMap names_map = DicomSeriesReader::GetSeries(this->GetDirectory(), this->m_SeriesRestrictions); const unsigned int size = names_map.size(); this->ResizeOutputs(size); Index: mitk/Core/Code/Algorithms/mitkDataNodeFactory.h =================================================================== --- mitk/Core/Code/Algorithms/mitkDataNodeFactory.h (revision 28789) +++ mitk/Core/Code/Algorithms/mitkDataNodeFactory.h (working copy) @@ -93,9 +93,6 @@ */ void SetImageSerie(bool serie); - itkGetMacro( UseSeriesDetails, bool ); - itkSetMacro( UseSeriesDetails, bool ); - void AddSeriesRestriction(const std::string &tag) {m_SeriesRestrictions.push_back(tag);} @@ -176,7 +173,6 @@ virtual void ReadFileSeriesTypeITKImageSeriesReader(); - bool m_UseSeriesDetails; std::vector m_SeriesRestrictions; int m_OldProgress; }; Index: mitk/Core/Code/IO/mitkDicomSeriesReader.cpp =================================================================== --- mitk/Core/Code/IO/mitkDicomSeriesReader.cpp (revision 28789) +++ mitk/Core/Code/IO/mitkDicomSeriesReader.cpp (working copy) @@ -30,11 +30,11 @@ typedef itk::GDCMSeriesFileNames DcmFileNamesGeneratorType; -DataNode::Pointer DicomSeriesReader::LoadDicomSeries(const StringContainer &filenames, UpdateCallBackMethod callback) +DataNode::Pointer DicomSeriesReader::LoadDicomSeries(const StringContainer &filenames, bool sort, bool check_4d, UpdateCallBackMethod callback) { DataNode::Pointer node = DataNode::New(); - if (DicomSeriesReader::LoadDicomSeries(filenames, *node, callback)) + if (DicomSeriesReader::LoadDicomSeries(filenames, *node, sort, check_4d, callback)) { return node; } @@ -44,7 +44,7 @@ } } -bool DicomSeriesReader::LoadDicomSeries(const StringContainer &filenames, DataNode &node, UpdateCallBackMethod callback) +bool DicomSeriesReader::LoadDicomSeries(const StringContainer &filenames, DataNode &node, bool sort, bool check_4d, UpdateCallBackMethod callback) { if(filenames.size() == 0) { @@ -64,34 +64,34 @@ switch (io->GetComponentType()) { case DcmIoType::UCHAR: - DicomSeriesReader::LoadDicom(filenames, node, callback); + DicomSeriesReader::LoadDicom(filenames, node, sort, check_4d, callback); return true; case DcmIoType::CHAR: - DicomSeriesReader::LoadDicom(filenames, node, callback); + DicomSeriesReader::LoadDicom(filenames, node, sort, check_4d, callback); return true; case DcmIoType::USHORT: - DicomSeriesReader::LoadDicom(filenames, node, callback); + DicomSeriesReader::LoadDicom(filenames, node, sort, check_4d, callback); return true; case DcmIoType::SHORT: - DicomSeriesReader::LoadDicom(filenames, node, callback); + DicomSeriesReader::LoadDicom(filenames, node, sort, check_4d, callback); return true; case DcmIoType::UINT: - DicomSeriesReader::LoadDicom(filenames, node, callback); + DicomSeriesReader::LoadDicom(filenames, node, sort, check_4d, callback); return true; case DcmIoType::INT: - DicomSeriesReader::LoadDicom(filenames, node, callback); + DicomSeriesReader::LoadDicom(filenames, node, sort, check_4d, callback); return true; case DcmIoType::ULONG: - DicomSeriesReader::LoadDicom(filenames, node, callback); + DicomSeriesReader::LoadDicom(filenames, node, sort, check_4d, callback); return true; case DcmIoType::LONG: - DicomSeriesReader::LoadDicom(filenames, node, callback); + DicomSeriesReader::LoadDicom(filenames, node, sort, check_4d, callback); return true; case DcmIoType::FLOAT: - DicomSeriesReader::LoadDicom(filenames, node, callback); + DicomSeriesReader::LoadDicom(filenames, node, sort, check_4d, callback); return true; case DcmIoType::DOUBLE: - DicomSeriesReader::LoadDicom(filenames, node, callback); + DicomSeriesReader::LoadDicom(filenames, node, sort, check_4d, callback); return true; default: MITK_ERROR << "Unknown pixel type!"; @@ -126,7 +126,7 @@ if (io->CanReadFile(filename.c_str())) { //Look at header Tag 3001,0010 if it is "Philips3D" - gdcm::PixmapReader reader; + gdcm::Reader reader; reader.SetFileName(filename.c_str()); reader.Read(); gdcm::DataSet &data_set = reader.GetFile().GetDataSet(); @@ -144,7 +144,7 @@ bool DicomSeriesReader::ReadPhilips3DDicom(const std::string &filename, mitk::Image::Pointer output_image) { - // Now get PhilipsSpecific Tags + // Now get PhilipsSpecific Tags gdcm::PixmapReader reader; reader.SetFileName(filename.c_str()); @@ -164,7 +164,7 @@ gdcm::Attribute<0x0018,0x6026> physicalTagY; gdcm::Attribute<0x3001,0x1002, gdcm::VR::US, gdcm::VM::VM1> physicalTagZ; // (Philips specific) - dimTagX.Set(data_set); + dimTagX.Set(data_set); dimTagY.Set(data_set); dimTagZ.Set(data_set); dimTagT.Set(data_set); @@ -229,26 +229,26 @@ myRegion.SetIndex( myIndex ); imageItk->SetSpacing(mySpacing); imageItk->SetRegions( myRegion); - imageItk->Allocate(); + imageItk->Allocate(); imageItk->FillBuffer(0); itk::ImageRegionIterator iterator(imageItk, imageItk->GetLargestPossibleRegion()); - iterator.GoToBegin(); + iterator.GoToBegin(); unsigned long pixCount = 0; unsigned long planeSize = dimX*dimY; - unsigned long planeCount = 0; - unsigned long timeCount = 0; + unsigned long planeCount = 0; + unsigned long timeCount = 0; unsigned long numberOfSlices = dimZ; while (!iterator.IsAtEnd()) - { - unsigned long adressedPixel = + { + 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++; + pixCount++; ++iterator; if (pixCount == planeSize) @@ -265,29 +265,43 @@ { break; } - } - mitk::CastToMitkImage(imageItk, output_image); + } + mitk::CastToMitkImage(imageItk, output_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++; + pixCount++; iterator++; - } - mitk::CastToMitkImage(imageItk, image); - */ + } + mitk::CastToMitkImage(imageItk, image); + */ return true; // actually never returns false yet.. but exception possible } #endif -DicomSeriesReader::UidFileNamesMap DicomSeriesReader::GetSeries(const std::string &dir, bool additional_criteria, const StringContainer &restrictions) +DicomSeriesReader::UidFileNamesMap DicomSeriesReader::GetSeries(const std::string &dir, const StringContainer &restrictions) { DcmFileNamesGeneratorType::Pointer name_generator = DcmFileNamesGeneratorType::New(); - name_generator->SetUseSeriesDetails(additional_criteria); - name_generator->SetDirectory(dir.c_str()); + /** + assumption about this method: + returns a map of uid-like-key --> list(filename) + each entry should contain filenames that have images of same + - TODO study instance uid + - TODO series instance uid + - 0020,0037 image orientation (patient) + - 0028,0030 pixel spacing (x,y) + - 0018,0050 slice thickness + + */ + + name_generator->SetUseSeriesDetails(true); + name_generator->AddSeriesRestriction("0020|0037"); // image orientation (patient) + name_generator->AddSeriesRestriction("0028|0030"); // pixel spacing (x,y) + const StringContainer::const_iterator restrictions_end = restrictions.end(); for(StringContainer::const_iterator it = restrictions.begin(); it != restrictions_end; ++it) @@ -295,6 +309,8 @@ name_generator->AddSeriesRestriction(*it); } + name_generator->SetDirectory(dir.c_str()); + UidFileNamesMap map; const StringContainer &series_uids = name_generator->GetSeriesUIDs(); const StringContainer::const_iterator series_end = series_uids.end(); @@ -309,13 +325,13 @@ return map; } -DicomSeriesReader::StringContainer DicomSeriesReader::GetSeries(const std::string &dir, const std::string &series_uid, bool additional_criteria, - const StringContainer &restrictions) +DicomSeriesReader::StringContainer DicomSeriesReader::GetSeries(const std::string &dir, const std::string &series_uid, const StringContainer &restrictions) { DcmFileNamesGeneratorType::Pointer name_generator = DcmFileNamesGeneratorType::New(); - name_generator->SetUseSeriesDetails(additional_criteria); - name_generator->SetDirectory(dir.c_str()); + name_generator->SetUseSeriesDetails(true); + name_generator->AddSeriesRestriction("0020|0037"); // image orientation (patient) + name_generator->AddSeriesRestriction("0028|0030"); // pixel spacing (x,y) const StringContainer::const_iterator restrictions_end = restrictions.end(); @@ -324,27 +340,68 @@ name_generator->AddSeriesRestriction(*it); } + name_generator->SetDirectory(dir.c_str()); + return name_generator->GetFileNames(series_uid); } +DicomSeriesReader::StringContainer DicomSeriesReader::SortSeriesSlices(const StringContainer &unsortedFilenames) +{ #if GDCM_MAJOR_VERSION >= 2 + gdcm::Sorter sorter; + + sorter.SetSortFunction(DicomSeriesReader::GdcmSortFunction); + sorter.Sort(unsortedFilenames); + return sorter.GetFilenames(); +#else + return unsortedFilenames; +#endif +} + +#if GDCM_MAJOR_VERSION >= 2 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) + gdcm::Attribute<0x0020,0x0037> image_orientation1; // Image Orientation (Patient) acq_time1.Set(ds1); image_pos1.Set(ds1); + image_orientation1.Set(ds1); gdcm::Attribute<0x0008,0x0032> acq_time2; gdcm::Attribute<0x0020,0x0032> image_pos2; + gdcm::Attribute<0x0020,0x0037> image_orientation2; acq_time2.Set(ds2); image_pos2.Set(ds2); + image_orientation2.Set(ds2); + if (image_orientation1 != image_orientation2) + { + MITK_ERROR << "Dicom images have different orientations."; + throw std::logic_error("Dicom images have different orientations."); + } + if (acq_time1 == acq_time2) { - return image_pos1 < image_pos2; + double normal[3]; + + normal[0] = image_orientation1[1] * image_orientation1[5] - image_orientation1[2] * image_orientation1[4]; + normal[1] = image_orientation1[2] * image_orientation1[3] - image_orientation1[0] * image_orientation1[5]; + normal[2] = image_orientation1[0] * image_orientation1[4] - image_orientation1[1] * image_orientation1[3]; + + double + dist1 = 0.0, + dist2 = 0.0; + + for (unsigned char i = 0u; i < 3u; ++i) + { + dist1 += normal[i] * image_pos1[i]; + dist2 += normal[i] * image_pos2[i]; + } + + return dist1 < dist2; } return acq_time1 < acq_time2; Index: mitk/Core/Code/IO/mitkDicomSeriesReader.h =================================================================== --- mitk/Core/Code/IO/mitkDicomSeriesReader.h (revision 28789) +++ mitk/Core/Code/IO/mitkDicomSeriesReader.h (working copy) @@ -43,114 +43,140 @@ namespace mitk { +/** +* Provides functions for loading DICOM series. +* The series is specified through an enumeration of all files contained in it. +* A method for the creation of file name enumerations of all series contained in +* a particular directory is also provided. +* After loading the series, the generated DataNode is not named. The caller is +* responsible for given the node a name. +*/ +class MITK_CORE_EXPORT DicomSeriesReader +{ +public: + typedef std::vector StringContainer; + typedef std::map UidFileNamesMap; + typedef void (*UpdateCallBackMethod)(float); + /** - * Provides functions for loading DICOM series. - * The series is specified through an enumeration of all files contained in it. - * A method for the creation of file name enumerations of all series contained in - * a particular directory is also provided. - * After loading the series, the generated DataNode is not named. The caller is - * responsible for given the node a name. + * Loads a DICOM series composed by the file names enumerated in the file names container. + * If a callback method is supplied, it will be called after every progress update with a progress value in [0,1]. */ - class MITK_CORE_EXPORT DicomSeriesReader - { - public: - typedef std::vector StringContainer; - typedef std::map UidFileNamesMap; - typedef void (*UpdateCallBackMethod)(float); + static DataNode::Pointer LoadDicomSeries(const StringContainer &filenames, bool sort = true, bool check_4d = true, UpdateCallBackMethod callback = 0); - /** - * Loads a DICOM series composed by the file names enumerated in the file names container. - * If a callback method is supplied, it will be called after every progress update with a progress value in [0,1]. - */ - static DataNode::Pointer LoadDicomSeries(const StringContainer &filenames, UpdateCallBackMethod callback = 0); + /** + * Loads a DICOM series composed by the file names enumerated in the file names container. + * If a callback method is supplied, it will be called after every progress update with a progress value in [0,1]. + */ + static bool LoadDicomSeries(const StringContainer &filenames, DataNode &node, bool sort = true, bool check_4d = true, UpdateCallBackMethod callback = 0); - /** - * Loads a DICOM series composed by the file names enumerated in the file names container. - * If a callback method is supplied, it will be called after every progress update with a progress value in [0,1]. - */ - static bool LoadDicomSeries(const StringContainer &filenames, DataNode &node, UpdateCallBackMethod callback = 0); + /** + * Checks if a specific file is a DICOM. + */ + static bool IsDicom(const std::string &filename); - /** - * Checks if a specific file is a DICOM. - */ - static bool IsDicom(const std::string &filename); - #if GDCM_MAJOR_VERSION >= 2 - /** - * Checks if a specific file is a Philips3D Ultrasound DICOM file. - */ - static bool IsPhilips3DDicom(const std::string &filename); + /** + * Checks if a specific file is a Philips3D Ultrasound DICOM file. + */ + static bool IsPhilips3DDicom(const std::string &filename); - /** - * Read a Philips3D Ultrasound DICOM file and put into an mitk image - */ - static bool ReadPhilips3DDicom(const std::string &filename, mitk::Image::Pointer output_image); + /** + * Read a Philips3D Ultrasound DICOM file and put into an mitk image + */ + static bool ReadPhilips3DDicom(const std::string &filename, mitk::Image::Pointer output_image); #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 - * restrictions can be specified. - */ - static UidFileNamesMap GetSeries(const std::string &dir, bool additional_criteria = false, - const StringContainer &restrictions = StringContainer()); + /** + * \brief Find all series (and sub-series -- see details) in a particular directory. + * + * For each series, an enumeration of the files contained in it is created. + * + * \return The resulting map will map SeriesInstanceUID to UNSORTED lists of file names. + * + * SeriesInstanceUID will be FORCED to be unique for each set of file names + * that should be loadable as a single mitk::Image. This implies that + * Image orientation, slice thickness, pixel spacing, rows, and columns + * must be the same for each file (i.e. the image slice contained in the file). + * + * If this separation logic requires that a SeriesInstanceUID must be made more specialized, + * it will follow the same logic as itk::GDCMSeriesFileNames to enhance the UID with + * more digits and dots. + * + * Optionally, more tags can be used to separate files into different logical series by setting + * the restrictions parameter. + */ + static UidFileNamesMap GetSeries(const std::string &dir, const StringContainer &restrictions = StringContainer()); - /** - * Find a particular series in a 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 - * restrictions can be specified. - */ - static StringContainer GetSeries(const std::string &dir, const std::string &series_uid, - bool additional_criteria = false, const StringContainer &restrictions = StringContainer()); - protected: - inline DicomSeriesReader() - {} + /** + * Find a particular series in a directory. + * For each series, an enumeration of the files contained in it is created. + * Optionally, more criteria (restrictions) can be used to distinguish between different series, and series + * restrictions can be specified. + */ + static StringContainer GetSeries(const std::string &dir, const std::string &series_uid, + const StringContainer &restrictions = StringContainer()); - inline ~DicomSeriesReader() - {} + /** + * Sort a set of file names in an order that is meaningful for loading them into an mitk::Image. + * + * \warning This method assumes that input files are similar in basic properties such as slice thicknes, image orientation, pixel spacing, rows, columns. + * + * It should always be ok to put the result of a call to GetSeries(..) into this method.(..). + * + * Sorting order is determined by + * + * 1. TODO + * 2. + */ + static StringContainer SortSeriesSlices(const StringContainer &unsortedFilenames); +protected: + inline DicomSeriesReader() + {} + inline ~DicomSeriesReader() + {} + #ifdef MITK_USE_GDCMIO - typedef itk::GDCMImageIO DcmIoType; + typedef itk::GDCMImageIO DcmIoType; #else - typedef itk::DICOMImageIO2 DcmIoType; + typedef itk::DICOMImageIO2 DcmIoType; #endif - class CallbackCommand : public itk::Command + class CallbackCommand : public itk::Command + { + public: + inline CallbackCommand(UpdateCallBackMethod callback) + : m_Callback(callback) + {} + + inline void Execute(const itk::Object *caller, const itk::EventObject&) { - public: - inline CallbackCommand(UpdateCallBackMethod callback) - : m_Callback(callback) - {} + (*this->m_Callback)(static_cast(caller)->GetProgress()); + } - inline void Execute(const itk::Object *caller, const itk::EventObject&) - { - (*this->m_Callback)(static_cast(caller)->GetProgress()); - } + inline void Execute(itk::Object *caller, const itk::EventObject&) + { + (*this->m_Callback)(static_cast(caller)->GetProgress()); + } + protected: + UpdateCallBackMethod m_Callback; + }; - inline void Execute(itk::Object *caller, const itk::EventObject&) - { - (*this->m_Callback)(static_cast(caller)->GetProgress()); - } - protected: - UpdateCallBackMethod m_Callback; - }; + /** + * Performs the loading of a series and creates an image having the specified pixel type. + */ + template + static void LoadDicom(const StringContainer &filenames, DataNode &node, bool sort, bool check_4d, UpdateCallBackMethod callback); - /** - * Performs the loading of a series and creates an image having the specified pixel type. - */ - template - static void LoadDicom(const StringContainer &filenames, DataNode &node, UpdateCallBackMethod callback); - #if GDCM_MAJOR_VERSION >= 2 - /* - * 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); + /* + * 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); #endif - }; +}; } Index: mitk/Core/Code/IO/mitkDicomSeriesReader.txx =================================================================== --- mitk/Core/Code/IO/mitkDicomSeriesReader.txx (revision 28789) +++ mitk/Core/Code/IO/mitkDicomSeriesReader.txx (working copy) @@ -21,117 +21,80 @@ #include #include -//#define GDCM_MAJOR_VERSION 3 - namespace mitk { - template - void DicomSeriesReader::LoadDicom(const StringContainer &filenames, DataNode &node, UpdateCallBackMethod callback) +template +void DicomSeriesReader::LoadDicom(const StringContainer &filenames, DataNode &node, bool sort, bool check_4d, 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 { - 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); + mitk::Image::Pointer image = mitk::Image::New(); + CallbackCommand *command = callback ? new CallbackCommand(callback) : 0; - try - { - mitk::Image::Pointer image = mitk::Image::New(); - CallbackCommand *command = callback ? new CallbackCommand(callback) : 0; - #if GDCM_MAJOR_VERSION >= 2 - /******** For Philips 3D+t images ********/ - if ( DicomSeriesReader::IsPhilips3DDicom(filenames.front().c_str()) ) - { - ReadPhilips3DDicom(filenames.front().c_str(), image); - node.SetData(image); - setlocale(LC_NUMERIC, previousCLocale); - std::cin.imbue(previousCppLocale); - return; - } + /******** For Philips 3D+t images ********/ + if ( DicomSeriesReader::IsPhilips3DDicom(filenames.front().c_str()) ) + { + ReadPhilips3DDicom(filenames.front().c_str(), image); + node.SetData(image); + setlocale(LC_NUMERIC, previousCLocale); + std::cin.imbue(previousCppLocale); + return; + } - /******** For 4D data split in multiple files ***************/ - std::list decomposed_filenames; - unsigned int volume_count = 1u; + /******** For 4D data split in multiple files ***************/ + std::list decomposed_filenames; + unsigned int volume_count = 1u; - gdcm::Sorter sorter; - - sorter.SetSortFunction(DicomSeriesReader::GdcmSortFunction); - sorter.Sort(filenames); - - gdcm::Tag tag(0x0020,0x1041); //Slice location + StringContainer sorted_filenames = sort + ? DicomSeriesReader::SortSeriesSlices(filenames) + : filenames; + if (check_4d) + { + gdcm::Tag tag(0x0020,0x0032); //Image position (Patient) gdcm::Scanner scanner; scanner.AddTag(tag); - scanner.Scan(sorter.GetFilenames()); + scanner.Scan(sorted_filenames); - const StringContainer::const_iterator f_end = sorter.GetFilenames().end(); - const char *act_value = scanner.GetValue(sorter.GetFilenames().front().c_str(), tag); + const StringContainer::const_iterator f_end = sorted_filenames.end(); + const char *act_value = scanner.GetValue(sorted_filenames.front().c_str(), tag); - decomposed_filenames.push_back(StringContainer()); - decomposed_filenames.back().push_back(sorter.GetFilenames().front()); + decomposed_filenames.back().push_back(sorted_filenames.front()); - for (StringContainer::const_iterator f_it = ++sorter.GetFilenames().begin(); f_it != f_end; ++f_it) + for (StringContainer::const_iterator f_it = ++sorted_filenames.begin(); f_it != f_end; ++f_it) { const char *value = scanner.GetValue(f_it->c_str(), tag); if (!strcmp(act_value, value)) { - act_value = value; decomposed_filenames.push_back(StringContainer()); ++volume_count; } decomposed_filenames.back().push_back(*f_it); } - if (volume_count > 1) - { - // It is 4D! Read it and store into mitk image + } + else + { + decomposed_filenames.push_back(sorted_filenames); + } - typedef itk::Image ImageType; - typedef itk::ImageSeriesReader ReaderType; + if (volume_count > 1u) + { + // It is 4D! Read it and store into mitk image - DcmIoType::Pointer io = DcmIoType::New(); - typename ReaderType::Pointer reader = ReaderType::New(); - - reader->SetImageIO(io); - reader->ReverseOrderOff(); - - if (command) - { - reader->AddObserver(itk::ProgressEvent(), command); - } - - const std::list::const_iterator df_end = decomposed_filenames.end(); - unsigned int act_volume = 1u; - - 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++); - } - node.SetData(image); - setlocale(LC_NUMERIC, previousCLocale); - std::cin.imbue(previousCppLocale); - return; // finished - } -#endif - /******** Normal Case, 3D (also for GDCM < 2 usable) ***************/ - - typedef itk::Image ImageType; + typedef itk::Image ImageType; typedef itk::ImageSeriesReader ReaderType; DcmIoType::Pointer io = DcmIoType::New(); @@ -145,28 +108,67 @@ reader->AddObserver(itk::ProgressEvent(), command); } - reader->SetFileNames(filenames); + const std::list::const_iterator df_end = decomposed_filenames.end(); + unsigned int act_volume = 1u; + + reader->SetFileNames(decomposed_filenames.front()); reader->Update(); - image->InitializeByItk(reader->GetOutput()); - image->SetImportVolume(reader->GetOutput()->GetBufferPointer()); + 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) << "]"; + 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++); + } node.SetData(image); setlocale(LC_NUMERIC, previousCLocale); std::cin.imbue(previousCppLocale); + return; // finished + } +#endif + /******** Normal Case, 3D (also for GDCM < 2 usable) ***************/ + 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); } - catch (std::exception& e) - { - 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] << "]"; + + 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