#include #include #include #include namespace gil = boost::gil; // define possible runtime image types typedef boost::mpl::vector< boost::gil::gray8_image_t, boost::gil::gray16_image_t, boost::gil::rgb8_image_t, boost::gil::rgb16_image_t > neuro_img_types; // generic implementation upon a view template void x_gradient(const SrcView &n_src, const DstView &n_dst) { gil::gil_function_requires >(); gil::gil_function_requires >(); gil::gil_function_requires::type, typename gil::color_space_type::type> >(); for (int y=0; y < n_src.height(); ++y) { typename SrcView::x_iterator src_it = n_src.row_begin(y); typename DstView::x_iterator dst_it = n_dst.row_begin(y); for (int x=1; x < n_src.width()-1; ++x) { for (int c=0; c < gil::num_channels::value; ++c) { dst_it[x][c] = (src_it[x-1][c]- src_it[x+1][c])/2; } } } } // Those two will generate actual code for each supported image type // so it can be processed at runtime. // See: http://www.boost.org/doc/libs/1_57_0/libs/gil/doc/html/giltutorial.html#DynamicImageSec // // Apparently this is a similar approach as a phx actor // template struct x_gradient_obj { typedef void result_type; // required typedef x_gradient_obj(const DstView &n_dst) : m_dst(n_dst) { } template void operator()(const SrcView &n_src) const { x_gradient(n_src, m_dst); } const DstView &m_dst; }; // provide an overload of x_gradient that takes image view variant // and calls GIL's apply_operation passing it the function object: template void x_gradient(const gil::any_image_view &n_src, const DstView &n_dst) { gil::apply_operation(n_src, x_gradient_obj(n_dst)); } int main(int argc, char **argv) { gil::any_image runtime_image; gil::jpeg_read_image("input.jpg", runtime_image); // target image buffer with same size as src but 8 bit gray gil::grey8s_image_t gradient(runtime_image.dimensions()); x_gradient(gil::const_view(runtime_image), gil::view(gradient)); gil::jpeg_write_view("x_gradient.jpg", gil::color_converted_view(gil::const_view(gradient))); }