X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=blobdiff_plain;f=tools%2FclitkDicom2Image.cxx;h=b3bcc902de0699f224e2047f9922f4f0f057bc29;hb=e4970a5c24b53d6842e4f8f02d63b957f03bfbba;hp=bb384581adbe4a8bad50a9cfcc2186df8d1edf3e;hpb=183710c2f0a135f129ccc40fe8c2af70ed9d35fb;p=clitk.git diff --git a/tools/clitkDicom2Image.cxx b/tools/clitkDicom2Image.cxx index bb38458..b3bcc90 100644 --- a/tools/clitkDicom2Image.cxx +++ b/tools/clitkDicom2Image.cxx @@ -1,103 +1,168 @@ /*========================================================================= - -Program: clitk -Module: $RCSfile: clitkDicom2Image.cxx,v $ -Language: C++ -Date: $Date: 2010/11/05 00:05:00 $ -Version: $Revision: 1.1 $ - -Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de -l'Image). All rights reserved. See Doc/License.txt or -http://www.creatis.insa-lyon.fr/Public/Gdcm/License.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 notices for more information. - -=========================================================================*/ - -/** - ================================================= - * @file clitkDicom2Image.cxx - * @author David Sarrut - * @date 26 Oct 2006 - * - * @brief - * - =================================================*/ + Program: vv http://www.creatis.insa-lyon.fr/rio/vv + + Authors belong to: + - University of LYON http://www.universite-lyon.fr/ + - Léon Bérard cancer center http://www.centreleonberard.fr + - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the copyright notices for more information. + + It is distributed under dual licence + + - BSD See included LICENSE.txt file + - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html +===========================================================================**/ // clitk includes +#include "clitkIO.h" #include "clitkDicom2Image_ggo.h" -#include +#include "clitkCommon.h" #include "clitkImageCommon.h" +#include "vvImageReader.h" +#include "vvImageWriter.h" +#include +#include +#include +#if GDCM_MAJOR_VERSION >= 2 + #include + #include + #include +#endif -// itk include -#include "itkImageRegionIterator.h" -#include "itkImageRegionConstIterator.h" - -// Why this is needed ??? -//const double itk::NumericTraits::Zero = 0.0; +#include //==================================================================== -int main(int argc, char * argv[]) { - +int main(int argc, char * argv[]) +{ // init command line GGO(clitkDicom2Image, args_info); + CLITK_INIT; + std::vector input_files; ///if std_input is given, read the input files from stdin - if (args_info.std_input_given) - { - while (true) - { - std::string tmp; - std::cin >> tmp; - if(std::cin.good()) - input_files.push_back(tmp); - else break; - } - args_info.inputs_num=input_files.size(); - } - else for (unsigned int i=0;i> tmp; + if(std::cin.good()) + input_files.push_back(tmp); + else break; + } + args_info.inputs_num=input_files.size(); + } else for (unsigned int i=0; i sliceLocations; - for(unsigned int i=0; iGetZOrigin()); - // check - /*if (!header->IsSignedPixelData()) { - std::cerr << "Pixel type not signed ! " << std::endl; - std::cerr << "In file " << input_files[i] << std::endl; - exit(0); - }*/ - if (header->GetPixelSize() != 2) { - std::cerr << "Pixel type 2 bytes ! " << std::endl; - std::cerr << "In file " << input_files[i] << std::endl; - exit(0); - } + std::string series_UID = ""; + std::set series_UIDs; + std::map< std::string, std::vector > theorigin; + std::map< std::string, std::vector > theorientation; + std::map< std::string, std::vector > sliceLocations; + std::map< std::string, std::vector > seriesFiles; +#if GDCM_MAJOR_VERSION >= 2 + if (args_info.verbose_flag) + std::cout << "Using GDCM-2.x" << std::endl; +#else + if (args_info.verbose_flag) { + std::cout << "Not using GDCM-2.x" << std::endl; + std::cout<< "The image orientation is not supported with this version of GDCM" <= 2 + gdcm::Reader hreader; + hreader.SetFileName(input_files[i].c_str()); + hreader.Read(); + gdcm::DataSet& ds = hreader.GetFile().GetDataSet(); + + if (args_info.extract_series_flag) { + gdcm::Attribute<0x20,0x000e> series_UID_att; + series_UID_att.SetFromDataSet(ds); + series_UID = series_UID_att.GetValue(); } - //=========================================== - // Sort slices locations ... + series_UIDs.insert(series_UID); + theorigin[series_UID] = gdcm::ImageHelper::GetOriginValue(hreader.GetFile()); + theorientation[series_UID] = gdcm::ImageHelper::GetDirectionCosinesValue(hreader.GetFile()); + if (args_info.patientSystem_flag) { + double n1 = theorientation[series_UID][1]*theorientation[series_UID][5]- + theorientation[series_UID][2]*theorientation[series_UID][4]; + double n2 = theorientation[series_UID][3]*theorientation[series_UID][2]- + theorientation[series_UID][5]*theorientation[series_UID][0]; + double n3 = theorientation[series_UID][0]*theorientation[series_UID][4]- + theorientation[series_UID][1]*theorientation[series_UID][3]; + double sloc = theorigin[series_UID][0]*n1+ + theorigin[series_UID][1]*n2+ + theorigin[series_UID][2]*n3; + sliceLocations[series_UID].push_back(sloc); + } else + sliceLocations[series_UID].push_back(theorigin[series_UID][2]); + seriesFiles[series_UID].push_back(input_files[i]); + + gdcm::Attribute<0x28, 0x100> pixel_size; + pixel_size.SetFromDataSet(ds); + /* if (pixel_size.GetValue() != 16) + { + std::cerr << "Pixel type not 2 bytes ! " << std::endl; + std::cerr << "In file " << input_files[i] << std::endl; + exit(0); + } + */ +#else + gdcm::File *header = new gdcm::File(); + header->SetFileName(input_files[i]); + header->SetMaxSizeLoadEntry(16384); // required ? + header->Load(); + + if (args_info.extract_series_flag) { + series_UID = header->GetEntryValue(0x20,0x000e).c_str(); + } + + series_UIDs.insert(series_UID); + theorigin[series_UID].resize(3); + theorigin[series_UID][0] = header->GetXOrigin(); + theorigin[series_UID][1] = header->GetYOrigin(); + theorigin[series_UID][2] = header->GetZOrigin(); + sliceLocations[series_UID].push_back(theorigin[series_UID][2]); + seriesFiles[series_UID].push_back(input_files[i]); + /*if (header->GetPixelSize() != 2) { + std::cerr << "Pixel type 2 bytes ! " << std::endl; + std::cerr << "In file " << input_files[i] << std::endl; + exit(0); + } + */ +#endif + } + + //=========================================== + // Sort slices locations ... + std::set::iterator sn = series_UIDs.begin(); + while ( sn != series_UIDs.end() ) { + std::vector locs = sliceLocations[*sn]; + std::vector origin = theorigin[*sn]; + std::vector files = seriesFiles[*sn]; std::vector sliceIndex; - clitk::GetSortedIndex(sliceLocations, sliceIndex); - if (args_info.verboseSliceLocation_flag) { - std::cout << sliceLocations[sliceIndex[0]] << " -> " - << sliceIndex[0] << " / " << 0 << " => " - << "0 mm " - << input_files[sliceIndex[0]] - << std::endl; + clitk::GetSortedIndex(locs, sliceIndex); + if (args_info.verbose_flag) { + std::cout << locs[sliceIndex[0]] << " -> " + << sliceIndex[0] << " / " << 0 << " => " + << "0 mm " + << files[sliceIndex[0]] + << std::endl; for(unsigned int i=1; i " - << sliceIndex[i] << " / " << i << " => " - << sliceLocations[sliceIndex[i]] - sliceLocations[sliceIndex[i-1]] - << "mm " - << input_files[sliceIndex[i]] - << std::endl; + std::cout << locs[sliceIndex[i]] << " -> " + << sliceIndex[i] << " / " << i << " => " + << locs[sliceIndex[i]] - locs[sliceIndex[i-1]] + << "mm " + << files[sliceIndex[i]] + << std::endl; } } @@ -106,83 +171,86 @@ int main(int argc, char * argv[]) { double currentDist; double dist=0; double tolerance = args_info.tolerance_arg; - double previous = sliceLocations[sliceIndex[0]]; + double previous = locs[sliceIndex[0]]; for(unsigned int i=1; i tolerance) { - std::cout << "ERROR : " << std::endl - << "Current slice pos is = " << sliceLocations[sliceIndex[i]] << std::endl - << "Previous slice pos is = " << previous << std::endl - << "Current file is = " << input_files[sliceIndex[i]] << std::endl - << "Current index is = " << i << std::endl - << "Current sortindex is = " << sliceIndex[i] << std::endl - << "Current slice diff = " << dist << std::endl - << "Current error = " << fabs(dist-currentDist) << std::endl; - exit(1); - } - } - else dist = currentDist; - previous = sliceLocations[sliceIndex[i]]; + if (fabs(dist-currentDist) > tolerance) { + std::cout << "ERROR : " << std::endl + << "Current slice pos is = " << locs[sliceIndex[i]] << std::endl + << "Previous slice pos is = " << previous << std::endl + << "Current file is = " << files[sliceIndex[i]] << std::endl + << "Current index is = " << i << std::endl + << "Current sortindex is = " << sliceIndex[i] << std::endl + << "Current slice diff = " << dist << std::endl + << "Current error = " << fabs(dist-currentDist) << std::endl; + exit(1); + } + } else dist = currentDist; + previous = locs[sliceIndex[i]]; } //=========================================== - // Create image - gdcm::File * header = clitk::readDicomHeader(input_files[sliceIndex.front()]); - typedef itk::Image ImageType; - typedef itk::Image ImageTypeOutput; - ImageType::SpacingType spacing; - ImageType::SizeType size; - ImageType::PointType origin; - spacing[0] = header->GetXSpacing(); - spacing[1] = header->GetYSpacing(); - spacing[2] = dist; - size[0] = header->GetXSize(); - size[1] = header->GetYSize(); - size[2] = sliceIndex.size(); - ///Optional use of special origin scheme used at CLB - if (args_info.focal_origin_flag) - { - origin[0] = -spacing[0]*size[0]/2; - origin[1] = -spacing[1]*size[1]/2; + // Create ordered vector of filenames + std::vector sorted_files; + sorted_files.resize(sliceIndex.size()); + for(unsigned int i=0; iSetInputFilenames(sorted_files); + reader->SetPatientCoordinateSystem(args_info.patientSystem_flag); + reader->Update(vvImageReader::DICOM); + if (reader->GetLastError().size() != 0) { + std::cerr << reader->GetLastError() << std::endl; + return 1; } - else - { - origin[0] = header->GetXOrigin(); - origin[1] = header->GetYOrigin(); + + vvImage::Pointer image = reader->GetOutput(); + vtkImageData* vtk_image = image->GetFirstVTKImageData(); + vtkImageChangeInformation* modifier = vtkImageChangeInformation::New(); + if (args_info.focal_origin_given) { + std::vector spacing = image->GetSpacing(); + std::vector size = image->GetSize(); + origin[0] = -spacing[0]*size[0]/2.0; + origin[1] = -spacing[1]*size[1]/2.0; +#if VTK_MAJOR_VERSION <= 5 + modifier->SetInput(vtk_image); +#else + modifier->SetInputData(vtk_image); +#endif + modifier->SetOutputOrigin(origin[0], origin[1], locs[sliceIndex[0]]); + modifier->Update(); + vvImage::Pointer focal_image = vvImage::New(); + focal_image->AddVtkImage(modifier->GetOutput()); + image = focal_image; } - origin[2] = header->GetZOrigin(); - ImageTypeOutput::Pointer output = ImageTypeOutput::New(); - itk::ImageRegion<3> region; - region.SetSize(size); - output->SetRegions(region); - output->SetOrigin(origin); - output->SetSpacing(spacing); - output->Allocate(); - - //=========================================== - // Fill image - ImageType::Pointer slice; - typedef itk::ImageRegionIterator IteratorType; - typedef itk::ImageRegionConstIterator ConstIteratorType; - IteratorType po(output, output->GetLargestPossibleRegion()); - po.Begin(); - for(unsigned int i=0; i(input_files[sliceIndex[i]]); - ConstIteratorType pi(slice, slice->GetLargestPossibleRegion()); - while ( !pi.IsAtEnd() ) { - po.Set((signed short)pi.Get()); - ++po; - ++pi; - } + + std::string outfile; + if (series_UIDs.size() == 1) + outfile = args_info.output_arg; + else { + std::ostringstream name; + std::vector directory = clitk::SplitFilename(args_info.output_arg); + if (directory.size() == 2) + name << directory[0] << "/" << *sn << "_" << directory[1]; + else + name << *sn << "_" << args_info.output_arg; + outfile = name.str(); } + vvImageWriter::Pointer writer = vvImageWriter::New(); + writer->SetInput(image); + if (args_info.patientSystem_flag && !image->GetTransform().empty()) + writer->SetSaveTransform(true); + writer->SetOutputFileName(outfile); + writer->Update(); - //=========================================== - // Write image - clitk::writeImage(output, - args_info.output_arg, - args_info.verbose_flag); - - // this is the end my friend - return 0; + modifier->Delete(); + + sn++; + } + + return 0; }