| #include <sstream> /* std::ostringstream */ |
| #include "tfxparam.h" |
| #include "stdfx.h" |
| #include "tfxattributes.h" |
| |
| #include "ino_common.h" |
| |
| class ino_motion_blur : public TStandardRasterFx |
| { |
| FX_PLUGIN_DECLARATION(ino_motion_blur) |
| TRasterFxPort m_input; |
| |
| TIntEnumParamP m_depend_move; |
| TDoubleParamP m_x1; |
| TDoubleParamP m_y1; |
| TDoubleParamP m_x2; |
| TDoubleParamP m_y2; |
| TDoubleParamP m_scale; |
| TDoubleParamP m_curve; |
| TDoubleParamP m_zanzo_length; |
| TDoubleParamP m_zanzo_power; |
| TBoolParamP m_alpha_rendering; |
| |
| public: |
| ino_motion_blur() |
| : m_depend_move(new TIntEnumParam(0, "P1 -> P2")), m_x1(0.0), m_y1(0.0), m_x2(1.0), m_y2(1.0), m_scale(1.0 * ino::param_range()), m_curve(1.0 * ino::param_range()), m_zanzo_length(0.0), m_zanzo_power(1.0 * ino::param_range()), m_alpha_rendering(true) |
| |
| { |
| this->m_x1->setMeasureName("fxLength"); |
| this->m_y1->setMeasureName("fxLength"); |
| this->m_x2->setMeasureName("fxLength"); |
| this->m_y2->setMeasureName("fxLength"); |
| this->m_zanzo_length->setMeasureName("fxLength"); |
| |
| addInputPort("Source", this->m_input); |
| |
| bindParam(this, "depend_move", this->m_depend_move); |
| bindParam(this, "x1", this->m_x1); |
| bindParam(this, "y1", this->m_y1); |
| bindParam(this, "x2", this->m_x2); |
| bindParam(this, "y2", this->m_y2); |
| bindParam(this, "scale", this->m_scale); |
| bindParam(this, "curve", this->m_curve); |
| bindParam(this, "zanzo_length", this->m_zanzo_length); |
| bindParam(this, "zanzo_power", this->m_zanzo_power); |
| bindParam(this, "alpha_rendering", |
| this->m_alpha_rendering); |
| |
| |
| this->m_depend_move->addItem(1, "Motion"); |
| |
| this->m_curve->setValueRange( |
| 0.1 * ino::param_range(), 10.0 * ino::param_range()); |
| this->m_zanzo_length->setValueRange( |
| 0.0, |
| 1000.0); |
| this->m_zanzo_power->setValueRange( |
| 0.0 * ino::param_range(), |
| 1.0 * ino::param_range()); |
| |
| this->getAttributes()->setIsSpeedAware(true); |
| } |
| |
| void get_render_vector( |
| const double frame, const TAffine affine, TPointD &rend_vect) |
| { |
| |
| if (0 == this->m_depend_move->getValue()) { |
| rend_vect.x = this->m_x2->getValue(frame) - |
| this->m_x1->getValue(frame); |
| rend_vect.y = this->m_y2->getValue(frame) - |
| this->m_y1->getValue(frame); |
| |
| rend_vect = rend_vect * ino::pixel_per_mm(); |
| |
| } else { |
| rend_vect = -this->getAttributes()->getSpeed(); |
| } |
| |
| |
| |
| |
| |
| |
| TAffine aff(affine); |
| aff.a13 = aff.a23 = 0; |
| |
| rend_vect = aff * rend_vect; |
| |
| |
| rend_vect = rend_vect * (this->m_scale->getValue(frame) / ino::param_range()); |
| |
| |
| |
| } |
| int get_render_margin( |
| const double frame, const TAffine affine) |
| { |
| TPointD rend_vect; |
| this->get_render_vector(frame, affine, rend_vect); |
| return static_cast<int>(ceil( |
| (fabs(rend_vect.x) < fabs(rend_vect.y)) |
| ? fabs(rend_vect.y) |
| : fabs(rend_vect.x)) + |
| 0.5); |
| } |
| void get_render_enlarge( |
| const double frame, const TAffine affine, TRectD &bBox) |
| { |
| const int margin = this->get_render_margin(frame, affine); |
| if (0 < margin) { |
| bBox = bBox.enlarge(static_cast<double>(margin)); |
| } |
| } |
| |
| bool doGetBBox( |
| double frame, TRectD &bBox, const TRenderSettings &info) |
| { |
| if (false == this->m_input.isConnected()) { |
| bBox = TRectD(); |
| return false; |
| } |
| const bool ret = this->m_input->doGetBBox(frame, bBox, info); |
| this->get_render_enlarge(frame, info.m_affine, bBox); |
| return ret; |
| } |
| int getMemoryRequirement( |
| const TRectD &rect, double frame, const TRenderSettings &info) |
| { |
| TRectD bBox(rect); |
| this->get_render_enlarge(frame, info.m_affine, bBox); |
| return TRasterFx::memorySize(bBox, info.m_bpp); |
| } |
| void transform( |
| double frame, int port, const TRectD &rectOnOutput, const TRenderSettings &infoOnOutput, TRectD &rectOnInput, TRenderSettings &infoOnInput) |
| { |
| rectOnInput = rectOnOutput; |
| infoOnInput = infoOnOutput; |
| this->get_render_enlarge( |
| frame, infoOnOutput.m_affine, rectOnInput); |
| } |
| bool canHandle( |
| const TRenderSettings &info, double frame) |
| { |
| if (0 == this->m_depend_move->getValue()) { |
| return true; |
| } else { |
| return isAlmostIsotropic(info.m_affine) || |
| m_scale->getValue(frame) == 0; |
| } |
| } |
| void doCompute( |
| TTile &tile, double frame, const TRenderSettings &rend_sets); |
| }; |
| FX_PLUGIN_IDENTIFIER(ino_motion_blur, "inoMotionBlurFx"); |
| |
| #include "igs_motion_blur.h" |
| namespace |
| { |
| template <class U, class T> |
| void arr_to_ras_( |
| const U *arr, const int channels, TRasterPT<T> ras, const int margin) |
| { |
| arr += (ras->getLx() + margin + margin) * margin * channels + |
| margin * channels; |
| |
| for (int yy = 0; yy < ras->getLy(); ++yy, arr += (ras->getLx() + margin + margin) * channels) { |
| const U *arrx = arr; |
| T *ras_sl = ras->pixels(yy); |
| for (int xx = 0; xx < ras->getLx(); ++xx, arrx += channels) { |
| ras_sl[xx].b = arrx[0]; |
| ras_sl[xx].g = arrx[1]; |
| ras_sl[xx].r = arrx[2]; |
| ras_sl[xx].m = arrx[3]; |
| } |
| } |
| } |
| void vec_to_ras_( |
| unsigned char *vec, const int channels, TRasterP ras, const int margin) |
| { |
| if ((TRaster32P)ras) { |
| arr_to_ras_<unsigned char, TPixel32>( |
| vec, channels, ras, margin); |
| } else if ((TRaster64P)ras) { |
| arr_to_ras_<unsigned short, TPixel64>( |
| reinterpret_cast<unsigned short *>(vec), channels, ras, margin); |
| } |
| } |
| void fx_( |
| const TRasterP in_ras |
| , |
| const int margin, TRasterP out_ras |
| , |
| const double x_vector, const double y_vector, const double scale, const double curve, const int zanzo_length, const double zanzo_power, const bool alp_rend_sw) |
| { |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| TRasterGR8P out_gr8( |
| in_ras->getLy(), in_ras->getLx() * ino::channels() * |
| ((TRaster64P)in_ras ? sizeof(unsigned short) : sizeof(unsigned char))); |
| out_gr8->lock(); |
| |
| igs::motion_blur::convert( |
| in_ras->getRawData() |
| |
| |
| |
| |
| |
| , |
| out_gr8->getRawData() |
| |
| , |
| in_ras->getLy(), in_ras->getLx(), ino::channels(), ino::bits(in_ras) |
| |
| , |
| x_vector, y_vector, scale, curve, zanzo_length, zanzo_power, alp_rend_sw); |
| |
| |
| |
| |
| |
| |
| |
| |
| ino::arr_to_ras( |
| out_gr8->getRawData(), ino::channels(), out_ras, margin); |
| out_gr8->unlock(); |
| } |
| } |
| |
| void ino_motion_blur::doCompute( |
| TTile &tile, double frame, const TRenderSettings &rend_sets) |
| { |
| |
| if (!this->m_input.isConnected()) { |
| tile.getRaster()->clear(); |
| return; |
| } |
| |
| |
| if (!((TRaster32P)tile.getRaster()) && |
| !((TRaster64P)tile.getRaster())) { |
| throw TRopException("unsupported input pixel type"); |
| } |
| |
| |
| const int depend_move = this->m_depend_move->getValue(); |
| const double scale = this->m_scale->getValue(frame) / |
| ino::param_range(); |
| const double curve = this->m_curve->getValue(frame) / |
| ino::param_range(); |
| const int zanzo_length = this->m_zanzo_length->getValue(frame) * |
| ino::pixel_per_mm() * sqrt(fabs(rend_sets.m_affine.det())) / ((rend_sets.m_shrinkX + rend_sets.m_shrinkY) / 2.0); |
| const double zanzo_power = this->m_zanzo_power->getValue(frame) / |
| ino::param_range(); |
| const bool alp_rend_sw = this->m_alpha_rendering->getValue(); |
| |
| |
| TPointD rend_vect; |
| this->get_render_vector(frame, rend_sets.m_affine, rend_vect); |
| |
| const int margin = static_cast<int>(ceil( |
| (fabs(rend_vect.x) < fabs(rend_vect.y)) |
| ? fabs(rend_vect.y) |
| : fabs(rend_vect.x)) + |
| 0.5); |
| |
| TRectD bBox = TRectD( |
| tile.m_pos |
| , |
| TDimensionD( |
| tile.getRaster()->getLx(), tile.getRaster()->getLy())); |
| if (0 < margin) { |
| bBox = bBox.enlarge(static_cast<double>(margin)); |
| } |
| |
| TTile enlarge_tile; |
| this->m_input->allocateAndCompute( |
| enlarge_tile, bBox.getP00(), TDimensionI( |
| static_cast<int>(bBox.getLx() + 0.5), static_cast<int>(bBox.getLy() + 0.5)), |
| tile.getRaster(), frame, rend_sets); |
| |
| |
| tile.getRaster()->clear(); |
| |
| |
| const bool log_sw = ino::log_enable_sw(); |
| |
| if (log_sw) { |
| std::ostringstream os; |
| os << "params" |
| << " depend_move_num " << depend_move |
| << " render_vector x " << rend_vect.x |
| << " y " << rend_vect.y |
| << " margin " << margin |
| << " scale " << scale |
| << " curve " << curve |
| << " z_len " << zanzo_length |
| << " z_pow " << zanzo_power |
| << " alp_rend_sw " << alp_rend_sw |
| << " tile w " << tile.getRaster()->getLx() |
| << " h " << tile.getRaster()->getLy() |
| << " pixbits " << ino::pixel_bits(tile.getRaster()) |
| << " frame " << frame |
| << " rand_sets affine_det " << rend_sets.m_affine.det() |
| << " a11 " << rend_sets.m_affine.a11 |
| << " a12 " << rend_sets.m_affine.a12 |
| << " a13 " << rend_sets.m_affine.a13 |
| << " a21 " << rend_sets.m_affine.a21 |
| << " a22 " << rend_sets.m_affine.a22 |
| << " a23 " << rend_sets.m_affine.a23 |
| << " x " << rend_sets.m_shrinkX |
| << " y " << rend_sets.m_shrinkY; |
| } |
| |
| try { |
| tile.getRaster()->lock(); |
| fx_(enlarge_tile.getRaster() |
| , |
| margin |
| , |
| tile.getRaster() |
| , |
| rend_vect.x, rend_vect.y, scale, curve, zanzo_length, zanzo_power, alp_rend_sw); |
| tile.getRaster()->unlock(); |
| } |
| |
| catch (std::bad_alloc &e) { |
| tile.getRaster()->unlock(); |
| if (log_sw) { |
| std::string str("std::bad_alloc <"); |
| str += e.what(); |
| str += '>'; |
| } |
| throw; |
| } catch (std::exception &e) { |
| tile.getRaster()->unlock(); |
| if (log_sw) { |
| std::string str("exception <"); |
| str += e.what(); |
| str += '>'; |
| } |
| throw; |
| } catch (...) { |
| tile.getRaster()->unlock(); |
| if (log_sw) { |
| std::string str("other exception"); |
| } |
| throw; |
| } |
| } |