TuttleOFX
1
|
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 }