eLynx SDK v3.3.0
C++ image processing API reference

How to add a filter to eLynx lab application?

To illustrate the tutorial we are going to add the Colorize filter.

This filter sets the hue and the saturation of an image.

Before adding a filter to eLynx lab application, the filter must exist from ImageVariant class.
If filter does not exist for ImageVariant, please refer to the article:
How to add image services?

To add a filter to eLynx lab application follow these steps:


Add global filter id

enum 
{
  // menu IDs
  ...
  elxID_ADJUST_COLORIZE
  ...
};

Go to top


Add access to filter from main menu

void OnAdjustColorize(wxCommandEvent& iEvent);
void OnAdjustColorizeUI(wxUpdateUIEvent& iEvent);
EVT_MENU(elxID_ADJUST_COLORIZE,             elxImageFrame::OnAdjustColorize)
EVT_UPDATE_UI(elxID_ADJUST_COLORIZE,        elxImageFrame::OnAdjustColorizeUI)

Depending on functionnnality type we add entry in menu, in one of these files:

For Colorize, we use file elxImageFrame_Adjust.cpp.

pgMenu->Append(elxID_ADJUST_COLORIZE,         _("Colorize"));
//----------------------------------------------------------------------------
//  OnAdjustColorizeUI
//----------------------------------------------------------------------------
void elxImageFrame::OnAdjustColorizeUI(wxUpdateUIEvent& iEvent) 
{
  const ImageVariant& image = _prDocument->GetImage();
  bool bEnable = image.IsValid() && !image.IsBayer() && image.IsColor();
  iEvent.Enable(bEnable);

} // OnAdjustColorizeUI
FilterMenuActivation.png

You can see that filter Colorize is enable for RGB color image and disable for grey image.

Go to top


Implement filter on menu event

#include "elxColorizePanel.h"
...
//----------------------------------------------------------------------------
//  OnAdjustColorize
//----------------------------------------------------------------------------
void elxImageFrame::OnAdjustColorize(wxCommandEvent& iEvent) 
{
  elxColorizePanel * paPanel = new elxColorizePanel(this);
  elxImageProcessingDialog * paDialog = new elxImageProcessingDialog(this, paPanel, _prDocument);
  if ( paDialog->ShowModal() == wxID_OK )
  {
    double hue, saturation;
    paPanel->GetSettings(hue, saturation);
    elxImageColorizeCommand * pgCommand = new elxImageColorizeCommand(hue, saturation);
    _prDocument->GetCommandProcessor()->Submit( pgCommand );
  }
  paPanel->Destroy(); paPanel=NULL;
  paDialog->Destroy(); paDialog = NULL;

} // OnAdjustColorize

1 - Invoke elxColorizePanel to get hue and saturation parameters for user interface,
2 - Invoke elxImageColorizeCommand to apply filter on the current image and to put the command in undo/redo command stack.

Go to top


Declare and implement the filter command

//----------------------------------------------------------------------------
//                       Image Colorize command
//----------------------------------------------------------------------------
class elxImageColorizeCommand : public elxImageCommand
{
public:
  elxImageColorizeCommand(double iHue, double iSaturation);
  virtual ~elxImageColorizeCommand() {}

  // virtual from elxImageCommand
  virtual bool Do(ImageVariant& ioImage);
  virtual wxString GetHelp() const { return _T("Colorize image"); }

protected:
  double _hue;
  double _saturation;
};
//############################################################################
//                       Image Colorize command
//############################################################################
//----------------------------------------------------------------------------
//  constructor
//----------------------------------------------------------------------------
elxImageColorizeCommand::elxImageColorizeCommand(double iHue, double iSaturation) :
  elxImageCommand( _T("Colorize") ),
  _hue(iHue),
  _saturation(iSaturation)
{}

//----------------------------------------------------------------------------
//  Do
//----------------------------------------------------------------------------
bool elxImageColorizeCommand::Do(ImageVariant& ioImage)
{
  return ioImage.Colorize(_hue, _saturation, the_StatusBarNotifier);
}

Go to top


Declare and implement the filter panel

