libs/gil/example/resize.cpp というのを見つけて、これはもしや?と思ったが、boost/gil/extension/numeric/* が、ごっそりと抜け落ちていてコンパイルできない…。どこにあるんだべーと探したら、GIL本家のダウンロードページにあった(現在、ここからサルベージするしかない)。
さっそく bicubic が落ちていないか探したが、bilinear までしか実装されていないようだ。チャレンジしようと思ったが、gil をよく知らないので苦労した。チュートリアルの日本語訳があって、非常に助かりました。
という訳で、csampler.hpp です。
/*************************************************************************************************/ #ifndef GIL_CSAMPLER_HPP #define GIL_CSAMPLER_HPP #include "../../extension/dynamic_image/dynamic_image_all.hpp" #include "pixel_numeric_operations.hpp" #include "sampler.hpp" namespace boost { namespace gil { struct truncate_channel_fn { template <typename SrcChannel, typename DstChannel> void operator()(const SrcChannel& src, DstChannel& dst) { typedef typename channel_traits<DstChannel>::value_type dst_value_t; if(std::numeric_limits<dst_value_t>::max() <= src) dst = std::numeric_limits<dst_value_t>::max(); else if( src < 0 ) dst = dst_value_t(); else dst = dst_value_t(src); } }; template <typename SrcPixel, typename DstPixel> void truncate_pixel(const SrcPixel& src, DstPixel& dst) { static_for_each(src,dst,truncate_channel_fn()); } /// \brief A sampler that sets the destination pixel as the bicubic interpolation of the four closest pixels from the source. /// If outside the bounds, it doesn't change the destination /// \ingroup ImageAlgorithms struct bicubic_sampler {}; template <typename DstP, typename SrcView, typename F> bool sample(bicubic_sampler, const SrcView& src, const point2<F>& p, DstP& result) { typedef typename SrcView::value_type SrcP; point2<int> p0(ifloor(p)); // the closest integer coordinate top left from p if (p0.x < 0 || p0.y < 0 || p0.x>=src.width() || p0.y>=src.height()) return false; pixel<F,devicen_layout_t<num_channels<SrcView>::value> > mp(0); // suboptimal typename SrcView::xy_locator loc=src.xy_at(p0.x,p0.y); for( int y = -1; y < 3; ++y ) { for( int x = -1; x < 3; ++x ) { point2<F> frac(std::abs(p.x-static_cast<F>(p0.x+x)),std::abs(p.y-static_cast<F>(p0.y+y))); F wx, wy; if( frac.x < static_cast<F>(1) ) wx = (frac.x - 1) * (frac.x * frac.x - frac.x - 1); else wx = (1 - frac.x) * (frac.x - 2) * (frac.x - 2); if( frac.y < static_cast<F>(1) ) wy = (frac.y - 1) * (frac.y * frac.y - frac.y - 1); else wy = (1 - frac.y) * (frac.y - 2) * (frac.y - 2); int offx = ( p0.x+x < 0 || p0.x+x>=src.width() ) ? 0 : x; int offy = ( p0.y+y < 0 || p0.y+y>=src.height() ) ? 0 : y; detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()( loc(offx,offy), wx * wy, mp ); } } // Convert from floating point average value to the source type SrcP src_result; truncate_pixel(mp,src_result); color_convert(src_result, result); return true; } } } // namespace boost::gil #endif
お試しコードは、resize.cpp をちょいと改造するだけ。せっかくの bicubic なので拡大してみました。
#include <boost/gil/image.hpp> #include <boost/gil/typedefs.hpp> #include <boost/gil/extension/io/jpeg_io.hpp> #include <boost/gil/extension/numeric/sampler.hpp> #include <boost/gil/extension/numeric/csampler.hpp> #include <boost/gil/extension/numeric/resample.hpp> int main() { using namespace boost::gil; rgb8_image_t img; jpeg_read_image("test.jpg",img); // test resize_view // Scale the image to 100x100 pixels using bilinear resampling rgb8_image_t square100x100(600,600); resize_view(const_view(img), view(square100x100), bicubic_sampler()); jpeg_write_view("out-resize.jpg",const_view(square100x100)); return 0; }
0 件のコメント:
コメントを投稿