1 #include <sstream> /* std::ostringstream */
2 #include "tfxparam.h"
3 #include "stdfx.h"
4
5 #include "ino_common.h"
6 namespace {
7 const double smoothing_edge_ = 1.0;
8 }
9 //------------------------------------------------------------
10 class ino_maxmin final : public TStandardRasterFx {
11 FX_PLUGIN_DECLARATION(ino_maxmin)
12 TRasterFxPort m_input;
13 TRasterFxPort m_refer;
14
15 TIntEnumParamP m_max_min_select;
16 TDoubleParamP m_radius;
17 TDoubleParamP m_polygon_number;
18 TDoubleParamP m_degree;
19 TBoolParamP m_alpha_rendering;
20
21 TIntEnumParamP m_ref_mode;
22
23 public:
ino_maxmin()24 ino_maxmin()
25 : m_max_min_select(new TIntEnumParam(0, "Max"))
26 , m_radius(1.0)
27 /* 1mmにしたければ 1.0 * 640. / 12. / 25.4 とする
28 0.35 = mm = ユーザ指定の初期値
29 640/12 = 53.33333 = toonz独自の係数 =tunit.cpp参照
30 25.4 = mm/inch
31 */
32 , m_polygon_number(2.0)
33 , m_degree(0.0)
34 , m_alpha_rendering(true)
35
36 , m_ref_mode(new TIntEnumParam()) {
37 this->m_radius->setMeasureName("fxLength");
38
39 addInputPort("Source", this->m_input);
40 addInputPort("Reference", this->m_refer);
41
42 bindParam(this, "max_min_select", this->m_max_min_select);
43 bindParam(this, "radius", this->m_radius);
44 bindParam(this, "polygon_number", this->m_polygon_number);
45 bindParam(this, "degree", this->m_degree);
46 bindParam(this, "alpha_rendering", this->m_alpha_rendering);
47
48 bindParam(this, "reference", this->m_ref_mode);
49
50 this->m_max_min_select->addItem(1, "Min");
51 this->m_radius->setValueRange(0.0, 100.0);
52 this->m_polygon_number->setValueRange(2.0, 16.0);
53 this->m_degree->setValueRange(0.0, std::numeric_limits<double>::max());
54
55 this->m_ref_mode->addItem(0, "Red");
56 this->m_ref_mode->addItem(1, "Green");
57 this->m_ref_mode->addItem(2, "Blue");
58 this->m_ref_mode->addItem(3, "Alpha");
59 this->m_ref_mode->addItem(4, "Luminance");
60 this->m_ref_mode->addItem(-1, "Nothing");
61 this->m_ref_mode->setDefaultValue(0);
62 this->m_ref_mode->setValue(0);
63 }
doGetBBox(double frame,TRectD & bBox,const TRenderSettings & info)64 bool doGetBBox(double frame, TRectD &bBox,
65 const TRenderSettings &info) override {
66 if (this->m_input.isConnected()) {
67 const bool ret = this->m_input->doGetBBox(frame, bBox, info);
68 const double margin =
69 ceil(ino::pixel_per_mm() *
70 (this->m_radius->getValue(frame) + smoothing_edge_));
71 if (0.0 < margin) {
72 bBox = bBox.enlarge(margin);
73 }
74 return ret;
75 } else {
76 bBox = TRectD();
77 return false;
78 }
79 }
canHandle(const TRenderSettings & info,double frame)80 bool canHandle(const TRenderSettings &info, double frame) override {
81 return true;
82 }
getMemoryRequirement(const TRectD & rect,double frame,const TRenderSettings & info)83 int getMemoryRequirement(const TRectD &rect, double frame,
84 const TRenderSettings &info) override {
85 const double radius = (this->m_radius->getValue(frame) + smoothing_edge_) *
86 ino::pixel_per_mm() *
87 sqrt(fabs(info.m_affine.det())) /
88 ((info.m_shrinkX + info.m_shrinkY) / 2.0);
89 return TRasterFx::memorySize(rect.enlarge(ceil(radius) + 0.5), info.m_bpp);
90 }
91 void doCompute(TTile &tile, double frame,
92 const TRenderSettings &rend_sets) override;
93 };
94 FX_PLUGIN_IDENTIFIER(ino_maxmin, "inoMaxMinFx");
95 //------------------------------------------------------------
96 #include "igs_maxmin.h"
97 namespace {
fx_(const TRasterP in_ras,const int margin,TRasterP out_ras,const TRasterP refer_ras,const int refer_mode,const int min_sw,const double radius,const double smoothing_edge,const int npolygon,const double degree,const bool alp_rend_sw,const int nthread)98 void fx_(const TRasterP in_ras // with margin
99 ,
100 const int margin, TRasterP out_ras // no margin
101
102 ,
103 const TRasterP refer_ras, const int refer_mode
104
105 ,
106 const int min_sw, const double radius, const double smoothing_edge,
107 const int npolygon, const double degree, const bool alp_rend_sw
108
109 ,
110 const int nthread) {
111 TRasterGR8P out_gr8(in_ras->getLy(),
112 in_ras->getLx() * ino::channels() *
113 ((TRaster64P)in_ras ? sizeof(unsigned short)
114 : sizeof(unsigned char)));
115 out_gr8->lock();
116
117 igs::maxmin::convert(
118 in_ras->getRawData() // BGRA
119 ,
120 out_gr8->getRawData()
121
122 ,
123 in_ras->getLy(), in_ras->getLx(), ino::channels(), ino::bits(in_ras)
124
125 ,
126 (((refer_ras != nullptr) && (0 <= refer_mode)) ? refer_ras->getRawData()
127 : nullptr) // BGRA
128 ,
129 (((refer_ras != nullptr) && (0 <= refer_mode)) ? ino::bits(refer_ras) : 0)
130
131 ,
132 refer_mode, radius, smoothing_edge // smooth_outer_range
133 ,
134 npolygon, degree + 180.0
135
136 ,
137 min_sw, alp_rend_sw, false
138
139 ,
140 nthread);
141
142 ino::arr_to_ras(out_gr8->getRawData(), ino::channels(), out_ras, margin);
143 out_gr8->unlock();
144 }
145 }
146 //------------------------------------------------------------
doCompute(TTile & tile,double frame,const TRenderSettings & rend_sets)147 void ino_maxmin::doCompute(TTile &tile, double frame,
148 const TRenderSettings &rend_sets) {
149 /* ------ 接続していなければ処理しない -------------------- */
150 if (!this->m_input.isConnected()) {
151 tile.getRaster()->clear(); /* 塗りつぶしクリア */
152 return;
153 }
154
155 /* ------ サポートしていないPixelタイプはエラーを投げる --- */
156 if (!((TRaster32P)tile.getRaster()) && !((TRaster64P)tile.getRaster())) {
157 throw TRopException("unsupported input pixel type");
158 }
159
160 /* ------ Pixel単位で動作パラメータを得る ----------------- */
161 const double mm2scale_shrink_pixel =
162 ino::pixel_per_mm() * sqrt(fabs(rend_sets.m_affine.det())) /
163 ((rend_sets.m_shrinkX + rend_sets.m_shrinkY) / 2.0);
164
165 /* 動作パラメータを得る */
166 const int min_sw = this->m_max_min_select->getValue(); // 0,1
167 const double radius = this->m_radius->getValue(frame) * mm2scale_shrink_pixel;
168 const int npolygon = this->m_polygon_number->getValue(frame);
169 const double degree = this->m_degree->getValue(frame);
170 const bool alp_rend_sw = this->m_alpha_rendering->getValue();
171
172 const int refer_mode = this->m_ref_mode->getValue();
173
174 /* tcomposer(RenderManager)でRenderingするときはthreadは1つ、
175 toonz(Desktop)でPreview,Outputするなら-1を指定
176 -1は自動でthread数を決めCPUを最大に使い高速化 */
177 const int nthread = -1;
178
179 /* ------ 参照マージン含めた画像生成 ---------------------- */
180 /* Rendering画像のBBox値 --> Pixel単位のdouble値 */
181 /* typedef TRectT<double> TRectD;
182 inline TRectT<double>::TRectT(
183 const TPointT<double> &bottomLeft
184 , const TDimensionT<double> &d
185 ) : x0(bottomLeft.x)
186 , y0(bottomLeft.y)
187 , x1(bottomLeft.x+d.lx)
188 , y1(bottomLeft.y+d.ly)
189 {}
190 */
191 TRectD enlarge_rect =
192 TRectD(tile.m_pos /* TPointD */
193 ,
194 TDimensionD(/* int --> doubleにしてセット */
195 tile.getRaster()->getLx(), tile.getRaster()->getLy()));
196 /* BBoxの拡大 Pixel単位 */
197 const int enlarge_pixel = (int)(ceil(radius + smoothing_edge_) + 0.5);
198 enlarge_rect = enlarge_rect.enlarge(enlarge_pixel);
199
200 /* void TRasterFx::allocateAndCompute(
201 TTile &tile,
202 const TPointD &pos, const TDimension &size,
203 const TRasterP &templateRas, double frame,
204 const TRenderSettings &info
205 ) {
206 if (templateRas) {
207 tile.getRaster() = templateRas->create(size.lx, size.ly);
208 } else {
209 tile.getRaster() = TRaster32P(size.lx, size.ly);
210 }
211 tile.m_pos = pos;
212 compute(tile, frame, info);
213 }
214 */
215 TTile enlarge_tile;
216 this->m_input->allocateAndCompute(
217 enlarge_tile, enlarge_rect.getP00(),
218 TDimensionI(/* Pixel単位のdouble -> intにしてセット */
219 (int)(enlarge_rect.getLx() + 0.5),
220 (int)(enlarge_rect.getLy() + 0.5)),
221 tile.getRaster(), frame, rend_sets);
222
223 /*------ 参照画像生成 --------------------------------------*/
224 TTile refer_tile;
225 bool refer_sw = false;
226 if (this->m_refer.isConnected()) {
227 refer_sw = true;
228 this->m_refer->allocateAndCompute(
229 refer_tile, enlarge_tile.m_pos,
230 TDimensionI(/* Pixel単位 */
231 enlarge_tile.getRaster()->getLx(),
232 enlarge_tile.getRaster()->getLy()),
233 enlarge_tile.getRaster(), frame, rend_sets);
234 }
235 /* ------ 保存すべき画像メモリを塗りつぶしクリア ---------- */
236 tile.getRaster()->clear(); /* 塗りつぶしクリア */
237
238 /* ------ (app_begin)log記憶 ------------------------------ */
239 const bool log_sw = ino::log_enable_sw();
240
241 if (log_sw) {
242 std::ostringstream os;
243 os << "params"
244 << " min_sw " << min_sw << " radius " << radius << " npolygon "
245 << npolygon << " degree " << degree << " alp_rend_sw " << alp_rend_sw
246 << " smoothing_edge " << smoothing_edge_ << " nthread " << nthread
247 << " refer_mode " << refer_mode << " tile w "
248 << tile.getRaster()->getLx() << " h " << tile.getRaster()->getLy()
249 << " pixbits " << ino::pixel_bits(tile.getRaster()) << " frame "
250 << frame << " rand_sets affine_det " << rend_sets.m_affine.det()
251 << " shrink x " << rend_sets.m_shrinkX << " y " << rend_sets.m_shrinkY;
252 if (refer_sw) {
253 os << " refer_tile.m_pos " << refer_tile.m_pos << " refer_tile_getLx "
254 << refer_tile.getRaster()->getLx() << " y "
255 << refer_tile.getRaster()->getLy();
256 }
257 }
258 /* ------ fx処理 ------------------------------------------ */
259 try {
260 tile.getRaster()->lock();
261 enlarge_tile.getRaster()->lock();
262 if (refer_tile.getRaster() != nullptr) {
263 refer_tile.getRaster()->lock();
264 }
265 fx_(enlarge_tile.getRaster() // in with margin
266 ,
267 enlarge_pixel // margin
268 ,
269 tile.getRaster() // out with no margin
270
271 ,
272 refer_tile.getRaster(), refer_mode
273
274 ,
275 min_sw, radius, smoothing_edge_, npolygon, degree, alp_rend_sw
276
277 ,
278 nthread);
279 if (refer_tile.getRaster() != nullptr) {
280 refer_tile.getRaster()->unlock();
281 }
282 enlarge_tile.getRaster()->unlock();
283 tile.getRaster()->unlock();
284 }
285 /* ------ error処理 --------------------------------------- */
286 catch (std::bad_alloc &e) {
287 if (refer_tile.getRaster() != nullptr) {
288 refer_tile.getRaster()->unlock();
289 }
290 enlarge_tile.getRaster()->unlock();
291 tile.getRaster()->unlock();
292 if (log_sw) {
293 std::string str("std::bad_alloc <");
294 str += e.what();
295 str += '>';
296 }
297 throw;
298 } catch (std::exception &e) {
299 if (refer_tile.getRaster() != nullptr) {
300 refer_tile.getRaster()->unlock();
301 }
302 enlarge_tile.getRaster()->unlock();
303 tile.getRaster()->unlock();
304 if (log_sw) {
305 std::string str("exception <");
306 str += e.what();
307 str += '>';
308 }
309 throw;
310 } catch (...) {
311 if (refer_tile.getRaster() != nullptr) {
312 refer_tile.getRaster()->unlock();
313 }
314 enlarge_tile.getRaster()->unlock();
315 tile.getRaster()->unlock();
316 if (log_sw) {
317 std::string str("other exception");
318 }
319 throw;
320 }
321 }
322