Filter panel allows user to interact with parameters to see how they affect the resulting image.
Create files elxColorizePanel.h and elxColorizePanel.cpp.

//============================================================================
//  elxColorizePanel.h
//============================================================================
//  Usage : image Colorize panel
//----------------------------------------------------------------------------
//  Copyright (C) 2007 by eLynx project
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Library General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
//  See the GNU Library General Public License for more details.
//----------------------------------------------------------------------------
#ifndef __elxColorizePanel_h__
#define __elxColorizePanel_h__

#include "elxImageProcessingPanel.h"

class elxDoubleTextSlider;

class elxColorizePanel : public elxImageProcessingPanel
{
  DECLARE_EVENT_TABLE();

public:
  elxColorizePanel(wxWindow * iprParent);
  virtual ~elxColorizePanel();

  void GetSettings(double& oHue, double& oSaturation);
  void OnUpdate(wxCommandEvent& iEvent);

  // virtual from elxImageProcessingPanel
  virtual void Init(const ImageVariant& iImage);
  virtual bool SupportChannelMask() { return false; }
  virtual void ResetSettings();
  virtual void LoadSettings();
  virtual void SaveSettings();
  virtual bool Process(ImageVariant& ioImage,
      uint iChannelMask = CM_All,
      ProgressNotifier& iNotifier=ProgressNotifier_NULL);

private:
  elxDoubleTextSlider * _pgSliderHue;
  elxDoubleTextSlider * _pgSliderSaturation;
};

#endif // __elxColorizePanel_h__
//============================================================================
//  elxColorizePanel.cpp
//============================================================================
//  Usage : image Colorize panel
//----------------------------------------------------------------------------
//  Copyright (C) 2007 by eLynx project
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Library General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
//  See the GNU Library General Public License for more details.
//----------------------------------------------------------------------------
#include <wx/stattext.h>
#include <wx/sizer.h>

#include "elxColorizePanel.h"
#include "elxDoubleTextSlider.h"

// === setting's name ===
#define PATH_Colorize "/Filters/Colorize/"
#define FIELD_Hue        wxString::FromAscii(PATH_Colorize"Hue")
#define FIELD_Saturation wxString::FromAscii(PATH_Colorize"Saturation")

// default for sepia tone
const double defaultHue = 0.10;
const double defaultSaturation = 0.54;

enum
{
  ID_HUE = 100,
  ID_SATURATION
};

BEGIN_EVENT_TABLE(elxColorizePanel, elxImageProcessingPanel)
  EVT_SLIDER(ID_HUE,        elxColorizePanel::OnUpdate ) 
  EVT_SLIDER(ID_SATURATION, elxColorizePanel::OnUpdate ) 
END_EVENT_TABLE()

//----------------------------------------------------------------------------
//  constructor 
//----------------------------------------------------------------------------
//  public
//----------------------------------------------------------------------------
elxColorizePanel::elxColorizePanel(wxWindow * iprParent) :

  elxImageProcessingPanel(iprParent),
  _pgSliderHue(NULL),
  _pgSliderSaturation(NULL)
{
  SetName( _T("Colorize") );

} // constructor

//----------------------------------------------------------------------------
//  destructor
//----------------------------------------------------------------------------
//  public
//----------------------------------------------------------------------------
elxColorizePanel::~elxColorizePanel()
{
} // destructor

//----------------------------------------------------------------------------
//  GetSettings
//----------------------------------------------------------------------------
void elxColorizePanel::GetSettings(double& oHue, double& oSaturation)
{
  oHue = _pgSliderHue->GetValue();
  oSaturation = _pgSliderSaturation->GetValue();

} // GetSettings

//----------------------------------------------------------------------------
//  OnUpdate
//----------------------------------------------------------------------------
void elxColorizePanel::OnUpdate(wxCommandEvent& iEvent)
{
  UpdateParentDialog();

} // OnUpdate

