Index: mitkDicomSeriesReader.cpp =================================================================== --- mitkDicomSeriesReader.cpp (revision 29316) +++ mitkDicomSeriesReader.cpp (working copy) @@ -360,8 +360,57 @@ } #if GDCM_MAJOR_VERSION >= 2 + +DicomSeriesReader::StringContainer DicomSeriesReader::Sort4DSeriesSlices(const StringContainer &unsortedFilenames) +{ + gdcm::Sorter sorter; + + sorter.SetSortFunction(DicomSeriesReader::Gdcm4DSortFunction); + sorter.Sort(unsortedFilenames); + return sorter.GetFilenames(); +} + bool DicomSeriesReader::GdcmSortFunction(const gdcm::DataSet &ds1, const gdcm::DataSet &ds2) { + gdcm::Attribute<0x0020,0x0032> image_pos1; // Image Position (Patient) + gdcm::Attribute<0x0020,0x0037> image_orientation1; // Image Orientation (Patient) + + image_pos1.Set(ds1); + image_orientation1.Set(ds1); + + gdcm::Attribute<0x0020,0x0032> image_pos2; + gdcm::Attribute<0x0020,0x0037> image_orientation2; + + 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."); + } + + 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; +} + +bool DicomSeriesReader::Gdcm4DSortFunction(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) Index: mitkDicomSeriesReader.h =================================================================== --- mitkDicomSeriesReader.h (revision 29316) +++ mitkDicomSeriesReader.h (working copy) @@ -60,6 +60,7 @@ /** * Loads a DICOM series composed by the file names enumerated in the file names container. + * Loading of 4D datasets will only work if both "sort" and "check_4d" parameters are enabled. * 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, bool sort = true, bool check_4d = true, UpdateCallBackMethod callback = 0); @@ -122,12 +123,11 @@ * * \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.(..). + * It should always be ok to put the result of a call to GetSeries(..) into this method. * - * Sorting order is determined by + * Images are sorted along a vector normal to the plane of the image (determined from "Image Orientation (Patient)") + * by the value of "Image Position (Patient)" projected onto that vector. * - * 1. TODO - * 2. */ static StringContainer SortSeriesSlices(const StringContainer &unsortedFilenames); protected: @@ -170,11 +170,14 @@ static void LoadDicom(const StringContainer &filenames, DataNode &node, bool sort, bool check_4d, UpdateCallBackMethod callback); #if GDCM_MAJOR_VERSION >= 2 + static StringContainer Sort4DSeriesSlices(const StringContainer &unsortedFilenames); + /* * 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); + static bool Gdcm4DSortFunction(const gdcm::DataSet &ds1, const gdcm::DataSet &ds2); #endif }; Index: mitkDicomSeriesReader.txx =================================================================== --- mitkDicomSeriesReader.txx (revision 29316) +++ mitkDicomSeriesReader.txx (working copy) @@ -56,9 +56,10 @@ unsigned int volume_count = 1u; StringContainer sorted_filenames = sort - ? DicomSeriesReader::SortSeriesSlices(filenames) + ? (check_4d ? DicomSeriesReader::Sort4DSeriesSlices(filenames) + : DicomSeriesReader::SortSeriesSlices(filenames)) : filenames; - if (check_4d) + if (check_4d && sort) { gdcm::Tag tag(0x0020,0x0032); //Image position (Patient) gdcm::Scanner scanner; @@ -74,9 +75,7 @@ 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)) + if (!strcmp(act_value, scanner.GetValue(f_it->c_str(), tag))) { decomposed_filenames.push_back(StringContainer()); ++volume_count; @@ -84,6 +83,13 @@ decomposed_filenames.back().push_back(*f_it); } + + const std::list::const_iterator df_end = decomposed_filenames.end(); + + for (std::list::iterator df_it = decomposed_filenames.begin(); df_it != df_end; ++df_it) + { + (*df_it) = DicomSeriesReader::SortSeriesSlices(*df_it); + } } else {