Go back to Richel Bilderbeek's homepage.

Go back to Richel Bilderbeek's C++ page.

 

 

 

 

 

(C++) GaborFilterWindowsOnly

 

 

 

 

 

 

Technical facts

 

 

 

 

 

 

ProjectGaborFilter.cpp

 

//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop
//---------------------------------------------------------------------------
USEFORM("UnitFormMain.cpp", FormMain);
USEFORM("UnitFormWhatsNew.cpp", FormWhatsNew);
//---------------------------------------------------------------------------
WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
        try
        {
                 Application->Initialize();
                 Application->Title = "GaborFilter";
                 Application->CreateForm(__classid(TFormMain), &FormMain);
                 Application->Run();
        }
        catch (Exception &exception)
        {
                 Application->ShowException(&exception);
        }
        catch (...)
        {
                 try
                 {
                         throw Exception("");
                 }
                 catch (Exception &exception)
                 {
                         Application->ShowException(&exception);
                 }
        }
        return 0;
}
//---------------------------------------------------------------------------

 

 

 

 

 

UnitFormMain.h

 

//---------------------------------------------------------------------------
/*
  GaborFilter, performs Gabor filter operations on images
  Copyright (C) 2010  Richèl Bilderbeek

  This program is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  This program 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 General Public License for more details.
  You should have received a copy of the GNU General Public License
  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
//---------------------------------------------------------------------------
// From http://www.richelbilderbeek.nl
//---------------------------------------------------------------------------
#ifndef UnitFormMainH
#define UnitFormMainH
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <ExtCtrls.hpp>
#include <Graphics.hpp>
#include <Grids.hpp>
#include <Dialogs.hpp>
#include <ComCtrls.hpp>
#include <Menus.hpp>
//---------------------------------------------------------------------------
#include <iosfwd>
#include <vector>
#include <cassert>
#include <algorithm>
#include <numeric>
//---------------------------------------------------------------------------
class TFormMain : public TForm
{
__published: // IDE-managed Components
        TScrollBox *ScrollBoxOriginal;
        TScrollBox *ScrollBoxResult;
        TImage *ImageSource;
        TImage *ImageTarget;
        TButton *ButtonLoad;
        TButton *ButtonSaveResult;
        TOpenDialog *OpenDialog1;
        TSaveDialog *SaveDialog1;
        TPageControl *PageControl;
        TTabSheet *TabSheetOriginal;
        TTabSheet *TabSheetFilter;
        TTabSheet *TabSheetResult;
        TPanel *PanelOriginal;
        TPanel *PanelResult;
        TPanel *PanelFilter;
        TTabSheet *TabSheetAbout;
        TPopupMenu *PopupMenuFilter;
        TMenuItem *ItemAddCol;
        TMenuItem *ItemAddRow;
        TMenuItem *N1;
        TMenuItem *ItemRemoveCol;
        TMenuItem *ItemRemoveRow;
        TRichEdit *RichEditLicence;
        TPanel *PanelAboutTop;
        TPanel *PanelAbout1;
        TPanel *PanelAbout2;
        TPanel *PanelAbout3;
        TPanel *PanelAbout6;
        TPanel *PanelAbout5;
        TPanel *PanelVersion;
        TImage *ImageRichel;
        TButton *ButtonDo;
        TTrackBar *TrackBarAngle;
        TLabel *LabelAngle;
        TTrackBar *TrackBarWavelength;
        TLabel *LabelWavelength;
        TTrackBar *TrackBarSize;
        TLabel *LabelSize;
        TImage *ImageFilter;
        TPanel *PanelTopRight;
        TLabel *LabelSigma;
        TButton *ButtonWhatsNew;
        TPanel *Panel1;
        void __fastcall ButtonLoadClick(TObject *Sender);
        void __fastcall ButtonSaveResultClick(TObject *Sender);
        void __fastcall ButtonDoClick(
          TObject *Sender);
        void __fastcall OnAnyTrackBarChange(TObject *Sender);
        void __fastcall ButtonWhatsNewClick(TObject *Sender);
private: // User declarations
  std::vector<std::vector<double> > mFilter;
public: // User declarations
        __fastcall TFormMain(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TFormMain *FormMain;
//---------------------------------------------------------------------------
const std::vector<std::vector<double> > CreateGaborFilter(
  const int sz,
  const double angle,
  const double wavelength,
  const double sigma);
//---------------------------------------------------------------------------
const std::vector<std::vector<double> > DoFilterOperation(
  const std::vector<std::vector<double> >& source, //y-x-ordered
  const std::vector<std::vector<double> >& filter); //y-x-ordered
//---------------------------------------------------------------------------
//Creates a 2D-std::vector (y-x-ordered) from a TImage
const std::vector<std::vector<int> > ImageToVector(const TImage * const image);
//---------------------------------------------------------------------------
const double GetFilterOperationPixel(
  const std::vector<std::vector<double> >& source, //y-x-ordered
  const int sourceX,
  const int sourceY,
  const std::vector<std::vector<double> >& filter); //y-x-ordered
//---------------------------------------------------------------------------
const std::pair<double,double> GetMinMax(const std::vector<std::vector<double> >& v);
//---------------------------------------------------------------------------
//Obtains the maximum element of a 2D container
//From http://www.richelbilderbeek.nl/CppMaxElement.html
template <class Container>
const Container::value_type::value_type MaxElement(const Container& v)
{
  assert(v.empty() == false && "Container must have a size");

  //Obtain an initial lowest value
  Container::value_type::value_type maxValue
    = *(std::max_element(v[0].begin(),v[0].end()));

  //Set the iterators
  const Container::const_iterator rowEnd = v.end();
  Container::const_iterator row = v.begin();
  ++row; //Move to the next position, as index 0 is already read from

  for ( ; row != rowEnd; ++row) //row is already initialized
  {
    const Container::value_type::value_type localMaxVal
      = *(std::max_element(row->begin(),row->end()));
    if (localMaxVal > maxValue) maxValue = localMaxVal;
  }
  return maxValue;
}
//---------------------------------------------------------------------------
//Obtains the minimum element of a 2D container
//From http://www.richelbilderbeek.nl/CppMinElement.html
template <class Container>
const Container::value_type::value_type MinElement(const Container& v)
{
  assert(v.empty() == false && "Container must have a size");

  //Obtain an initial lowest value
  Container::value_type::value_type minValue
    = *(std::min_element(v[0].begin(),v[0].end()));

  //Set the iterators
  const Container::const_iterator rowEnd = v.end();
  Container::const_iterator row = v.begin();
  ++row; //Move to the next position, as index 0 is already read from

  for ( ; row != rowEnd; ++row) //row is already initialized
  {
    const Container::value_type::value_type localMinVal
      = *(std::min_element(row->begin(),row->end()));
    if (localMinVal < minValue) minValue = localMinVal;
  }
  return minValue;
}
//---------------------------------------------------------------------------
//From http://www.richelbilderbeek.nl/CppRescale.html
const double Rescale(
  const double value,
  const double oldMin,
  const double oldMax,
  const double newMin,
  const double newMax);
//---------------------------------------------------------------------------
//From http://www.richelbilderbeek.nl/CppRescale.html
const std::vector<std::vector<double> > Rescale(
  std::vector<std::vector<double> > v,
  const double newMin,
  const double newMax);
//---------------------------------------------------------------------------
template <class Source, class Target>
const std::vector<std::vector<Target> > Convert(
  const std::vector<std::vector<Source> >& v)
{
  const int maxy = static_cast<int>(v.size());
  assert(maxy>0);
  const int maxx = static_cast<int>(v[0].size());
  std::vector<std::vector<Target> > t(maxy,std::vector<Target>(maxx));
  for (int y=0; y!=maxy; ++y)
  {
    for (int x=0; x!=maxx; ++x)
    {
      t[y][x] = static_cast<Target>(v[y][x]);
    }
  }
  return t;
}
//---------------------------------------------------------------------------
//Fills a TImage from a 2D-std::vector (y-x-ordered)
void VectorToImage(const std::vector<std::vector<int> >& v, const TImage * const image);
//---------------------------------------------------------------------------
//From http://richelbilderbeek.nl/CppToolGaborFilter.html
const double CalculateSigma(const int sz);
//---------------------------------------------------------------------------

#endif

 

 

 

 

 

UnitFormMain.cpp

 

//---------------------------------------------------------------------------
/*
  GaborFilter, performs Gabor filter operations on images
  Copyright (C) 2010  Richèl Bilderbeek

  This program is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  This program 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 General Public License for more details.
  You should have received a copy of the GNU General Public License
  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
//---------------------------------------------------------------------------
// From http://www.richelbilderbeek.nl
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop

#include <algorithm>
#include <cassert>
#include <cmath>
#include <functional>
#include <vector>
#include <boost/scoped_ptr.hpp>
#include "UnitFormMain.h"
#include "UnitSurfacePlotter.h"
#include "UnitFormWhatsNew.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TFormMain *FormMain;
//---------------------------------------------------------------------------
__fastcall TFormMain::TFormMain(TComponent* Owner)
        : TForm(Owner)
{
  const int sz = 200;
  ImageSource->Picture->Bitmap->Width  = sz;
  ImageSource->Picture->Bitmap->Height = sz;
  //Create test image
  const double midx = static_cast<double>(sz) / 2.0;
  const double midy = static_cast<double>(sz) / 2.0;
  Extctrls::TImage * image = ImageSource;
  for (int y=0; y!=sz; ++y)
  {
    unsigned char * const line
      = static_cast<unsigned char *>(image->Picture->Bitmap->ScanLine[y]);
    const double dy = static_cast<double>(y) - midy;
    for (int x=0; x!=sz; ++x)
    {
      const double dx = static_cast<double>(x) - midx;
      const double distance = std::sqrt( (dx*dx)+(dy*dy) );
      const int grey = (std::sin(distance*0.8) > 0.0 ? 255 : 0);
      assert(grey>=0.0 && grey<256.0);
      line[x*3+2] = grey;
      line[x*3+1] = grey;
      line[x*3+0] = grey;
    }
  }
  image->Refresh();
  OnAnyTrackBarChange(0);  
}
//---------------------------------------------------------------------------
void __fastcall TFormMain::ButtonLoadClick(TObject *Sender)
{
  if (OpenDialog1->Execute()==false) return;
  ImageSource->Picture->LoadFromFile(OpenDialog1->FileName);
  OnAnyTrackBarChange(0);
  ++PageControl->ActivePageIndex;
}
//---------------------------------------------------------------------------
void __fastcall TFormMain::ButtonSaveResultClick(TObject *Sender)
{
  if (SaveDialog1->Execute()==false) return;
  ImageTarget->Picture->SaveToFile(SaveDialog1->FileName);
  ShowMessage("Image saved successfully");
  ++PageControl->ActivePageIndex;
}
//---------------------------------------------------------------------------
//Creates a 2D-std::vector (y-x-ordered) from a TImage
//From http://www.richelbilderbeek.nl/CppImageToVector.html
const std::vector<std::vector<int> > ImageToVector(const TImage * const image)
{
  assert(image!=0 && "Image must not be NULL");
  assert(image->Picture->Bitmap!=0 && "Bitmap must not be NULL");
  assert(image->Picture->Bitmap->PixelFormat == pf24bit && "Bitmap must be 24 bit");

  const int width  = image->Picture->Bitmap->Width;
  const int height = image->Picture->Bitmap->Height;

  std::vector<std::vector<int> > v(height,std::vector<int>(width));

  for (int y=0; y!=height; ++y)
  {
    assert(y >= 0);
    assert(y < static_cast<int>(v.size()));
    std::vector<int>& vLine = v[y];
    const unsigned char * const line
      = static_cast<const unsigned char *>(image->Picture->Bitmap->ScanLine[y]);
    for (int x=0; x!=width; ++x)
    {
      assert(x >= 0);
      assert(x < static_cast<int>(vLine.size()));
      const double grey = static_cast<double>(line[x*3+0] + line[x*3+1] + line[x*3+2])
        / 3.0;
      vLine[x] = grey;
      assert(grey>=0.0 && grey<256.0);
    }
  }
  return v;
}
//---------------------------------------------------------------------------
//Draws a (grey) TImage from a 2D-std::vector (y-x-ordered)
//From http://www.richelbilderbeek.nl/CppVectorToImage.html
void VectorToImage(const std::vector<std::vector<int> >& v, const TImage * const image)
{
  assert(image!=0 && "Image must not be NULL");
  assert(image->Picture->Bitmap!=0 && "Bitmap must not be NULL");
  assert(image->Picture->Bitmap->PixelFormat == pf24bit && "Bitmap must be 24 bit");

  const int height = v.size();
  const int width  = v[0].size();

  image->Picture->Bitmap->Height = height;
  image->Picture->Bitmap->Width  = width;

  for (int y=0; y!=height; ++y)
  {
    assert(y >= 0);
    assert(y < static_cast<int>(v.size()));
    const std::vector<int>& vLine = v[y];
    unsigned char * const line
      = static_cast<unsigned char *>(image->Picture->Bitmap->ScanLine[y]);
    for (int x=0; x!=width; ++x)
    {
      assert(x >= 0);
      assert(x < static_cast<int>(vLine.size()));
      const int grey = vLine[x];
      line[x*3+2] = grey; //Red
      line[x*3+1] = grey; //Green
      line[x*3+0] = grey; //Blue
    }
  }
}
//---------------------------------------------------------------------------
//Return a y-x-ordered 2D std::vector with the intensitief of grey
//values from range [MinElement(filter),MaxElement(filter)]
//after the filter operation
//From http://www.richelbilderbeek.nl/CppDoFilterOperation.html
const std::vector<std::vector<double> > DoFilterOperation(
  const std::vector<std::vector<double> >& source, //y-x-ordered
  const std::vector<std::vector<double> >& filter) //y-x-ordered
{
  assert(!source.empty());
  assert(!filter.empty());
  const int maxx = static_cast<int>(source[0].size());
  const int maxy = static_cast<int>(source.size());
  std::vector<std::vector<double> > v(maxy,std::vector<double>(maxx));
  const int midX = static_cast<int>(filter[0].size()) / 2;
  const int midY = static_cast<int>(filter.size()   ) / 2;

  for (int y=0; y!=maxy; ++y)
  {
    const int writeY = y;
    assert(writeY >= 0 && writeY < static_cast<int>(v.size()) );
    std::vector<double>& vLine = v[writeY];
    for (int x=0; x!=maxx; ++x)
    {
      //The x and y values are the topleft coordinate of where
      //  the filter will be applied to. This coordinat can be out of
      //  the range, but at least one pixel of where the filter will be
      //  applied to will be in range
      //The pixel value is normalized to the area the
      //  filter operation took place on
      vLine[x] = GetFilterOperationPixel(source,x-midX,y-midY,filter);
    }
  }
  assert(source[0].size()==v[0].size());
  assert(source.size()==v.size());
  return v;
}
//---------------------------------------------------------------------------
//The sourceX and sourceY values are the topleft coordinate of where
//  the filter will be applied to. This coordinat can be out of
//  the range, but at least one pixel of where the filter will be
//  applied to will be in range. If there are no pixels in range,
//  an assertion will fail.
//The pixel value is normalized to the area the
//  filter operation took place on. Therefore, this area must be non-zero
//The outcome of this filter operation will be written to
//  (x + midX, y + midY), which HAS to be in range
//From http://www.richelbilderbeek.nl/CppDoFilterOperation.html
const double GetFilterOperationPixel(
  const std::vector<std::vector<double> >& source, //y-x-ordered
  const int sourceX,
  const int sourceY,
  const std::vector<std::vector<double> >& filter) //y-x-ordered
{
  assert(!source.empty());
  assert(!filter.empty());
  const int sourceMaxY = static_cast<int>(source.size());
  const int sourceMaxX = static_cast<int>(source[0].size());
  const int filterMaxY = static_cast<int>(filter.size());
  const int filterMaxX = static_cast<int>(filter[0].size());

  double result = 0.0;
  int nPixels = 0;
  for (int y=0; y!=filterMaxY; ++y)
  {
    const int readY = sourceY + y;
    if ( readY < 0 || readY >= sourceMaxY) continue;
    assert(y >= 0);
    assert(y < static_cast<int>(filter.size()));
    const std::vector<double>& lineFilter = filter[y];
    assert(readY >= 0);
    assert(readY < static_cast<int>(source.size()));
    const std::vector<double>& lineSource = source[readY];
    for (int x=0; x!=filterMaxX; ++x)
    {
      const int readX = sourceX + x;
      if ( readX < 0 || readX >= sourceMaxX) continue;
      assert(x >= 0);
      assert(x < filterMaxX);
      assert(readX >= 0);
      assert(readX < sourceMaxX);
      const double deltaResult = lineSource[readX] * lineFilter[x];
      result += deltaResult;
      ++nPixels;
    }
  }
  assert(nPixels!=0);
  const double filteredValue = result / static_cast<double>(nPixels);
  return filteredValue;

}
//---------------------------------------------------------------------------
const std::pair<double,double> GetMinMax(const std::vector<std::vector<double> >& v)
{
  assert(!v.empty());
  const int maxy = static_cast<int>(v.size());
  assert(maxy > 0);
  const int maxx = v[0].size();
  assert(maxx > 0);
  double min = 0.0;
  double max = 0.0;
  for(int y=0; y!=maxy; ++y)
  {
    assert(y >= 0);
    assert(y  < static_cast<int>(v.size()) );

    const std::vector<double>& row = v[y];
    for(int x=0; x!=maxx; ++x)
    {
      assert(x >= 0);
      assert(x  < static_cast<int>(row.size()) );

      const double value = row[x];
      if (value < 0.0) min +=value;
      else if (value > 0.0) max +=value;
    }
  }
  return std::make_pair(min, max);
}
//---------------------------------------------------------------------------
void __fastcall TFormMain::ButtonDoClick(
      TObject *Sender)
{

  const std::vector<std::vector<int> > source_int = ImageToVector(ImageSource);
  const std::vector<std::vector<double> > source = Convert<int,double>(source_int);
  const std::vector<std::vector<double> > result_unscaled = DoFilterOperation(source,mFilter);
  const std::vector<std::vector<double> > result_scaled = Rescale(result_unscaled,0.0,255.9);
  const std::vector<std::vector<int> > result = Convert<double,int>(result_scaled);
  VectorToImage(result,ImageTarget);
  ImageTarget->Visible = true;
  ImageTarget->Refresh();
  ButtonSaveResult->Enabled = true;
  ++PageControl->ActivePageIndex;
}
//---------------------------------------------------------------------------
#include <cassert>
#include <algorithm>
//From http://www.richelbilderbeek.nl/CppRescale.html
const double Rescale(
  const double value,
  const double oldMin,
  const double oldMax,
  const double newMin,
  const double newMax)
{
  assert(value >= oldMin);
  assert(value <= oldMax);
  const double oldDistance = oldMax - oldMin;
  //At which relative distance is value on oldMin to oldMax ?
  const double distance = (value - oldMin) / oldDistance;
  assert(distance >= 0.0);
  assert(distance <= 1.0);
  const double newDistance = newMax - newMin;
  const double newValue = newMin + (distance * newDistance);
  assert(newValue >= newMin);
  assert(newValue <= newMax);
  return newValue;
}

//---------------------------------------------------------------------------
#include <cassert>
#include <algorithm>
#include <vector>
//From http://www.richelbilderbeek.nl/CppRescale.html
const std::vector<double> Rescale(
  std::vector<double> v,
  const double newMin,
  const double newMax)
{
  const double oldMin = *std::min_element(v.begin(),v.end());
  const double oldMax = *std::max_element(v.begin(),v.end());
  typedef std::vector<double>::iterator Iter;
  Iter i = v.begin();
  const Iter j = v.end();
  for ( ; i!=j; ++i)
  {
    *i = Rescale(*i,oldMin,oldMax,newMin,newMax);
  }
  return v;
}
//---------------------------------------------------------------------------
//From http://www.richelbilderbeek.nl/CppRescale.html
const std::vector<std::vector<double> > Rescale(
  std::vector<std::vector<double> > v,
  const double newMin,
  const double newMax)
{
  const double oldMin = MinElement(v);
  const double oldMax = MaxElement(v);
  typedef std::vector<std::vector<double> >::iterator RowIter;
  RowIter y = v.begin();
  const RowIter maxy = v.end();
  for ( ; y!=maxy; ++y)
  {
    typedef std::vector<double>::iterator ColIter;
    ColIter x = y->begin();
    const ColIter maxx = y->end();
    for ( ; x!=maxx; ++x)
    {
      *x = Rescale(*x,oldMin,oldMax,newMin,newMax);
    }
  }
  return v;
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::OnAnyTrackBarChange(
      TObject *Sender)
{
  const int sz = TrackBarSize->Position;
  const double angle = 2.0 * M_PI
    * static_cast<double>(TrackBarAngle->Position)
    / static_cast<double>(TrackBarAngle->Max);
  const double wavelength = 16.0
    * static_cast<double>(TrackBarWavelength->Position)
    / static_cast<double>(TrackBarWavelength->Max);
  const double sigma = CalculateSigma(sz/2);
  LabelSize->Caption = "Size: " + IntToStr(sz) + " pixels";
  LabelAngle->Caption = "Angle: " + FloatToStr(angle) + " radians";
  LabelWavelength->Caption = "Wavelength: " + FloatToStr(wavelength) + " pixels";
  LabelSigma->Caption = "Sigma: " + FloatToStr(sigma);

  mFilter = CreateGaborFilter(sz,angle,wavelength,sigma);

  SurfacePlotter p(ImageFilter);
  p.SetSurfaceGrey(mFilter);
  ImageFilter->Refresh();


}
//---------------------------------------------------------------------------
//From http://richelbilderbeek.nl/CppToolGaborFilter.html
//Returns a y-x-ordered 2D std::vector
//f_Gabor(x)
// = cos(frequency*x)
// * exp(-(x*x)/(sigma*sigma))
const std::vector<std::vector<double> > CreateGaborFilter(
  const int sz,
  const double angle,
  const double wavelength,
  const double sigma)
{
  std::vector<std::vector<double> > v(sz,std::vector<double>(sz,0.0));
  const double midx = static_cast<double>(sz / 2);
  const double midy = static_cast<double>(sz / 2);
  const double frequency = 1.0 / wavelength;
  for (int y=0; y!=sz; ++y)
  {
    for (int x=0; x!=sz; ++x)
    {
      const double dx = midx - static_cast<double>(x);
      const double dy = midy - static_cast<double>(y);
      const double distance = std::sqrt((dx * dx) + (dy * dy));
      const double fx = std::cos(angle) * frequency;
      const double fy = std::sin(angle) * frequency;
      const double cosine = std::cos((dx * fx) + (dy * fy));
      const double gauss = std::exp( -(distance * distance) / (2.0 * sigma * sigma));
      const double z = cosine * gauss;
      v[x][y] = z;
    }
  }
  return v;
}
//---------------------------------------------------------------------------
//From http://richelbilderbeek.nl/CppToolGaborFilter.html
//Notes:
// - sz is not the total width/height of the filter, it is that
//   value halved
// - std::log takes the natural logarithm
const double CalculateSigma(const int sz)
{
  const double s = static_cast<double>(sz);
  return std::sqrt(-(s * s) / (2.0*std::log(1.0/510.0)));
}
//---------------------------------------------------------------------------
void __fastcall TFormMain::ButtonWhatsNewClick(TObject *Sender)
{
  boost::scoped_ptr<TFormWhatsNew> f(new TFormWhatsNew(0));
  f->ShowModal();
}
//---------------------------------------------------------------------------

 

 

 

 

 

UnitFormWhatsNew.h

 

//---------------------------------------------------------------------------
/*
  GaborFilter, performs Gabor filter operations on images
  Copyright (C) 2010  Richèl Bilderbeek

  This program is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  This program 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 General Public License for more details.
  You should have received a copy of the GNU General Public License
  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
//---------------------------------------------------------------------------
// From http://www.richelbilderbeek.nl
//---------------------------------------------------------------------------
#ifndef UnitFormWhatsNewH
#define UnitFormWhatsNewH
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <ComCtrls.hpp>
//---------------------------------------------------------------------------
class TFormWhatsNew : public TForm
{
__published: // IDE-managed Components
        TRichEdit *RichEdit;
private: // User declarations
public: // User declarations
        __fastcall TFormWhatsNew(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TFormWhatsNew *FormWhatsNew;
//---------------------------------------------------------------------------
#endif

 

 

 

 

 

UnitFormWhatsNew.cpp

 

//---------------------------------------------------------------------------
/*
  GaborFilter, performs Gabor filter operations on images
  Copyright (C) 2010  Richèl Bilderbeek

  This program is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  This program 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 General Public License for more details.
  You should have received a copy of the GNU General Public License
  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
//---------------------------------------------------------------------------
// From http://www.richelbilderbeek.nl
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop

#include "UnitFormWhatsNew.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TFormWhatsNew *FormWhatsNew;
//---------------------------------------------------------------------------
__fastcall TFormWhatsNew::TFormWhatsNew(TComponent* Owner)
        : TForm(Owner)
{
}
//---------------------------------------------------------------------------

 

 

 

 

 

UnitSurfacePlotter.h

 

//---------------------------------------------------------------------------
#ifndef UnitSurfacePlotterH
#define UnitSurfacePlotterH
//---------------------------------------------------------------------------
/*
  SurfacePlotter, class to plot a 2D std::vector
  Copyright (C) 2010  Richèl Bilderbeek

  This program is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  This program 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 General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
//---------------------------------------------------------------------------
// From http://www.richelbilderbeek.nl
//---------------------------------------------------------------------------
#include <vector>
#include <algorithm>
#include <cassert>

#include <Graphics.hpp> //VCL specific
#include <ExtCtrls.hpp> //VCL specific
//---------------------------------------------------------------------------
// From http://www.richelbilderbeek.nl
//---------------------------------------------------------------------------
struct SurfacePlotter
{
  SurfacePlotter(Extctrls::TImage * const image)
  : mImage(image)
  {
    assert(mImage);
    assert(mImage->Picture->Bitmap!=0);
    assert(mImage->Picture->Bitmap->PixelFormat == pf24bit);
  }
  //Sets the image of the surface plot to the values of the vector
  //The doubles can be in any range
  void SetSurfaceGrey(const std::vector<std::vector<double> >& surface)
  {
    //Get the size
    const int maxx = surface.size();
    const int maxy = surface[0].size();
    //Resize Image to the correct size
    mImage->Picture->Bitmap->Width  = maxx;
    mImage->Picture->Bitmap->Height = maxy;
    //Minimum and maximum are not given, so these need to be calculated
    double minVal = *(std::min_element(surface[0].begin(),surface[0].end()));
    double maxVal = *(std::max_element(surface[0].begin(),surface[0].end()));
    for (int x=1; x!=maxx; ++x) //1, because 0 gets know the lines above
    {
      const double localMinVal = *(std::min_element(surface[x].begin(),surface[x].end()));
      const double localMaxVal = *(std::max_element(surface[x].begin(),surface[x].end()));
      if (localMinVal < minVal) minVal = localMinVal;
      if (localMaxVal > maxVal) maxVal = localMaxVal;
    }
    if (minVal == maxVal)
    {
      //Draw black
      for (int y=0; y!=maxy; ++y)
      {
        unsigned char * const line
          = static_cast<unsigned char *>(mImage->Picture->Bitmap->ScanLine[y]);
        for (int x=0; x!=maxx; ++x)
        {
          line[x*3+0] = 0; //Blue
          line[x*3+1] = 0; //Green
          line[x*3+2] = 0; //Red
        }
      }
      return;
    }

    //Draw the pixels
    for (int y=0; y!=maxy; ++y)
    {
      unsigned char * const line
        = static_cast<unsigned char *>(mImage->Picture->Bitmap->ScanLine[y]);
      for (int x=0; x!=maxx; ++x)
      {
        assert(minVal != maxVal);
        assert(minVal < maxVal);
        const double greyValueDouble = (surface[x][y] - minVal) / (maxVal - minVal);
        assert(greyValueDouble >= 0.0 && greyValueDouble <= 1.0);
        const char greyValue = greyValueDouble * 255.0;
        line[x*3+0] = greyValue; //Blue
        line[x*3+1] = greyValue; //Green
        line[x*3+2] = greyValue; //Red
      }
    }
  }
  //Sets the image of the surface plot to the values of the vector
  //Assumes that the chars are in the range [0,255] (a char's range)
  //If the chars are in a shorter range, they will NOT be rescaled to [0,255]
  void SetSurfaceGrey(const std::vector<std::vector<char> >& surface)
  {
    const int maxx = surface.size();
    const int maxy = surface[0].size();
    mImage->Picture->Bitmap->Width = maxx;
    mImage->Picture->Bitmap->Height = maxy;

    for (int y=0; y!=maxy; ++y)
    {
      unsigned char * const line
        = static_cast<unsigned char *>(mImage->Picture->Bitmap->ScanLine[y]);
      for (int x=0; x!=maxx; ++x)
      {
        const char greyValue = surface[x][y];
        line[x*3+0] = greyValue; //Blue
        line[x*3+1] = greyValue; //Green
        line[x*3+2] = greyValue; //Red
      }
    }
  }
  private:
  Extctrls::TImage * const mImage;
};
//---------------------------------------------------------------------------
#endif

 

 

 

 

 

UnitSurfacePlotter.cpp

 

//---------------------------------------------------------------------------


#pragma hdrstop

#include "UnitSurfacePlotter.h"

//---------------------------------------------------------------------------

#pragma package(smart_init)

 

 

 

 

 

Go back to Richel Bilderbeek's C++ page.

Go back to Richel Bilderbeek's homepage.

 

Valid XHTML 1.0 Strict

This page has been created by the tool CodeToHtml