//----------------------------------------------------------------------------
//  Init
//----------------------------------------------------------------------------
//  virtual public from elxImageProcessingPanel
//----------------------------------------------------------------------------
void elxColorizePanel::Init(const ImageVariant& iImage)
{
  // === sliders ===
  wxStaticText * pgLabelHue = new wxStaticText(this, -1, _T("Hue:"));
  wxStaticText * pgLabelSaturation = new wxStaticText(this, -1, _T("Saturation:"));

  int Tick = 100;
  int digits = 3;
  wxString Format( _T("%0.2lf") );
  double min=0.0, max=1.0;

  _pgSliderHue = new elxDoubleTextSlider(this, ID_HUE, defaultHue, Tick, min, max, Format, digits);
  _pgSliderSaturation = new elxDoubleTextSlider(this, ID_SATURATION, defaultSaturation, Tick, min, max, Format, digits);

  wxBoxSizer * pgSizerHue = new wxBoxSizer(wxHORIZONTAL);
  pgSizerHue->Add(pgLabelHue,   0, wxALL | wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL);
  pgSizerHue->Add(_pgSliderHue, 0, wxALL | wxALIGN_RIGHT);

  wxBoxSizer * pgSizerSaturation = new wxBoxSizer(wxHORIZONTAL);
  pgSizerSaturation->Add(pgLabelSaturation,   0, wxALL | wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL);
  pgSizerSaturation->Add(_pgSliderSaturation, 0, wxALL | wxALIGN_RIGHT);

  // === main sizer ===
  wxBoxSizer * pgBoxSizer = new wxBoxSizer(wxVERTICAL);
  pgBoxSizer->Add(pgSizerHue, 0, wxALL | wxALIGN_RIGHT);
  pgBoxSizer->Add(pgSizerSaturation, 0, wxALL | wxALIGN_RIGHT);

  SetAutoLayout( true );
  SetSizer( pgBoxSizer );

  pgBoxSizer->SetSizeHints( this );
  pgBoxSizer->Fit( this );

  Centre( wxBOTH );

} // Init

//----------------------------------------------------------------------------
//  ResetSettings
//----------------------------------------------------------------------------
//  virtual public from elxImageProcessingPanel
//----------------------------------------------------------------------------
void elxColorizePanel::ResetSettings()
{
  _pgSliderHue->UpdateValue( double(defaultHue) );
  _pgSliderSaturation->UpdateValue( double(defaultSaturation) );

} // ResetSettings

//----------------------------------------------------------------------------
//  LoadSettings
//----------------------------------------------------------------------------
//  virtual public from elxImageProcessingPanel
//----------------------------------------------------------------------------
void elxColorizePanel::LoadSettings()
{
  // load config file
  wxConfigBase * prConfig = wxConfigBase::Get();
  if (NULL == prConfig)
    return;

  double l = defaultHue;
  prConfig->Read(FIELD_Hue, &l);
  _pgSliderHue->UpdateValue(l);

  l = defaultSaturation;
  prConfig->Read(FIELD_Saturation, &l);
  _pgSliderSaturation->UpdateValue(l);
  
} // LoadSettings

//----------------------------------------------------------------------------
//  SaveSettings
//----------------------------------------------------------------------------
//  virtual public from elxImageProcessingPanel
//----------------------------------------------------------------------------
void elxColorizePanel::SaveSettings()
{
  // load config file
  wxConfigBase * prConfig = wxConfigBase::Get();
  if (NULL == prConfig)
    return;

  prConfig->Write(FIELD_Hue, (double)_pgSliderHue->GetValue());
  prConfig->Write(FIELD_Saturation, (double)_pgSliderSaturation->GetValue());
  prConfig->Flush();

} // SaveSettings

//----------------------------------------------------------------------------
//  Process
//----------------------------------------------------------------------------
//  virtual public from elxImageProcessingPanel
//----------------------------------------------------------------------------
bool elxColorizePanel::Process(
    ImageVariant& ioImage,
    uint iChannelMask, 
    ProgressNotifier& iNotifier)
{
  double hue, saturation;
  GetSettings(hue, saturation);
  return ioImage.Colorize(hue, saturation, iNotifier);

} // Process
colorizePanel1.png

Filter with default values, Sepia tone.
colorizePanel2.png

Filter with modified values for blue tone.

Go to top


Generated on Thu Dec 9 2010 by doxygen 1.7.2