From 76f43aa4f38939f58b05de5c49399b8ce19076cc Mon Sep 17 00:00:00 2001
From: tbaudier <thomas.baudier@creatis.insa-lyon.fr>
Date: Fri, 10 Feb 2017 16:13:21 +0100
Subject: [PATCH] Add histogram tool

---
 tools/CMakeLists.txt                       |   3 +
 tools/clitkHistogramImage.cxx              |  41 +++
 tools/clitkHistogramImage.ggo              |  15 +
 tools/clitkHistogramImageGenericFilter.cxx | 165 +++++++++++
 tools/clitkHistogramImageGenericFilter.h   |  79 +++++
 vv/CMakeLists.txt                          |   2 +
 vv/icons/histogram.png                     | Bin 0 -> 688 bytes
 vv/qt_ui/vvToolHistogram.ui                | 106 +++++++
 vv/vvIcons.qrc                             |   1 +
 vv/vvToolHistogram.cxx                     | 327 +++++++++++++++++++++
 vv/vvToolHistogram.h                       |  75 +++++
 11 files changed, 814 insertions(+)
 create mode 100644 tools/clitkHistogramImage.cxx
 create mode 100644 tools/clitkHistogramImage.ggo
 create mode 100644 tools/clitkHistogramImageGenericFilter.cxx
 create mode 100644 tools/clitkHistogramImageGenericFilter.h
 create mode 100644 vv/icons/histogram.png
 create mode 100644 vv/qt_ui/vvToolHistogram.ui
 create mode 100644 vv/vvToolHistogram.cxx
 create mode 100644 vv/vvToolHistogram.h

diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt
index 422d8f9..f2cc79c 100644
--- a/tools/CMakeLists.txt
+++ b/tools/CMakeLists.txt
@@ -12,6 +12,9 @@ add_library(clitkBinarizeImageLib clitkBinarizeImageGenericFilter.cxx ${clitkBin
 WRAP_GGO(clitkProfileImage_GGO_C clitkProfileImage.ggo)
 add_library(clitkProfileImageLib clitkProfileImageGenericFilter.cxx ${clitkProfileImage_GGO_C})
 
+WRAP_GGO(clitkHistogramImage_GGO_C clitkHistogramImage.ggo)
+add_library(clitkHistogramImageLib clitkHistogramImageGenericFilter.cxx ${clitkHistogramImage_GGO_C})
+
 WRAP_GGO(clitkImageArithm_GGO_C clitkImageArithm.ggo)
 add_library(clitkImageArithmImageLib clitkImageArithmGenericFilter.cxx ${clitkImageArithm_GGO_C})
 
diff --git a/tools/clitkHistogramImage.cxx b/tools/clitkHistogramImage.cxx
new file mode 100644
index 0000000..0cb5ac9
--- /dev/null
+++ b/tools/clitkHistogramImage.cxx
@@ -0,0 +1,41 @@
+/*=========================================================================
+  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
+#include "clitkHistogramImage_ggo.h"
+#include "clitkHistogramImageGenericFilter.h"
+
+//--------------------------------------------------------------------
+int main(int argc, char * argv[])
+{
+
+  // Init command line
+  GGO(clitkHistogramImage, args_info);
+  CLITK_INIT;
+
+  // Filter
+  typedef clitk::HistogramImageGenericFilter FilterType;
+  FilterType::Pointer filter = FilterType::New();
+
+  filter->SetArgsInfo(args_info);
+
+  CLITK_TRY_CATCH_EXIT(filter->Update());
+
+  return EXIT_SUCCESS;
+} // This is the end, my friend
+//--------------------------------------------------------------------
diff --git a/tools/clitkHistogramImage.ggo b/tools/clitkHistogramImage.ggo
new file mode 100644
index 0000000..6689677
--- /dev/null
+++ b/tools/clitkHistogramImage.ggo
@@ -0,0 +1,15 @@
+#File clitkHistogramImage.ggo
+package "clitkHistogramImage"
+version "1.0"
+purpose "Save the histogram of the input image in the output text file"
+
+option "config"	  	-	"Config file"			        string  no
+option "verbose"   	v  	"Verbose"			            flag	off
+option "imagetypes" -   "Display allowed image types"   flag	off
+
+option "input"      i   "Input image filename"          string  yes
+option "output"     o   "Output texte filename"         string  yes
+option "size"       s   "size of the bin"               double  no
+
+
+
diff --git a/tools/clitkHistogramImageGenericFilter.cxx b/tools/clitkHistogramImageGenericFilter.cxx
new file mode 100644
index 0000000..49e3fa0
--- /dev/null
+++ b/tools/clitkHistogramImageGenericFilter.cxx
@@ -0,0 +1,165 @@
+/*=========================================================================
+  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
+===========================================================================**/
+#ifndef clitkHistogramImageGenericFilter_cxx
+#define clitkHistogramImageGenericFilter_cxx
+
+/* =================================================
+ * @file   clitkHistogramImageGenericFilter.cxx
+ * @author Thomas Baudier <thomas.baudier@creatis.insa-lyon.fr>
+ * @date   22 dec 2015
+ *
+ * @brief
+ *
+ ===================================================*/
+
+#include "clitkHistogramImageGenericFilter.h"
+
+// itk include
+#include <itkImageToHistogramFilter.h>
+#include <itkStatisticsImageFilter.h>
+
+#include <clitkCommon.h>
+
+
+
+namespace clitk
+{
+
+//--------------------------------------------------------------------
+HistogramImageGenericFilter::HistogramImageGenericFilter():
+  ImageToImageGenericFilter<Self>("HistogramImage")
+{
+  InitializeImageType<2>();
+  InitializeImageType<3>();
+  InitializeImageType<4>();
+  mBinSize = 100;
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template<unsigned int Dim>
+void HistogramImageGenericFilter::InitializeImageType()
+{
+  ADD_DEFAULT_IMAGE_TYPES(Dim);
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+vtkFloatArray* HistogramImageGenericFilter::GetArrayX()
+{
+  return(mArrayX);
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+vtkFloatArray* HistogramImageGenericFilter::GetArrayY()
+{
+  return(mArrayY);
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+void HistogramImageGenericFilter::SetArgsInfo(const args_info_type & a)
+{
+  mArgsInfo=a;
+  if (mArgsInfo.verbose_given)
+    SetIOVerbose(mArgsInfo.verbose_flag);
+  if (mArgsInfo.imagetypes_given && mArgsInfo.imagetypes_flag)
+    this->PrintAvailableImageTypes();
+
+  if (mArgsInfo.input_given) {
+    SetInputFilename(mArgsInfo.input_arg);
+  }
+  if (mArgsInfo.output_given) {
+    SetOutputFilename(mArgsInfo.output_arg);
+  }
+  if (mArgsInfo.size_given) {
+    SetSizeBin(mArgsInfo.size_arg);
+  }
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+void HistogramImageGenericFilter::SetSizeBin(const double size)
+{
+  mBinSize = size;
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+// Update with the number of dimensions and the pixeltype
+//--------------------------------------------------------------------
+template<class InputImageType>
+void
+HistogramImageGenericFilter::UpdateWithInputImageType()
+{
+
+  // Reading input
+  typename InputImageType::Pointer input = this->template GetInput<InputImageType>(0);
+  typedef typename InputImageType::PixelType PixelType;
+  typedef typename InputImageType::IndexType IndexType;
+  typedef typename itk::Statistics::ImageToHistogramFilter<InputImageType> HistogramFilterType;
+  typedef typename itk::StatisticsImageFilter<InputImageType> StatisticsImageFilterType;
+
+  //compute range
+  typename StatisticsImageFilterType::Pointer statisticsImageFilter = StatisticsImageFilterType::New ();
+  statisticsImageFilter->SetInput(input);
+  statisticsImageFilter->Update();
+  double range = statisticsImageFilter->GetMaximum() - statisticsImageFilter->GetMinimum();
+  //compute bin number
+  typedef typename HistogramFilterType::HistogramSizeType SizeType;
+  SizeType binNumber(1);
+  mBinSize = std::log(range);
+  binNumber[0] = (int)(range/mBinSize);
+  if (binNumber[0] == 0)
+    binNumber[0] = 1;
+
+  //compute histogram
+  typename HistogramFilterType::Pointer histogramFilter = HistogramFilterType::New();
+  histogramFilter->SetHistogramSize(binNumber);
+  histogramFilter->SetAutoMinimumMaximum(true);
+  typename HistogramFilterType::HistogramMeasurementVectorType lowerBound(1);
+  typename HistogramFilterType::HistogramMeasurementVectorType upperBound(1);
+  lowerBound[0] = statisticsImageFilter->GetMinimum();
+  upperBound[0] = statisticsImageFilter->GetMaximum();
+  histogramFilter->SetHistogramBinMinimum(lowerBound);
+  histogramFilter->SetHistogramBinMaximum(upperBound);
+  histogramFilter->SetInput(input);
+  histogramFilter->Update();
+
+  mArrayX = vtkSmartPointer<vtkFloatArray>::New();
+  mArrayY = vtkSmartPointer<vtkFloatArray>::New();
+
+  for(unsigned int i = 0; i < histogramFilter->GetOutput()->GetSize()[0]; ++i)
+  {
+    mArrayY->InsertNextTuple1(histogramFilter->GetOutput()->GetFrequency(i));
+    mArrayX->InsertNextTuple1(statisticsImageFilter->GetMinimum() + (i+0.5)*mBinSize);
+  }
+}
+//--------------------------------------------------------------------
+
+
+}//end clitk
+
+#endif  //#define clitkHistogramImageGenericFilter_cxx
diff --git a/tools/clitkHistogramImageGenericFilter.h b/tools/clitkHistogramImageGenericFilter.h
new file mode 100644
index 0000000..d963fbc
--- /dev/null
+++ b/tools/clitkHistogramImageGenericFilter.h
@@ -0,0 +1,79 @@
+/*=========================================================================
+  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
+===========================================================================**/
+
+#ifndef clitkHistogramImageGenericFilter_h
+#define clitkHistogramImageGenericFilter_h
+
+#include "clitkIO.h"
+#include "clitkImageToImageGenericFilter.h"
+#include "clitkHistogramImage_ggo.h"
+
+#include <vtkIntArray.h>
+#include <vtkFloatArray.h>
+#include <itkHistogram.h>
+
+//--------------------------------------------------------------------
+namespace clitk
+{
+
+  class ITK_EXPORT HistogramImageGenericFilter:
+    public ImageToImageGenericFilter<HistogramImageGenericFilter>
+  {
+
+  public:
+    //--------------------------------------------------------------------
+    typedef HistogramImageGenericFilter         Self;
+    typedef itk::SmartPointer<Self>           Pointer;
+    typedef itk::SmartPointer<const Self>     ConstPointer;
+    typedef args_info_clitkHistogramImage       args_info_type;
+
+    //--------------------------------------------------------------------
+    // Method for creation through the object factory
+    // and Run-time type information (and related methods)
+    itkNewMacro(Self);  
+    itkTypeMacro(HistogramImageGenericFilter, LightObject);
+
+    //--------------------------------------------------------------------
+    void SetArgsInfo(const args_info_type & a);
+    void SetSizeBin (const double size);
+
+    //--------------------------------------------------------------------
+    // Main function called each time the filter is updated
+    template<class InputImageType>  
+    void UpdateWithInputImageType();
+
+    vtkFloatArray* GetArrayX();
+    vtkFloatArray* GetArrayY();
+
+  protected:
+    HistogramImageGenericFilter();
+    template<unsigned int Dim> void InitializeImageType();
+    args_info_type mArgsInfo;
+    
+    double mBinSize;
+    
+    vtkSmartPointer<vtkFloatArray> mArrayX;
+    vtkSmartPointer<vtkFloatArray> mArrayY;
+
+  }; // end class
+  //--------------------------------------------------------------------
+
+} // end namespace clitk
+//--------------------------------------------------------------------
+
+#endif // #define clitkHistogramImageGenericFilter_h
diff --git a/vv/CMakeLists.txt b/vv/CMakeLists.txt
index f43f41a..1374745 100644
--- a/vv/CMakeLists.txt
+++ b/vv/CMakeLists.txt
@@ -22,6 +22,7 @@ set(vv_TOOLS
   vvToolROIManager
   vvToolSegmentation
   vvToolProfile
+  vvToolHistogram
   ## these ones are for tests (not working)
   # vvToolTest
   # vvToolFoo
@@ -38,6 +39,7 @@ set(vv_TOOLS
 #  >> add the relevant $_LIBS variable to the tool that has dependencies?
 set(vvToolBinarize_LIBS clitkBinarizeImageLib)
 set(vvToolProfile_LIBS clitkProfileImageLib)
+set(vvToolHistogram_LIBS clitkHistogramImageLib)
 set(vvToolResample_LIBS clitkResampleImageLib)
 set(vvToolConvert_LIBS clitkImageConvertLib)
 set(vvToolExtractPatient_LIBS clitkSegmentationGgoLib)
diff --git a/vv/icons/histogram.png b/vv/icons/histogram.png
new file mode 100644
index 0000000000000000000000000000000000000000..2690413117835b530ae4a3d5b6a2e45de5ab94a9
GIT binary patch
literal 688
zcmV;h0#E&kP)<h;3K|Lk000e1NJLTq001fg001Qj1^@s6G?jaf00006VoOIv0RI60
z0RN!9r;`8x010qNS#tmY3ljhU3ljkVnw%H_000McNliru;Q|Q{IT?4i94Y_+0zFAY
zK~z}7?O08V6G0GtHTl@plOucdH{`Z)6NFri>w^AJ5o8tI%Q7gFoQL%iLC=Eh++@L-
zdLHJ3p4iFsM3PL@4oRS<y6VlVs_yC*k~oCn;XuZJp#Ln;uB&1cMTq0r`poxz3<iUC
z0FC1qqw&c4Y!=S;&*(Cfr>Bo0BKa4X&ohug5Hxn)Bof`GOm@5;?%h8I;NkA>2LP;O
zx^6UygmdVp&n^G}4<7oZ?CAIiPp21v77`l2)xlDl{a?L*x1Ai-lo+0kGgoT36v<@@
zQb7_)l0a2UxvC;b6KG1LX@aj`K5ws>R283YZYr!?zIj#A5fK6aNhxIK&tGQq4VqI`
zXMmCu;S4lM65M|OhA{kKHDr^K#M{f)I2%6!N%;Or$#NaAjTybZzCyp(Uu&$Al9`^6
z#60|n;cyJ5nq@218KCpd<oiBm;j9TrJG;e)07&$EeM}~kTAL(664Ip2vl%2==B8~*
zq0=PHHhpKHrqN=~8h{m`#)>8DnET_V!~n^{>Gb?X?L3Qf+Ll=tvRsSlH%r}4$K?gt
z@I_YJs#DI{+}e4?Tyr-LebWm6s~hJa2oOcl=0J^*Z}pfu8jn^s<h4NC6!MkDv;=Zz
zhyJ>v^4iX1ZH~6>2E|*qMeZdRMQGb74(kHK!e(#RKo*OIQ+H#66cN!~11+lFcATk%
z-pI>VRMB#-cH3Ctwhqk8DL!d?F;#XZhmL)JRWBlsMC7N4q^)KYz%2kD*~Lt2*VSK7
WISTRWtFQh50000<MNUMnLSTa0Mm<FU

literal 0
HcmV?d00001

diff --git a/vv/qt_ui/vvToolHistogram.ui b/vv/qt_ui/vvToolHistogram.ui
new file mode 100644
index 0000000..01851e0
--- /dev/null
+++ b/vv/qt_ui/vvToolHistogram.ui
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>vvToolHistogram</class>
+ <widget class="QWidget" name="vvToolHistogram">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>506</width>
+    <height>452</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Histogram image</string>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
+    <layout class="QVBoxLayout" name="verticalLayout_3">
+     <item>
+      <layout class="QGridLayout" name="gridLayout_2">
+       <property name="horizontalSpacing">
+        <number>6</number>
+       </property>
+       <item row="2" column="3">
+        <layout class="QHBoxLayout" name="horizontalLayout_6">
+         <item>
+          <widget class="QPushButton" name="mSaveHistogramButton">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="text">
+            <string>Save Histogram</string>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </item>
+       <item row="1" column="3">
+        <layout class="QHBoxLayout" name="horizontalLayout_2">
+         <item>
+          <widget class="QLabel" name="mPosPoint2Label">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="minimumSize">
+            <size>
+             <width>200</width>
+             <height>0</height>
+            </size>
+           </property>
+           <property name="text">
+            <string/>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </item>
+       <item row="1" column="1">
+        <layout class="QHBoxLayout" name="horizontalLayout_3"/>
+       </item>
+      </layout>
+     </item>
+    </layout>
+   </item>
+   <item>
+    <layout class="QVBoxLayout" name="verticalLayout_2">
+     <item>
+      <widget class="Line" name="line_2">
+       <property name="orientation">
+        <enum>Qt::Horizontal</enum>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QVTKWidget" name="HistogramWidget" native="true">
+       <property name="minimumSize">
+        <size>
+         <width>0</width>
+         <height>300</height>
+        </size>
+       </property>
+       <property name="mouseTracking">
+        <bool>true</bool>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+  </layout>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>QVTKWidget</class>
+   <extends>QWidget</extends>
+   <header>QVTKWidget.h</header>
+  </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/vv/vvIcons.qrc b/vv/vvIcons.qrc
index a5e31cc..6bb8c93 100644
--- a/vv/vvIcons.qrc
+++ b/vv/vvIcons.qrc
@@ -13,6 +13,7 @@
     <file>icons/1b.png</file>
     <file>icons/binarize.png</file>
     <file>icons/profile.png</file>
+    <file>icons/histogram.png</file>
     <file>icons/resample.png</file>
     <file>icons/crop.png</file>
     <file>icons/splashscreen2.png</file>
diff --git a/vv/vvToolHistogram.cxx b/vv/vvToolHistogram.cxx
new file mode 100644
index 0000000..e9418c4
--- /dev/null
+++ b/vv/vvToolHistogram.cxx
@@ -0,0 +1,327 @@
+/*=========================================================================
+  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
+  ===========================================================================**/
+
+#include <QFileDialog>
+#include <QShortcut>
+
+#include <algorithm>
+
+// vv
+#include "vvToolHistogram.h"
+#include "vvProgressDialog.h"
+#include "vvSlicerManager.h"
+#include "vvSlicer.h"
+#include "vvToolInputSelectorWidget.h"
+
+// vtk
+#include <vtkAxis.h>
+#include <vtkImageActor.h>
+#include <vtkCamera.h>
+#include <vtkImageClip.h>
+#include <vtkRenderWindow.h>
+#include <vtkChartXY.h>
+#include <vtkPlot.h>
+#include <vtkRendererCollection.h>
+#include <vtkRenderer.h>
+
+#include <vtkLine.h>
+#include <vtkCellArray.h>
+#include <vtkCellData.h>
+#include <vtkPolyDataMapper.h>
+#include <vtkProperty.h>
+#include <vtkBox.h>
+#include <vtkInformation.h>
+
+#ifdef Q_OS_OSX
+# include "vvOSXHelper.h"
+#endif
+
+//------------------------------------------------------------------------------
+// Create the tool and automagically (I like this word) insert it in
+// the main window menu.
+ADD_TOOL(vvToolHistogram);
+//------------------------------------------------------------------------------
+
+
+//------------------------------------------------------------------------------
+void vvToolHistogram::Initialize()
+{ 
+  SetToolName("Histogram");
+  SetToolMenuName("Intensity Histogram");
+  SetToolIconFilename(":/common/icons/histogram.png");
+  SetToolTip("Display the histogram of the image.");
+  SetToolExperimental(false);
+}
+//------------------------------------------------------------------------------
+
+
+//------------------------------------------------------------------------------
+vvToolHistogram::vvToolHistogram(vvMainWindowBase * parent, Qt::WindowFlags f)
+  :vvToolWidgetBase(parent,f),
+   vvToolBase<vvToolHistogram>(parent),
+   Ui::vvToolHistogram()
+{ 
+  // GUI Initialization
+  Ui_vvToolHistogram::setupUi(mToolWidget);
+
+  // Connect signals & slots
+  connect(mSaveHistogramButton, SIGNAL(clicked()), this, SLOT(SaveAs()));
+
+  // Initialize some widget
+  HistogramWidget->hide();
+    
+  mView = vtkSmartPointer<vtkContextView>::New();
+  vtkSmartPointer<vtkChartXY> chart = vtkSmartPointer<vtkChartXY>::New();
+  chart->SetAutoSize(false);
+  chart->SetRenderEmpty(true);
+  mView->GetScene()->AddItem(chart);
+  this->HistogramWidget->GetRenderWindow()->GetRenderers()->RemoveAllItems();
+  this->HistogramWidget->GetRenderWindow()->AddRenderer(mView->GetRenderer());
+  HistogramWidget->show();
+
+#ifdef Q_OS_OSX
+  disableGLHiDPI(HistogramWidget->winId());
+#endif
+
+  // Main filter
+  mFilter = clitk::HistogramImageGenericFilter::New();
+
+  // Set how many inputs are needed for this tool
+  AddInputSelector("Select one image", mFilter);
+}
+//------------------------------------------------------------------------------
+
+
+//------------------------------------------------------------------------------
+vvToolHistogram::~vvToolHistogram()
+{ 
+}
+//------------------------------------------------------------------------------
+
+
+//------------------------------------------------------------------------------
+void vvToolHistogram::computeHistogram()
+{
+    if (!mCurrentSlicerManager) close();
+    QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
+    GetArgsInfoFromGUI();
+    HistogramWidget->hide();
+   
+    // Main filter
+    mFilter->SetInputVVImage(mCurrentImage);
+    mFilter->SetArgsInfo(mArgsInfo);
+    mFilter->Update();
+    
+    //Creation of the XY chart
+    vtkSmartPointer<vtkTable> table = vtkSmartPointer<vtkTable>::New();
+    vtkSmartPointer<vtkFloatArray> arrX = vtkSmartPointer<vtkFloatArray>::New();
+    vtkSmartPointer<vtkFloatArray> arrY = vtkSmartPointer<vtkFloatArray>::New();
+    arrX = mFilter->GetArrayX();
+    arrY = mFilter->GetArrayY();
+    arrX->SetName("Intensity");
+    arrY->SetName("#Voxels");
+    
+    table->AddColumn(arrX);
+    table->AddColumn(arrY);
+    
+    mView->GetRenderer()->SetBackground(1.0, 1.0, 1.0);
+ 
+    vtkSmartPointer<vtkChartXY> chart = vtkSmartPointer<vtkChartXY>::New();
+    chart->SetAutoSize(true);
+    mView->GetScene()->ClearItems();
+    mView->GetScene()->AddItem(chart);
+    vtkPlot *line = chart->AddPlot(vtkChart::LINE);
+#if VTK_MAJOR_VERSION <= 5
+    line->SetInput(table, 0, 1);
+#else
+    line->SetInputData(table, 0, 1);
+#endif
+    line->SetColor(0, 255, 0, 255);
+    line->SetWidth(1.0);
+    chart->GetAxis(vtkAxis::LEFT)->SetTitle("#Voxels");
+    chart->GetAxis(vtkAxis::BOTTOM)->SetTitle("Intensity");
+    
+    this->HistogramWidget->GetRenderWindow()->GetRenderers()->RemoveAllItems();
+    this->HistogramWidget->GetRenderWindow()->AddRenderer(mView->GetRenderer());
+    HistogramWidget->show();
+    
+    QApplication::restoreOverrideCursor();
+}
+//------------------------------------------------------------------------------
+
+
+//------------------------------------------------------------------------------
+void vvToolHistogram::RemoveVTKObjects()
+{ 
+  if (mCurrentSlicerManager)
+  {
+    connect(mCurrentSlicerManager, SIGNAL(callAddLandmark(float,float,float,float)), mCurrentSlicerManager, SLOT(AddLandmark(float,float,float,float)));
+
+    mCurrentSlicerManager->Render();
+  }
+}
+//------------------------------------------------------------------------------
+
+
+//------------------------------------------------------------------------------
+bool vvToolHistogram::close()
+{ 
+  //RemoveVTKObjects();
+
+  return vvToolWidgetBase::close();
+}
+//------------------------------------------------------------------------------
+
+
+//------------------------------------------------------------------------------
+void vvToolHistogram::closeEvent(QCloseEvent *event)
+{ 
+  RemoveVTKObjects();
+  event->accept();
+}
+//------------------------------------------------------------------------------
+
+
+//------------------------------------------------------------------------------
+void vvToolHistogram::reject()
+{ 
+  // DD("vvToolHistogram::reject");
+  RemoveVTKObjects();
+  return vvToolWidgetBase::reject();
+}
+//------------------------------------------------------------------------------
+
+
+//------------------------------------------------------------------------------
+void vvToolHistogram::InputIsSelected(vvSlicerManager * m)
+{ 
+  mCurrentSlicerManager = m;
+
+  mSaveHistogramButton->setEnabled(true);
+  mTextFileName = "Histogram.txt";
+
+  computeHistogram();
+
+  disconnect(mCurrentSlicerManager, SIGNAL(callAddLandmark(float,float,float,float)), mCurrentSlicerManager, SLOT(AddLandmark(float,float,float,float)));
+}
+//------------------------------------------------------------------------------
+
+
+//------------------------------------------------------------------------------
+void vvToolHistogram::GetArgsInfoFromGUI()
+{ 
+
+  /* //KEEP THIS FOR READING GGO FROM FILE
+     int argc=1;
+     std::string a = "toto";
+     char * const* argv = new char*;
+     //a.c_str();
+     struct cmdline_parser_params p;
+     p.check_required = 0;
+     int good = cmdline_parser_ext(argc, argv, &args_info, &p);
+     DD(good);
+  */
+  cmdline_parser_clitkHistogramImage_init(&mArgsInfo); // Initialisation to default
+
+  mArgsInfo.verbose_flag = false;
+
+  // Required (even if not used)
+  mArgsInfo.input_given = 0;
+  mArgsInfo.output_given = 0;
+
+  mArgsInfo.input_arg = new char;
+  mArgsInfo.output_arg = new char;
+
+}
+//------------------------------------------------------------------------------
+
+
+//------------------------------------------------------------------------------
+void vvToolHistogram::apply()
+{ 
+  close();
+}
+//------------------------------------------------------------------------------
+
+
+//------------------------------------------------------------------------------
+void vvToolHistogram::SaveAs()
+{ 
+  QStringList OutputListeFormat;
+  OutputListeFormat.clear();
+  OutputListeFormat.push_back(".txt");
+  
+  QString Extensions = "AllFiles(*.*)";
+  for (int i = 0; i < OutputListeFormat.count(); i++) {
+    Extensions += ";;Text File ( *";
+    Extensions += OutputListeFormat[i];
+    Extensions += ")";
+  }
+  QString fileName = QFileDialog::getSaveFileName(this, tr("Save As"), mTextFileName.c_str(), Extensions);
+  if (!fileName.isEmpty()) {
+    std::string fileformat = itksys::SystemTools::GetFilenameLastExtension(fileName.toStdString());
+    QString fileQFormat = fileformat.c_str();
+    if (OutputListeFormat.contains(fileformat.c_str()) || fileQFormat.isEmpty()) {
+        QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
+        std::string action = "Saving";
+        vvProgressDialog progress("Saving "+fileName.toStdString());
+        qApp->processEvents();
+        
+        if (!mCurrentSlicerManager) {
+            close();
+            return;
+        }
+
+        // Output
+        mTextFileName = fileName.toStdString();
+        if (fileQFormat.isEmpty())
+            mTextFileName += ".txt";
+        ofstream fileOpen(mTextFileName.c_str(), std::ofstream::trunc);
+  
+        if(!fileOpen) {
+            cerr << "Error during saving" << endl;
+            QApplication::restoreOverrideCursor();
+            close();
+            return;
+        }
+        
+        vtkSmartPointer<vtkFloatArray> arrX = vtkSmartPointer<vtkFloatArray>::New();
+        vtkSmartPointer<vtkFloatArray> arrY = vtkSmartPointer<vtkFloatArray>::New();
+        vtkSmartPointer<vtkFloatArray> coords = vtkSmartPointer<vtkFloatArray>::New();
+        arrX = mFilter->GetArrayX();
+        arrY = mFilter->GetArrayY();
+        int i(0);
+        fileOpen << "Value represents the number of voxels around the corresponding intensity (by default the windows size around intensity is log(range))" << endl;
+        fileOpen << "Intensity" << "\t" << "Value" << endl;
+   
+        while (i<arrX->GetNumberOfTuples()) {
+            fileOpen << arrX->GetTuple(i)[0] << "\t" << arrY->GetTuple(i)[0] << endl;
+            ++i;
+        }
+
+        fileOpen.close();
+        QApplication::restoreOverrideCursor();
+    } else {
+      QString error = fileformat.c_str();
+      error += " format unknown !!!\n";
+      QMessageBox::information(this,tr("Saving Problem"),error);
+      SaveAs();
+    }
+  }
+}
+//------------------------------------------------------------------------------
diff --git a/vv/vvToolHistogram.h b/vv/vvToolHistogram.h
new file mode 100644
index 0000000..c567862
--- /dev/null
+++ b/vv/vvToolHistogram.h
@@ -0,0 +1,75 @@
+/*=========================================================================
+  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
+===========================================================================**/
+#ifndef VVTOOLHISTOGRAM_H
+#define VVTOOLHISTOGRAM_H
+
+#include <QtGlobal>
+#include <QtDesigner/QDesignerExportWidget>
+
+#include "vvToolBase.h"
+#include "vvToolWidgetBase.h"
+#include "ui_vvToolHistogram.h"
+
+#include "clitkHistogramImage_ggo.h"
+#include "clitkHistogramImageGenericFilter.h"
+#include <vtkTable.h>
+#include <vtkContextView.h>
+#include <vtkContextScene.h>
+
+//------------------------------------------------------------------------------
+class vvToolHistogram:
+  public vvToolWidgetBase,
+  public vvToolBase<vvToolHistogram>, 
+  private Ui::vvToolHistogram
+{
+  Q_OBJECT
+    public:
+  vvToolHistogram(vvMainWindowBase * parent=0, Qt::WindowFlags f=0);
+  ~vvToolHistogram();
+
+  //-----------------------------------------------------
+  static void Initialize();
+  void GetArgsInfoFromGUI();
+  virtual void InputIsSelected(vvSlicerManager * m);
+
+  void computeHistogram();
+  void SetPoints();
+
+  //-----------------------------------------------------
+  public slots:
+  virtual void apply();
+  virtual bool close();
+  virtual void reject();
+
+  void SaveAs();
+
+ protected:
+  void RemoveVTKObjects();
+  virtual void closeEvent(QCloseEvent *event);
+  Ui::vvToolHistogram ui;
+  args_info_clitkHistogramImage mArgsInfo;
+
+  vtkSmartPointer<vtkContextView> mView;
+  clitk::HistogramImageGenericFilter::Pointer mFilter;
+  std::string mTextFileName;
+
+}; // end class vvToolHistogram
+//------------------------------------------------------------------------------
+
+#endif
+
-- 
2.49.0