int main(int argc, char *argv[])
{
  // Verify arguments
  if(argc < 6)
    {
    std::cerr << "Required: outputFilename sizeX sizeY components value" << std::endl;
    return EXIT_FAILURE;
    }

  // Parse arguments
  std::string outputFilename = argv[1];

  std::stringstream ss;
  ss << argv[2] << " " << argv[3] << " " << argv[4];

  itk::Size<2> size = {{0,0}};
  unsigned int components = 0;
  float value = 0.0f;
  ss >> size[0] >> size[1] >> components >> value;


  // Output arguments
  std::cout << "outputFilename " << outputFilename << std::endl;
  std::cout << "size " << size << std::endl;
  std::cout << "value " << value << std::endl;

  ImageType::Pointer image = ImageType::New();
  itk::Index<2> index = {{0,0}};

  itk::ImageRegion<2> region(index, size);

  image->SetRegions(region);
  image->SetNumberOfComponentsPerPixel(components);
  image->Allocate();

  typename itk::ImageRegionIterator<ImageType> imageIterator(image, image->GetLargestPossibleRegion());

  ImageType::PixelType pixel;
  pixel.SetSize(components);
  pixel.Fill(value);
  
  while(!imageIterator.IsAtEnd())
    {
    imageIterator.Set(pixel);

    ++imageIterator;
    }

  // Write the result
  typedef  itk::ImageFileWriter<ImageType> WriterType;
  WriterType::Pointer writer = WriterType::New();
  writer->SetFileName(outputFilename);
  writer->SetInput(image);
  writer->Update();

  return EXIT_SUCCESS;
}
void TestComputeMaskedImage1DHistogram()
{
//  // Single channel
//  {
//  typedef itk::Image<unsigned char, 2> ImageType;
//  ImageType::Pointer image = ImageType::New();
//  ImageType::IndexType corner = {{0,0}};

//  ImageType::SizeType size = {{100,100}};

//  ImageType::RegionType region(corner, size);

//  image->SetRegions(region);
//  image->Allocate();

//  itk::ImageRegionIterator<ImageType> imageIterator(image,region);

//  while(!imageIterator.IsAtEnd())
//    {
//    if(imageIterator.GetIndex()[0] < 70)
//      {
//      imageIterator.Set(255);
//      }
//    else
//      {
//      imageIterator.Set(0);
//      }

//    ++imageIterator;
//    }

//  ImageType::PixelType rangeMin = 0;
//  ImageType::PixelType rangeMax = 255;

//  unsigned int numberOfBins = 10;
//  typedef int BinValueType;
//  typedef Histogram<BinValueType>::HistogramType HistogramType;

//  HistogramType histogram = Histogram<BinValueType>::ComputeImageHistogram1D(image.GetPointer(),
//                                                         image->GetLargestPossibleRegion(),
//                                                         numberOfBins, rangeMin, rangeMax);

//  Histogram<BinValueType>::OutputHistogram(histogram);
//  std::cout << std::endl;
//  }

   // Multi channel VectorImage
   {
   typedef itk::VectorImage<unsigned char, 2> ImageType;
   ImageType::Pointer image = ImageType::New();
   ImageType::IndexType corner = {{0,0}};

   ImageType::SizeType size = {{100,100}};

   ImageType::RegionType region(corner, size);

   image->SetRegions(region);
   image->SetNumberOfComponentsPerPixel(3);
   image->Allocate();

   Mask::Pointer mask = Mask::New();
   mask->SetRegions(region);
   mask->Allocate();

   itk::ImageRegionIterator<ImageType> imageIterator(image,region);

   while(!imageIterator.IsAtEnd())
   {
     ImageType::PixelType pixel(image->GetNumberOfComponentsPerPixel());
     if(imageIterator.GetIndex()[0] < 70)
     {
       for(unsigned int i = 0; i < pixel.GetSize(); ++i)
       {
         pixel[i] = 255;
       }
     }
     else
     {
       for(unsigned int i = 0; i < pixel.GetSize(); ++i)
       {
         pixel[i] = 0;
       }
     }
     imageIterator.Set(pixel);
     ++imageIterator;
   }

//   TypeTraits<ImageType::PixelType>::ComponentType rangeMin = 0;
//   TypeTraits<ImageType::PixelType>::ComponentType rangeMax = 255;

   ImageType::PixelType rangeMins;
   rangeMins.SetSize(image->GetNumberOfComponentsPerPixel());
   rangeMins.Fill(0);

   ImageType::PixelType rangeMaxs;
   rangeMaxs.SetSize(image->GetNumberOfComponentsPerPixel());
   rangeMaxs.Fill(255);

   unsigned int numberOfBinsPerComponent = 10;
   typedef int BinValueType;

   itk::ImageRegion<2> imageRegion = image->GetLargestPossibleRegion();
   itk::ImageRegion<2> maskRegion = image->GetLargestPossibleRegion();

   typedef MaskedHistogramGenerator<BinValueType> HistogramGeneratorType;
   typedef HistogramGeneratorType::HistogramType HistogramType;

   bool allowOutside = false;

   HistogramType histogram =
       HistogramGeneratorType::ComputeMaskedImage1DHistogram(image.GetPointer(), imageRegion,
                                                      mask.GetPointer(), maskRegion,
                                                      numberOfBinsPerComponent, rangeMins, rangeMaxs,
                                                      allowOutside, HoleMaskPixelTypeEnum::VALID);

   histogram.Print();
   std::cout << std::endl;
   }

//  // Multi channel Image<CovariantVector>
//  {
//  typedef itk::Image<itk::CovariantVector<unsigned char, 3>, 2> ImageType;
//  ImageType::Pointer image = ImageType::New();
//  ImageType::IndexType corner = {{0,0}};

//  ImageType::SizeType size = {{100,100}};

//  ImageType::RegionType region(corner, size);

//  image->SetRegions(region);
//  image->Allocate();

//  itk::ImageRegionIterator<ImageType> imageIterator(image,region);

//  while(!imageIterator.IsAtEnd())
//    {
//    ImageType::PixelType pixel(image->GetNumberOfComponentsPerPixel());
//    if(imageIterator.GetIndex()[0] < 70)
//      {
//      for(unsigned int i = 0; i < pixel.GetNumberOfComponents(); ++i)
//        {
//        pixel[i] = 255;
//        }
//      }
//    else
//      {
//      for(unsigned int i = 0; i < pixel.GetNumberOfComponents(); ++i)
//        {
//        pixel[i] = 0;
//        }
//      }
//    imageIterator.Set(pixel);
//    ++imageIterator;
//    }

//  TypeTraits<ImageType::PixelType>::ComponentType rangeMin = 0;
//  TypeTraits<ImageType::PixelType>::ComponentType rangeMax = 255;

//  unsigned int numberOfBinsPerComponent = 10;
//  typedef int BinValueType;
//  Histogram<BinValueType>::HistogramType histogram = Histogram<BinValueType>::ComputeImageHistogram1D(image.GetPointer(),
//                                                         image->GetLargestPossibleRegion(),
//                                                         numberOfBinsPerComponent, rangeMin, rangeMax);

//  Histogram<BinValueType>::OutputHistogram(histogram);
//  std::cout << std::endl;
//  }
}
int main(int, char*[])
{
//  typedef itk::Image<itk::CovariantVector<int, 3>, 2> ImageType;
  typedef itk::Image<itk::CovariantVector<unsigned char, 3>, 2> ImageType;

  ImageType::PixelType red;
  red.Fill(0);
  red[0] = 255;

  ImageType::PixelType black;
  black.Fill(0);

  ImageType::PixelType white;
  white.Fill(255);

  ImageType::PixelType green; // Note this is not 255 because then the magnitude of red and green would be the same,
  // which makes debugging hard since the gradient of the magnitude image is used internally (in IntroducedEnergy).
  green.Fill(0);
  green[1] = 122;

  ImageType::PixelType blue;
  blue.Fill(0);
  blue[2] = 255;

  ImageType::Pointer image = ImageType::New();
  itk::Index<2> imageCorner = {{0,0}};
  itk::Size<2> imageSize = {{100,100}};

  itk::ImageRegion<2> region(imageCorner,imageSize);
  image->SetRegions(region);
  image->Allocate();

  Mask::Pointer mask = Mask::New();
  mask->SetRegions(region);
  mask->Allocate();

  itk::ImageRegionIteratorWithIndex<Mask> initializeMaskIterator(mask, mask->GetLargestPossibleRegion());

  while(!initializeMaskIterator.IsAtEnd())
  {
    if(initializeMaskIterator.GetIndex()[0] < 55)
    {
      initializeMaskIterator.Set(mask->GetHoleValue());
    }
    else
    {
      initializeMaskIterator.Set(mask->GetValidValue());
    }

    ++initializeMaskIterator;
  }

  ITKHelpers::WriteImage(mask.GetPointer(), "mask.png");

  // Create a red image
  itk::ImageRegionIterator<ImageType> initializeIterator(image, image->GetLargestPossibleRegion());

  while(!initializeIterator.IsAtEnd())
  {
    initializeIterator.Set(red);

    ++initializeIterator;
  }

  // Setup source and target patch
  itk::Size<2> patchSize = {{10,10}};

  itk::Index<2> sourceCorner = {{10,10}};
  itk::ImageRegion<2> sourceRegion(sourceCorner, patchSize);

  itk::Index<2> targetCorner = {{50,50}};
  itk::ImageRegion<2> targetRegion(targetCorner, patchSize);

  itk::Index<2> perfectSourceCorner = {{75,75}};
  itk::ImageRegion<2> perfectSourceRegion(perfectSourceCorner, patchSize);

  // Make the source patch green
  itk::ImageRegionIterator<ImageType> sourceRegionIterator(image, sourceRegion);

  while(!sourceRegionIterator.IsAtEnd())
  {
    sourceRegionIterator.Set(green);

    ++sourceRegionIterator;
  }

  ITKHelpers::WriteImage(image.GetPointer(), "image.png");

  {
    ImageType::Pointer regionHighlightImage = ImageType::New();
    ITKHelpers::DeepCopy(image.GetPointer(), regionHighlightImage.GetPointer());

    ITKHelpers::OutlineRegion(regionHighlightImage.GetPointer(), sourceRegion, white);
    ITKHelpers::OutlineRegion(regionHighlightImage.GetPointer(), targetRegion, black);
    ITKHelpers::OutlineRegion(regionHighlightImage.GetPointer(), perfectSourceRegion, blue);

    ITKHelpers::WriteImage(regionHighlightImage.GetPointer(), "regions.png");
  }

  IntroducedEnergy<ImageType> introducedEnergy;
  introducedEnergy.SetDebugImages(true);

  // Bad match
  {
    std::cout << "Bad match:" << std::endl;

    float patchBoundaryEnergy = introducedEnergy.ComputeIntroducedEnergyPatchBoundary(image, mask, sourceRegion, targetRegion);
    std::cout << "patchBoundaryEnergy: " << patchBoundaryEnergy << std::endl;

    float maskBoundaryEnergy = introducedEnergy.ComputeIntroducedEnergyMaskBoundary(image, mask, sourceRegion, targetRegion);
    std::cout << "maskBoundaryEnergy: " << maskBoundaryEnergy << std::endl;

    float totalEnergy = introducedEnergy.ComputeIntroducedEnergy(image, mask, sourceRegion, targetRegion);
    std::cout << "totalEnergy: " << totalEnergy << std::endl;
  }

  // Perfect match
  {
    std::cout << "Perfect match:" << std::endl;
  //  IntroducedEnergy<ImageType> introducedEnergy;
    typedef IntroducedEnergy<ImageType> IntroducedEnergyType;

    float patchBoundaryEnergy = introducedEnergy.ComputeIntroducedEnergyPatchBoundary(image, mask, perfectSourceRegion, targetRegion);
    std::cout << "patchBoundaryEnergy: " << patchBoundaryEnergy << std::endl;

    float maskBoundaryEnergy = introducedEnergy.ComputeIntroducedEnergyMaskBoundary(image, mask, perfectSourceRegion, targetRegion);
    std::cout << "maskBoundaryEnergy: " << maskBoundaryEnergy << std::endl;

    float totalEnergy = introducedEnergy.ComputeIntroducedEnergy(image, mask, perfectSourceRegion, targetRegion);
    std::cout << "totalEnergy: " << totalEnergy << std::endl;
  }

  return EXIT_SUCCESS;
}
void mitk::DiffusionPropertyHelper::AverageRedundantGradients(double precision)
{

  mitk::GradientDirectionsProperty* DirectionsProperty = static_cast<mitk::GradientDirectionsProperty*>( m_Image->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() );
  GradientDirectionsContainerType::Pointer oldDirs = DirectionsProperty->GetGradientDirectionsContainer();

  GradientDirectionsContainerType::Pointer newDirs =
    CalcAveragedDirectionSet(precision, oldDirs);

  // if sizes equal, we do not need to do anything in this function
  if(oldDirs->size() == newDirs->size())
    return;

  // new image
  ImageType::Pointer oldImage = ImageType::New();
  mitk::CastToItkImage( m_Image, oldImage);
  ImageType::Pointer newITKImage = ImageType::New();
  newITKImage->SetSpacing( oldImage->GetSpacing() );   // Set the image spacing
  newITKImage->SetOrigin( oldImage->GetOrigin() );     // Set the image origin
  newITKImage->SetDirection( oldImage->GetDirection() );  // Set the image direction
  newITKImage->SetLargestPossibleRegion( oldImage->GetLargestPossibleRegion() );
  newITKImage->SetVectorLength( newDirs->size() );
  newITKImage->SetBufferedRegion( oldImage->GetLargestPossibleRegion() );
  newITKImage->Allocate();

  // average image data that corresponds to identical directions
  itk::ImageRegionIterator< ImageType > newIt(newITKImage, newITKImage->GetLargestPossibleRegion());
  newIt.GoToBegin();
  itk::ImageRegionIterator< ImageType > oldIt(oldImage, oldImage->GetLargestPossibleRegion());
  oldIt.GoToBegin();

  // initial new value of voxel
  ImageType::PixelType newVec;
  newVec.SetSize(newDirs->size());
  newVec.AllocateElements(newDirs->size());

  // find which gradients should be averaged
  GradientDirectionsContainerType::Pointer oldDirections = oldDirs;
  std::vector<std::vector<int> > dirIndices;
  for(GradientDirectionsContainerType::ConstIterator gdcitNew = newDirs->Begin();
    gdcitNew != newDirs->End(); ++gdcitNew)
  {
    dirIndices.push_back(std::vector<int>(0));
    for(GradientDirectionsContainerType::ConstIterator gdcitOld = oldDirs->Begin();
      gdcitOld != oldDirections->End(); ++gdcitOld)
    {
      if(AreAlike(gdcitNew.Value(), gdcitOld.Value(), precision))
      {
        //MITK_INFO << gdcitNew.Value() << "  " << gdcitOld.Value();
        dirIndices[gdcitNew.Index()].push_back(gdcitOld.Index());
      }
    }
  }

  //int ind1 = -1;
  while(!newIt.IsAtEnd())
  {

    // progress
    //typename ImageType::IndexType ind = newIt.GetIndex();
    //ind1 = ind.m_Index[2];

    // init new vector with zeros
    newVec.Fill(0.0);

    // the old voxel value with duplicates
    ImageType::PixelType oldVec = oldIt.Get();

    for(unsigned int i=0; i<dirIndices.size(); i++)
    {
      // do the averaging
      const unsigned int numavg = dirIndices[i].size();
      unsigned int sum = 0;
      for(unsigned int j=0; j<numavg; j++)
      {
        //MITK_INFO << newVec[i] << " << " << oldVec[dirIndices[i].at(j)];
        sum += oldVec[dirIndices[i].at(j)];
      }
      if(numavg == 0)
      {
        MITK_ERROR << "VectorImage: Error on averaging. Possibly due to corrupted data";
        return;
      }
      newVec[i] = sum / numavg;
    }

    newIt.Set(newVec);

    ++newIt;
    ++oldIt;
  }

  mitk::GrabItkImageMemory( newITKImage, m_Image );

  m_Image->SetProperty( mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( newDirs ) );
  m_Image->SetProperty( mitk::DiffusionPropertyHelper::ORIGINALGRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( newDirs ) );
  ApplyMeasurementFrame();
  UpdateBValueMap();
  std::cout << std::endl;
}