# HistogramXYPlot

VTKExamples/Cxx/WishList/Images/HistogramXYPlot

### Description

This example works but there is an issue with vtkImageAccumulate.

It appears the maximum frequency of a histogram generated by vtkImageAccumulate, when that frequency corresponds to the value of 0, cannot be disabled by setting ignore zero to true! See lines 245 and 218 in vtkImageAccumulate.cxx

### Code

HistogramXYPlot.cxx

    #include <vtkVersion.h>
    #include <vtkSmartPointer.h>

    #include <string>

    #include <vtkActor.h>
    #include <vtkImageAccumulate.h>
    #include <vtkImageData.h>
    #include <vtkImageExtractComponents.h>
    #include <vtkJPEGReader.h>
    #include <vtkRenderWindow.h>
    #include <vtkRenderWindowInteractor.h>
    #include <vtkRenderer.h>
    #include <vtkXYPlotActor.h>

    int main(int argc, char *argv[])
    {
      // Handle the arguments
      if( argc < 2 )
      {
        std::cout << "Usage: " << argv[0] << " Filename.jpg, [optional ignore zero:] <y/n>" << std::endl;
        return EXIT_FAILURE;
      }

      int ignoreZero = 0;
      if( argc == 3 )
      {
        std::string ignore = argv[2];
        std::cout << ignore << std::endl;
        if( ignore == "y" || ignore == "Y" )
        {
          ignoreZero = 1;
        }
      }

      // Read a jpeg image
      vtkSmartPointer<vtkJPEGReader> reader =
        vtkSmartPointer<vtkJPEGReader>::New();
      if( !reader->CanReadFile( argv[1] ) )
      {
        std::cout << "Error: cannot read " << argv[1] << std::endl;
        return EXIT_FAILURE;
      }
      reader->SetFileName( argv[1] );
      reader->Update();

      int numComponents = reader->GetOutput()->GetNumberOfScalarComponents();
      if( numComponents > 3 )
      {
        std::cout << "Error: cannot process an image with "
                  << numComponents << " components!" << std::endl;
        return EXIT_FAILURE;
      }

      // Create a vtkXYPlotActor
      vtkSmartPointer<vtkXYPlotActor> plot =
        vtkSmartPointer<vtkXYPlotActor>::New();
      plot->ExchangeAxesOff();
      plot->SetLabelFormat( "%g" );
      plot->SetXTitle( "Level" );
      plot->SetYTitle( "Frequency" );
      plot->SetXValuesToValue();

      double xmax = 0.;
      double ymax = 0.;

      double colors[3][3] = {
        { 1, 0, 0 },
        { 0, 1, 0 },
        { 0, 0, 1 } };

      const char* labels[3] = {
        "Red", "Green", "Blue" };

      // Process the image, extracting and plotting a histogram for each
      // component
      for( int i = 0; i < numComponents; ++i )
      {
        vtkSmartPointer<vtkImageExtractComponents> extract =
          vtkSmartPointer<vtkImageExtractComponents>::New();
        extract->SetInputConnection( reader->GetOutputPort() );
        extract->SetComponents( i );
        extract->Update();

        double range[2];
        extract->GetOutput()->GetScalarRange( range );

        vtkSmartPointer<vtkImageAccumulate> histogram =
          vtkSmartPointer<vtkImageAccumulate>::New();
        histogram->SetInputConnection( extract->GetOutputPort() );
        histogram->SetComponentExtent(
          0,
          static_cast<int>(range[1])-static_cast<int>(range[0])-1,0,0,0,0 );
        histogram->SetComponentOrigin( range[0],0,0 );
        histogram->SetComponentSpacing( 1,0,0 );
        histogram->SetIgnoreZero( ignoreZero );
        histogram->Update();

        if( range[1] > xmax )
        {
          xmax = range[1];
        }
        if( histogram->GetOutput()->GetScalarRange()[1] > ymax )
        {
          ymax = histogram->GetOutput()->GetScalarRange()[1];
        }

    #if VTK_MAJOR_VERSION <= 5
        plot->AddInput( histogram->GetOutput() );
    #else
        plot->AddDataSetInputConnection( histogram->GetOutputPort() );
    #endif
        if( numComponents > 1 )
        {
          plot->SetPlotColor(i,colors[i]);
          plot->SetPlotLabel(i,labels[i]);
          plot->LegendOn();
        }
      }

      plot->SetXRange( 0, xmax );
      plot->SetYRange( 0, ymax );

      // Visualize the histogram(s)
      vtkSmartPointer<vtkRenderer> renderer =
        vtkSmartPointer<vtkRenderer>::New();
      renderer->AddActor(plot);

      vtkSmartPointer<vtkRenderWindow> renderWindow =
        vtkSmartPointer<vtkRenderWindow>::New();
      renderWindow->AddRenderer( renderer );
      renderWindow->SetSize(640, 480);

      vtkSmartPointer<vtkRenderWindowInteractor> interactor =
        vtkSmartPointer<vtkRenderWindowInteractor>::New();
      interactor->SetRenderWindow( renderWindow );

      // Initialize the event loop and then start it
      interactor->Initialize();
      interactor->Start();

      return EXIT_SUCCESS;
    }

### CMakeLists.txt

    cmake_minimum_required(VERSION 2.8)

    PROJECT(HistogramXYPlot)

    find_package(VTK REQUIRED)
    include(${VTK_USE_FILE})

    add_executable(HistogramXYPlot MACOSX_BUNDLE HistogramXYPlot.cxx)

    target_link_libraries(HistogramXYPlot ${VTK_LIBRARIES})

### Download and Build HistogramXYPlot

Click here to download HistogramXYPlot and its CMakeLists.txt file. Once the tarball HistogramXYPlot.tar has been downloaded and extracted,

    cd HistogramXYPlot/build

If VTK is installed:

    cmake ..

If VTK is not installed but compiled on your system, you will need to specify the path to your VTK build:

    cmake -DVTK_DIR:PATH=/home/me/vtk_build ..

Build the project:

    make

and run it:

    ./HistogramXYPlot

WINDOWS USERS PLEASE NOTE: Be sure to add the VTK bin directory to your path. This will resolve the VTK dll's at run time.