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