TuttleOFX
1
|
00001 #ifndef _TERRY_MATH_HPP_ 00002 #define _TERRY_MATH_HPP_ 00003 00004 #include "basic_colors.hpp" 00005 00006 namespace terry { 00007 00008 /** 00009 * @brief Compute min & max value from a view 00010 * 00011 * @param[in] view Source view 00012 * @param[out] max maximum image value 00013 * @param[out] min minimum image value 00014 * 00015 */ 00016 template <typename View, typename T> 00017 void maxmin( const View& view, T& max, T& min ) 00018 { 00019 using namespace boost::gil; 00020 typedef typename View::x_iterator iterator; 00021 typedef typename channel_type<View>::type dPix_t; 00022 const int nc = view.num_channels(); 00023 int w = view.width(); 00024 int h = view.height(); 00025 max = min = view( 0, 0 )[0]; 00026 for( int y = 0; y < h; ++y ) 00027 { 00028 iterator view_it = view.row_begin( y ); 00029 for( int x = 0; x < w; ++x ) 00030 { 00031 for( int c = 0; c < nc; c++ ) 00032 { 00033 const dPix_t val = ( *view_it )[c]; 00034 if( val > max ) 00035 { 00036 max = val; 00037 } 00038 else if( val < min ) 00039 { 00040 min = val; 00041 } 00042 } 00043 ++view_it; 00044 } 00045 } 00046 } 00047 00048 /** 00049 * @brief Normalize a view (using contrast streching) 00050 * 00051 * @param[in, out] dst Source and destination view 00052 * @param[in] a lower limit 00053 * @param[in] b upper limit 00054 * @return Return the normalized image 00055 */ 00056 template <class S_VIEW, class D_VIEW, typename T> 00057 D_VIEW& normalize( const S_VIEW& src, D_VIEW& dst, const T a, const T b ) 00058 { 00059 using namespace boost::gil; 00060 typedef typename S_VIEW::x_iterator sIterator; 00061 typedef typename D_VIEW::x_iterator dIterator; 00062 typedef typename channel_type<D_VIEW>::type dPix_t; 00063 dPix_t m, M; 00064 maxmin( dst, M, m ); 00065 const float fm = m, fM = M; 00066 int w = dst.width(); 00067 int h = dst.height(); 00068 00069 if( m == M ) 00070 { 00071 fill_black( dst ); 00072 } 00073 else if( m != a || M != b ) 00074 { 00075 int nc = dst.num_channels(); 00076 for( int y = 0; y < h; ++y ) 00077 { 00078 sIterator src_it = src.row_begin( y ); 00079 dIterator dst_it = dst.row_begin( y ); 00080 for( int x = 0; x < w; ++x ) 00081 { 00082 for( int c = 0; c < nc; c++ ) 00083 { 00084 ( *dst_it )[c] = (dPix_t)( ( ( *src_it )[c] - fm ) / ( fM - fm ) * ( b - a ) + a ); 00085 } 00086 ++dst_it; 00087 ++src_it; 00088 } 00089 } 00090 } 00091 return dst; 00092 } 00093 00094 template <class S_VIEW, class D_VIEW, typename T> 00095 D_VIEW& multiply( const S_VIEW& src, D_VIEW& dst, const T factor ) 00096 { 00097 using namespace boost::gil; 00098 typedef typename S_VIEW::x_iterator sIterator; 00099 typedef typename D_VIEW::x_iterator dIterator; 00100 typedef typename channel_type<D_VIEW>::type dPix_t; 00101 00102 const int nc = src.num_channels(); 00103 const int w = src.width(); 00104 const int h = src.height(); 00105 int x, y, c; 00106 for( y = 0; y < h; y++ ) 00107 { 00108 sIterator src_it = src.row_begin( y ); 00109 dIterator dst_it = dst.row_begin( y ); 00110 for( x = 0; x < w; x++ ) 00111 { 00112 for( c = 0; c < nc; c++ ) 00113 { 00114 ( *dst_it )[c] = (dPix_t)( ( *src_it )[c] * factor ); 00115 } 00116 ++src_it; 00117 ++dst_it; 00118 } 00119 } 00120 return dst; 00121 } 00122 00123 } 00124 00125 #endif 00126