shun-iwasawa 13c4cf
#pragma once
shun-iwasawa 13c4cf
shun-iwasawa 13c4cf
/*--------------------------------
shun-iwasawa 13c4cf
Iwa_TangentFlowFx
shun-iwasawa 13c4cf
Computing a smooth, feature-preserving local edge flow (edge tangent flow, ETF)
shun-iwasawa 13c4cf
Implementation of "Coherent Line Drawing" by H.Kang et al, Proc. NPAR 2007.
shun-iwasawa 13c4cf
----------------------------------*/
shun-iwasawa 13c4cf
shun-iwasawa 13c4cf
#ifndef IWA_TANGENT_FLOW_FX_H
shun-iwasawa 13c4cf
#define IWA_TANGENT_FLOW_FX_H
shun-iwasawa 13c4cf
shun-iwasawa 13c4cf
#include "stdfx.h"
shun-iwasawa 13c4cf
#include "tfxparam.h"
shun-iwasawa 13c4cf
shun-iwasawa 13c4cf
#include <qthread></qthread>
shun-iwasawa 13c4cf
shun-iwasawa 13c4cf
struct double2 {
shun-iwasawa 13c4cf
  double x, y;
shun-iwasawa 13c4cf
  double2(double _x = 0., double _y = 0.) {
shun-iwasawa 13c4cf
    x = _x;
shun-iwasawa 13c4cf
    y = _y;
shun-iwasawa 13c4cf
  }
shun-iwasawa 13c4cf
};
shun-iwasawa 13c4cf
struct int2 {
shun-iwasawa 13c4cf
  int x, y;
shun-iwasawa 13c4cf
shun-iwasawa 13c4cf
  int2 operator+(const int2& other) const {
shun-iwasawa 13c4cf
    return int2{x + other.x, y + other.y};
shun-iwasawa 13c4cf
  }
shun-iwasawa 13c4cf
  int2 operator-(const int2& other) const {
shun-iwasawa 13c4cf
    return int2{x - other.x, y - other.y};
shun-iwasawa 13c4cf
  }
shun-iwasawa 13c4cf
  int len2() const { return x * x + y * y; }
shun-iwasawa 13c4cf
  int2(int _x = 0, int _y = 0) {
shun-iwasawa 13c4cf
    x = _x;
shun-iwasawa 13c4cf
    y = _y;
shun-iwasawa 13c4cf
  }
shun-iwasawa 13c4cf
};
shun-iwasawa 13c4cf
shun-iwasawa 13c4cf
class SobelFilterWorker : public QThread {
shun-iwasawa 13c4cf
  double* m_source_buf;
shun-iwasawa 13c4cf
  double2* m_flow_buf;
shun-iwasawa 13c4cf
  double* m_grad_mag_buf;
shun-iwasawa 13c4cf
  int2* m_offset_buf;
shun-iwasawa 13c4cf
  double m_mag_threshold;
shun-iwasawa 13c4cf
  TDimension m_dim;
shun-iwasawa 13c4cf
  int m_yFrom, m_yTo;
shun-iwasawa 13c4cf
shun-iwasawa 13c4cf
  bool m_hasEmptyVector = false;
shun-iwasawa 13c4cf
shun-iwasawa 13c4cf
public:
shun-iwasawa 13c4cf
  SobelFilterWorker(double* source_buf, double2* flow_buf, double* grad_mag_buf,
shun-iwasawa 13c4cf
                    int2* offset_buf, double mag_threshold, TDimension dim,
shun-iwasawa 13c4cf
                    int yFrom, int yTo)
shun-iwasawa 13c4cf
      : m_source_buf(source_buf)
shun-iwasawa 13c4cf
      , m_flow_buf(flow_buf)
shun-iwasawa 13c4cf
      , m_grad_mag_buf(grad_mag_buf)
shun-iwasawa 13c4cf
      , m_offset_buf(offset_buf)
shun-iwasawa 13c4cf
      , m_mag_threshold(mag_threshold)
shun-iwasawa 13c4cf
      , m_dim(dim)
shun-iwasawa 13c4cf
      , m_yFrom(yFrom)
shun-iwasawa 13c4cf
      , m_yTo(yTo) {}
shun-iwasawa 13c4cf
shun-iwasawa 13c4cf
  void run();
shun-iwasawa 13c4cf
shun-iwasawa 13c4cf
  bool hasEmptyVector() { return m_hasEmptyVector; }
shun-iwasawa 13c4cf
};
shun-iwasawa 13c4cf
shun-iwasawa 13c4cf
class TangentFlowWorker : public QThread {
shun-iwasawa 13c4cf
  double2* m_flow_cur_buf;
shun-iwasawa 13c4cf
  double2* m_flow_new_buf;
shun-iwasawa 13c4cf
  double* m_grad_mag_buf;
shun-iwasawa 13c4cf
  TDimension m_dim;
shun-iwasawa 13c4cf
  int m_kernelRadius;
shun-iwasawa 13c4cf
  int m_yFrom, m_yTo;
shun-iwasawa 13c4cf
shun-iwasawa 13c4cf
public:
shun-iwasawa 13c4cf
  TangentFlowWorker(double2* flow_cur_buf, double2* flow_new_buf,
shun-iwasawa 13c4cf
                    double* grad_mag_buf, TDimension dim, int kernelRadius,
shun-iwasawa 13c4cf
                    int yFrom, int yTo)
shun-iwasawa 13c4cf
      : m_flow_cur_buf(flow_cur_buf)
shun-iwasawa 13c4cf
      , m_flow_new_buf(flow_new_buf)
shun-iwasawa 13c4cf
      , m_grad_mag_buf(grad_mag_buf)
shun-iwasawa 13c4cf
      , m_dim(dim)
shun-iwasawa 13c4cf
      , m_kernelRadius(kernelRadius)
shun-iwasawa 13c4cf
      , m_yFrom(yFrom)
shun-iwasawa 13c4cf
      , m_yTo(yTo) {}
shun-iwasawa 13c4cf
shun-iwasawa 13c4cf
  void run();
shun-iwasawa 13c4cf
};
shun-iwasawa 13c4cf
shun-iwasawa 13c4cf
class Iwa_TangentFlowFx final : public TStandardRasterFx {
shun-iwasawa 13c4cf
  FX_PLUGIN_DECLARATION(Iwa_TangentFlowFx)
shun-iwasawa 13c4cf
shun-iwasawa 13c4cf
protected:
shun-iwasawa 13c4cf
  TRasterFxPort m_source;
shun-iwasawa 13c4cf
shun-iwasawa 13c4cf
  TIntParamP m_iteration;
shun-iwasawa 13c4cf
  TDoubleParamP m_kernelRadius;
shun-iwasawa 13c4cf
shun-iwasawa 13c4cf
  TDoubleParamP m_threshold;
shun-iwasawa 13c4cf
shun-iwasawa 13c4cf
  TBoolParamP m_alignDirection;
shun-iwasawa 13c4cf
  TDoubleParamP m_pivotAngle;
shun-iwasawa 13c4cf
shun-iwasawa 13c4cf
  // obtain source tile brightness, normalizing 0 to 1
shun-iwasawa 13c4cf
  template <typename pixel="" raster,="" typename=""></typename>
shun-iwasawa 13c4cf
  void setSourceTileToBuffer(const RASTER srcRas, double* buf);
shun-iwasawa 13c4cf
shun-iwasawa 13c4cf
  // render vector field in red & green channels
shun-iwasawa 13c4cf
  template <typename pixel="" raster,="" typename=""></typename>
shun-iwasawa 13c4cf
  void setOutputRaster(double2* buf, double* grad_buf, const RASTER dstRas);
shun-iwasawa 13c4cf
shun-iwasawa 13c4cf
  // compute the initial vector field.
shun-iwasawa 13c4cf
  // apply sobel filter, rotate by 90 degrees and normalize.
shun-iwasawa 13c4cf
  // also obtaining gradient magnitude (length of the vector length)
shun-iwasawa 13c4cf
  // empty regions will be filled by using Fast Sweeping Method
shun-iwasawa 13c4cf
  void computeInitialFlow(double* source_buf, double2* flow_buf,
shun-iwasawa 13c4cf
                          double* grad_mag_buf, const TDimension dim,
shun-iwasawa 13c4cf
                          double mag_threshold);
shun-iwasawa 13c4cf
  // 基準の角度に向きを合わせる
shun-iwasawa 13c4cf
  void alignFlowDirection(double2* flow_buf, const TDimension dim,
shun-iwasawa 13c4cf
                          const double2& pivotVec);
shun-iwasawa 13c4cf
shun-iwasawa 13c4cf
public:
shun-iwasawa 13c4cf
  Iwa_TangentFlowFx();
shun-iwasawa 13c4cf
shun-iwasawa 13c4cf
  void doCompute(TTile& tile, double frame,
shun-iwasawa 13c4cf
                 const TRenderSettings& settings) override;
shun-iwasawa 13c4cf
shun-iwasawa 13c4cf
  bool doGetBBox(double frame, TRectD& bBox,
shun-iwasawa 13c4cf
                 const TRenderSettings& info) override;
shun-iwasawa 13c4cf
shun-iwasawa 13c4cf
  bool canHandle(const TRenderSettings& info, double frame) override;
shun-iwasawa 13c4cf
};
shun-iwasawa 13c4cf
shun-iwasawa 13c4cf
#endif