1 #include <sstream> /* std::ostringstream */
2 #include "tfxparam.h"
3 #include "stdfx.h"
4 
5 #include "ino_common.h"
6 #include "igs_fog.h"
7 //------------------------------------------------------------
8 class ino_fog final : public TStandardRasterFx {
9   FX_PLUGIN_DECLARATION(ino_fog)
10   TRasterFxPort m_input;
11   TDoubleParamP m_radius;
12   TDoubleParamP m_curve;
13   TDoubleParamP m_power;
14   TDoubleParamP m_threshold_min;
15   TDoubleParamP m_threshold_max;
16   TBoolParamP m_alpha_rendering;
17 
18 public:
ino_fog()19   ino_fog()
20       : m_radius(1.0)
21       , m_curve(1.0 * ino::param_range())
22       , m_power(1.0 * ino::param_range())
23       , m_threshold_min(0.0 * ino::param_range())
24       , m_threshold_max(0.0 * ino::param_range())
25       , m_alpha_rendering(false) {
26     this->m_radius->setMeasureName("fxLength");
27 
28     addInputPort("Source", this->m_input);
29 
30     bindParam(this, "radius", this->m_radius);
31     bindParam(this, "curve", this->m_curve);
32     bindParam(this, "power", this->m_power);
33     bindParam(this, "threshold_min", this->m_threshold_min);
34     bindParam(this, "threshold_max", this->m_threshold_max);
35     bindParam(this, "alpha_rendering", this->m_alpha_rendering);
36 
37     this->m_radius->setValueRange(0.0, 100.0);
38     this->m_curve->setValueRange(0.1 * ino::param_range(),
39                                  10.0 * ino::param_range()); /* gammaカーブ */
40     this->m_power->setValueRange(-2.0 * ino::param_range(),
41                                  2.0 * ino::param_range());
42     this->m_threshold_min->setValueRange(0.0 * ino::param_range(),
43                                          1.01 * ino::param_range());
44     this->m_threshold_max->setValueRange(0.0 * ino::param_range(),
45                                          1.01 * ino::param_range());
46   }
47   //------------------------------------------------------------
get_render_real_radius(const double frame,const TAffine affine)48   double get_render_real_radius(const double frame, const TAffine affine) {
49     return this->m_radius->getValue(frame) *
50            ino::pixel_per_mm()        /* render用単位にする */
51            * sqrt(fabs(affine.det())) /* 拡大縮小のGeometryを反映 */
52         ;
53   }
get_render_enlarge(const double frame,const TAffine affine,TRectD & bBox)54   void get_render_enlarge(const double frame, const TAffine affine,
55                           TRectD &bBox) {
56     const int margin =
57         static_cast<int>(ceil(this->get_render_real_radius(frame, affine)));
58     if (0 < margin) {
59       bBox = bBox.enlarge(static_cast<double>(margin));
60     }
61   }
62   //------------------------------------------------------------
doGetBBox(double frame,TRectD & bBox,const TRenderSettings & info)63   bool doGetBBox(double frame, TRectD &bBox,
64                  const TRenderSettings &info) override {
65     if (false == this->m_input.isConnected()) {
66       bBox = TRectD();
67       return false;
68     }
69     const bool ret = this->m_input->doGetBBox(frame, bBox, info);
70     this->get_render_enlarge(frame, info.m_affine, bBox);
71     return ret;
72   }
getMemoryRequirement(const TRectD & rect,double frame,const TRenderSettings & info)73   int getMemoryRequirement(const TRectD &rect, double frame,
74                            const TRenderSettings &info) override {
75     TRectD bBox(rect);
76     this->get_render_enlarge(frame, info.m_affine, bBox);
77     return TRasterFx::memorySize(bBox, info.m_bpp);
78   }
transform(double frame,int port,const TRectD & rectOnOutput,const TRenderSettings & infoOnOutput,TRectD & rectOnInput,TRenderSettings & infoOnInput)79   void transform(double frame, int port, const TRectD &rectOnOutput,
80                  const TRenderSettings &infoOnOutput, TRectD &rectOnInput,
81                  TRenderSettings &infoOnInput) override {
82     rectOnInput = rectOnOutput;
83     infoOnInput = infoOnOutput;
84     this->get_render_enlarge(frame, infoOnOutput.m_affine, rectOnInput);
85   }
canHandle(const TRenderSettings & info,double frame)86   bool canHandle(const TRenderSettings &info, double frame) override {
87     return true;
88   }
89   void doCompute(TTile &tile, double frame,
90                  const TRenderSettings &rend_sets) override;
91 };
92 FX_PLUGIN_IDENTIFIER(ino_fog, "inoFogFx");
93 //------------------------------------------------------------
94 namespace {
fx_(const TRasterP in_ras,const int margin,TRasterP out_ras,const int nthread,const double radius,const double curve,const double power,const double threshold_min,const double threshold_max,const bool alp_rend_sw)95 void fx_(const TRasterP in_ras  // with margin
96          ,
97          const int margin, TRasterP out_ras  // no margin
98          ,
99          const int nthread, const double radius, const double curve,
100          const double power, const double threshold_min,
101          const double threshold_max, const bool alp_rend_sw) {
102   TRasterGR8P out_gr8(in_ras->getLy(),
103                       in_ras->getLx() * ino::channels() *
104                           ((TRaster64P)in_ras ? sizeof(unsigned short)
105                                               : sizeof(unsigned char)));
106   out_gr8->lock();
107 
108   TRasterGR8P ref_gr8(in_ras->getLy(), in_ras->getLx() * sizeof(double));
109   ref_gr8->lock();
110 
111   igs::fog::convert(
112       in_ras->getRawData()  // BGRA
113       ,
114       out_gr8->getRawData(), reinterpret_cast<double *>(ref_gr8->getRawData())
115 
116                                  ,
117       in_ras->getLy(), in_ras->getLx(), ino::channels(), ino::bits(in_ras)
118 
119                                                              ,
120       nthread
121 
122       ,
123       radius, curve, 2, 0.0, power, threshold_min, threshold_max, alp_rend_sw);
124   ref_gr8->unlock();
125 
126   ino::arr_to_ras(out_gr8->getRawData(), ino::channels(), out_ras, margin);
127   out_gr8->unlock();
128 }
129 }
130 //------------------------------------------------------------
doCompute(TTile & tile,double frame,const TRenderSettings & rend_sets)131 void ino_fog::doCompute(TTile &tile, double frame,
132                         const TRenderSettings &rend_sets) {
133   /*------ 接続していなければ処理しない ----------------------*/
134   if (!this->m_input.isConnected()) {
135     tile.getRaster()->clear(); /* 塗りつぶしクリア */
136     return;
137   }
138   /*------ サポートしていないPixelタイプはエラーを投げる -----*/
139   if (!((TRaster32P)tile.getRaster()) && !((TRaster64P)tile.getRaster())) {
140     throw TRopException("unsupported input pixel type");
141   }
142   /*------ 動作パラメータを得る ------------------------------*/
143   const double radius = this->get_render_real_radius(frame, rend_sets.m_affine);
144   const double curve  = this->m_curve->getValue(frame) / ino::param_range();
145   const double power  = this->m_power->getValue(frame) / ino::param_range();
146   const double threshold_min =
147       this->m_threshold_min->getValue(frame) / ino::param_range();
148   const double threshold_max =
149       this->m_threshold_max->getValue(frame) / ino::param_range();
150   const bool alp_rend_sw = this->m_alpha_rendering->getValue();
151   const int nthread      = 1;
152   /*------ fogがからないパラメータ値のときはfog処理しない ----*/
153   if (!igs::fog::have_change(radius, power, threshold_min)) {
154     this->m_input->compute(tile, frame, rend_sets);
155     return;
156   }
157   /*------ 表示の範囲を得る ----------------------------------*/
158   TRectD bBox =
159       TRectD(tile.m_pos /* Render画像上(Pixel単位)の位置 */
160              ,
161              TDimensionD(/* Render画像上(Pixel単位)のサイズ */
162                          tile.getRaster()->getLx(), tile.getRaster()->getLy()));
163   /*------ fog半径(=マージン)分表示範囲を広げる --------------*/
164   const int int_radius = static_cast<int>(ceil(radius));
165   if (0 < int_radius) {
166     bBox = bBox.enlarge(static_cast<double>(int_radius));
167   }
168   TTile enlarge_tile;
169   this->m_input->allocateAndCompute(
170       enlarge_tile, bBox.getP00(),
171       TDimensionI(/* Pixel単位に四捨五入 */
172                   static_cast<int>(bBox.getLx() + 0.5),
173                   static_cast<int>(bBox.getLy() + 0.5)),
174       tile.getRaster(), frame, rend_sets);
175   /* ------ 保存すべき画像メモリを塗りつぶしクリア ---------- */
176   tile.getRaster()->clear(); /* 塗りつぶしクリア */
177 
178   /* ------ (app_begin)log記憶 ------------------------------ */
179   const bool log_sw = ino::log_enable_sw();
180 
181   if (log_sw) {
182     std::ostringstream os;
183     os << "params"
184        << "  nthread " << nthread << "  usr_radius "
185        << this->m_radius->getValue(frame) << "  real_radius " << radius
186        << "  int_radius " << int_radius << "  curve " << curve << "  power "
187        << power << "  threshold_min " << threshold_min << "  threshold_max "
188        << threshold_max << "  alp_rend_sw " << alp_rend_sw << "   tile w "
189        << tile.getRaster()->getLx() << "  h " << tile.getRaster()->getLy()
190        << "  pixbits " << ino::pixel_bits(tile.getRaster()) << "   frame "
191        << frame << "   rand_sets affine_det " << rend_sets.m_affine.det()
192        << "  shrink x " << rend_sets.m_shrinkX << "  y " << rend_sets.m_shrinkY;
193   }
194   /* ------ fx処理 ------------------------------------------ */
195   try {
196     tile.getRaster()->lock();
197     fx_(enlarge_tile.getRaster()  // with margin
198         ,
199         int_radius  // margin
200         ,
201         tile.getRaster()  // no margin
202         ,
203         nthread, radius, curve, power, threshold_min, threshold_max,
204         alp_rend_sw);
205     tile.getRaster()->unlock();
206   }
207   /* ------ error処理 --------------------------------------- */
208   catch (std::bad_alloc &e) {
209     tile.getRaster()->unlock();
210     if (log_sw) {
211       std::string str("std::bad_alloc <");
212       str += e.what();
213       str += '>';
214     }
215     throw;
216   } catch (std::exception &e) {
217     tile.getRaster()->unlock();
218     if (log_sw) {
219       std::string str("exception <");
220       str += e.what();
221       str += '>';
222     }
223     throw;
224   } catch (...) {
225     tile.getRaster()->unlock();
226     if (log_sw) {
227       std::string str("other exception");
228     }
229     throw;
230   }
231 }
232