/*!
  \file
  \brief 画像の生成

  \author Satofumi KAMIMURA

  $Id: PixelMap.cpp 1536 2009-11-19 01:21:26Z satofumi $
*/

#include "PixelMap.h"
#include "Point.h"
#include "Color.h"
#include <opencv/cv.h>
#include <opencv/highgui.h>

#include <cstdio>

using namespace qrk;
using namespace std;


struct PixelMap::pImpl
{
  IplImage* image_;
  CvSize image_size_;
  Point<long> min_;


  pImpl(const Rect<long>& rect) : min_(rect.x, rect.y)
  {
    image_size_.width = rect.w + 2;
    image_size_.height = rect.h + 2;
    fprintf(stderr, "[%d, %d]\n", image_size_.width, image_size_.height);

    image_ = cvCreateImage(image_size_, IPL_DEPTH_8U, 3);
    cvZero(image_);
  }


  void generate(void)
  {
    if (! image_) {
      return;
    }

    // !!!

    cvSaveImage("map.png", image_);
    cvReleaseImage(&image_);
  }
};


PixelMap::PixelMap(const Rect<long>& rect) : pimpl(new pImpl(rect))
{
}


PixelMap::~PixelMap(void)
{
}


void PixelMap::addPoints(const Grid& grid, const qrk::Color& color,
                         int max_score)
{
  int width_step = pimpl->image_->widthStep;

  for (Grid::const_iterator y_it = grid.begin(); y_it != grid.end(); ++y_it) {
    int y = pimpl->image_size_.height - (y_it->first - pimpl->min_.y);

    for (map<int, int>::const_iterator x_it = y_it->second.begin();
         x_it != y_it->second.end(); ++x_it) {
      int x = x_it->first - pimpl->min_.x;

      double p = min(2.0 * x_it->second / max_score, 1.0);
      unsigned char r = static_cast<unsigned char>(255.0 * p * color.r);
      unsigned char g = static_cast<unsigned char>(255.0 * p * color.g);
      unsigned char b = static_cast<unsigned char>(255.0 * p * color.b);

      pimpl->image_->imageData[width_step * y + x * 3] = b;
      pimpl->image_->imageData[width_step * y + x * 3 + 1] = g;
      pimpl->image_->imageData[width_step * y + x * 3 + 2] = r;
    }
  }
}


void PixelMap::generate(void)
{
  pimpl->generate();
}
