Functional Desire

While processing some images, I realized how often I was repeating many of the same things for every operation. There were several lines required to loop through the image and ignore the background pixels. I couldn’t help but ask myself why am I duplicating this code? I’m staring at the only relevant lines of code (sometimes only 1 or two lines) wrapped by these loops and guards.

Allow me to start with an extremely contrived example:


    const unsigned int THRES = 120;
    const int wd = image->GetWidth();
    const int ht = image->GetHeight();
    for(int x=0; x < wd;++x){
        for(y = 0; y < ht; ++y){
            COLORREF px = image->GetPixel(x,y);
            if(! IS_BACKGROUND(px) ){
                     //process the pixel ( distinct section)
            }
         }
     }

Obviously, I am not offended by seven lines for the loop. Since most of my methods are tied into event handlers from the GUI, in order to avoid multiple passes over the image, many of the same operations are tied into that loop. This example should suffice to make my point.

Say that I want to simply convert all white pixels (considered background) to red. I could define the loop structure a method which takes and executes a functor. This method is named iterate_Image below. I created a simple iterator method for the CImage class (in poor form since I’m not really using the CImage class in my project).


#include <algorithm>
#include <functional>

namespace ImProc
{
  template<class Function>
  Function iterate_Image(CImageIterator* first, CImageIterator* last, Function f)
  {
	  while ( *first != *last){
		  f(first,first->GetPixel());
		  (*first)++;
	  }
    return f;
  }
}

/*--Process Pixel method--*/
void procPixel(CImageIterator* cit, COLORREF px){
    if(IS_WHITE(px)/*simple macro*/){
        cit->SetPixel(0x0000ff);
    }
}

/*--quick testing method--*/
void CImageViewerView::OnDraw(CDC* pDC)
{
	using namespace std::tr1;

	CImageViewerDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc || (pDoc->GetPathName() == ""))return;

	shared_ptr<CImage> img = pDoc->GetImage();  /*testing in OnDraw method, but..ya, don't do that*/
	CImageIterator* it= new CImageIterator(img);
	function<void(CImageIterator*,COLORREF)> fct = procPixel; //store in function wrapper (from tr1)
	ImProc::iterate_Image(it,it->end(),fct /*or simply &procPixel*/);

	img->Draw(pDC->m_hDC,0,0);
	delete it;
}

Thats tolerable, but being forced to jump to the definition of procPixel is not particularly desirable. I wanted to write it as lambda expression. I naturally pulled the lambda’s out of the boost/tr1 library implementation. Syntactically, it wasn’t exactly what I wanted, but worked easily for simple things. I had just enough exposure to FC++ [ http://www.cc.gatech.edu/~yannis/fc++/boostpaper/fcpp.html ] to know that it existed. Anyway, I encourage you to read comparisons from other sources. The C++0x implementation looks much more promising…

Let me show you the updated OnDraw method using lambdas from FC++.


void CImageViewerView::OnDraw(CDC* pDC)
{
    using namespace boost::fcpp;
    using namespace std::tr1;

    CImageViewerDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);
    if (!pDoc || (pDoc->GetPathName() == ""))
        return;

    shared_ptr<CImage> img = pDoc->GetImage();  /*testing in OnDraw method, but..ya, don't do that*/
    CImageIterator* it= new CImageIterator(img);

    lambda_var<1> IT;
    lambda_var<2> PX;

    ImProc::iterate_Image(it,it->end(),
        lambda(IT,PX)[
            IT %ptr_to_fun(&CImageIterator::SetPixel)%
                if0[
                    PX %equal% ((COLORREF)0x000000),
                    0x0000ff,    //true
                    PX    //false
                ]
        ]
    );

    img->Draw(pDC->m_hDC,0,0);
    delete it;
}

You’ll notice that I had to got rid of my macro call to show a typical comparison. The one thing I noticed, is that in some cases you have to be extremely careful with the types. Failing to do so might lead to some cryptic compiler errors. I am using the infix notation to improve the flow of the embedded lambda syntax. Imagine the boolean expression was written as equal[ PX ][ (COLORREF)0x000000 ]. Similarly, the SetPixel method used is defined as follows (as you’d imagine).


void SetPixel(COLORREF)const;

As we all got exposure to from extension methods (.net dudes anyway =P), all this class junk just implies the object variable as the first argument to the method. So imagine instead that the definition were more like the following.


void SetPixel(CImageIterator*,COLORREF) const;

In case you didn’t before, you can see how the call to the member function works. That infix syntax also helps the call look more familiar. If we extend this out we can get another argument with currying. Unfortunately, it seems to only support 3 arguments, hence the need for an iterator class. <tangent>Of course, in the case of the CImage class, I only really need the void* of the pixel, and it would be more performant..blah blah. </tangent>

Now back to the original point. If you’re wondering why you would want to learn a load of syntax, heres my unqualified rational. If we had a function that handles converting these white pixels to red, called ConvertWhiteToRed (clever?), and wanted to reuse all that loop logic, the benefits are a bit more apparent. First, you are reusing code, which is always a plus (please continue to picture more filters and things going on in than in my loop examples). Second, we get rid of the indirection we would have just passing a functor. The code inside ConvertWhiteToRed actually converts the white pixels to red! Third, the syntax enabled by FC++ makes reading this code fairly reasonable. In my example, I laid out the conditional statement into a block so you can see how embedding lambdas might read for more in depth operations. There is also support for monads in the library.

Ya, so all that was a fun but unnecessary divergence from my project. If you want to play with lambdas etc within imperative languages, C# provides a more natural feel (since its built in?..maybe…hint,hint =P). I realize this was a simple example, and created quickly…so if you find mistakes please kindly correct them. Next up, working with contracts (Eiffel anyone?). I just watched a video on spec# and it seems like it would be worth my time to look at for a bit. Check it out at Channel9 (along with all the other awesome videos there) http://beta.channel9.msdn.com/shows/Going+Deep/Expert-to-Expert-Contract-Oriented-Programming-and-Spec/ . Then back to the project at some point.

Leave a Comment