/*
 * Generate the information decribing the output data. The default
 * implementation of this method will copy information from the input to the
 * output. A filter may override this method if its output will have different
 * information than its input. For instance, a filter that shrinks an image will
 * need to provide an implementation for this method that changes the spacing of
 * the pixels. Such filters should call their superclass' implementation of this
 * method prior to changing the information values they need (i.e.
 * GenerateOutputInformation() should call
 * Superclass::GenerateOutputInformation() prior to changing the information.
 */
void mitk::ExtractImageFilter::GenerateOutputInformation()
{
 Image::Pointer output = this->GetOutput();
 Image::ConstPointer input = this->GetInput();
 if (input.IsNull()) return;

 if ( m_SliceDimension >= input->GetDimension() && input->GetDimension() != 2 )
 {
   MITK_ERROR << "mitk::ExtractImageFilter:GenerateOutputInformation  m_SliceDimension == " << m_SliceDimension << " makes no sense with an " << input->GetDimension() << "D image." << std::endl;
   itkExceptionMacro("This is not a sensible value for m_SliceDimension.");
   return;
 }

 unsigned int sliceDimension( m_SliceDimension );
 if ( input->GetDimension() == 2)
 {
   sliceDimension = 2;
 }

  unsigned int tmpDimensions[2];

  switch ( sliceDimension )
  {
    default:
    case 2: 
      // orientation = PlaneGeometry::Axial;
      tmpDimensions[0] = input->GetDimension(0);
      tmpDimensions[1] = input->GetDimension(1);
      break;
    case 1: 
      // orientation = PlaneGeometry::Frontal;
      tmpDimensions[0] = input->GetDimension(0);
      tmpDimensions[1] = input->GetDimension(2);
      break;
    case 0: 
      // orientation = PlaneGeometry::Sagittal;
      tmpDimensions[0] = input->GetDimension(1);
      tmpDimensions[1] = input->GetDimension(2);
      break;
  }

  output->Initialize(input->GetPixelType(), 2, tmpDimensions, 1 /*input->GetNumberOfChannels()*/);

  // initialize the spacing of the output
/*
  Vector3D spacing = input->GetSlicedGeometry()->GetSpacing();
  if(input->GetDimension()>=2)
    spacing[2]=spacing[1];
  else
    spacing[2] = 1.0;
  output->GetSlicedGeometry()->SetSpacing(spacing);
*/

  output->SetPropertyList(input->GetPropertyList()->Clone());
}
void mitk::OverwriteSliceImageFilter::GenerateData()
{
  //
  // this is the place to implement the major part of undo functionality (bug #491)
  // here we have to create undo/do operations
  //
  // WHO is the operation actor? This object may not be destroyed ever (design of undo stack)!
  // -> some singleton method of this filter?
  //
  // neccessary additional objects:
  //  - something that executes the operations
  //  - the operation class (must hold a binary diff or something)
  //  - observer commands to know when the image is deleted (no further action then, perhaps even remove the operations from the undo stack)
  //
  Image::ConstPointer input = ImageToImageFilter::GetInput(0);
  Image::ConstPointer input3D = input;

  Image::ConstPointer slice = m_SliceImage;

  if ( input.IsNull() || slice.IsNull() ) return;

  switch (m_SliceDimension)
  {
    default:
    case 2:
      m_Dimension0 = 0;
      m_Dimension1 = 1;
      break;
    case 1:
      m_Dimension0 = 0;
      m_Dimension1 = 2;
      break;
    case 0:
      m_Dimension0 = 1;
      m_Dimension1 = 2;
      break;
  }

  if ( slice->GetDimension() < 2 || input->GetDimension() > 4 ||
       slice->GetDimension(0) != input->GetDimension(m_Dimension0) ||
       slice->GetDimension(1) != input->GetDimension(m_Dimension1) ||
       m_SliceIndex >= input->GetDimension(m_SliceDimension)
     )
  {
   itkExceptionMacro("Slice and image dimensions differ or slice index is too large. Sorry, cannot work like this.");
   return;
  }

  if ( input->GetDimension() == 4 )
  {
    ImageTimeSelector::Pointer timeSelector = ImageTimeSelector::New();
    timeSelector->SetInput( input );
    timeSelector->SetTimeNr( m_TimeStep );
    timeSelector->UpdateLargestPossibleRegion();
    input3D = timeSelector->GetOutput();
  }

  if ( m_SliceDifferenceImage.IsNull() ||
       m_SliceDifferenceImage->GetDimension(0) != m_SliceImage->GetDimension(0) ||
       m_SliceDifferenceImage->GetDimension(1) != m_SliceImage->GetDimension(1) )
  {
    m_SliceDifferenceImage = mitk::Image::New();
    mitk::PixelType pixelType( mitk::MakeScalarPixelType<short signed int>() );
    m_SliceDifferenceImage->Initialize( pixelType, 2, m_SliceImage->GetDimensions() );
  }

  //MITK_INFO << "Overwriting slice " << m_SliceIndex << " in dimension " << m_SliceDimension << " at time step " << m_TimeStep << std::endl;
  // this will do a long long if/else to find out both pixel types
  AccessFixedDimensionByItk( input3D, ItkImageSwitch, 3 );

  SegmentationInterpolationController* interpolator = SegmentationInterpolationController::InterpolatorForImage( input );
  if (interpolator)
  {
    interpolator->BlockModified(true);
    interpolator->SetChangedSlice( m_SliceDifferenceImage, m_SliceDimension, m_SliceIndex, m_TimeStep );
  }

  if ( m_CreateUndoInformation )
  {
    // create do/undo operations (we don't execute the doOp here, because it has already been executed during calculation of the diff image
    ApplyDiffImageOperation* doOp = new ApplyDiffImageOperation( OpTEST, const_cast<Image*>(input.GetPointer()), m_SliceDifferenceImage, m_TimeStep, m_SliceDimension, m_SliceIndex );
    ApplyDiffImageOperation* undoOp = new ApplyDiffImageOperation( OpTEST, const_cast<Image*>(input.GetPointer()), m_SliceDifferenceImage, m_TimeStep, m_SliceDimension, m_SliceIndex );
    undoOp->SetFactor( -1.0 );
    OperationEvent* undoStackItem = new OperationEvent( DiffImageApplier::GetInstanceForUndo(), doOp, undoOp, this->EventDescription(m_SliceDimension, m_SliceIndex, m_TimeStep) );
    UndoController::GetCurrentUndoModel()->SetOperationEvent( undoStackItem );
  }

  // this image is modified (good to know for the renderer)
  input->Modified();

  if (interpolator)
  {
    interpolator->BlockModified(false);
  }
}