TuttleOFX  1
test.cpp
Go to the documentation of this file.
00001 // test.cpp : Defines the entry point for the console application.
00002 //
00003 
00004 #include "stdafx.h"
00005 
00006 #include <boost/gil/extension/io/bmp_io.hpp>
00007 
00008 #include <boost/gil/extension/opencv/convert.hpp>
00009 
00010 using namespace std;
00011 using namespace boost;
00012 using namespace gil;
00013 using namespace opencv;
00014 
00015 // Models a Unary Function
00016 template <typename P>   // Models PixelValueConcept
00017 struct mandelbrot_fn {
00018     typedef point2<ptrdiff_t>    point_t;
00019 
00020     typedef mandelbrot_fn        const_t;
00021     typedef P                    value_type;
00022     typedef value_type           reference;
00023     typedef value_type           const_reference;
00024     typedef point_t              argument_type;
00025     typedef reference            result_type;
00026     BOOST_STATIC_CONSTANT(bool, is_mutable=false);
00027 
00028     value_type                    _in_color,_out_color;
00029     point_t                       _img_size;
00030     static const int MAX_ITER=1000;        // max number of iterations
00031 
00032     mandelbrot_fn() {}
00033     mandelbrot_fn(const point_t& sz, const value_type& in_color, const value_type& out_color) : _in_color(in_color), _out_color(out_color), _img_size(sz) {}
00034 
00035     result_type operator()(const point_t& p) const {
00036         // normalize the coords to (-2..1, -1.5..1.5)
00037         // (actually make y -1.0..2 so it is asymmetric, so we can verify some view factory methods)
00038         double t=get_num_iter(point2<double>(p.x/(double)_img_size.x*3-2, p.y/(double)_img_size.y*3-1.0f));//1.5f));
00039         t=pow(t,0.2);
00040 
00041         value_type ret;
00042         for (int k=0; k<num_channels<P>::value; ++k)
00043             ret[k]=(typename channel_type<P>::type)(_in_color[k]*t + _out_color[k]*(1-t));
00044         return ret;
00045     }
00046 
00047 private:
00048     double get_num_iter(const point2<double>& p) const {
00049         point2<double> Z(0,0);
00050         for (int i=0; i<MAX_ITER; ++i) {
00051             Z = point2<double>(Z.x*Z.x - Z.y*Z.y + p.x, 2*Z.x*Z.y + p.y);
00052             if (Z.x*Z.x + Z.y*Z.y > 4)
00053                 return i/(double)MAX_ITER;
00054         }
00055         return 0;
00056     }
00057 };
00058 
00059 struct set_to_max
00060 {
00061    template <typename CHANNEL > void operator()(CHANNEL& c) const
00062    {
00063       c = channel_traits< CHANNEL >::max_value();
00064    }
00065 };
00066 
00067 struct set_to_min
00068 {
00069    template <typename CHANNEL > void operator()(CHANNEL& c) const
00070    {
00071       c = channel_traits< CHANNEL >::min_value();
00072    }
00073 };
00074 
00075 
00076 template< class PIXEL
00077         , class VIEW >
00078 inline
00079 PIXEL min_channel_values( const VIEW& view )
00080 {
00081    PIXEL min;
00082 
00083    // initialize the min pixel with the max values
00084    static_for_each( min, set_to_max() );
00085 
00086    for( int y=0; y < view.height(); ++y )
00087    {
00088       VIEW::x_iterator x_it = view.row_begin( y );
00089 
00090       for( int x = 0; x < view.width(); ++x )
00091       {
00092          typename PIXEL::const_reference p = x_it[x];
00093 
00094          for( int i = 0; i < num_channels<PIXEL>::type::value; ++i )
00095          {
00096             if( dynamic_at_c( p, i ) < dynamic_at_c( min, i )) /// @todo: use ( p[i] < min[i] ), more readable...
00097             {
00098                dynamic_at_c( min, i ) = dynamic_at_c( p, i );
00099             }
00100          }
00101       }
00102    }
00103 
00104    return min;
00105 }
00106 
00107 template <typename T>
00108 struct add_vector
00109 {
00110    typedef std::vector<T> type;
00111 };
00112 
00113 template< class PIXEL
00114         , class VIEW >
00115 inline
00116 PIXEL min_channel_values_( const VIEW&  view
00117                         , const size_t percent = 1 )
00118 {
00119    typedef mpl::transform1< color_space_type<VIEW>::type, add_vector<mpl::_1> >::type channels_t;
00120 
00121    typedef kth_semantic_element_type< PIXEL, 0 >::type channel_t; //channel_0 = semantic_at_c<0>( PIXEL() );
00122    channel_t max = channel_traits<channel_t>::max_value();
00123 
00124    return PIXEL();
00125 }
00126 
00127 
00128 template< class PIXEL
00129         , class VIEW >
00130 inline
00131 PIXEL max_channel_values( const VIEW& view )
00132 {
00133    PIXEL max;
00134 
00135    // initialize the max pixel with the min values
00136    static_for_each( max, set_to_min() );
00137 
00138    // find the max values
00139    for( VIEW::iterator it = view.begin()
00140       ; it != view.end()
00141       ; ++it )
00142    {
00143       for( int i = 0; i < num_channels<PIXEL>::type::value; ++i )
00144       {
00145          if( dynamic_at_c( *it, i ) > dynamic_at_c( max, i ))
00146          {
00147             dynamic_at_c( max, i ) = dynamic_at_c( *it, i );
00148          }
00149       }
00150    }
00151 
00152    return max;
00153 }
00154 
00155 template< class PIXEL
00156         , class VIEW >
00157 inline
00158 boost::fusion::vector<PIXEL, PIXEL>
00159 minmax_channel_values( const VIEW& view )
00160 {
00161    PIXEL min, max;
00162 
00163    static_for_each( min, set_to_max() );
00164    static_for_each( max, set_to_min() );
00165 
00166    // find the max values
00167    for( VIEW::iterator it = view.begin()
00168       ; it != view.end()
00169       ; ++it )
00170    {
00171       for( int i = 0; i < num_channels<PIXEL>::type::value; ++i )
00172       {
00173          if( dynamic_at_c( *it, i ) < dynamic_at_c( min, i ))
00174          {
00175             dynamic_at_c( min, i ) = dynamic_at_c( *it, i );
00176          }
00177 
00178          if( dynamic_at_c( *it, i ) > dynamic_at_c( max, i ))
00179          {
00180             dynamic_at_c( max, i ) = dynamic_at_c( *it, i );
00181          }
00182       }
00183    }
00184 
00185    return boost::fusion::vector<PIXEL, PIXEL>( min, max );
00186 }
00187 
00188 struct calc_diff
00189 {
00190    template <typename CHANNEL > void operator()( CHANNEL&       diff
00191                                                , const CHANNEL& min
00192                                                , const CHANNEL& max ) const
00193    {
00194       diff = max - min;
00195    }
00196 };
00197 
00198 typedef channel_type<rgb16_pixel_t>::type channel_t;
00199 
00200 template< class SRC
00201         , class DST
00202         >
00203 void down_sample( const SRC& src_view
00204                 , const DST& dst_view  )
00205 {
00206    assert( src_view.dimensions() == dst_view.dimensions() );
00207 
00208    // @todo Take care of signed images. Bransform them into unsigned images
00209    // by adding half the value range to the channels.
00210 
00211    typedef SRC::value_type src_pixel_t;
00212    typedef DST::value_type dst_pixel_t;
00213    typedef channel_type<dst_pixel_t>::type dst_channel_t;
00214 
00215    boost::fusion::vector<src_pixel_t,src_pixel_t> minmax = minmax_channel_values<src_pixel_t>( src_view );
00216 
00217    const src_pixel_t& min = at_c<0>( minmax );
00218    const src_pixel_t& max = at_c<1>( minmax );
00219 
00220    // calculate the diff
00221    src_pixel_t diff;
00222    static_for_each( diff, min, max, calc_diff() );
00223 
00224 
00225    // sample down
00226    dst_channel_t dst_max = channel_traits< dst_channel_t >::max_value();
00227 
00228    for( int y=0; y < src_view.height(); ++y )
00229    {
00230       SRC::x_iterator src_it = src_view.row_begin( y );
00231       DST::x_iterator dst_it = dst_view.row_begin( y );
00232 
00233       for( int x = 0; x < src_view.width(); ++x )
00234       {
00235          typename src_pixel_t::const_reference src = src_it[x];
00236          typename dst_pixel_t::reference       dst = dst_it[x];
00237 
00238          for( int i = 0; i < num_channels<src_pixel_t>::type::value; ++i )
00239          {
00240             if( dynamic_at_c( diff, i ) == 0 )
00241             {
00242                dynamic_at_c( dst, i ) = 0;
00243             }
00244             else
00245             {
00246                dynamic_at_c( dst, i ) = static_cast<dst_channel_t>( dst_max * ( static_cast<float>( dynamic_at_c( src, i ) 
00247                                                                                                   - dynamic_at_c( min, i )) 
00248                                                                               / static_cast<float>( dynamic_at_c( diff, i ))));
00249             } // else
00250 
00251          } //for
00252 
00253       } //for
00254 
00255    } // for
00256 }
00257 
00258 // channel_wise calculation.
00259 
00260 // @todo need better name
00261 template< typename DST_MAX >
00262 struct foo
00263 {
00264    foo( const DST_MAX& dst_max )
00265    : _dst_max( dst_max ){}
00266 
00267    template < typename DST_CHANNEL
00268             , typename SRC_CHANNEL >
00269    void operator()( DST_CHANNEL&  dst
00270                   , SRC_CHANNEL&  src
00271                   , SRC_CHANNEL&  min
00272                   , SRC_CHANNEL&  diff )
00273    const
00274    {
00275       if( diff == 0 )
00276       {
00277          dst = 0;
00278 
00279          return;
00280       }
00281 
00282       float d = ( static_cast<float>( _dst_max )
00283                 * ( ( static_cast<float>( src ) - static_cast<float>( min ))
00284                   / static_cast<float>( diff )));
00285 
00286       dst_channel = static_cast<DST_CHANNEL>( dst );
00287    }
00288 
00289    DST_MAX _dst_max;
00290 };
00291 
00292 // pixel_wise calculation.
00293 
00294 // @todo need better name
00295 template< typename SRC_VIEW
00296         , typename SRC_PIXEL
00297         , typename DST_VIEW
00298         , typename DST_MAX
00299         >
00300 struct do_it
00301 {
00302    do_it( const DST_VIEW&  dst_view
00303         , const DST_MAX&   dst_max
00304         , const SRC_PIXEL& min
00305         , const SRC_PIXEL& diff      )
00306    : _dst_view( dst_view )
00307    , _min( min )
00308    , _diff( diff )
00309    , _op( dst_max )
00310    {
00311       _dst_it = dst_view.begin();
00312    }
00313 
00314    void operator()( SRC_PIXEL& src ) 
00315    {
00316       static_for_each( *_dst_it
00317                      , src
00318                      , _min
00319                      , _diff
00320                      , _op    );
00321       ++_dst_it;
00322    }
00323 
00324    typename DST_VIEW::iterator _dst_it;
00325 
00326    foo<DST_MAX> _op;
00327 
00328    DST_VIEW _dst_view;
00329 
00330    SRC_PIXEL _min;
00331    SRC_PIXEL _diff;
00332 };
00333 
00334 int main(int argc, char* argv[])
00335 {
00336    {
00337       rgb8_image_t dst( 10, 10 );
00338 
00339       min_channel_values<rgb8_image_t::value_type>( view( dst ));
00340    }
00341 
00342    {
00343 /*
00344       bits8 max = 255;
00345       rgb16_pixel_t min;
00346       rgb16_pixel_t diff;
00347 
00348 
00349       rgb16_image_t src( 640, 480 );
00350       rgb8_image_t dst( 640, 480 );
00351 
00352 
00353       do_it< rgb16_view_t
00354            , rgb16_pixel_t
00355            , rgb8_view_t
00356            , bits8
00357            > d( view( dst ), max, min, diff );
00358 
00359       for_each_pixel( view( src ), d );
00360 
00361       bmp_write_view( ".\\red.bmp", view( dst ));
00362 */
00363    }
00364 
00365    {
00366       typedef rgb16_image_t src_image_t;
00367       typedef src_image_t::view_t src_view_t;
00368       typedef src_view_t::value_type src_pixel_t;
00369       typedef channel_type<src_pixel_t>::type src_channel_t;
00370       src_channel_t max_value = channel_traits<src_channel_t>::max_value();
00371       
00372 
00373       typedef mandelbrot_fn<src_pixel_t> deref_t;
00374       typedef deref_t::point_t           point_t;
00375 
00376       typedef virtual_2d_locator<deref_t,false> locator_t;
00377       typedef image_view<locator_t> my_virt_view_t;
00378 
00379       function_requires<PixelLocatorConcept<locator_t> >();
00380       gil_function_requires<StepIteratorConcept<locator_t::x_iterator> >();
00381 
00382       point_t dims( 640, 480 );
00383       my_virt_view_t mandel( dims
00384                            , locator_t( point_t( 0, 0 )
00385                            , point_t( 1 , 1)
00386                            , deref_t( dims
00387                                     , src_pixel_t( max_value,         0, 0 )
00388                                     , src_pixel_t(         0, max_value, 0 ))));
00389 
00390 
00391       src_image_t img( dims );
00392       copy_pixels( mandel, view( img ));
00393 
00394       // @todo How to compute the unsigned xxx8_image_t from src_image_t?
00395       rgb8_image_t eight_bit_img( dims );
00396 
00397       down_sample( view( img )
00398                  , view( eight_bit_img ));
00399 
00400       bmp_write_view( ".\\mandelbrot.bmp", view( eight_bit_img ));
00401    }
00402 
00403         return 0;
00404 }