/*!
  \file
  \brief カメラ制御

  \author Satofumi KAMIMURA

  $Id: CameraDevice.cpp 1418 2009-10-15 16:26:16Z satofumi $

  http://opencv.jp のサンプルより
*/

#include "CameraDevice.h"
#include <highgui.h>
#include <cv.h>


using namespace qrk;


struct CameraDevice::pImpl
{
  CvCapture* capture_;
  int width_;
  int height_;

  IplImage* resized_;


  pImpl(void)
  : capture_(NULL), width_(320), height_(240),
    resized_(cvCreateImage(cvSize(width_, height_), IPL_DEPTH_8U, 3))
  {
  }


  ~pImpl(void)
  {
    cvReleaseImage(&resized_);
  }


  void setCaptureSize(int width, int height)
  {
    if ((! capture_) || ((width == width_) && (height == height_))) {
      return;
    }
    width_ = width;
    height_ = height;

    cvSetCaptureProperty(capture_, CV_CAP_PROP_FRAME_WIDTH, width);
    cvSetCaptureProperty(capture_, CV_CAP_PROP_FRAME_HEIGHT, height);

    cvReleaseImage(&resized_);
    resized_ = cvCreateImage(cvSize(width_, height_), IPL_DEPTH_8U, 3);
  }


  bool capture(const char* fileName)
  {
    IplImage* frame = cvQueryFrame(capture_);
    if (! frame) {
      return false;
    }

    bool ret = true;
    if ((frame->width != width_) || (frame->height != height_)) {
      // リサイズしてから保存
      cvResize(frame, resized_, CV_INTER_LINEAR);
    }

    if (! cvSaveImage(fileName, (resized_) ? resized_ : frame)) {
      ret = false;
    }
    return ret;
  }
};


CameraDevice::CameraDevice(void) : pimpl(new pImpl)
{
}


CameraDevice::~CameraDevice(void)
{
}


const char* CameraDevice::what(void) const
{
  return "Not implemented.";
}


// !!! 複数カメラに対応できるようにする
// !!! 複数オブジェクトから同一カメラに接続しないための保証を実装すべき
bool CameraDevice::connect(void)
{
  pimpl->capture_ = cvCreateCameraCapture(0);

  return (pimpl->capture_ == NULL) ? false : true;
}


void CameraDevice::disconnect(void)
{
  if (pimpl->capture_) {
    cvReleaseCapture(&pimpl->capture_);
    pimpl->capture_ = NULL;
  }
}


void CameraDevice::setCaptureSize(int width, int height)
{
  return pimpl->setCaptureSize(width, height);
}


bool CameraDevice::capture(const char* fileName)
{
  return pimpl->capture(fileName);
}
