GILの練習

GILの練習に、勉強中のboostをできるだけ濫用したサンプルを作ってみた。
しかし、GILの学習曲線はまるで地を這うようだ。


白い画像を生成してから、
乱数で座標を生成して点を打ちます。

#include <iostream>
#include <boost/random.hpp>
#include <boost/gil/gil_all.hpp>
#include <boost/gil/extension/io/bmp_dynamic_io.hpp>
#include <boost/timer.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/iterator/iterator_facade.hpp>

// 乱数イテレータ
template<typename Value, class Engine, class Distribution>
struct randomIterator 
: public boost::iterator_facade<randomIterator<Value, Engine, Distribution>, Value, boost::forward_traversal_tag, Value>
{
  typedef boost::variate_generator<Engine, Distribution> Generator;
  Generator *rand_;
  unsigned int counter_;

  randomIterator(const Distribution &distribution)
  : rand_(new Generator(Engine(), distribution)), counter_(0)
  {
  }

  randomIterator(const Distribution &distribution, boost::uint32_t seed)
  : rand_(new Generator(Engine(seed), distribution)), counter_(0)
  {
  }

  randomIterator(const int endCount)
  : rand_(NULL), counter_(endCount)
  {
  }

  ~randomIterator()
  {
    delete rand_;
  }

  Value dereference() const { 
    return rand_->operator()();
  }
  void increment(){ 
    ++counter_;
  }
  bool equal(const randomIterator &rhs) const 
  {
    return counter_==rhs.counter_;
  }
};

// GIL用
namespace GIL=boost::gil;

// 座標単位
typedef int unit_t;

typedef GIL::point2<unit_t> point_t;
typedef GIL::rgb8_image_t image_t;
typedef GIL::rgb8_view_t view_t;
typedef GIL::rgb8_pixel_t pixel_t;

// 点打ち
struct FPut
{
  const view_t &view_;
  const pixel_t &color_;

  FPut(const view_t &view, const pixel_t &color)
  : view_(view), color_(color)
  {}

  void operator()(const unit_t value)
  {
    view_[value]=color_;
  }
};

void test_1(const char *fileName, unsigned int imageSize, unsigned int pointCount)
{
  std::cerr << fileName << '(' << imageSize << 'x' << imageSize << ") " << pointCount << " random points." << std::endl;

  // create image
  image_t img(imageSize, imageSize);
  // fill white
  GIL::fill_pixels(GIL::view(img), pixel_t(255, 255, 255));

  // random engine
  typedef boost::mt19937 Engine;
  //typedef boost::rand48 Engine;
  //typedef boost::ecuyer1988 Engine;
  //typedef boost::kreutzer1986 Engine;
  //typedef boost::hellekalek1995 Engine;
  //typedef boost::lagged_fibonacci607 Engine;

  // distribution 
  typedef boost::uniform_int<unit_t> Distribution;
  Distribution dist(static_cast<unit_t>(0), static_cast<unit_t>(imageSize*imageSize-1));
  //typedef boost::binomial_distribution<unit_t> Distribution;
  //Distribution dist(static_cast<unit_t>(imageSize-1));

  // put random points
  typedef randomIterator<unit_t, Engine, Distribution >MersenneIterator;
  std::for_each(
      MersenneIterator(dist), 
      MersenneIterator(pointCount),
      FPut(GIL::view(img), pixel_t(0,0,0)));
  // write bitmap
  GIL::bmp_write_view(fileName, GIL::view(img));
}

int main(int argc, char **argv)
{
  if(argc<4){
    std::cerr << "usage: " << argv[0] << " {write bitmap} {btimap size} {point number}" << std::endl;
    return 1;
  }

  boost::timer t;
  test_1(argv[1], 
    boost::lexical_cast<unsigned int>(argv[2]), 
    boost::lexical_cast<unsigned int>(argv[3]));
  std::cerr << t.elapsed() << " sec." << std::endl;
  return 0;
}
>release\sample.exe tmp2.bmp 200 10000
tmp2.bmp(200x200) 1000000 random points.
0.265 sec.