Example #1
0
void
NrrdPlugin::readSlice(int idx[3], int sz[3],
		       int nbytes, uchar *slice)
{
  typedef itk::Image<T, 3> ImageType;

  typedef itk::ImageFileReader<ImageType> ReaderType;
  ReaderType::Pointer reader = ReaderType::New();
  reader->SetFileName(m_fileName[0].toAscii().data());
  typedef itk::NrrdImageIO NrrdIOType;
  NrrdIOType::Pointer nrrdIO = NrrdIOType::New();
  reader->SetImageIO(nrrdIO);

  typedef itk::RegionOfInterestImageFilter<ImageType,ImageType> RegionExtractor;

  ImageType::RegionType region;
  ImageType::SizeType size;
  ImageType::IndexType index;
  index[2] = idx[2];
  index[1] = idx[1];
  index[0] = idx[0];
  size[2] = sz[2];
  size[1] = sz[1];
  size[0] = sz[0];
  region.SetIndex(index);
  region.SetSize(size);
  
  // Extract the relevant sub-region.
  RegionExtractor::Pointer extractor = RegionExtractor::New();
  extractor->SetInput(reader->GetOutput());
  extractor->SetRegionOfInterest(region);
  extractor->Update();
  ImageType *dimg = extractor->GetOutput();
  char *tdata = (char*)(dimg->GetBufferPointer());
  memcpy(slice, tdata, nbytes);
}
//#################### PRIVATE METHODS ####################
void DICOMVolumeLoader::execute_impl()
try
{
	typedef itk::GDCMImageIO ImageIO;
	typedef itk::Image<int,2> Image2D;
	typedef itk::Image<int,3> Image3D;
	typedef itk::JoinSeriesImageFilter<Image2D,Image3D> Joiner;
	typedef itk::ImageFileReader<Image2D> Reader;
	typedef itk::RegionOfInterestImageFilter<Image2D,Image2D> RegionExtractor;

	// Set up the desired region for each of the slices.
	Image2D::RegionType region;
	itk::Index<2> index = {{m_volumeChoice.minX, m_volumeChoice.minY}};
	itk::Size<2> size = {{m_volumeChoice.maxX + 1 - m_volumeChoice.minX, m_volumeChoice.maxY + 1 - m_volumeChoice.minY}};
	region.SetIndex(index);
	region.SetSize(size);

	std::vector<std::string> imageFilenames = m_dicomdir->image_filenames(m_volumeChoice.patientKey, m_volumeChoice.studyKey, m_volumeChoice.seriesKey);
	std::vector<Image2D::Pointer> images(imageFilenames.size());
	for(int i=m_volumeChoice.minZ; i<=m_volumeChoice.maxZ; ++i)
	{
		std::string imageFilename = m_volumeChoice.filePrefix + imageFilenames[i];

		if(!is_aborted())
		{
			set_progress(i - m_volumeChoice.minZ);
			set_status("Loading image " + imageFilename + "...");
		}
		else return;

		// Load the image.
		Reader::Pointer reader = Reader::New();
		reader->SetFileName(imageFilename);
		ImageIO::Pointer gdcmImageIO = ImageIO::New();
		reader->SetImageIO(gdcmImageIO);
		reader->Update();

		// Extract the relevant sub-region.
		RegionExtractor::Pointer extractor = RegionExtractor::New();
		extractor->SetInput(reader->GetOutput());
		extractor->SetRegionOfInterest(region);
		extractor->Update();

		// Store the image.
		images[i] = extractor->GetOutput();
		images[i]->SetMetaDataDictionary(reader->GetMetaDataDictionary());
	}

	// Get the window centre and width if they haven't been explicitly specified by the user.
	if(m_volumeChoice.windowSettings.unspecified())
	{
		std::string windowCentreStr = read_header_field(images[m_volumeChoice.minZ], "0028|1050");
		std::string windowWidthStr = read_header_field(images[m_volumeChoice.minZ], "0028|1051");
		std::string validChars = "-0123456789";
		windowCentreStr = windowCentreStr.substr(0, windowCentreStr.find_first_not_of(validChars));
		windowWidthStr = windowWidthStr.substr(0, windowWidthStr.find_first_not_of(validChars));
		double windowCentre = lexical_cast<double>(windowCentreStr);
		double windowWidth = lexical_cast<double>(windowWidthStr);
		m_volumeChoice.windowSettings = WindowSettings(windowCentre, windowWidth);
	}

	// Make the images into a volume.
	Joiner::Pointer joiner = Joiner::New();

	double minSliceLocation = 0;
	try							{ minSliceLocation = lexical_cast<double>(read_header_field(images[m_volumeChoice.minZ], "0020|1041")); }
	catch(bad_lexical_cast&)	{ throw Exception("The SliceLocation value for the slice was not of the appropriate type"); }
	joiner->SetOrigin(minSliceLocation);

	double sliceThickness = 0;
	if(m_volumeChoice.minZ + 1 <= m_volumeChoice.maxZ)
	{
		try
		{
			double nextSliceLocation = lexical_cast<double>(read_header_field(images[m_volumeChoice.minZ+1], "0020|1041"));
			sliceThickness = fabs(nextSliceLocation - minSliceLocation);
		}
		catch(bad_lexical_cast&)	{}
	}
	if(sliceThickness == 0)
	{
		try							{ sliceThickness = lexical_cast<double>(read_header_field(images[m_volumeChoice.minZ], "0018|0050")); }
		catch(bad_lexical_cast&)	{ throw Exception("The SliceThickness value for the slice was not of the appropriate type"); }
	}
	joiner->SetSpacing(sliceThickness);

	for(int i=m_volumeChoice.minZ; i<=m_volumeChoice.maxZ; ++i) joiner->PushBackInput(images[i]);
	joiner->Update();
	Image3D::Pointer volumeImage = joiner->GetOutput();

	// Determine the modality of the images.
	DICOMVolume::Modality modality = DICOMVolume::UNSUPPORTED_MODALITY;
	std::string modalityString = read_header_field(images[m_volumeChoice.minZ], "0008|0060");
	if(modalityString == "CT")		modality = DICOMVolume::CT;
	else if(modalityString == "MR")	modality = DICOMVolume::MR;

	if(modality == DICOMVolume::UNSUPPORTED_MODALITY)
	{
		throw Exception("Cannot currently handle modalities other than CT and MR - sorry!");
	}

	m_volume.reset(new DICOMVolume(volumeImage, modality));
}
catch(std::exception& e)
{
	abort();
	set_status(e.what());
}