From cbfde43fb808b2df2839973627d4965557edc36a Mon Sep 17 00:00:00 2001 From: shun-iwasawa Date: Thu, 20 May 2021 15:33:50 +0900 Subject: [PATCH] linear option for all layer blending ino fxs --- stuff/config/current.txt | 63 +++ .../layouts/fxs/STD_inoColorBurnFx.xml | 6 + .../layouts/fxs/STD_inoColorDodgeFx.xml | 6 + .../layouts/fxs/STD_inoCrossDissolveFx.xml | 6 + .../profiles/layouts/fxs/STD_inoDarkenFx.xml | 6 + .../layouts/fxs/STD_inoDarkerColorFx.xml | 6 + .../profiles/layouts/fxs/STD_inoDivideFx.xml | 6 + .../layouts/fxs/STD_inoHardLightFx.xml | 6 + .../profiles/layouts/fxs/STD_inoHardMixFx.xml | 6 + .../profiles/layouts/fxs/STD_inoLightenFx.xml | 6 + .../layouts/fxs/STD_inoLighterColorFx.xml | 6 + .../layouts/fxs/STD_inoLinearBurnFx.xml | 6 + .../layouts/fxs/STD_inoLinearDodgeFx.xml | 6 + .../layouts/fxs/STD_inoLinearLightFx.xml | 6 + .../layouts/fxs/STD_inoMultiplyFx.xml | 6 + stuff/profiles/layouts/fxs/STD_inoOverFx.xml | 6 + .../profiles/layouts/fxs/STD_inoOverlayFx.xml | 6 + .../layouts/fxs/STD_inoPinLightFx.xml | 6 + .../profiles/layouts/fxs/STD_inoScreenFx.xml | 6 + .../layouts/fxs/STD_inoSoftLightFx.xml | 6 + .../layouts/fxs/STD_inoSubtractFx.xml | 6 + .../layouts/fxs/STD_inoVividLightFx.xml | 6 + toonz/sources/stdfx/ino_blend_add.cpp | 470 +---------------- toonz/sources/stdfx/ino_blend_color_burn.cpp | 328 +----------- toonz/sources/stdfx/ino_blend_color_dodge.cpp | 328 +----------- .../stdfx/ino_blend_cross_dissolve.cpp | 331 +----------- toonz/sources/stdfx/ino_blend_darken.cpp | 328 +----------- .../sources/stdfx/ino_blend_darker_color.cpp | 331 +----------- toonz/sources/stdfx/ino_blend_divide.cpp | 328 +----------- toonz/sources/stdfx/ino_blend_hard_light.cpp | 328 +----------- toonz/sources/stdfx/ino_blend_hard_mix.cpp | 328 +----------- toonz/sources/stdfx/ino_blend_lighten.cpp | 328 +----------- .../sources/stdfx/ino_blend_lighter_color.cpp | 331 +----------- toonz/sources/stdfx/ino_blend_linear_burn.cpp | 328 +----------- .../sources/stdfx/ino_blend_linear_dodge.cpp | 331 +----------- .../sources/stdfx/ino_blend_linear_light.cpp | 331 +----------- toonz/sources/stdfx/ino_blend_multiply.cpp | 328 +----------- toonz/sources/stdfx/ino_blend_over.cpp | 328 +----------- toonz/sources/stdfx/ino_blend_overlay.cpp | 328 +----------- toonz/sources/stdfx/ino_blend_pin_light.cpp | 328 +----------- toonz/sources/stdfx/ino_blend_screen.cpp | 328 +----------- toonz/sources/stdfx/ino_blend_soft_light.cpp | 328 +----------- toonz/sources/stdfx/ino_blend_subtract.cpp | 339 +----------- toonz/sources/stdfx/ino_blend_vivid_light.cpp | 328 +----------- toonz/sources/stdfx/ino_common.cpp | 494 +++++++++++++++++- toonz/sources/stdfx/ino_common.h | 69 ++- 46 files changed, 894 insertions(+), 7242 deletions(-) diff --git a/stuff/config/current.txt b/stuff/config/current.txt index f18526ee..67ca4587 100644 --- a/stuff/config/current.txt +++ b/stuff/config/current.txt @@ -846,67 +846,130 @@ "STD_inoColorBurnFx" "Color Burn Ino" "STD_inoColorBurnFx.opacity" "Opacity" "STD_inoColorBurnFx.clipping_mask" "Clipping Mask" + "STD_inoColorBurnFx.linear" "Linear Color Space" + "STD_inoColorBurnFx.gamma" "Gamma" + "STD_inoColorBurnFx.premultiplied" "Source is Premultiplied" "STD_inoColorDodgeFx" "Color Dodge Ino" "STD_inoColorDodgeFx.opacity" "Opacity" "STD_inoColorDodgeFx.clipping_mask" "Clipping Mask" + "STD_inoColorDodgeFx.linear" "Linear Color Space" + "STD_inoColorDodgeFx.gamma" "Gamma" + "STD_inoColorDodgeFx.premultiplied" "Source is Premultiplied" "STD_inoCrossDissolveFx" "Cross Dissolve Ino" "STD_inoCrossDissolveFx.opacity" "Opacity" "STD_inoCrossDissolveFx.clipping_mask" "Clipping Mask" + "STD_inoCrossDissolveFx.linear" "Linear Color Space" + "STD_inoCrossDissolveFx.gamma" "Gamma" + "STD_inoCrossDissolveFx.premultiplied" "Source is Premultiplied" "STD_inoDarkenFx" "Darken Ino" "STD_inoDarkenFx.opacity" "Opacity" "STD_inoDarkenFx.clipping_mask" "Clipping Mask" + "STD_inoDarkenFx.linear" "Linear Color Space" + "STD_inoDarkenFx.gamma" "Gamma" + "STD_inoDarkenFx.premultiplied" "Source is Premultiplied" "STD_inoDarkerColorFx" "Darker Color Ino" "STD_inoDarkerColorFx.opacity" "Opacity" "STD_inoDarkerColorFx.clipping_mask" "Clipping Mask" + "STD_inoDarkerColorFx.linear" "Linear Color Space" + "STD_inoDarkerColorFx.gamma" "Gamma" + "STD_inoDarkerColorFx.premultiplied" "Source is Premultiplied" "STD_inoDivideFx" "Divide Ino" "STD_inoDivideFx.opacity" "Opacity" "STD_inoDivideFx.clipping_mask" "Clipping Mask" + "STD_inoDivideFx.linear" "Linear Color Space" + "STD_inoDivideFx.gamma" "Gamma" + "STD_inoDivideFx.premultiplied" "Source is Premultiplied" "STD_inoHardLightFx" "Hard Light Ino" "STD_inoHardLightFx.opacity" "Opacity" "STD_inoHardLightFx.clipping_mask" "Clipping Mask" + "STD_inoHardLightFx.linear" "Linear Color Space" + "STD_inoHardLightFx.gamma" "Gamma" + "STD_inoHardLightFx.premultiplied" "Source is Premultiplied" "STD_inoHardMixFx" "Hard Mix Ino" "STD_inoHardMixFx.opacity" "Opacity" "STD_inoHardMixFx.clipping_mask" "Clipping Mask" + "STD_inoHardMixFx.linear" "Linear Color Space" + "STD_inoHardMixFx.gamma" "Gamma" + "STD_inoHardMixFx.premultiplied" "Source is Premultiplied" "STD_inoLightenFx" "Lighten Ino" "STD_inoLightenFx.opacity" "Opacity" "STD_inoLightenFx.clipping_mask" "Clipping Mask" + "STD_inoLightenFx.linear" "Linear Color Space" + "STD_inoLightenFx.gamma" "Gamma" + "STD_inoLightenFx.premultiplied" "Source is Premultiplied" "STD_inoLighterColorFx" "Lighter Color Ino" "STD_inoLighterColorFx.opacity" "Opacity" "STD_inoLighterColorFx.clipping_mask" "Clipping Mask" + "STD_inoLighterColorFx.linear" "Linear Color Space" + "STD_inoLighterColorFx.gamma" "Gamma" + "STD_inoLighterColorFx.premultiplied" "Source is Premultiplied" "STD_inoLinearBurnFx" "Linear Burn Ino" "STD_inoLinearBurnFx.opacity" "Opacity" "STD_inoLinearBurnFx.clipping_mask" "Clipping Mask" + "STD_inoLinearBurnFx.linear" "Linear Color Space" + "STD_inoLinearBurnFx.gamma" "Gamma" + "STD_inoLinearBurnFx.premultiplied" "Source is Premultiplied" "STD_inoLinearDodgeFx" "Linear Dodge Ino" "STD_inoLinearDodgeFx.opacity" "Opacity" "STD_inoLinearDodgeFx.clipping_mask" "Clipping Mask" + "STD_inoLinearDodgeFx.linear" "Linear Color Space" + "STD_inoLinearDodgeFx.gamma" "Gamma" + "STD_inoLinearDodgeFx.premultiplied" "Source is Premultiplied" "STD_inoLinearLightFx" "Linear Light Ino" "STD_inoLinearLightFx.opacity" "Opacity" "STD_inoLinearLightFx.clipping_mask" "Clipping Mask" + "STD_inoLinearLightFx.linear" "Linear Color Space" + "STD_inoLinearLightFx.gamma" "Gamma" + "STD_inoLinearLightFx.premultiplied" "Source is Premultiplied" "STD_inoMultiplyFx" "Multiply Ino" "STD_inoMultiplyFx.opacity" "Opacity" "STD_inoMultiplyFx.clipping_mask" "Clipping Mask" + "STD_inoMultiplyFx.linear" "Linear Color Space" + "STD_inoMultiplyFx.gamma" "Gamma" + "STD_inoMultiplyFx.premultiplied" "Source is Premultiplied" "STD_inoOverFx" "Over Ino" "STD_inoOverFx.opacity" "Opacity" "STD_inoOverFx.clipping_mask" "Clipping Mask" + "STD_inoOverFx.linear" "Linear Color Space" + "STD_inoOverFx.gamma" "Gamma" + "STD_inoOverFx.premultiplied" "Source is Premultiplied" "STD_inoOverlayFx" "Overlay Ino" "STD_inoOverlayFx.opacity" "Opacity" "STD_inoOverlayFx.clipping_mask" "Clipping Mask" + "STD_inoOverlayFx.linear" "Linear Color Space" + "STD_inoOverlayFx.gamma" "Gamma" + "STD_inoOverlayFx.premultiplied" "Source is Premultiplied" "STD_inoPinLightFx" "Pin Light Ino" "STD_inoPinLightFx.opacity" "Opacity" "STD_inoPinLightFx.clipping_mask" "Clipping Mask" + "STD_inoPinLightFx.linear" "Linear Color Space" + "STD_inoPinLightFx.gamma" "Gamma" + "STD_inoPinLightFx.premultiplied" "Source is Premultiplied" "STD_inoScreenFx" "Screen Ino" "STD_inoScreenFx.opacity" "Opacity" "STD_inoScreenFx.clipping_mask" "Clipping Mask" + "STD_inoScreenFx.linear" "Linear Color Space" + "STD_inoScreenFx.gamma" "Gamma" + "STD_inoScreenFx.premultiplied" "Source is Premultiplied" "STD_inoSoftLightFx" "Soft Light Ino" "STD_inoSoftLightFx.opacity" "Opacity" "STD_inoSoftLightFx.clipping_mask" "Clipping Mask" + "STD_inoSoftLightFx.linear" "Linear Color Space" + "STD_inoSoftLightFx.gamma" "Gamma" + "STD_inoSoftLightFx.premultiplied" "Source is Premultiplied" "STD_inoSubtractFx" "Subtract Ino" "STD_inoSubtractFx.opacity" "Opacity" "STD_inoSubtractFx.clipping_mask" "Clipping Mask" "STD_inoSubtractFx.alpha_rendering" "Alpha Rendering" + "STD_inoSubtractFx.linear" "Linear Color Space" + "STD_inoSubtractFx.gamma" "Gamma" + "STD_inoSubtractFx.premultiplied" "Source is Premultiplied" "STD_inoVividLightFx" "Vivid Light Ino" "STD_inoVividLightFx.opacity" "Opacity" "STD_inoVividLightFx.clipping_mask" "Clipping Mask" + "STD_inoVividLightFx.linear" "Linear Color Space" + "STD_inoVividLightFx.gamma" "Gamma" + "STD_inoVividLightFx.premultiplied" "Source is Premultiplied" "STD_inoBlurFx" "Blur Ino" "STD_inoBlurFx.radius" "Radius" "STD_inoBlurFx.reference" "Reference" diff --git a/stuff/profiles/layouts/fxs/STD_inoColorBurnFx.xml b/stuff/profiles/layouts/fxs/STD_inoColorBurnFx.xml index 4e061e87..6073f3c5 100644 --- a/stuff/profiles/layouts/fxs/STD_inoColorBurnFx.xml +++ b/stuff/profiles/layouts/fxs/STD_inoColorBurnFx.xml @@ -2,5 +2,11 @@ opacity clipping_mask + + linear + + gamma + premultiplied + diff --git a/stuff/profiles/layouts/fxs/STD_inoColorDodgeFx.xml b/stuff/profiles/layouts/fxs/STD_inoColorDodgeFx.xml index 808776ba..3d4e87df 100644 --- a/stuff/profiles/layouts/fxs/STD_inoColorDodgeFx.xml +++ b/stuff/profiles/layouts/fxs/STD_inoColorDodgeFx.xml @@ -2,5 +2,11 @@ opacity clipping_mask + + linear + + gamma + premultiplied + diff --git a/stuff/profiles/layouts/fxs/STD_inoCrossDissolveFx.xml b/stuff/profiles/layouts/fxs/STD_inoCrossDissolveFx.xml index fa04bd36..171b7395 100644 --- a/stuff/profiles/layouts/fxs/STD_inoCrossDissolveFx.xml +++ b/stuff/profiles/layouts/fxs/STD_inoCrossDissolveFx.xml @@ -2,5 +2,11 @@ opacity clipping_mask + + linear + + gamma + premultiplied + diff --git a/stuff/profiles/layouts/fxs/STD_inoDarkenFx.xml b/stuff/profiles/layouts/fxs/STD_inoDarkenFx.xml index 4d9555b6..8041df33 100644 --- a/stuff/profiles/layouts/fxs/STD_inoDarkenFx.xml +++ b/stuff/profiles/layouts/fxs/STD_inoDarkenFx.xml @@ -2,5 +2,11 @@ opacity clipping_mask + + linear + + gamma + premultiplied + diff --git a/stuff/profiles/layouts/fxs/STD_inoDarkerColorFx.xml b/stuff/profiles/layouts/fxs/STD_inoDarkerColorFx.xml index 3d28fe53..358c5a06 100644 --- a/stuff/profiles/layouts/fxs/STD_inoDarkerColorFx.xml +++ b/stuff/profiles/layouts/fxs/STD_inoDarkerColorFx.xml @@ -2,5 +2,11 @@ opacity clipping_mask + + linear + + gamma + premultiplied + diff --git a/stuff/profiles/layouts/fxs/STD_inoDivideFx.xml b/stuff/profiles/layouts/fxs/STD_inoDivideFx.xml index e52dc55e..42eaca07 100644 --- a/stuff/profiles/layouts/fxs/STD_inoDivideFx.xml +++ b/stuff/profiles/layouts/fxs/STD_inoDivideFx.xml @@ -2,5 +2,11 @@ opacity clipping_mask + + linear + + gamma + premultiplied + diff --git a/stuff/profiles/layouts/fxs/STD_inoHardLightFx.xml b/stuff/profiles/layouts/fxs/STD_inoHardLightFx.xml index 0c624e78..8b822ef4 100644 --- a/stuff/profiles/layouts/fxs/STD_inoHardLightFx.xml +++ b/stuff/profiles/layouts/fxs/STD_inoHardLightFx.xml @@ -2,5 +2,11 @@ opacity clipping_mask + + linear + + gamma + premultiplied + diff --git a/stuff/profiles/layouts/fxs/STD_inoHardMixFx.xml b/stuff/profiles/layouts/fxs/STD_inoHardMixFx.xml index 30e073c8..c69b3928 100644 --- a/stuff/profiles/layouts/fxs/STD_inoHardMixFx.xml +++ b/stuff/profiles/layouts/fxs/STD_inoHardMixFx.xml @@ -2,5 +2,11 @@ opacity clipping_mask + + linear + + gamma + premultiplied + diff --git a/stuff/profiles/layouts/fxs/STD_inoLightenFx.xml b/stuff/profiles/layouts/fxs/STD_inoLightenFx.xml index f8ccb1f3..6c6a7600 100644 --- a/stuff/profiles/layouts/fxs/STD_inoLightenFx.xml +++ b/stuff/profiles/layouts/fxs/STD_inoLightenFx.xml @@ -2,5 +2,11 @@ opacity clipping_mask + + linear + + gamma + premultiplied + diff --git a/stuff/profiles/layouts/fxs/STD_inoLighterColorFx.xml b/stuff/profiles/layouts/fxs/STD_inoLighterColorFx.xml index 56d6903c..a143e51d 100644 --- a/stuff/profiles/layouts/fxs/STD_inoLighterColorFx.xml +++ b/stuff/profiles/layouts/fxs/STD_inoLighterColorFx.xml @@ -2,5 +2,11 @@ opacity clipping_mask + + linear + + gamma + premultiplied + diff --git a/stuff/profiles/layouts/fxs/STD_inoLinearBurnFx.xml b/stuff/profiles/layouts/fxs/STD_inoLinearBurnFx.xml index 54b4cec6..ed64746a 100644 --- a/stuff/profiles/layouts/fxs/STD_inoLinearBurnFx.xml +++ b/stuff/profiles/layouts/fxs/STD_inoLinearBurnFx.xml @@ -2,5 +2,11 @@ opacity clipping_mask + + linear + + gamma + premultiplied + diff --git a/stuff/profiles/layouts/fxs/STD_inoLinearDodgeFx.xml b/stuff/profiles/layouts/fxs/STD_inoLinearDodgeFx.xml index 8f6d1e9d..70f34a5b 100644 --- a/stuff/profiles/layouts/fxs/STD_inoLinearDodgeFx.xml +++ b/stuff/profiles/layouts/fxs/STD_inoLinearDodgeFx.xml @@ -2,5 +2,11 @@ opacity clipping_mask + + linear + + gamma + premultiplied + diff --git a/stuff/profiles/layouts/fxs/STD_inoLinearLightFx.xml b/stuff/profiles/layouts/fxs/STD_inoLinearLightFx.xml index ff371166..303bd46c 100644 --- a/stuff/profiles/layouts/fxs/STD_inoLinearLightFx.xml +++ b/stuff/profiles/layouts/fxs/STD_inoLinearLightFx.xml @@ -2,5 +2,11 @@ opacity clipping_mask + + linear + + gamma + premultiplied + diff --git a/stuff/profiles/layouts/fxs/STD_inoMultiplyFx.xml b/stuff/profiles/layouts/fxs/STD_inoMultiplyFx.xml index bee79259..5064564c 100644 --- a/stuff/profiles/layouts/fxs/STD_inoMultiplyFx.xml +++ b/stuff/profiles/layouts/fxs/STD_inoMultiplyFx.xml @@ -2,5 +2,11 @@ opacity clipping_mask + + linear + + gamma + premultiplied + diff --git a/stuff/profiles/layouts/fxs/STD_inoOverFx.xml b/stuff/profiles/layouts/fxs/STD_inoOverFx.xml index 5d2de36e..5d3f173e 100644 --- a/stuff/profiles/layouts/fxs/STD_inoOverFx.xml +++ b/stuff/profiles/layouts/fxs/STD_inoOverFx.xml @@ -2,5 +2,11 @@ opacity clipping_mask + + linear + + gamma + premultiplied + diff --git a/stuff/profiles/layouts/fxs/STD_inoOverlayFx.xml b/stuff/profiles/layouts/fxs/STD_inoOverlayFx.xml index b44ce299..d87c028e 100644 --- a/stuff/profiles/layouts/fxs/STD_inoOverlayFx.xml +++ b/stuff/profiles/layouts/fxs/STD_inoOverlayFx.xml @@ -2,5 +2,11 @@ opacity clipping_mask + + linear + + gamma + premultiplied + diff --git a/stuff/profiles/layouts/fxs/STD_inoPinLightFx.xml b/stuff/profiles/layouts/fxs/STD_inoPinLightFx.xml index ce8953d5..d8332df0 100644 --- a/stuff/profiles/layouts/fxs/STD_inoPinLightFx.xml +++ b/stuff/profiles/layouts/fxs/STD_inoPinLightFx.xml @@ -2,5 +2,11 @@ opacity clipping_mask + + linear + + gamma + premultiplied + diff --git a/stuff/profiles/layouts/fxs/STD_inoScreenFx.xml b/stuff/profiles/layouts/fxs/STD_inoScreenFx.xml index 8543c3a5..5e301a89 100644 --- a/stuff/profiles/layouts/fxs/STD_inoScreenFx.xml +++ b/stuff/profiles/layouts/fxs/STD_inoScreenFx.xml @@ -2,5 +2,11 @@ opacity clipping_mask + + linear + + gamma + premultiplied + diff --git a/stuff/profiles/layouts/fxs/STD_inoSoftLightFx.xml b/stuff/profiles/layouts/fxs/STD_inoSoftLightFx.xml index 8ece638e..416be102 100644 --- a/stuff/profiles/layouts/fxs/STD_inoSoftLightFx.xml +++ b/stuff/profiles/layouts/fxs/STD_inoSoftLightFx.xml @@ -2,5 +2,11 @@ opacity clipping_mask + + linear + + gamma + premultiplied + diff --git a/stuff/profiles/layouts/fxs/STD_inoSubtractFx.xml b/stuff/profiles/layouts/fxs/STD_inoSubtractFx.xml index 8c3c0757..4922cf04 100644 --- a/stuff/profiles/layouts/fxs/STD_inoSubtractFx.xml +++ b/stuff/profiles/layouts/fxs/STD_inoSubtractFx.xml @@ -3,5 +3,11 @@ opacity clipping_mask alpha_rendering + + linear + + gamma + premultiplied + diff --git a/stuff/profiles/layouts/fxs/STD_inoVividLightFx.xml b/stuff/profiles/layouts/fxs/STD_inoVividLightFx.xml index c2269723..12eb439c 100644 --- a/stuff/profiles/layouts/fxs/STD_inoVividLightFx.xml +++ b/stuff/profiles/layouts/fxs/STD_inoVividLightFx.xml @@ -2,5 +2,11 @@ opacity clipping_mask + + linear + + gamma + premultiplied + diff --git a/toonz/sources/stdfx/ino_blend_add.cpp b/toonz/sources/stdfx/ino_blend_add.cpp index 3ed79a8f..6bcebdc7 100644 --- a/toonz/sources/stdfx/ino_blend_add.cpp +++ b/toonz/sources/stdfx/ino_blend_add.cpp @@ -3,6 +3,7 @@ #include "stdfx.h" #include "ino_common.h" +#include "igs_color_blend.h" //------------------------------------------------------------ // Regarding computation in linear color space mode is based on the "ComposeAdd" @@ -10,475 +11,24 @@ // "ComposeAdd" is the "Source is premultiplied" option; the semi-transparent // pixels are un-premultiplied before converting to linear color space. Also // modified the transfer functions to use standard gamma correction. -//------------------------------------------------------------ - -namespace { -inline void to_xyz(double *xyz, double const *bgr) { - xyz[0] = 0.6069 * bgr[2] + 0.1735 * bgr[1] + 0.2003 * bgr[0]; // X - xyz[1] = 0.2989 * bgr[2] + 0.5866 * bgr[1] + 0.1145 * bgr[0]; // Y - xyz[2] = 0.0000 * bgr[2] + 0.0661 * bgr[1] + 1.1162 * bgr[0]; // Z -} - -inline void to_bgr(double *bgr, double const *xyz) { - bgr[0] = +0.0585 * xyz[0] - 0.1187 * xyz[1] + 0.9017 * xyz[2]; // blue - bgr[1] = -0.9844 * xyz[0] + 1.9985 * xyz[1] - 0.0279 * xyz[2]; // green - bgr[2] = +1.9104 * xyz[0] - 0.5338 * xyz[1] - 0.2891 * xyz[2]; // red -} - -// convert sRGB color space to power space -template -inline T to_linear_color_space(T nonlinear_color, T exposure, T gamma) { - // return -std::log(T(1) - std::pow(nonlinear_color, gamma)) / exposure; - return std::pow(nonlinear_color, gamma) / exposure; -} -// convert power space to sRGB color space -template -inline T to_nonlinear_color_space(T linear_color, T exposure, T gamma) { - // return std::pow(T(1) - std::exp(-exposure * linear_color), T(1) / gamma); - return std::pow(linear_color * exposure, T(1) / gamma); -} - -template -const T &clamp(const T &v, const T &lo, const T &hi) { - assert(!(hi < lo)); - return (v < lo) ? lo : (hi < v) ? hi : v; -} -} // namespace +//------------- /* tnzbase --> Source Files --> tfx --> binaryFx.cppを参照 */ class ino_blend_add final : public TBlendForeBackRasterFx { FX_PLUGIN_DECLARATION(ino_blend_add) - TRasterFxPort m_up; - TRasterFxPort m_down; - TDoubleParamP m_opacity; - TBoolParamP m_clipping_mask; - - TBoolParamP m_linear; - TDoubleParamP m_gamma; - - // If the pixel is premultiplied, divide color data by the alpha before - // converting from the colorspace, and then multiply by the alpha afterwards. - // This will correct the color of the semi-transparent pixels in most cases. - TBoolParamP m_premultiplied; public: - ino_blend_add() - : m_opacity(1.0 * ino::param_range()) - , m_clipping_mask(true) - , m_linear(false) - , m_gamma(2.2) - , m_premultiplied(true) { - addInputPort("Fore", this->m_up); - addInputPort("Back", this->m_down); - bindParam(this, "opacity", this->m_opacity); - bindParam(this, "clipping_mask", this->m_clipping_mask); - bindParam(this, "linear", this->m_linear); - bindParam(this, "gamma", this->m_gamma); - bindParam(this, "premultiplied", this->m_premultiplied); + ino_blend_add() : TBlendForeBackRasterFx(true) { + // expand the opacity range this->m_opacity->setValueRange(0, 10.0 * ino::param_range()); - this->m_gamma->setValueRange(0.2, 5.0); } ~ino_blend_add() {} - bool canHandle(const TRenderSettings &rs, double frame) override { - return true; - } - bool doGetBBox(double frame, TRectD &bBox, - const TRenderSettings &rs) override { - TRectD up_bx; - const bool up_sw = - (m_up.isConnected() ? m_up->doGetBBox(frame, up_bx, rs) : false); - TRectD dn_bx; - const bool dn_sw = - (m_down.isConnected() ? m_down->doGetBBox(frame, dn_bx, rs) : false); - if (up_sw && dn_sw) { - bBox = up_bx + dn_bx; - return !bBox.isEmpty(); - } else if (up_sw) { - bBox = up_bx; - return true; - } else if (dn_sw) { - bBox = dn_bx; - return true; - } else { - bBox = TRectD(); - return false; - } - } - // TRect getInvalidRect(const TRect &max) {return max;} - // void doSetParam(const std::string &name, const TParamP ¶m) {} - int getMemoryRequirement(const TRectD &rect, double frame, - const TRenderSettings &rs) override { - return TRasterFx::memorySize(rect, rs.m_bpp); - } - void doDryCompute(TRectD &rect, double frame, - const TRenderSettings &rs) override { - this->dryComputeUpAndDown(rect, frame, rs, false); + void brendKernel(double& dnr, double& dng, double& dnb, double& dna, + const double upr, double upg, double upb, double upa, + const double up_opacity, + const bool alpha_rendering_sw = true) override { + igs::color::add(dnr, dng, dnb, dna, upr, upg, upb, upa, up_opacity); } - void doCompute(TTile &tile, double frame, const TRenderSettings &rs) override; - void computeUpAndDown(TTile &tile, double frame, const TRenderSettings &rs, - TRasterP &dn_ras, TRasterP &up_ras, - bool upComputesWholeTile = false); - void dryComputeUpAndDown(TRectD &rect, double frame, - const TRenderSettings &rs, - bool upComputesWholeTile = false - /* - upComputesWholeTile は Screen, Min, Blendでtrueにして使用している。 - */ - ); }; -FX_PLUGIN_IDENTIFIER(ino_blend_add, "inoAddFx"); -//------------------------------------------------------------ -namespace { -/* より大きな四角エリアにPixel整数値で密着する */ -void makeRectCoherent(TRectD &rect, const TPointD &pos) { - rect -= pos; - rect.x0 = tfloor(rect.x0); /* ((x)<(int)(x)? (int)(x)-1: (int)(x))*/ - rect.y0 = tfloor(rect.y0); - rect.x1 = tceil(rect.x1); /* ((int)(x)<(x)? (int)(x)+1: (int)(x))*/ - rect.y1 = tceil(rect.y1); - rect += pos; -} -} // namespace -void ino_blend_add::computeUpAndDown(TTile &tile, double frame, - const TRenderSettings &rs, - TRasterP &dn_ras, TRasterP &up_ras, - bool upComputesWholeTile) { - /* ------ サポートしていないPixelタイプはエラーを投げる --- */ - if (!((TRaster32P)tile.getRaster()) && !((TRaster64P)tile.getRaster())) { - throw TRopException("unsupported input pixel type"); - } - /* -m_down,m_upは繋がっている方があればそれを表示する -両方とも接続していれば合成処理する -表示スイッチを切ってあるならm_upを表示する -fxをreplaceすると、 - m_source --> m_up (=port0) - m_refernce --> m_down(=port1) -となる -*/ - const bool up_is = (this->m_up.isConnected() && - this->m_up.getFx()->getTimeRegion().contains(frame)); - const bool down_is = (this->m_down.isConnected() && - this->m_down.getFx()->getTimeRegion().contains(frame)); - /* ------ 両方とも切断の時処理しない ---------------------- */ - if (!up_is && !down_is) { - tile.getRaster()->clear(); - return; - } - /* ------ up接続かつdown切断の時 -------------------------- */ - if (up_is && !down_is) { - this->m_up->compute(tile, frame, rs); - return; - } - /* ------ down接続時 downのみ描画して... ------------------ */ - if (down_is) { - this->m_down->compute(tile, frame, rs); - } - /* ------ up切断時 ---------------------------------------- */ - if (!up_is) { - return; - } - - /* upと重なる部分を描画する */ - - /* ------ tileの範囲 -------------------------------------- */ - const TDimension tsz(tile.getRaster()->getSize()); /* 整数 */ - const TRectD tileRect(tile.m_pos, TDimensionD(tsz.lx, tsz.ly)); - TRectD upBBox; - if (upComputesWholeTile) { - upBBox = tileRect; - } /* tile全体を得る */ - else { /* 厳密なエリア... */ - this->m_up->getBBox(frame, upBBox, rs); - upBBox *= tileRect; /* upとtileの交差エリア */ - - /* より大きな四角エリアにPixel整数値で密着する */ - makeRectCoherent(upBBox, tile.m_pos); // double-->int grid - } - - TDimensionI upSize( /* TRectDをTDimensionIに変換 */ - tround(upBBox.getLx()) // getLx() = "x1>=x0?x1-x0:0" - , - tround(upBBox.getLy()) // getLy() = "y1>=y0?y1-y0:0" - ); - if ((upSize.lx <= 0) || (upSize.ly <= 0)) { - return; - } - - /* ------ upのメモリ確保と描画 ---------------------------- */ - TTile upTile; - this->m_up->allocateAndCompute(upTile, upBBox.getP00(), upSize, - tile.getRaster() /* 32/64bitsの判定に使う */ - , - frame, rs); - /* ------ upとdownのTRasterを得る ------------------------- */ - TRectI dnRect(upTile.getRaster()->getSize()); // TDimensionI(-) - - dnRect += convert(upTile.m_pos - tile.m_pos); /* uptile->tile原点 */ - /* - ここで問題はdoubleの位置を、四捨五入して整数値にしていること - 移動してから四捨五入ではないの??? - dnRectの元位置が整数位置なので、問題ないか... - */ - - dn_ras = upComputesWholeTile ? tile.getRaster() - : tile.getRaster()->extract(dnRect); - up_ras = upTile.getRaster(); - assert(dn_ras->getSize() == up_ras->getSize()); -} -void ino_blend_add::dryComputeUpAndDown(TRectD &rect, double frame, - const TRenderSettings &rs, - bool upComputesWholeTile) { - const bool up_is = (this->m_up.isConnected() && - this->m_up.getFx()->getTimeRegion().contains(frame)); - const bool down_is = (this->m_down.isConnected() && - this->m_down.getFx()->getTimeRegion().contains(frame)); - /* ------ 両方とも切断の時処理しない ---------------------- */ - if (!up_is && !down_is) { - return; - } - /* ------ up接続かつdown切断の時 -------------------------- */ - if (up_is && !down_is) { - this->m_up->dryCompute(rect, frame, rs); - return; - } - /* ------ down接続時 -------------------------------------- */ - if (down_is) { - this->m_down->dryCompute(rect, frame, rs); - } - /* ------ up切断時 ---------------------------------------- */ - if (!up_is) { - return; - } - - /* ------ tileのgeometryを計算する ------------------------ */ - TRectD upBBox; - - if (upComputesWholeTile) { - upBBox = rect; - } else { - this->m_up->getBBox(frame, upBBox, rs); - upBBox *= rect; - makeRectCoherent(upBBox, rect.getP00()); - } - if ((upBBox.getLx() > 0.5) && (upBBox.getLy() > 0.5)) { - this->m_up->dryCompute(upBBox, frame, rs); - } -} -//------------------------------------------------------------ -#include /* std::ostringstream */ -#include "igs_color_blend.h" -namespace { -template -void tmpl_(TRasterPT dn_ras_out, const TRasterPT &up_ras, - const double up_opacity, const bool clipping_mask_sw) { - double maxi = static_cast(T::maxChannelValue); // 255or65535 - - assert(dn_ras_out->getSize() == up_ras->getSize()); - - for (int yy = 0; yy < dn_ras_out->getLy(); ++yy) { - T *out_pix = dn_ras_out->pixels(yy); - const T *const out_end = out_pix + dn_ras_out->getLx(); - const T *up_pix = up_ras->pixels(yy); - for (; out_pix < out_end; ++out_pix, ++up_pix) { - double upr = static_cast(up_pix->r) / maxi; - double upg = static_cast(up_pix->g) / maxi; - double upb = static_cast(up_pix->b) / maxi; - double upa = static_cast(up_pix->m) / maxi; - double dnr = static_cast(out_pix->r) / maxi; - double dng = static_cast(out_pix->g) / maxi; - double dnb = static_cast(out_pix->b) / maxi; - double dna = static_cast(out_pix->m) / maxi; - igs::color::add(dnr, dng, dnb, dna, upr, upg, upb, upa, - clipping_mask_sw ? up_opacity * dna : up_opacity); - out_pix->r = static_cast(dnr * (maxi + 0.999999)); - out_pix->g = static_cast(dng * (maxi + 0.999999)); - out_pix->b = static_cast(dnb * (maxi + 0.999999)); - out_pix->m = static_cast(dna * (maxi + 0.999999)); - } - } -} - -template -void linearAdd(TRasterPT dn_ras_out, const TRasterPT &up_ras, - const double up_opacity, const bool clipping_mask_sw, - const double gamma, const bool premultiplied_sw) { - double maxi = static_cast(T::maxChannelValue); // 255or65535 - double limit = (maxi + 0.5) / (maxi + 1.0); - - assert(dn_ras_out->getSize() == up_ras->getSize()); - - for (int yy = 0; yy < dn_ras_out->getLy(); ++yy) { - T *out_pix = dn_ras_out->pixels(yy); - const T *const out_end = out_pix + dn_ras_out->getLx(); - const T *up_pix = up_ras->pixels(yy); - for (; out_pix < out_end; ++out_pix, ++up_pix) { - if (up_pix->m <= 0 || up_opacity <= 0) { - continue; - } - - double dna = static_cast(out_pix->m) / maxi; - double tmp_opacity = clipping_mask_sw ? up_opacity * dna : up_opacity; - if (tmp_opacity <= 0) continue; - - double dnBGR[3]; - dnBGR[0] = static_cast(out_pix->b) / maxi; - dnBGR[1] = static_cast(out_pix->g) / maxi; - dnBGR[2] = static_cast(out_pix->r) / maxi; - double dnXYZ[3] = {0.0, 0.0, 0.0}; - if (dna > 0.0) { - for (int c = 0; c < 3; c++) { - if (premultiplied_sw) - dnBGR[c] = to_linear_color_space(dnBGR[c] / dna, 1.0, gamma) * dna; - else - dnBGR[c] = to_linear_color_space(dnBGR[c], 1.0, gamma); - } - to_xyz(dnXYZ, dnBGR); - } - - double exposure = 1.0 / tmp_opacity; - double upBGR[3]; - upBGR[0] = static_cast(up_pix->b) / maxi; - upBGR[1] = static_cast(up_pix->g) / maxi; - upBGR[2] = static_cast(up_pix->r) / maxi; - double upa = static_cast(up_pix->m) / maxi; - for (int c = 0; c < 3; c++) { - if (premultiplied_sw) - upBGR[c] = - to_linear_color_space(upBGR[c] / upa, exposure, gamma) * upa; - else - upBGR[c] = to_linear_color_space(upBGR[c], exposure, gamma); - } - - double upXYZ[3]; - to_xyz(upXYZ, upBGR); - - for (int c = 0; c < 3; c++) dnXYZ[c] += upXYZ[c]; - - to_bgr(dnBGR, dnXYZ); - // just do over-composite for alpha channel - dna = upa * tmp_opacity + dna * (1.0 - upa * tmp_opacity); - dna = clamp(dna, 0.0, 1.0); - // premultiply the result - double nonlinear_b = - to_nonlinear_color_space(dnBGR[0] / dna, 1.0, gamma) * dna; - double nonlinear_g = - to_nonlinear_color_space(dnBGR[1] / dna, 1.0, gamma) * dna; - double nonlinear_r = - to_nonlinear_color_space(dnBGR[2] / dna, 1.0, gamma) * dna; - - out_pix->r = - static_cast(clamp(nonlinear_r, 0.0, 1.0) * (maxi + 0.999999)); - out_pix->g = - static_cast(clamp(nonlinear_g, 0.0, 1.0) * (maxi + 0.999999)); - out_pix->b = - static_cast(clamp(nonlinear_b, 0.0, 1.0) * (maxi + 0.999999)); - out_pix->m = static_cast(dna * (maxi + 0.999999)); - } - } -} - -void fx_(TRasterP &dn_ras_out, const TRasterP &up_ras, const TPoint &pos, - const double up_opacity, const bool clipping_mask_sw, - const bool linear_sw, const double gamma, - const bool premultiplied_sw) { - /* 交差したエリアを処理するようにする、いるのか??? */ - TRect outRect(dn_ras_out->getBounds()); - TRect upRect(up_ras->getBounds() + pos); - TRect intersection = outRect * upRect; - if (intersection.isEmpty()) return; - - TRasterP cRout = dn_ras_out->extract(intersection); - TRect rr = intersection - pos; - TRasterP cRup = up_ras->extract(rr); - - TRaster32P rout32 = cRout, rup32 = cRup; - TRaster64P rout64 = cRout, rup64 = cRup; - - if (rout32 && rup32) { - if (linear_sw) - linearAdd(rout32, rup32, up_opacity, clipping_mask_sw, - gamma, premultiplied_sw); - else - tmpl_(rout32, rup32, up_opacity, clipping_mask_sw); - } else if (rout64 && rup64) { - if (linear_sw) - linearAdd(rout64, rup64, up_opacity, clipping_mask_sw, - gamma, premultiplied_sw); - else - tmpl_(rout64, rup64, up_opacity, clipping_mask_sw); - } else { - throw TRopException("unsupported pixel type"); - } -} -} // namespace -void ino_blend_add::doCompute(TTile &tile, double frame, - const TRenderSettings &rs) { - /* ------ 画像生成 ---------------------------------------- */ - TRasterP dn_ras, up_ras; - this->computeUpAndDown(tile, frame, rs, dn_ras, up_ras); - if (!dn_ras || !up_ras) { - return; - } - /* ------ 動作パラメータを得る ---------------------------- */ - const double up_opacity = - this->m_opacity->getValue(frame) / ino::param_range(); - const double gamma = this->m_gamma->getValue(frame); - /* ------ (app_begin)log記憶 ------------------------------ */ - const bool log_sw = ino::log_enable_sw(); - - if (log_sw) { - std::ostringstream os; - os << "params" - << " up_opacity " << up_opacity << " dn_tile w " << dn_ras->getLx() - << " wrap " << dn_ras->getWrap() << " h " << dn_ras->getLy() - << " pixbits " << ino::pixel_bits(dn_ras) << " up_tile w " - << up_ras->getLx() << " wrap " << up_ras->getWrap() << " h " - << up_ras->getLy() << " pixbits " << ino::pixel_bits(up_ras) - << " frame " << frame; - } - /* ------ fx処理 ------------------------------------------ */ - try { - if (dn_ras) { - dn_ras->lock(); - } - if (up_ras) { - up_ras->lock(); - } - fx_(dn_ras, up_ras, TPoint(), up_opacity, this->m_clipping_mask->getValue(), - this->m_linear->getValue(), gamma, this->m_premultiplied->getValue()); - if (up_ras) { - up_ras->unlock(); - } - if (dn_ras) { - dn_ras->unlock(); - } - } - /* ------ error処理 --------------------------------------- */ - catch (std::exception &e) { - if (up_ras) { - up_ras->unlock(); - } - if (dn_ras) { - dn_ras->unlock(); - } - if (log_sw) { - std::string str("exception <"); - str += e.what(); - str += '>'; - } - throw; - } catch (...) { - if (up_ras) { - up_ras->unlock(); - } - if (dn_ras) { - dn_ras->unlock(); - } - if (log_sw) { - std::string str("other exception"); - } - throw; - } -} +FX_PLUGIN_IDENTIFIER(ino_blend_add, "inoAddFx"); \ No newline at end of file diff --git a/toonz/sources/stdfx/ino_blend_color_burn.cpp b/toonz/sources/stdfx/ino_blend_color_burn.cpp index 2c186270..6c143fec 100644 --- a/toonz/sources/stdfx/ino_blend_color_burn.cpp +++ b/toonz/sources/stdfx/ino_blend_color_burn.cpp @@ -3,333 +3,19 @@ #include "stdfx.h" #include "ino_common.h" +#include "igs_color_blend.h" /* tnzbase --> Source Files --> tfx --> binaryFx.cppを参照 */ class ino_blend_color_burn final : public TBlendForeBackRasterFx { FX_PLUGIN_DECLARATION(ino_blend_color_burn) - TRasterFxPort m_up; - TRasterFxPort m_down; - TDoubleParamP m_opacity; - TBoolParamP m_clipping_mask; public: - ino_blend_color_burn() - : m_opacity(1.0 * ino::param_range()), m_clipping_mask(true) { - addInputPort("Fore", this->m_up); - addInputPort("Back", this->m_down); - bindParam(this, "opacity", this->m_opacity); - bindParam(this, "clipping_mask", this->m_clipping_mask); - this->m_opacity->setValueRange(0, 1.0 * ino::param_range()); - } + ino_blend_color_burn() : TBlendForeBackRasterFx(true) {} ~ino_blend_color_burn() {} - bool canHandle(const TRenderSettings &rs, double frame) override { - return true; + void brendKernel(double& dnr, double& dng, double& dnb, double& dna, + const double upr, double upg, double upb, double upa, + const double up_opacity, + const bool alpha_rendering_sw = true) override { + igs::color::color_burn(dnr, dng, dnb, dna, upr, upg, upb, upa, up_opacity); } - bool doGetBBox(double frame, TRectD &bBox, - const TRenderSettings &rs) override { - TRectD up_bx; - const bool up_sw = - (m_up.isConnected() ? m_up->doGetBBox(frame, up_bx, rs) : false); - TRectD dn_bx; - const bool dn_sw = - (m_down.isConnected() ? m_down->doGetBBox(frame, dn_bx, rs) : false); - if (up_sw && dn_sw) { - bBox = up_bx + dn_bx; - return !bBox.isEmpty(); - } else if (up_sw) { - bBox = up_bx; - return true; - } else if (dn_sw) { - bBox = dn_bx; - return true; - } else { - bBox = TRectD(); - return false; - } - } - // TRect getInvalidRect(const TRect &max) {return max;} - // void doSetParam(const std::string &name, const TParamP ¶m) {} - int getMemoryRequirement(const TRectD &rect, double frame, - const TRenderSettings &rs) override { - return TRasterFx::memorySize(rect, rs.m_bpp); - } - - void doDryCompute(TRectD &rect, double frame, - const TRenderSettings &rs) override { - this->dryComputeUpAndDown(rect, frame, rs, false); - } - void doCompute(TTile &tile, double frame, const TRenderSettings &rs) override; - void computeUpAndDown(TTile &tile, double frame, const TRenderSettings &rs, - TRasterP &dn_ras, TRasterP &up_ras, - bool upComputesWholeTile = false); - void dryComputeUpAndDown(TRectD &rect, double frame, - const TRenderSettings &rs, - bool upComputesWholeTile = false - /* - upComputesWholeTile は Screen, Min, Blendでtrueにして使用している。 - */ - ); }; FX_PLUGIN_IDENTIFIER(ino_blend_color_burn, "inoColorBurnFx"); -//------------------------------------------------------------ -namespace { -/* より大きな四角エリアにPixel整数値で密着する */ -void makeRectCoherent(TRectD &rect, const TPointD &pos) { - rect -= pos; - rect.x0 = tfloor(rect.x0); /* ((x)<(int)(x)? (int)(x)-1: (int)(x))*/ - rect.y0 = tfloor(rect.y0); - rect.x1 = tceil(rect.x1); /* ((int)(x)<(x)? (int)(x)+1: (int)(x))*/ - rect.y1 = tceil(rect.y1); - rect += pos; -} -} -void ino_blend_color_burn::computeUpAndDown(TTile &tile, double frame, - const TRenderSettings &rs, - TRasterP &dn_ras, TRasterP &up_ras, - bool upComputesWholeTile) { - /* ------ サポートしていないPixelタイプはエラーを投げる --- */ - if (!((TRaster32P)tile.getRaster()) && !((TRaster64P)tile.getRaster())) { - throw TRopException("unsupported input pixel type"); - } - /* -m_down,m_upは繋がっている方があればそれを表示する -両方とも接続していれば合成処理する -表示スイッチを切ってあるならm_upを表示する -fxをreplaceすると、 - m_source --> m_up (=port0) - m_refernce --> m_down(=port1) -となる -*/ - const bool up_is = (this->m_up.isConnected() && - this->m_up.getFx()->getTimeRegion().contains(frame)); - const bool down_is = (this->m_down.isConnected() && - this->m_down.getFx()->getTimeRegion().contains(frame)); - /* ------ 両方とも切断の時処理しない ---------------------- */ - if (!up_is && !down_is) { - tile.getRaster()->clear(); - return; - } - /* ------ up接続かつdown切断の時 -------------------------- */ - if (up_is && !down_is) { - this->m_up->compute(tile, frame, rs); - return; - } - /* ------ down接続時 downのみ描画して... ------------------ */ - if (down_is) { - this->m_down->compute(tile, frame, rs); - } - /* ------ up切断時 ---------------------------------------- */ - if (!up_is) { - return; - } - - /* upと重なる部分を描画する */ - - /* ------ tileの範囲 -------------------------------------- */ - const TDimension tsz(tile.getRaster()->getSize()); /* 整数 */ - const TRectD tileRect(tile.m_pos, TDimensionD(tsz.lx, tsz.ly)); - TRectD upBBox; - if (upComputesWholeTile) { - upBBox = tileRect; - } /* tile全体を得る */ - else { /* 厳密なエリア... */ - this->m_up->getBBox(frame, upBBox, rs); - upBBox *= tileRect; /* upとtileの交差エリア */ - - /* より大きな四角エリアにPixel整数値で密着する */ - makeRectCoherent(upBBox, tile.m_pos); // double-->int grid - } - - TDimensionI upSize( /* TRectDをTDimensionIに変換 */ - tround(upBBox.getLx()) // getLx() = "x1>=x0?x1-x0:0" - , - tround(upBBox.getLy()) // getLy() = "y1>=y0?y1-y0:0" - ); - if ((upSize.lx <= 0) || (upSize.ly <= 0)) { - return; - } - - /* ------ upのメモリ確保と描画 ---------------------------- */ - TTile upTile; - this->m_up->allocateAndCompute(upTile, upBBox.getP00(), upSize, - tile.getRaster() /* 32/64bitsの判定に使う */ - , - frame, rs); - /* ------ upとdownのTRasterを得る ------------------------- */ - TRectI dnRect(upTile.getRaster()->getSize()); // TDimensionI(-) - - dnRect += convert(upTile.m_pos - tile.m_pos); /* uptile->tile原点 */ - /* - ここで問題はdoubleの位置を、四捨五入して整数値にしていること - 移動してから四捨五入ではないの??? - dnRectの元位置が整数位置なので、問題ないか... - */ - - dn_ras = upComputesWholeTile ? tile.getRaster() - : tile.getRaster()->extract(dnRect); - up_ras = upTile.getRaster(); - assert(dn_ras->getSize() == up_ras->getSize()); -} -void ino_blend_color_burn::dryComputeUpAndDown(TRectD &rect, double frame, - const TRenderSettings &rs, - bool upComputesWholeTile) { - const bool up_is = (this->m_up.isConnected() && - this->m_up.getFx()->getTimeRegion().contains(frame)); - const bool down_is = (this->m_down.isConnected() && - this->m_down.getFx()->getTimeRegion().contains(frame)); - /* ------ 両方とも切断の時処理しない ---------------------- */ - if (!up_is && !down_is) { - return; - } - /* ------ up接続かつdown切断の時 -------------------------- */ - if (up_is && !down_is) { - this->m_up->dryCompute(rect, frame, rs); - return; - } - /* ------ down接続時 -------------------------------------- */ - if (down_is) { - this->m_down->dryCompute(rect, frame, rs); - } - /* ------ up切断時 ---------------------------------------- */ - if (!up_is) { - return; - } - - /* ------ tileのgeometryを計算する ------------------------ */ - TRectD upBBox; - - if (upComputesWholeTile) { - upBBox = rect; - } else { - this->m_up->getBBox(frame, upBBox, rs); - upBBox *= rect; - makeRectCoherent(upBBox, rect.getP00()); - } - if ((upBBox.getLx() > 0.5) && (upBBox.getLy() > 0.5)) { - this->m_up->dryCompute(upBBox, frame, rs); - } -} -//------------------------------------------------------------ -#include /* std::ostringstream */ -#include "igs_color_blend.h" -namespace { -template -void tmpl_(TRasterPT dn_ras_out, const TRasterPT &up_ras, - const double up_opacity, const bool clipping_mask_sw) { - double maxi = static_cast(T::maxChannelValue); // 255or65535 - - assert(dn_ras_out->getSize() == up_ras->getSize()); - - for (int yy = 0; yy < dn_ras_out->getLy(); ++yy) { - T *out_pix = dn_ras_out->pixels(yy); - const T *const out_end = out_pix + dn_ras_out->getLx(); - const T *up_pix = up_ras->pixels(yy); - for (; out_pix < out_end; ++out_pix, ++up_pix) { - double upr = static_cast(up_pix->r) / maxi; - double upg = static_cast(up_pix->g) / maxi; - double upb = static_cast(up_pix->b) / maxi; - double upa = static_cast(up_pix->m) / maxi; - double dnr = static_cast(out_pix->r) / maxi; - double dng = static_cast(out_pix->g) / maxi; - double dnb = static_cast(out_pix->b) / maxi; - double dna = static_cast(out_pix->m) / maxi; - igs::color::color_burn(dnr, dng, dnb, dna, upr, upg, upb, upa, - clipping_mask_sw ? up_opacity * dna : up_opacity); - out_pix->r = static_cast(dnr * (maxi + 0.999999)); - out_pix->g = static_cast(dng * (maxi + 0.999999)); - out_pix->b = static_cast(dnb * (maxi + 0.999999)); - out_pix->m = static_cast(dna * (maxi + 0.999999)); - } - } -} -void fx_(TRasterP &dn_ras_out, const TRasterP &up_ras, const TPoint &pos, - const double up_opacity, const bool clipping_mask_sw) { - /* 交差したエリアを処理するようにする、いるのか??? */ - TRect outRect(dn_ras_out->getBounds()); - TRect upRect(up_ras->getBounds() + pos); - TRect intersection = outRect * upRect; - if (intersection.isEmpty()) return; - - TRasterP cRout = dn_ras_out->extract(intersection); - TRect rr = intersection - pos; - TRasterP cRup = up_ras->extract(rr); - - TRaster32P rout32 = cRout, rup32 = cRup; - TRaster64P rout64 = cRout, rup64 = cRup; - - if (rout32 && rup32) { - tmpl_(rout32, rup32, up_opacity, clipping_mask_sw); - } else if (rout64 && rup64) { - tmpl_(rout64, rup64, up_opacity, clipping_mask_sw); - } else { - throw TRopException("unsupported pixel type"); - } -} -} -void ino_blend_color_burn::doCompute(TTile &tile, double frame, - const TRenderSettings &rs) { - /* ------ 画像生成 ---------------------------------------- */ - TRasterP dn_ras, up_ras; - this->computeUpAndDown(tile, frame, rs, dn_ras, up_ras); - if (!dn_ras || !up_ras) { - return; - } - /* ------ 動作パラメータを得る ---------------------------- */ - const double up_opacity = - this->m_opacity->getValue(frame) / ino::param_range(); - /* ------ (app_begin)log記憶 ------------------------------ */ - const bool log_sw = ino::log_enable_sw(); - - if (log_sw) { - std::ostringstream os; - os << "params" - << " up_opacity " << up_opacity << " dn_tile w " << dn_ras->getLx() - << " wrap " << dn_ras->getWrap() << " h " << dn_ras->getLy() - << " pixbits " << ino::pixel_bits(dn_ras) << " up_tile w " - << up_ras->getLx() << " wrap " << up_ras->getWrap() << " h " - << up_ras->getLy() << " pixbits " << ino::pixel_bits(up_ras) - << " frame " << frame; - } - /* ------ fx処理 ------------------------------------------ */ - try { - if (dn_ras) { - dn_ras->lock(); - } - if (up_ras) { - up_ras->lock(); - } - fx_(dn_ras, up_ras, TPoint(), up_opacity, - this->m_clipping_mask->getValue()); - if (up_ras) { - up_ras->unlock(); - } - if (dn_ras) { - dn_ras->unlock(); - } - } - /* ------ error処理 --------------------------------------- */ - catch (std::exception &e) { - if (up_ras) { - up_ras->unlock(); - } - if (dn_ras) { - dn_ras->unlock(); - } - if (log_sw) { - std::string str("exception <"); - str += e.what(); - str += '>'; - } - throw; - } catch (...) { - if (up_ras) { - up_ras->unlock(); - } - if (dn_ras) { - dn_ras->unlock(); - } - if (log_sw) { - std::string str("other exception"); - } - throw; - } -} diff --git a/toonz/sources/stdfx/ino_blend_color_dodge.cpp b/toonz/sources/stdfx/ino_blend_color_dodge.cpp index ddda38eb..eaf4180f 100644 --- a/toonz/sources/stdfx/ino_blend_color_dodge.cpp +++ b/toonz/sources/stdfx/ino_blend_color_dodge.cpp @@ -3,333 +3,19 @@ #include "stdfx.h" #include "ino_common.h" +#include "igs_color_blend.h" /* tnzbase --> Source Files --> tfx --> binaryFx.cppを参照 */ class ino_blend_color_dodge final : public TBlendForeBackRasterFx { FX_PLUGIN_DECLARATION(ino_blend_color_dodge) - TRasterFxPort m_up; - TRasterFxPort m_down; - TDoubleParamP m_opacity; - TBoolParamP m_clipping_mask; public: - ino_blend_color_dodge() - : m_opacity(1.0 * ino::param_range()), m_clipping_mask(true) { - addInputPort("Fore", this->m_up); - addInputPort("Back", this->m_down); - bindParam(this, "opacity", this->m_opacity); - bindParam(this, "clipping_mask", this->m_clipping_mask); - this->m_opacity->setValueRange(0, 1.0 * ino::param_range()); - } + ino_blend_color_dodge() : TBlendForeBackRasterFx(true) {} ~ino_blend_color_dodge() {} - bool canHandle(const TRenderSettings &rs, double frame) override { - return true; + void brendKernel(double& dnr, double& dng, double& dnb, double& dna, + const double upr, double upg, double upb, double upa, + const double up_opacity, + const bool alpha_rendering_sw = true) override { + igs::color::color_dodge(dnr, dng, dnb, dna, upr, upg, upb, upa, up_opacity); } - bool doGetBBox(double frame, TRectD &bBox, - const TRenderSettings &rs) override { - TRectD up_bx; - const bool up_sw = - (m_up.isConnected() ? m_up->doGetBBox(frame, up_bx, rs) : false); - TRectD dn_bx; - const bool dn_sw = - (m_down.isConnected() ? m_down->doGetBBox(frame, dn_bx, rs) : false); - if (up_sw && dn_sw) { - bBox = up_bx + dn_bx; - return !bBox.isEmpty(); - } else if (up_sw) { - bBox = up_bx; - return true; - } else if (dn_sw) { - bBox = dn_bx; - return true; - } else { - bBox = TRectD(); - return false; - } - } - // TRect getInvalidRect(const TRect &max) {return max;} - // void doSetParam(const std::string &name, const TParamP ¶m) {} - int getMemoryRequirement(const TRectD &rect, double frame, - const TRenderSettings &rs) override { - return TRasterFx::memorySize(rect, rs.m_bpp); - } - - void doDryCompute(TRectD &rect, double frame, - const TRenderSettings &rs) override { - this->dryComputeUpAndDown(rect, frame, rs, false); - } - void doCompute(TTile &tile, double frame, const TRenderSettings &rs) override; - void computeUpAndDown(TTile &tile, double frame, const TRenderSettings &rs, - TRasterP &dn_ras, TRasterP &up_ras, - bool upComputesWholeTile = false); - void dryComputeUpAndDown(TRectD &rect, double frame, - const TRenderSettings &rs, - bool upComputesWholeTile = false - /* - upComputesWholeTile は Screen, Min, Blendでtrueにして使用している。 - */ - ); }; FX_PLUGIN_IDENTIFIER(ino_blend_color_dodge, "inoColorDodgeFx"); -//------------------------------------------------------------ -namespace { -/* より大きな四角エリアにPixel整数値で密着する */ -void makeRectCoherent(TRectD &rect, const TPointD &pos) { - rect -= pos; - rect.x0 = tfloor(rect.x0); /* ((x)<(int)(x)? (int)(x)-1: (int)(x))*/ - rect.y0 = tfloor(rect.y0); - rect.x1 = tceil(rect.x1); /* ((int)(x)<(x)? (int)(x)+1: (int)(x))*/ - rect.y1 = tceil(rect.y1); - rect += pos; -} -} -void ino_blend_color_dodge::computeUpAndDown(TTile &tile, double frame, - const TRenderSettings &rs, - TRasterP &dn_ras, TRasterP &up_ras, - bool upComputesWholeTile) { - /* ------ サポートしていないPixelタイプはエラーを投げる --- */ - if (!((TRaster32P)tile.getRaster()) && !((TRaster64P)tile.getRaster())) { - throw TRopException("unsupported input pixel type"); - } - /* -m_down,m_upは繋がっている方があればそれを表示する -両方とも接続していれば合成処理する -表示スイッチを切ってあるならm_upを表示する -fxをreplaceすると、 - m_source --> m_up (=port0) - m_refernce --> m_down(=port1) -となる -*/ - const bool up_is = (this->m_up.isConnected() && - this->m_up.getFx()->getTimeRegion().contains(frame)); - const bool down_is = (this->m_down.isConnected() && - this->m_down.getFx()->getTimeRegion().contains(frame)); - /* ------ 両方とも切断の時処理しない ---------------------- */ - if (!up_is && !down_is) { - tile.getRaster()->clear(); - return; - } - /* ------ up接続かつdown切断の時 -------------------------- */ - if (up_is && !down_is) { - this->m_up->compute(tile, frame, rs); - return; - } - /* ------ down接続時 downのみ描画して... ------------------ */ - if (down_is) { - this->m_down->compute(tile, frame, rs); - } - /* ------ up切断時 ---------------------------------------- */ - if (!up_is) { - return; - } - - /* upと重なる部分を描画する */ - - /* ------ tileの範囲 -------------------------------------- */ - const TDimension tsz(tile.getRaster()->getSize()); /* 整数 */ - const TRectD tileRect(tile.m_pos, TDimensionD(tsz.lx, tsz.ly)); - TRectD upBBox; - if (upComputesWholeTile) { - upBBox = tileRect; - } /* tile全体を得る */ - else { /* 厳密なエリア... */ - this->m_up->getBBox(frame, upBBox, rs); - upBBox *= tileRect; /* upとtileの交差エリア */ - - /* より大きな四角エリアにPixel整数値で密着する */ - makeRectCoherent(upBBox, tile.m_pos); // double-->int grid - } - - TDimensionI upSize( /* TRectDをTDimensionIに変換 */ - tround(upBBox.getLx()) // getLx() = "x1>=x0?x1-x0:0" - , - tround(upBBox.getLy()) // getLy() = "y1>=y0?y1-y0:0" - ); - if ((upSize.lx <= 0) || (upSize.ly <= 0)) { - return; - } - - /* ------ upのメモリ確保と描画 ---------------------------- */ - TTile upTile; - this->m_up->allocateAndCompute(upTile, upBBox.getP00(), upSize, - tile.getRaster() /* 32/64bitsの判定に使う */ - , - frame, rs); - /* ------ upとdownのTRasterを得る ------------------------- */ - TRectI dnRect(upTile.getRaster()->getSize()); // TDimensionI(-) - - dnRect += convert(upTile.m_pos - tile.m_pos); /* uptile->tile原点 */ - /* - ここで問題はdoubleの位置を、四捨五入して整数値にしていること - 移動してから四捨五入ではないの??? - dnRectの元位置が整数位置なので、問題ないか... - */ - - dn_ras = upComputesWholeTile ? tile.getRaster() - : tile.getRaster()->extract(dnRect); - up_ras = upTile.getRaster(); - assert(dn_ras->getSize() == up_ras->getSize()); -} -void ino_blend_color_dodge::dryComputeUpAndDown(TRectD &rect, double frame, - const TRenderSettings &rs, - bool upComputesWholeTile) { - const bool up_is = (this->m_up.isConnected() && - this->m_up.getFx()->getTimeRegion().contains(frame)); - const bool down_is = (this->m_down.isConnected() && - this->m_down.getFx()->getTimeRegion().contains(frame)); - /* ------ 両方とも切断の時処理しない ---------------------- */ - if (!up_is && !down_is) { - return; - } - /* ------ up接続かつdown切断の時 -------------------------- */ - if (up_is && !down_is) { - this->m_up->dryCompute(rect, frame, rs); - return; - } - /* ------ down接続時 -------------------------------------- */ - if (down_is) { - this->m_down->dryCompute(rect, frame, rs); - } - /* ------ up切断時 ---------------------------------------- */ - if (!up_is) { - return; - } - - /* ------ tileのgeometryを計算する ------------------------ */ - TRectD upBBox; - - if (upComputesWholeTile) { - upBBox = rect; - } else { - this->m_up->getBBox(frame, upBBox, rs); - upBBox *= rect; - makeRectCoherent(upBBox, rect.getP00()); - } - if ((upBBox.getLx() > 0.5) && (upBBox.getLy() > 0.5)) { - this->m_up->dryCompute(upBBox, frame, rs); - } -} -//------------------------------------------------------------ -#include /* std::ostringstream */ -#include "igs_color_blend.h" -namespace { -template -void tmpl_(TRasterPT dn_ras_out, const TRasterPT &up_ras, - const double up_opacity, const bool clipping_mask_sw) { - double maxi = static_cast(T::maxChannelValue); // 255or65535 - - assert(dn_ras_out->getSize() == up_ras->getSize()); - - for (int yy = 0; yy < dn_ras_out->getLy(); ++yy) { - T *out_pix = dn_ras_out->pixels(yy); - const T *const out_end = out_pix + dn_ras_out->getLx(); - const T *up_pix = up_ras->pixels(yy); - for (; out_pix < out_end; ++out_pix, ++up_pix) { - double upr = static_cast(up_pix->r) / maxi; - double upg = static_cast(up_pix->g) / maxi; - double upb = static_cast(up_pix->b) / maxi; - double upa = static_cast(up_pix->m) / maxi; - double dnr = static_cast(out_pix->r) / maxi; - double dng = static_cast(out_pix->g) / maxi; - double dnb = static_cast(out_pix->b) / maxi; - double dna = static_cast(out_pix->m) / maxi; - igs::color::color_dodge(dnr, dng, dnb, dna, upr, upg, upb, upa, - clipping_mask_sw ? up_opacity * dna : up_opacity); - out_pix->r = static_cast(dnr * (maxi + 0.999999)); - out_pix->g = static_cast(dng * (maxi + 0.999999)); - out_pix->b = static_cast(dnb * (maxi + 0.999999)); - out_pix->m = static_cast(dna * (maxi + 0.999999)); - } - } -} -void fx_(TRasterP &dn_ras_out, const TRasterP &up_ras, const TPoint &pos, - const double up_opacity, const bool clipping_mask_sw) { - /* 交差したエリアを処理するようにする、いるのか??? */ - TRect outRect(dn_ras_out->getBounds()); - TRect upRect(up_ras->getBounds() + pos); - TRect intersection = outRect * upRect; - if (intersection.isEmpty()) return; - - TRasterP cRout = dn_ras_out->extract(intersection); - TRect rr = intersection - pos; - TRasterP cRup = up_ras->extract(rr); - - TRaster32P rout32 = cRout, rup32 = cRup; - TRaster64P rout64 = cRout, rup64 = cRup; - - if (rout32 && rup32) { - tmpl_(rout32, rup32, up_opacity, clipping_mask_sw); - } else if (rout64 && rup64) { - tmpl_(rout64, rup64, up_opacity, clipping_mask_sw); - } else { - throw TRopException("unsupported pixel type"); - } -} -} -void ino_blend_color_dodge::doCompute(TTile &tile, double frame, - const TRenderSettings &rs) { - /* ------ 画像生成 ---------------------------------------- */ - TRasterP dn_ras, up_ras; - this->computeUpAndDown(tile, frame, rs, dn_ras, up_ras); - if (!dn_ras || !up_ras) { - return; - } - /* ------ 動作パラメータを得る ---------------------------- */ - const double up_opacity = - this->m_opacity->getValue(frame) / ino::param_range(); - /* ------ (app_begin)log記憶 ------------------------------ */ - const bool log_sw = ino::log_enable_sw(); - - if (log_sw) { - std::ostringstream os; - os << "params" - << " up_opacity " << up_opacity << " dn_tile w " << dn_ras->getLx() - << " wrap " << dn_ras->getWrap() << " h " << dn_ras->getLy() - << " pixbits " << ino::pixel_bits(dn_ras) << " up_tile w " - << up_ras->getLx() << " wrap " << up_ras->getWrap() << " h " - << up_ras->getLy() << " pixbits " << ino::pixel_bits(up_ras) - << " frame " << frame; - } - /* ------ fx処理 ------------------------------------------ */ - try { - if (dn_ras) { - dn_ras->lock(); - } - if (up_ras) { - up_ras->lock(); - } - fx_(dn_ras, up_ras, TPoint(), up_opacity, - this->m_clipping_mask->getValue()); - if (up_ras) { - up_ras->unlock(); - } - if (dn_ras) { - dn_ras->unlock(); - } - } - /* ------ error処理 --------------------------------------- */ - catch (std::exception &e) { - if (up_ras) { - up_ras->unlock(); - } - if (dn_ras) { - dn_ras->unlock(); - } - if (log_sw) { - std::string str("exception <"); - str += e.what(); - str += '>'; - } - throw; - } catch (...) { - if (up_ras) { - up_ras->unlock(); - } - if (dn_ras) { - dn_ras->unlock(); - } - if (log_sw) { - std::string str("other exception"); - } - throw; - } -} diff --git a/toonz/sources/stdfx/ino_blend_cross_dissolve.cpp b/toonz/sources/stdfx/ino_blend_cross_dissolve.cpp index 9c774f64..c323c50a 100644 --- a/toonz/sources/stdfx/ino_blend_cross_dissolve.cpp +++ b/toonz/sources/stdfx/ino_blend_cross_dissolve.cpp @@ -3,335 +3,20 @@ #include "stdfx.h" #include "ino_common.h" +#include "igs_color_blend.h" /* tnzbase --> Source Files --> tfx --> binaryFx.cppを参照 */ class ino_blend_cross_dissolve final : public TBlendForeBackRasterFx { FX_PLUGIN_DECLARATION(ino_blend_cross_dissolve) - TRasterFxPort m_up; - TRasterFxPort m_down; - TDoubleParamP m_opacity; - TBoolParamP m_clipping_mask; public: - ino_blend_cross_dissolve() - : m_opacity(1.0 * ino::param_range()), m_clipping_mask(false) { - addInputPort("Fore", this->m_up); - addInputPort("Back", this->m_down); - bindParam(this, "opacity", this->m_opacity); - bindParam(this, "clipping_mask", this->m_clipping_mask); - this->m_opacity->setValueRange(0, 1.0 * ino::param_range()); - } + ino_blend_cross_dissolve() : TBlendForeBackRasterFx(false) {} ~ino_blend_cross_dissolve() {} - bool canHandle(const TRenderSettings &rs, double frame) override { - return true; + void brendKernel(double& dnr, double& dng, double& dnb, double& dna, + const double upr, double upg, double upb, double upa, + const double up_opacity, + const bool alpha_rendering_sw = true) override { + igs::color::cross_dissolve(dnr, dng, dnb, dna, upr, upg, upb, upa, + up_opacity); } - bool doGetBBox(double frame, TRectD &bBox, - const TRenderSettings &rs) override { - TRectD up_bx; - const bool up_sw = - (m_up.isConnected() ? m_up->doGetBBox(frame, up_bx, rs) : false); - TRectD dn_bx; - const bool dn_sw = - (m_down.isConnected() ? m_down->doGetBBox(frame, dn_bx, rs) : false); - if (up_sw && dn_sw) { - bBox = up_bx + dn_bx; - return !bBox.isEmpty(); - } else if (up_sw) { - bBox = up_bx; - return true; - } else if (dn_sw) { - bBox = dn_bx; - return true; - } else { - bBox = TRectD(); - return false; - } - } - // TRect getInvalidRect(const TRect &max) {return max;} - // void doSetParam(const std::string &name, const TParamP ¶m) {} - int getMemoryRequirement(const TRectD &rect, double frame, - const TRenderSettings &rs) override { - return TRasterFx::memorySize(rect, rs.m_bpp); - } - - void doDryCompute(TRectD &rect, double frame, - const TRenderSettings &rs) override { - this->dryComputeUpAndDown(rect, frame, rs, false); - } - void doCompute(TTile &tile, double frame, const TRenderSettings &rs) override; - void computeUpAndDown(TTile &tile, double frame, const TRenderSettings &rs, - TRasterP &dn_ras, TRasterP &up_ras, - bool upComputesWholeTile = false); - void dryComputeUpAndDown(TRectD &rect, double frame, - const TRenderSettings &rs, - bool upComputesWholeTile = false - /* - upComputesWholeTile は Screen, Min, Blendでtrueにして使用している。 - */ - ); }; FX_PLUGIN_IDENTIFIER(ino_blend_cross_dissolve, "inoCrossDissolveFx"); -//------------------------------------------------------------ -namespace { -/* より大きな四角エリアにPixel整数値で密着する */ -void makeRectCoherent(TRectD &rect, const TPointD &pos) { - rect -= pos; - rect.x0 = tfloor(rect.x0); /* ((x)<(int)(x)? (int)(x)-1: (int)(x))*/ - rect.y0 = tfloor(rect.y0); - rect.x1 = tceil(rect.x1); /* ((int)(x)<(x)? (int)(x)+1: (int)(x))*/ - rect.y1 = tceil(rect.y1); - rect += pos; -} -} -void ino_blend_cross_dissolve::computeUpAndDown(TTile &tile, double frame, - const TRenderSettings &rs, - TRasterP &dn_ras, - TRasterP &up_ras, - bool upComputesWholeTile) { - /* ------ サポートしていないPixelタイプはエラーを投げる --- */ - if (!((TRaster32P)tile.getRaster()) && !((TRaster64P)tile.getRaster())) { - throw TRopException("unsupported input pixel type"); - } - /* -m_down,m_upは繋がっている方があればそれを表示する -両方とも接続していれば合成処理する -表示スイッチを切ってあるならm_upを表示する -fxをreplaceすると、 - m_source --> m_up (=port0) - m_refernce --> m_down(=port1) -となる -*/ - const bool up_is = (this->m_up.isConnected() && - this->m_up.getFx()->getTimeRegion().contains(frame)); - const bool down_is = (this->m_down.isConnected() && - this->m_down.getFx()->getTimeRegion().contains(frame)); - /* ------ 両方とも切断の時処理しない ---------------------- */ - if (!up_is && !down_is) { - tile.getRaster()->clear(); - return; - } - /* ------ up接続かつdown切断の時 -------------------------- */ - if (up_is && !down_is) { - this->m_up->compute(tile, frame, rs); - return; - } - /* ------ down接続時 downのみ描画して... ------------------ */ - if (down_is) { - this->m_down->compute(tile, frame, rs); - } - /* ------ up切断時 ---------------------------------------- */ - if (!up_is) { - return; - } - - /* upと重なる部分を描画する */ - - /* ------ tileの範囲 -------------------------------------- */ - const TDimension tsz(tile.getRaster()->getSize()); /* 整数 */ - const TRectD tileRect(tile.m_pos, TDimensionD(tsz.lx, tsz.ly)); - TRectD upBBox; - if (upComputesWholeTile) { - upBBox = tileRect; - } /* tile全体を得る */ - else { /* 厳密なエリア... */ - this->m_up->getBBox(frame, upBBox, rs); - upBBox *= tileRect; /* upとtileの交差エリア */ - - /* より大きな四角エリアにPixel整数値で密着する */ - makeRectCoherent(upBBox, tile.m_pos); // double-->int grid - } - - TDimensionI upSize( /* TRectDをTDimensionIに変換 */ - tround(upBBox.getLx()) // getLx() = "x1>=x0?x1-x0:0" - , - tround(upBBox.getLy()) // getLy() = "y1>=y0?y1-y0:0" - ); - if ((upSize.lx <= 0) || (upSize.ly <= 0)) { - return; - } - - /* ------ upのメモリ確保と描画 ---------------------------- */ - TTile upTile; - this->m_up->allocateAndCompute(upTile, upBBox.getP00(), upSize, - tile.getRaster() /* 32/64bitsの判定に使う */ - , - frame, rs); - /* ------ upとdownのTRasterを得る ------------------------- */ - TRectI dnRect(upTile.getRaster()->getSize()); // TDimensionI(-) - - dnRect += convert(upTile.m_pos - tile.m_pos); /* uptile->tile原点 */ - /* - ここで問題はdoubleの位置を、四捨五入して整数値にしていること - 移動してから四捨五入ではないの??? - dnRectの元位置が整数位置なので、問題ないか... - */ - - dn_ras = upComputesWholeTile ? tile.getRaster() - : tile.getRaster()->extract(dnRect); - up_ras = upTile.getRaster(); - assert(dn_ras->getSize() == up_ras->getSize()); -} -void ino_blend_cross_dissolve::dryComputeUpAndDown(TRectD &rect, double frame, - const TRenderSettings &rs, - bool upComputesWholeTile) { - const bool up_is = (this->m_up.isConnected() && - this->m_up.getFx()->getTimeRegion().contains(frame)); - const bool down_is = (this->m_down.isConnected() && - this->m_down.getFx()->getTimeRegion().contains(frame)); - /* ------ 両方とも切断の時処理しない ---------------------- */ - if (!up_is && !down_is) { - return; - } - /* ------ up接続かつdown切断の時 -------------------------- */ - if (up_is && !down_is) { - this->m_up->dryCompute(rect, frame, rs); - return; - } - /* ------ down接続時 -------------------------------------- */ - if (down_is) { - this->m_down->dryCompute(rect, frame, rs); - } - /* ------ up切断時 ---------------------------------------- */ - if (!up_is) { - return; - } - - /* ------ tileのgeometryを計算する ------------------------ */ - TRectD upBBox; - - if (upComputesWholeTile) { - upBBox = rect; - } else { - this->m_up->getBBox(frame, upBBox, rs); - upBBox *= rect; - makeRectCoherent(upBBox, rect.getP00()); - } - if ((upBBox.getLx() > 0.5) && (upBBox.getLy() > 0.5)) { - this->m_up->dryCompute(upBBox, frame, rs); - } -} -//------------------------------------------------------------ -#include /* std::ostringstream */ -#include "igs_color_blend.h" -namespace { -template -void tmpl_(TRasterPT dn_ras_out, const TRasterPT &up_ras, - const double up_opacity, const bool clipping_mask_sw) { - double maxi = static_cast(T::maxChannelValue); // 255or65535 - - assert(dn_ras_out->getSize() == up_ras->getSize()); - - for (int yy = 0; yy < dn_ras_out->getLy(); ++yy) { - T *out_pix = dn_ras_out->pixels(yy); - const T *const out_end = out_pix + dn_ras_out->getLx(); - const T *up_pix = up_ras->pixels(yy); - for (; out_pix < out_end; ++out_pix, ++up_pix) { - double upr = static_cast(up_pix->r) / maxi; - double upg = static_cast(up_pix->g) / maxi; - double upb = static_cast(up_pix->b) / maxi; - double upa = static_cast(up_pix->m) / maxi; - double dnr = static_cast(out_pix->r) / maxi; - double dng = static_cast(out_pix->g) / maxi; - double dnb = static_cast(out_pix->b) / maxi; - double dna = static_cast(out_pix->m) / maxi; - igs::color::cross_dissolve( - dnr, dng, dnb, dna, upr, upg, upb, upa, - clipping_mask_sw ? up_opacity * dna : up_opacity); - out_pix->r = static_cast(dnr * (maxi + 0.999999)); - out_pix->g = static_cast(dng * (maxi + 0.999999)); - out_pix->b = static_cast(dnb * (maxi + 0.999999)); - out_pix->m = static_cast(dna * (maxi + 0.999999)); - } - } -} -void fx_(TRasterP &dn_ras_out, const TRasterP &up_ras, const TPoint &pos, - const double up_opacity, const bool clipping_mask_sw) { - /* 交差したエリアを処理するようにする、いるのか??? */ - TRect outRect(dn_ras_out->getBounds()); - TRect upRect(up_ras->getBounds() + pos); - TRect intersection = outRect * upRect; - if (intersection.isEmpty()) return; - - TRasterP cRout = dn_ras_out->extract(intersection); - TRect rr = intersection - pos; - TRasterP cRup = up_ras->extract(rr); - - TRaster32P rout32 = cRout, rup32 = cRup; - TRaster64P rout64 = cRout, rup64 = cRup; - - if (rout32 && rup32) { - tmpl_(rout32, rup32, up_opacity, clipping_mask_sw); - } else if (rout64 && rup64) { - tmpl_(rout64, rup64, up_opacity, clipping_mask_sw); - } else { - throw TRopException("unsupported pixel type"); - } -} -} -void ino_blend_cross_dissolve::doCompute(TTile &tile, double frame, - const TRenderSettings &rs) { - /* ------ 画像生成 ---------------------------------------- */ - TRasterP dn_ras, up_ras; - this->computeUpAndDown(tile, frame, rs, dn_ras, up_ras); - if (!dn_ras || !up_ras) { - return; - } - /* ------ 動作パラメータを得る ---------------------------- */ - const double up_opacity = - this->m_opacity->getValue(frame) / ino::param_range(); - /* ------ (app_begin)log記憶 ------------------------------ */ - const bool log_sw = ino::log_enable_sw(); - - if (log_sw) { - std::ostringstream os; - os << "params" - << " up_opacity " << up_opacity << " dn_tile w " << dn_ras->getLx() - << " wrap " << dn_ras->getWrap() << " h " << dn_ras->getLy() - << " pixbits " << ino::pixel_bits(dn_ras) << " up_tile w " - << up_ras->getLx() << " wrap " << up_ras->getWrap() << " h " - << up_ras->getLy() << " pixbits " << ino::pixel_bits(up_ras) - << " frame " << frame; - } - /* ------ fx処理 ------------------------------------------ */ - try { - if (dn_ras) { - dn_ras->lock(); - } - if (up_ras) { - up_ras->lock(); - } - fx_(dn_ras, up_ras, TPoint(), up_opacity, - this->m_clipping_mask->getValue()); - if (up_ras) { - up_ras->unlock(); - } - if (dn_ras) { - dn_ras->unlock(); - } - } - /* ------ error処理 --------------------------------------- */ - catch (std::exception &e) { - if (up_ras) { - up_ras->unlock(); - } - if (dn_ras) { - dn_ras->unlock(); - } - if (log_sw) { - std::string str("exception <"); - str += e.what(); - str += '>'; - } - throw; - } catch (...) { - if (up_ras) { - up_ras->unlock(); - } - if (dn_ras) { - dn_ras->unlock(); - } - if (log_sw) { - std::string str("other exception"); - } - throw; - } -} diff --git a/toonz/sources/stdfx/ino_blend_darken.cpp b/toonz/sources/stdfx/ino_blend_darken.cpp index bbfc76ff..6015bb40 100644 --- a/toonz/sources/stdfx/ino_blend_darken.cpp +++ b/toonz/sources/stdfx/ino_blend_darken.cpp @@ -3,333 +3,19 @@ #include "stdfx.h" #include "ino_common.h" +#include "igs_color_blend.h" /* tnzbase --> Source Files --> tfx --> binaryFx.cppを参照 */ class ino_blend_darken final : public TBlendForeBackRasterFx { FX_PLUGIN_DECLARATION(ino_blend_darken) - TRasterFxPort m_up; - TRasterFxPort m_down; - TDoubleParamP m_opacity; - TBoolParamP m_clipping_mask; public: - ino_blend_darken() - : m_opacity(1.0 * ino::param_range()), m_clipping_mask(false) { - addInputPort("Fore", this->m_up); - addInputPort("Back", this->m_down); - bindParam(this, "opacity", this->m_opacity); - bindParam(this, "clipping_mask", this->m_clipping_mask); - this->m_opacity->setValueRange(0, 1.0 * ino::param_range()); - } + ino_blend_darken() : TBlendForeBackRasterFx(false) {} ~ino_blend_darken() {} - bool canHandle(const TRenderSettings &rs, double frame) override { - return true; + void brendKernel(double& dnr, double& dng, double& dnb, double& dna, + const double upr, double upg, double upb, double upa, + const double up_opacity, + const bool alpha_rendering_sw = true) override { + igs::color::darken(dnr, dng, dnb, dna, upr, upg, upb, upa, up_opacity); } - bool doGetBBox(double frame, TRectD &bBox, - const TRenderSettings &rs) override { - TRectD up_bx; - const bool up_sw = - (m_up.isConnected() ? m_up->doGetBBox(frame, up_bx, rs) : false); - TRectD dn_bx; - const bool dn_sw = - (m_down.isConnected() ? m_down->doGetBBox(frame, dn_bx, rs) : false); - if (up_sw && dn_sw) { - bBox = up_bx + dn_bx; - return !bBox.isEmpty(); - } else if (up_sw) { - bBox = up_bx; - return true; - } else if (dn_sw) { - bBox = dn_bx; - return true; - } else { - bBox = TRectD(); - return false; - } - } - // TRect getInvalidRect(const TRect &max) {return max;} - // void doSetParam(const std::string &name, const TParamP ¶m) {} - int getMemoryRequirement(const TRectD &rect, double frame, - const TRenderSettings &rs) override { - return TRasterFx::memorySize(rect, rs.m_bpp); - } - - void doDryCompute(TRectD &rect, double frame, - const TRenderSettings &rs) override { - this->dryComputeUpAndDown(rect, frame, rs, false); - } - void doCompute(TTile &tile, double frame, const TRenderSettings &rs) override; - void computeUpAndDown(TTile &tile, double frame, const TRenderSettings &rs, - TRasterP &dn_ras, TRasterP &up_ras, - bool upComputesWholeTile = false); - void dryComputeUpAndDown(TRectD &rect, double frame, - const TRenderSettings &rs, - bool upComputesWholeTile = false - /* - upComputesWholeTile は Screen, Min, Blendでtrueにして使用している。 - */ - ); }; FX_PLUGIN_IDENTIFIER(ino_blend_darken, "inoDarkenFx"); -//------------------------------------------------------------ -namespace { -/* より大きな四角エリアにPixel整数値で密着する */ -void makeRectCoherent(TRectD &rect, const TPointD &pos) { - rect -= pos; - rect.x0 = tfloor(rect.x0); /* ((x)<(int)(x)? (int)(x)-1: (int)(x))*/ - rect.y0 = tfloor(rect.y0); - rect.x1 = tceil(rect.x1); /* ((int)(x)<(x)? (int)(x)+1: (int)(x))*/ - rect.y1 = tceil(rect.y1); - rect += pos; -} -} -void ino_blend_darken::computeUpAndDown(TTile &tile, double frame, - const TRenderSettings &rs, - TRasterP &dn_ras, TRasterP &up_ras, - bool upComputesWholeTile) { - /* ------ サポートしていないPixelタイプはエラーを投げる --- */ - if (!((TRaster32P)tile.getRaster()) && !((TRaster64P)tile.getRaster())) { - throw TRopException("unsupported input pixel type"); - } - /* -m_down,m_upは繋がっている方があればそれを表示する -両方とも接続していれば合成処理する -表示スイッチを切ってあるならm_upを表示する -fxをreplaceすると、 - m_source --> m_up (=port0) - m_refernce --> m_down(=port1) -となる -*/ - const bool up_is = (this->m_up.isConnected() && - this->m_up.getFx()->getTimeRegion().contains(frame)); - const bool down_is = (this->m_down.isConnected() && - this->m_down.getFx()->getTimeRegion().contains(frame)); - /* ------ 両方とも切断の時処理しない ---------------------- */ - if (!up_is && !down_is) { - tile.getRaster()->clear(); - return; - } - /* ------ up接続かつdown切断の時 -------------------------- */ - if (up_is && !down_is) { - this->m_up->compute(tile, frame, rs); - return; - } - /* ------ down接続時 downのみ描画して... ------------------ */ - if (down_is) { - this->m_down->compute(tile, frame, rs); - } - /* ------ up切断時 ---------------------------------------- */ - if (!up_is) { - return; - } - - /* upと重なる部分を描画する */ - - /* ------ tileの範囲 -------------------------------------- */ - const TDimension tsz(tile.getRaster()->getSize()); /* 整数 */ - const TRectD tileRect(tile.m_pos, TDimensionD(tsz.lx, tsz.ly)); - TRectD upBBox; - if (upComputesWholeTile) { - upBBox = tileRect; - } /* tile全体を得る */ - else { /* 厳密なエリア... */ - this->m_up->getBBox(frame, upBBox, rs); - upBBox *= tileRect; /* upとtileの交差エリア */ - - /* より大きな四角エリアにPixel整数値で密着する */ - makeRectCoherent(upBBox, tile.m_pos); // double-->int grid - } - - TDimensionI upSize( /* TRectDをTDimensionIに変換 */ - tround(upBBox.getLx()) // getLx() = "x1>=x0?x1-x0:0" - , - tround(upBBox.getLy()) // getLy() = "y1>=y0?y1-y0:0" - ); - if ((upSize.lx <= 0) || (upSize.ly <= 0)) { - return; - } - - /* ------ upのメモリ確保と描画 ---------------------------- */ - TTile upTile; - this->m_up->allocateAndCompute(upTile, upBBox.getP00(), upSize, - tile.getRaster() /* 32/64bitsの判定に使う */ - , - frame, rs); - /* ------ upとdownのTRasterを得る ------------------------- */ - TRectI dnRect(upTile.getRaster()->getSize()); // TDimensionI(-) - - dnRect += convert(upTile.m_pos - tile.m_pos); /* uptile->tile原点 */ - /* - ここで問題はdoubleの位置を、四捨五入して整数値にしていること - 移動してから四捨五入ではないの??? - dnRectの元位置が整数位置なので、問題ないか... - */ - - dn_ras = upComputesWholeTile ? tile.getRaster() - : tile.getRaster()->extract(dnRect); - up_ras = upTile.getRaster(); - assert(dn_ras->getSize() == up_ras->getSize()); -} -void ino_blend_darken::dryComputeUpAndDown(TRectD &rect, double frame, - const TRenderSettings &rs, - bool upComputesWholeTile) { - const bool up_is = (this->m_up.isConnected() && - this->m_up.getFx()->getTimeRegion().contains(frame)); - const bool down_is = (this->m_down.isConnected() && - this->m_down.getFx()->getTimeRegion().contains(frame)); - /* ------ 両方とも切断の時処理しない ---------------------- */ - if (!up_is && !down_is) { - return; - } - /* ------ up接続かつdown切断の時 -------------------------- */ - if (up_is && !down_is) { - this->m_up->dryCompute(rect, frame, rs); - return; - } - /* ------ down接続時 -------------------------------------- */ - if (down_is) { - this->m_down->dryCompute(rect, frame, rs); - } - /* ------ up切断時 ---------------------------------------- */ - if (!up_is) { - return; - } - - /* ------ tileのgeometryを計算する ------------------------ */ - TRectD upBBox; - - if (upComputesWholeTile) { - upBBox = rect; - } else { - this->m_up->getBBox(frame, upBBox, rs); - upBBox *= rect; - makeRectCoherent(upBBox, rect.getP00()); - } - if ((upBBox.getLx() > 0.5) && (upBBox.getLy() > 0.5)) { - this->m_up->dryCompute(upBBox, frame, rs); - } -} -//------------------------------------------------------------ -#include /* std::ostringstream */ -#include "igs_color_blend.h" -namespace { -template -void tmpl_(TRasterPT dn_ras_out, const TRasterPT &up_ras, - const double up_opacity, const bool clipping_mask_sw) { - double maxi = static_cast(T::maxChannelValue); // 255or65535 - - assert(dn_ras_out->getSize() == up_ras->getSize()); - - for (int yy = 0; yy < dn_ras_out->getLy(); ++yy) { - T *out_pix = dn_ras_out->pixels(yy); - const T *const out_end = out_pix + dn_ras_out->getLx(); - const T *up_pix = up_ras->pixels(yy); - for (; out_pix < out_end; ++out_pix, ++up_pix) { - double upr = static_cast(up_pix->r) / maxi; - double upg = static_cast(up_pix->g) / maxi; - double upb = static_cast(up_pix->b) / maxi; - double upa = static_cast(up_pix->m) / maxi; - double dnr = static_cast(out_pix->r) / maxi; - double dng = static_cast(out_pix->g) / maxi; - double dnb = static_cast(out_pix->b) / maxi; - double dna = static_cast(out_pix->m) / maxi; - igs::color::darken(dnr, dng, dnb, dna, upr, upg, upb, upa, - clipping_mask_sw ? up_opacity * dna : up_opacity); - out_pix->r = static_cast(dnr * (maxi + 0.999999)); - out_pix->g = static_cast(dng * (maxi + 0.999999)); - out_pix->b = static_cast(dnb * (maxi + 0.999999)); - out_pix->m = static_cast(dna * (maxi + 0.999999)); - } - } -} -void fx_(TRasterP &dn_ras_out, const TRasterP &up_ras, const TPoint &pos, - const double up_opacity, const bool clipping_mask_sw) { - /* 交差したエリアを処理するようにする、いるのか??? */ - TRect outRect(dn_ras_out->getBounds()); - TRect upRect(up_ras->getBounds() + pos); - TRect intersection = outRect * upRect; - if (intersection.isEmpty()) return; - - TRasterP cRout = dn_ras_out->extract(intersection); - TRect rr = intersection - pos; - TRasterP cRup = up_ras->extract(rr); - - TRaster32P rout32 = cRout, rup32 = cRup; - TRaster64P rout64 = cRout, rup64 = cRup; - - if (rout32 && rup32) { - tmpl_(rout32, rup32, up_opacity, clipping_mask_sw); - } else if (rout64 && rup64) { - tmpl_(rout64, rup64, up_opacity, clipping_mask_sw); - } else { - throw TRopException("unsupported pixel type"); - } -} -} -void ino_blend_darken::doCompute(TTile &tile, double frame, - const TRenderSettings &rs) { - /* ------ 画像生成 ---------------------------------------- */ - TRasterP dn_ras, up_ras; - this->computeUpAndDown(tile, frame, rs, dn_ras, up_ras); - if (!dn_ras || !up_ras) { - return; - } - /* ------ 動作パラメータを得る ---------------------------- */ - const double up_opacity = - this->m_opacity->getValue(frame) / ino::param_range(); - /* ------ (app_begin)log記憶 ------------------------------ */ - const bool log_sw = ino::log_enable_sw(); - - if (log_sw) { - std::ostringstream os; - os << "params" - << " up_opacity " << up_opacity << " dn_tile w " << dn_ras->getLx() - << " wrap " << dn_ras->getWrap() << " h " << dn_ras->getLy() - << " pixbits " << ino::pixel_bits(dn_ras) << " up_tile w " - << up_ras->getLx() << " wrap " << up_ras->getWrap() << " h " - << up_ras->getLy() << " pixbits " << ino::pixel_bits(up_ras) - << " frame " << frame; - } - /* ------ fx処理 ------------------------------------------ */ - try { - if (dn_ras) { - dn_ras->lock(); - } - if (up_ras) { - up_ras->lock(); - } - fx_(dn_ras, up_ras, TPoint(), up_opacity, - this->m_clipping_mask->getValue()); - if (up_ras) { - up_ras->unlock(); - } - if (dn_ras) { - dn_ras->unlock(); - } - } - /* ------ error処理 --------------------------------------- */ - catch (std::exception &e) { - if (up_ras) { - up_ras->unlock(); - } - if (dn_ras) { - dn_ras->unlock(); - } - if (log_sw) { - std::string str("exception <"); - str += e.what(); - str += '>'; - } - throw; - } catch (...) { - if (up_ras) { - up_ras->unlock(); - } - if (dn_ras) { - dn_ras->unlock(); - } - if (log_sw) { - std::string str("other exception"); - } - throw; - } -} diff --git a/toonz/sources/stdfx/ino_blend_darker_color.cpp b/toonz/sources/stdfx/ino_blend_darker_color.cpp index 658a94d0..3e2c67c6 100644 --- a/toonz/sources/stdfx/ino_blend_darker_color.cpp +++ b/toonz/sources/stdfx/ino_blend_darker_color.cpp @@ -3,335 +3,20 @@ #include "stdfx.h" #include "ino_common.h" +#include "igs_color_blend.h" /* tnzbase --> Source Files --> tfx --> binaryFx.cppを参照 */ class ino_blend_darker_color final : public TBlendForeBackRasterFx { FX_PLUGIN_DECLARATION(ino_blend_darker_color) - TRasterFxPort m_up; - TRasterFxPort m_down; - TDoubleParamP m_opacity; - TBoolParamP m_clipping_mask; public: - ino_blend_darker_color() - : m_opacity(1.0 * ino::param_range()), m_clipping_mask(false) { - addInputPort("Fore", this->m_up); - addInputPort("Back", this->m_down); - bindParam(this, "opacity", this->m_opacity); - bindParam(this, "clipping_mask", this->m_clipping_mask); - this->m_opacity->setValueRange(0, 1.0 * ino::param_range()); - } + ino_blend_darker_color() : TBlendForeBackRasterFx(false) {} ~ino_blend_darker_color() {} - bool canHandle(const TRenderSettings &rs, double frame) override { - return true; + void brendKernel(double& dnr, double& dng, double& dnb, double& dna, + const double upr, double upg, double upb, double upa, + const double up_opacity, + const bool alpha_rendering_sw = true) override { + igs::color::darker_color(dnr, dng, dnb, dna, upr, upg, upb, upa, + up_opacity); } - bool doGetBBox(double frame, TRectD &bBox, - const TRenderSettings &rs) override { - TRectD up_bx; - const bool up_sw = - (m_up.isConnected() ? m_up->doGetBBox(frame, up_bx, rs) : false); - TRectD dn_bx; - const bool dn_sw = - (m_down.isConnected() ? m_down->doGetBBox(frame, dn_bx, rs) : false); - if (up_sw && dn_sw) { - bBox = up_bx + dn_bx; - return !bBox.isEmpty(); - } else if (up_sw) { - bBox = up_bx; - return true; - } else if (dn_sw) { - bBox = dn_bx; - return true; - } else { - bBox = TRectD(); - return false; - } - } - // TRect getInvalidRect(const TRect &max) {return max;} - // void doSetParam(const std::string &name, const TParamP ¶m) {} - int getMemoryRequirement(const TRectD &rect, double frame, - const TRenderSettings &rs) override { - return TRasterFx::memorySize(rect, rs.m_bpp); - } - - void doDryCompute(TRectD &rect, double frame, - const TRenderSettings &rs) override { - this->dryComputeUpAndDown(rect, frame, rs, false); - } - void doCompute(TTile &tile, double frame, const TRenderSettings &rs) override; - void computeUpAndDown(TTile &tile, double frame, const TRenderSettings &rs, - TRasterP &dn_ras, TRasterP &up_ras, - bool upComputesWholeTile = false); - void dryComputeUpAndDown(TRectD &rect, double frame, - const TRenderSettings &rs, - bool upComputesWholeTile = false - /* - upComputesWholeTile は Screen, Min, Blendでtrueにして使用している。 - */ - ); }; FX_PLUGIN_IDENTIFIER(ino_blend_darker_color, "inoDarkerColorFx"); -//------------------------------------------------------------ -namespace { -/* より大きな四角エリアにPixel整数値で密着する */ -void makeRectCoherent(TRectD &rect, const TPointD &pos) { - rect -= pos; - rect.x0 = tfloor(rect.x0); /* ((x)<(int)(x)? (int)(x)-1: (int)(x))*/ - rect.y0 = tfloor(rect.y0); - rect.x1 = tceil(rect.x1); /* ((int)(x)<(x)? (int)(x)+1: (int)(x))*/ - rect.y1 = tceil(rect.y1); - rect += pos; -} -} -void ino_blend_darker_color::computeUpAndDown(TTile &tile, double frame, - const TRenderSettings &rs, - TRasterP &dn_ras, - TRasterP &up_ras, - bool upComputesWholeTile) { - /* ------ サポートしていないPixelタイプはエラーを投げる --- */ - if (!((TRaster32P)tile.getRaster()) && !((TRaster64P)tile.getRaster())) { - throw TRopException("unsupported input pixel type"); - } - /* -m_down,m_upは繋がっている方があればそれを表示する -両方とも接続していれば合成処理する -表示スイッチを切ってあるならm_upを表示する -fxをreplaceすると、 - m_source --> m_up (=port0) - m_refernce --> m_down(=port1) -となる -*/ - const bool up_is = (this->m_up.isConnected() && - this->m_up.getFx()->getTimeRegion().contains(frame)); - const bool down_is = (this->m_down.isConnected() && - this->m_down.getFx()->getTimeRegion().contains(frame)); - /* ------ 両方とも切断の時処理しない ---------------------- */ - if (!up_is && !down_is) { - tile.getRaster()->clear(); - return; - } - /* ------ up接続かつdown切断の時 -------------------------- */ - if (up_is && !down_is) { - this->m_up->compute(tile, frame, rs); - return; - } - /* ------ down接続時 downのみ描画して... ------------------ */ - if (down_is) { - this->m_down->compute(tile, frame, rs); - } - /* ------ up切断時 ---------------------------------------- */ - if (!up_is) { - return; - } - - /* upと重なる部分を描画する */ - - /* ------ tileの範囲 -------------------------------------- */ - const TDimension tsz(tile.getRaster()->getSize()); /* 整数 */ - const TRectD tileRect(tile.m_pos, TDimensionD(tsz.lx, tsz.ly)); - TRectD upBBox; - if (upComputesWholeTile) { - upBBox = tileRect; - } /* tile全体を得る */ - else { /* 厳密なエリア... */ - this->m_up->getBBox(frame, upBBox, rs); - upBBox *= tileRect; /* upとtileの交差エリア */ - - /* より大きな四角エリアにPixel整数値で密着する */ - makeRectCoherent(upBBox, tile.m_pos); // double-->int grid - } - - TDimensionI upSize( /* TRectDをTDimensionIに変換 */ - tround(upBBox.getLx()) // getLx() = "x1>=x0?x1-x0:0" - , - tround(upBBox.getLy()) // getLy() = "y1>=y0?y1-y0:0" - ); - if ((upSize.lx <= 0) || (upSize.ly <= 0)) { - return; - } - - /* ------ upのメモリ確保と描画 ---------------------------- */ - TTile upTile; - this->m_up->allocateAndCompute(upTile, upBBox.getP00(), upSize, - tile.getRaster() /* 32/64bitsの判定に使う */ - , - frame, rs); - /* ------ upとdownのTRasterを得る ------------------------- */ - TRectI dnRect(upTile.getRaster()->getSize()); // TDimensionI(-) - - dnRect += convert(upTile.m_pos - tile.m_pos); /* uptile->tile原点 */ - /* - ここで問題はdoubleの位置を、四捨五入して整数値にしていること - 移動してから四捨五入ではないの??? - dnRectの元位置が整数位置なので、問題ないか... - */ - - dn_ras = upComputesWholeTile ? tile.getRaster() - : tile.getRaster()->extract(dnRect); - up_ras = upTile.getRaster(); - assert(dn_ras->getSize() == up_ras->getSize()); -} -void ino_blend_darker_color::dryComputeUpAndDown(TRectD &rect, double frame, - const TRenderSettings &rs, - bool upComputesWholeTile) { - const bool up_is = (this->m_up.isConnected() && - this->m_up.getFx()->getTimeRegion().contains(frame)); - const bool down_is = (this->m_down.isConnected() && - this->m_down.getFx()->getTimeRegion().contains(frame)); - /* ------ 両方とも切断の時処理しない ---------------------- */ - if (!up_is && !down_is) { - return; - } - /* ------ up接続かつdown切断の時 -------------------------- */ - if (up_is && !down_is) { - this->m_up->dryCompute(rect, frame, rs); - return; - } - /* ------ down接続時 -------------------------------------- */ - if (down_is) { - this->m_down->dryCompute(rect, frame, rs); - } - /* ------ up切断時 ---------------------------------------- */ - if (!up_is) { - return; - } - - /* ------ tileのgeometryを計算する ------------------------ */ - TRectD upBBox; - - if (upComputesWholeTile) { - upBBox = rect; - } else { - this->m_up->getBBox(frame, upBBox, rs); - upBBox *= rect; - makeRectCoherent(upBBox, rect.getP00()); - } - if ((upBBox.getLx() > 0.5) && (upBBox.getLy() > 0.5)) { - this->m_up->dryCompute(upBBox, frame, rs); - } -} -//------------------------------------------------------------ -#include /* std::ostringstream */ -#include "igs_color_blend.h" -namespace { -template -void tmpl_(TRasterPT dn_ras_out, const TRasterPT &up_ras, - const double up_opacity, const bool clipping_mask_sw) { - double maxi = static_cast(T::maxChannelValue); // 255or65535 - - assert(dn_ras_out->getSize() == up_ras->getSize()); - - for (int yy = 0; yy < dn_ras_out->getLy(); ++yy) { - T *out_pix = dn_ras_out->pixels(yy); - const T *const out_end = out_pix + dn_ras_out->getLx(); - const T *up_pix = up_ras->pixels(yy); - for (; out_pix < out_end; ++out_pix, ++up_pix) { - double upr = static_cast(up_pix->r) / maxi; - double upg = static_cast(up_pix->g) / maxi; - double upb = static_cast(up_pix->b) / maxi; - double upa = static_cast(up_pix->m) / maxi; - double dnr = static_cast(out_pix->r) / maxi; - double dng = static_cast(out_pix->g) / maxi; - double dnb = static_cast(out_pix->b) / maxi; - double dna = static_cast(out_pix->m) / maxi; - igs::color::darker_color( - dnr, dng, dnb, dna, upr, upg, upb, upa, - clipping_mask_sw ? up_opacity * dna : up_opacity); - out_pix->r = static_cast(dnr * (maxi + 0.999999)); - out_pix->g = static_cast(dng * (maxi + 0.999999)); - out_pix->b = static_cast(dnb * (maxi + 0.999999)); - out_pix->m = static_cast(dna * (maxi + 0.999999)); - } - } -} -void fx_(TRasterP &dn_ras_out, const TRasterP &up_ras, const TPoint &pos, - const double up_opacity, const bool clipping_mask_sw) { - /* 交差したエリアを処理するようにする、いるのか??? */ - TRect outRect(dn_ras_out->getBounds()); - TRect upRect(up_ras->getBounds() + pos); - TRect intersection = outRect * upRect; - if (intersection.isEmpty()) return; - - TRasterP cRout = dn_ras_out->extract(intersection); - TRect rr = intersection - pos; - TRasterP cRup = up_ras->extract(rr); - - TRaster32P rout32 = cRout, rup32 = cRup; - TRaster64P rout64 = cRout, rup64 = cRup; - - if (rout32 && rup32) { - tmpl_(rout32, rup32, up_opacity, clipping_mask_sw); - } else if (rout64 && rup64) { - tmpl_(rout64, rup64, up_opacity, clipping_mask_sw); - } else { - throw TRopException("unsupported pixel type"); - } -} -} -void ino_blend_darker_color::doCompute(TTile &tile, double frame, - const TRenderSettings &rs) { - /* ------ 画像生成 ---------------------------------------- */ - TRasterP dn_ras, up_ras; - this->computeUpAndDown(tile, frame, rs, dn_ras, up_ras); - if (!dn_ras || !up_ras) { - return; - } - /* ------ 動作パラメータを得る ---------------------------- */ - const double up_opacity = - this->m_opacity->getValue(frame) / ino::param_range(); - /* ------ (app_begin)log記憶 ------------------------------ */ - const bool log_sw = ino::log_enable_sw(); - - if (log_sw) { - std::ostringstream os; - os << "params" - << " up_opacity " << up_opacity << " dn_tile w " << dn_ras->getLx() - << " wrap " << dn_ras->getWrap() << " h " << dn_ras->getLy() - << " pixbits " << ino::pixel_bits(dn_ras) << " up_tile w " - << up_ras->getLx() << " wrap " << up_ras->getWrap() << " h " - << up_ras->getLy() << " pixbits " << ino::pixel_bits(up_ras) - << " frame " << frame; - } - /* ------ fx処理 ------------------------------------------ */ - try { - if (dn_ras) { - dn_ras->lock(); - } - if (up_ras) { - up_ras->lock(); - } - fx_(dn_ras, up_ras, TPoint(), up_opacity, - this->m_clipping_mask->getValue()); - if (up_ras) { - up_ras->unlock(); - } - if (dn_ras) { - dn_ras->unlock(); - } - } - /* ------ error処理 --------------------------------------- */ - catch (std::exception &e) { - if (up_ras) { - up_ras->unlock(); - } - if (dn_ras) { - dn_ras->unlock(); - } - if (log_sw) { - std::string str("exception <"); - str += e.what(); - str += '>'; - } - throw; - } catch (...) { - if (up_ras) { - up_ras->unlock(); - } - if (dn_ras) { - dn_ras->unlock(); - } - if (log_sw) { - std::string str("other exception"); - } - throw; - } -} diff --git a/toonz/sources/stdfx/ino_blend_divide.cpp b/toonz/sources/stdfx/ino_blend_divide.cpp index 42cd07ac..8d91a197 100644 --- a/toonz/sources/stdfx/ino_blend_divide.cpp +++ b/toonz/sources/stdfx/ino_blend_divide.cpp @@ -3,333 +3,19 @@ #include "stdfx.h" #include "ino_common.h" +#include "igs_color_blend.h" /* tnzbase --> Source Files --> tfx --> binaryFx.cppを参照 */ class ino_blend_divide final : public TBlendForeBackRasterFx { FX_PLUGIN_DECLARATION(ino_blend_divide) - TRasterFxPort m_up; - TRasterFxPort m_down; - TDoubleParamP m_opacity; - TBoolParamP m_clipping_mask; public: - ino_blend_divide() - : m_opacity(1.0 * ino::param_range()), m_clipping_mask(true) { - addInputPort("Fore", this->m_up); - addInputPort("Back", this->m_down); - bindParam(this, "opacity", this->m_opacity); - bindParam(this, "clipping_mask", this->m_clipping_mask); - this->m_opacity->setValueRange(0, 1.0 * ino::param_range()); - } + ino_blend_divide() : TBlendForeBackRasterFx(true) {} ~ino_blend_divide() {} - bool canHandle(const TRenderSettings &rs, double frame) override { - return true; + void brendKernel(double& dnr, double& dng, double& dnb, double& dna, + const double upr, double upg, double upb, double upa, + const double up_opacity, + const bool alpha_rendering_sw = true) override { + igs::color::divide(dnr, dng, dnb, dna, upr, upg, upb, upa, up_opacity); } - bool doGetBBox(double frame, TRectD &bBox, - const TRenderSettings &rs) override { - TRectD up_bx; - const bool up_sw = - (m_up.isConnected() ? m_up->doGetBBox(frame, up_bx, rs) : false); - TRectD dn_bx; - const bool dn_sw = - (m_down.isConnected() ? m_down->doGetBBox(frame, dn_bx, rs) : false); - if (up_sw && dn_sw) { - bBox = up_bx + dn_bx; - return !bBox.isEmpty(); - } else if (up_sw) { - bBox = up_bx; - return true; - } else if (dn_sw) { - bBox = dn_bx; - return true; - } else { - bBox = TRectD(); - return false; - } - } - // TRect getInvalidRect(const TRect &max) {return max;} - // void doSetParam(const std::string &name, const TParamP ¶m) {} - int getMemoryRequirement(const TRectD &rect, double frame, - const TRenderSettings &rs) override { - return TRasterFx::memorySize(rect, rs.m_bpp); - } - - void doDryCompute(TRectD &rect, double frame, - const TRenderSettings &rs) override { - this->dryComputeUpAndDown(rect, frame, rs, false); - } - void doCompute(TTile &tile, double frame, const TRenderSettings &rs) override; - void computeUpAndDown(TTile &tile, double frame, const TRenderSettings &rs, - TRasterP &dn_ras, TRasterP &up_ras, - bool upComputesWholeTile = false); - void dryComputeUpAndDown(TRectD &rect, double frame, - const TRenderSettings &rs, - bool upComputesWholeTile = false - /* - upComputesWholeTile は Screen, Min, Blendでtrueにして使用している。 - */ - ); }; FX_PLUGIN_IDENTIFIER(ino_blend_divide, "inoDivideFx"); -//------------------------------------------------------------ -namespace { -/* より大きな四角エリアにPixel整数値で密着する */ -void makeRectCoherent(TRectD &rect, const TPointD &pos) { - rect -= pos; - rect.x0 = tfloor(rect.x0); /* ((x)<(int)(x)? (int)(x)-1: (int)(x))*/ - rect.y0 = tfloor(rect.y0); - rect.x1 = tceil(rect.x1); /* ((int)(x)<(x)? (int)(x)+1: (int)(x))*/ - rect.y1 = tceil(rect.y1); - rect += pos; -} -} -void ino_blend_divide::computeUpAndDown(TTile &tile, double frame, - const TRenderSettings &rs, - TRasterP &dn_ras, TRasterP &up_ras, - bool upComputesWholeTile) { - /* ------ サポートしていないPixelタイプはエラーを投げる --- */ - if (!((TRaster32P)tile.getRaster()) && !((TRaster64P)tile.getRaster())) { - throw TRopException("unsupported input pixel type"); - } - /* -m_down,m_upは繋がっている方があればそれを表示する -両方とも接続していれば合成処理する -表示スイッチを切ってあるならm_upを表示する -fxをreplaceすると、 - m_source --> m_up (=port0) - m_refernce --> m_down(=port1) -となる -*/ - const bool up_is = (this->m_up.isConnected() && - this->m_up.getFx()->getTimeRegion().contains(frame)); - const bool down_is = (this->m_down.isConnected() && - this->m_down.getFx()->getTimeRegion().contains(frame)); - /* ------ 両方とも切断の時処理しない ---------------------- */ - if (!up_is && !down_is) { - tile.getRaster()->clear(); - return; - } - /* ------ up接続かつdown切断の時 -------------------------- */ - if (up_is && !down_is) { - this->m_up->compute(tile, frame, rs); - return; - } - /* ------ down接続時 downのみ描画して... ------------------ */ - if (down_is) { - this->m_down->compute(tile, frame, rs); - } - /* ------ up切断時 ---------------------------------------- */ - if (!up_is) { - return; - } - - /* upと重なる部分を描画する */ - - /* ------ tileの範囲 -------------------------------------- */ - const TDimension tsz(tile.getRaster()->getSize()); /* 整数 */ - const TRectD tileRect(tile.m_pos, TDimensionD(tsz.lx, tsz.ly)); - TRectD upBBox; - if (upComputesWholeTile) { - upBBox = tileRect; - } /* tile全体を得る */ - else { /* 厳密なエリア... */ - this->m_up->getBBox(frame, upBBox, rs); - upBBox *= tileRect; /* upとtileの交差エリア */ - - /* より大きな四角エリアにPixel整数値で密着する */ - makeRectCoherent(upBBox, tile.m_pos); // double-->int grid - } - - TDimensionI upSize( /* TRectDをTDimensionIに変換 */ - tround(upBBox.getLx()) // getLx() = "x1>=x0?x1-x0:0" - , - tround(upBBox.getLy()) // getLy() = "y1>=y0?y1-y0:0" - ); - if ((upSize.lx <= 0) || (upSize.ly <= 0)) { - return; - } - - /* ------ upのメモリ確保と描画 ---------------------------- */ - TTile upTile; - this->m_up->allocateAndCompute(upTile, upBBox.getP00(), upSize, - tile.getRaster() /* 32/64bitsの判定に使う */ - , - frame, rs); - /* ------ upとdownのTRasterを得る ------------------------- */ - TRectI dnRect(upTile.getRaster()->getSize()); // TDimensionI(-) - - dnRect += convert(upTile.m_pos - tile.m_pos); /* uptile->tile原点 */ - /* - ここで問題はdoubleの位置を、四捨五入して整数値にしていること - 移動してから四捨五入ではないの??? - dnRectの元位置が整数位置なので、問題ないか... - */ - - dn_ras = upComputesWholeTile ? tile.getRaster() - : tile.getRaster()->extract(dnRect); - up_ras = upTile.getRaster(); - assert(dn_ras->getSize() == up_ras->getSize()); -} -void ino_blend_divide::dryComputeUpAndDown(TRectD &rect, double frame, - const TRenderSettings &rs, - bool upComputesWholeTile) { - const bool up_is = (this->m_up.isConnected() && - this->m_up.getFx()->getTimeRegion().contains(frame)); - const bool down_is = (this->m_down.isConnected() && - this->m_down.getFx()->getTimeRegion().contains(frame)); - /* ------ 両方とも切断の時処理しない ---------------------- */ - if (!up_is && !down_is) { - return; - } - /* ------ up接続かつdown切断の時 -------------------------- */ - if (up_is && !down_is) { - this->m_up->dryCompute(rect, frame, rs); - return; - } - /* ------ down接続時 -------------------------------------- */ - if (down_is) { - this->m_down->dryCompute(rect, frame, rs); - } - /* ------ up切断時 ---------------------------------------- */ - if (!up_is) { - return; - } - - /* ------ tileのgeometryを計算する ------------------------ */ - TRectD upBBox; - - if (upComputesWholeTile) { - upBBox = rect; - } else { - this->m_up->getBBox(frame, upBBox, rs); - upBBox *= rect; - makeRectCoherent(upBBox, rect.getP00()); - } - if ((upBBox.getLx() > 0.5) && (upBBox.getLy() > 0.5)) { - this->m_up->dryCompute(upBBox, frame, rs); - } -} -//------------------------------------------------------------ -#include /* std::ostringstream */ -#include "igs_color_blend.h" -namespace { -template -void tmpl_(TRasterPT dn_ras_out, const TRasterPT &up_ras, - const double up_opacity, const bool clipping_mask_sw) { - double maxi = static_cast(T::maxChannelValue); // 255or65535 - - assert(dn_ras_out->getSize() == up_ras->getSize()); - - for (int yy = 0; yy < dn_ras_out->getLy(); ++yy) { - T *out_pix = dn_ras_out->pixels(yy); - const T *const out_end = out_pix + dn_ras_out->getLx(); - const T *up_pix = up_ras->pixels(yy); - for (; out_pix < out_end; ++out_pix, ++up_pix) { - double upr = static_cast(up_pix->r) / maxi; - double upg = static_cast(up_pix->g) / maxi; - double upb = static_cast(up_pix->b) / maxi; - double upa = static_cast(up_pix->m) / maxi; - double dnr = static_cast(out_pix->r) / maxi; - double dng = static_cast(out_pix->g) / maxi; - double dnb = static_cast(out_pix->b) / maxi; - double dna = static_cast(out_pix->m) / maxi; - igs::color::divide(dnr, dng, dnb, dna, upr, upg, upb, upa, - clipping_mask_sw ? up_opacity * dna : up_opacity); - out_pix->r = static_cast(dnr * (maxi + 0.999999)); - out_pix->g = static_cast(dng * (maxi + 0.999999)); - out_pix->b = static_cast(dnb * (maxi + 0.999999)); - out_pix->m = static_cast(dna * (maxi + 0.999999)); - } - } -} -void fx_(TRasterP &dn_ras_out, const TRasterP &up_ras, const TPoint &pos, - const double up_opacity, const bool clipping_mask_sw) { - /* 交差したエリアを処理するようにする、いるのか??? */ - TRect outRect(dn_ras_out->getBounds()); - TRect upRect(up_ras->getBounds() + pos); - TRect intersection = outRect * upRect; - if (intersection.isEmpty()) return; - - TRasterP cRout = dn_ras_out->extract(intersection); - TRect rr = intersection - pos; - TRasterP cRup = up_ras->extract(rr); - - TRaster32P rout32 = cRout, rup32 = cRup; - TRaster64P rout64 = cRout, rup64 = cRup; - - if (rout32 && rup32) { - tmpl_(rout32, rup32, up_opacity, clipping_mask_sw); - } else if (rout64 && rup64) { - tmpl_(rout64, rup64, up_opacity, clipping_mask_sw); - } else { - throw TRopException("unsupported pixel type"); - } -} -} -void ino_blend_divide::doCompute(TTile &tile, double frame, - const TRenderSettings &rs) { - /* ------ 画像生成 ---------------------------------------- */ - TRasterP dn_ras, up_ras; - this->computeUpAndDown(tile, frame, rs, dn_ras, up_ras); - if (!dn_ras || !up_ras) { - return; - } - /* ------ 動作パラメータを得る ---------------------------- */ - const double up_opacity = - this->m_opacity->getValue(frame) / ino::param_range(); - /* ------ (app_begin)log記憶 ------------------------------ */ - const bool log_sw = ino::log_enable_sw(); - - if (log_sw) { - std::ostringstream os; - os << "params" - << " up_opacity " << up_opacity << " dn_tile w " << dn_ras->getLx() - << " wrap " << dn_ras->getWrap() << " h " << dn_ras->getLy() - << " pixbits " << ino::pixel_bits(dn_ras) << " up_tile w " - << up_ras->getLx() << " wrap " << up_ras->getWrap() << " h " - << up_ras->getLy() << " pixbits " << ino::pixel_bits(up_ras) - << " frame " << frame; - } - /* ------ fx処理 ------------------------------------------ */ - try { - if (dn_ras) { - dn_ras->lock(); - } - if (up_ras) { - up_ras->lock(); - } - fx_(dn_ras, up_ras, TPoint(), up_opacity, - this->m_clipping_mask->getValue()); - if (up_ras) { - up_ras->unlock(); - } - if (dn_ras) { - dn_ras->unlock(); - } - } - /* ------ error処理 --------------------------------------- */ - catch (std::exception &e) { - if (up_ras) { - up_ras->unlock(); - } - if (dn_ras) { - dn_ras->unlock(); - } - if (log_sw) { - std::string str("exception <"); - str += e.what(); - str += '>'; - } - throw; - } catch (...) { - if (up_ras) { - up_ras->unlock(); - } - if (dn_ras) { - dn_ras->unlock(); - } - if (log_sw) { - std::string str("other exception"); - } - throw; - } -} diff --git a/toonz/sources/stdfx/ino_blend_hard_light.cpp b/toonz/sources/stdfx/ino_blend_hard_light.cpp index bc405698..5a839027 100644 --- a/toonz/sources/stdfx/ino_blend_hard_light.cpp +++ b/toonz/sources/stdfx/ino_blend_hard_light.cpp @@ -3,333 +3,19 @@ #include "stdfx.h" #include "ino_common.h" +#include "igs_color_blend.h" /* tnzbase --> Source Files --> tfx --> binaryFx.cppを参照 */ class ino_blend_hard_light final : public TBlendForeBackRasterFx { FX_PLUGIN_DECLARATION(ino_blend_hard_light) - TRasterFxPort m_up; - TRasterFxPort m_down; - TDoubleParamP m_opacity; - TBoolParamP m_clipping_mask; public: - ino_blend_hard_light() - : m_opacity(1.0 * ino::param_range()), m_clipping_mask(true) { - addInputPort("Fore", this->m_up); - addInputPort("Back", this->m_down); - bindParam(this, "opacity", this->m_opacity); - bindParam(this, "clipping_mask", this->m_clipping_mask); - this->m_opacity->setValueRange(0, 1.0 * ino::param_range()); - } + ino_blend_hard_light() : TBlendForeBackRasterFx(true) {} ~ino_blend_hard_light() {} - bool canHandle(const TRenderSettings &rs, double frame) override { - return true; + void brendKernel(double& dnr, double& dng, double& dnb, double& dna, + const double upr, double upg, double upb, double upa, + const double up_opacity, + const bool alpha_rendering_sw = true) override { + igs::color::hard_light(dnr, dng, dnb, dna, upr, upg, upb, upa, up_opacity); } - bool doGetBBox(double frame, TRectD &bBox, - const TRenderSettings &rs) override { - TRectD up_bx; - const bool up_sw = - (m_up.isConnected() ? m_up->doGetBBox(frame, up_bx, rs) : false); - TRectD dn_bx; - const bool dn_sw = - (m_down.isConnected() ? m_down->doGetBBox(frame, dn_bx, rs) : false); - if (up_sw && dn_sw) { - bBox = up_bx + dn_bx; - return !bBox.isEmpty(); - } else if (up_sw) { - bBox = up_bx; - return true; - } else if (dn_sw) { - bBox = dn_bx; - return true; - } else { - bBox = TRectD(); - return false; - } - } - // TRect getInvalidRect(const TRect &max) {return max;} - // void doSetParam(const std::string &name, const TParamP ¶m) {} - int getMemoryRequirement(const TRectD &rect, double frame, - const TRenderSettings &rs) override { - return TRasterFx::memorySize(rect, rs.m_bpp); - } - - void doDryCompute(TRectD &rect, double frame, - const TRenderSettings &rs) override { - this->dryComputeUpAndDown(rect, frame, rs, false); - } - void doCompute(TTile &tile, double frame, const TRenderSettings &rs) override; - void computeUpAndDown(TTile &tile, double frame, const TRenderSettings &rs, - TRasterP &dn_ras, TRasterP &up_ras, - bool upComputesWholeTile = false); - void dryComputeUpAndDown(TRectD &rect, double frame, - const TRenderSettings &rs, - bool upComputesWholeTile = false - /* - upComputesWholeTile は Screen, Min, Blendでtrueにして使用している。 - */ - ); }; FX_PLUGIN_IDENTIFIER(ino_blend_hard_light, "inoHardLightFx"); -//------------------------------------------------------------ -namespace { -/* より大きな四角エリアにPixel整数値で密着する */ -void makeRectCoherent(TRectD &rect, const TPointD &pos) { - rect -= pos; - rect.x0 = tfloor(rect.x0); /* ((x)<(int)(x)? (int)(x)-1: (int)(x))*/ - rect.y0 = tfloor(rect.y0); - rect.x1 = tceil(rect.x1); /* ((int)(x)<(x)? (int)(x)+1: (int)(x))*/ - rect.y1 = tceil(rect.y1); - rect += pos; -} -} -void ino_blend_hard_light::computeUpAndDown(TTile &tile, double frame, - const TRenderSettings &rs, - TRasterP &dn_ras, TRasterP &up_ras, - bool upComputesWholeTile) { - /* ------ サポートしていないPixelタイプはエラーを投げる --- */ - if (!((TRaster32P)tile.getRaster()) && !((TRaster64P)tile.getRaster())) { - throw TRopException("unsupported input pixel type"); - } - /* -m_down,m_upは繋がっている方があればそれを表示する -両方とも接続していれば合成処理する -表示スイッチを切ってあるならm_upを表示する -fxをreplaceすると、 - m_source --> m_up (=port0) - m_refernce --> m_down(=port1) -となる -*/ - const bool up_is = (this->m_up.isConnected() && - this->m_up.getFx()->getTimeRegion().contains(frame)); - const bool down_is = (this->m_down.isConnected() && - this->m_down.getFx()->getTimeRegion().contains(frame)); - /* ------ 両方とも切断の時処理しない ---------------------- */ - if (!up_is && !down_is) { - tile.getRaster()->clear(); - return; - } - /* ------ up接続かつdown切断の時 -------------------------- */ - if (up_is && !down_is) { - this->m_up->compute(tile, frame, rs); - return; - } - /* ------ down接続時 downのみ描画して... ------------------ */ - if (down_is) { - this->m_down->compute(tile, frame, rs); - } - /* ------ up切断時 ---------------------------------------- */ - if (!up_is) { - return; - } - - /* upと重なる部分を描画する */ - - /* ------ tileの範囲 -------------------------------------- */ - const TDimension tsz(tile.getRaster()->getSize()); /* 整数 */ - const TRectD tileRect(tile.m_pos, TDimensionD(tsz.lx, tsz.ly)); - TRectD upBBox; - if (upComputesWholeTile) { - upBBox = tileRect; - } /* tile全体を得る */ - else { /* 厳密なエリア... */ - this->m_up->getBBox(frame, upBBox, rs); - upBBox *= tileRect; /* upとtileの交差エリア */ - - /* より大きな四角エリアにPixel整数値で密着する */ - makeRectCoherent(upBBox, tile.m_pos); // double-->int grid - } - - TDimensionI upSize( /* TRectDをTDimensionIに変換 */ - tround(upBBox.getLx()) // getLx() = "x1>=x0?x1-x0:0" - , - tround(upBBox.getLy()) // getLy() = "y1>=y0?y1-y0:0" - ); - if ((upSize.lx <= 0) || (upSize.ly <= 0)) { - return; - } - - /* ------ upのメモリ確保と描画 ---------------------------- */ - TTile upTile; - this->m_up->allocateAndCompute(upTile, upBBox.getP00(), upSize, - tile.getRaster() /* 32/64bitsの判定に使う */ - , - frame, rs); - /* ------ upとdownのTRasterを得る ------------------------- */ - TRectI dnRect(upTile.getRaster()->getSize()); // TDimensionI(-) - - dnRect += convert(upTile.m_pos - tile.m_pos); /* uptile->tile原点 */ - /* - ここで問題はdoubleの位置を、四捨五入して整数値にしていること - 移動してから四捨五入ではないの??? - dnRectの元位置が整数位置なので、問題ないか... - */ - - dn_ras = upComputesWholeTile ? tile.getRaster() - : tile.getRaster()->extract(dnRect); - up_ras = upTile.getRaster(); - assert(dn_ras->getSize() == up_ras->getSize()); -} -void ino_blend_hard_light::dryComputeUpAndDown(TRectD &rect, double frame, - const TRenderSettings &rs, - bool upComputesWholeTile) { - const bool up_is = (this->m_up.isConnected() && - this->m_up.getFx()->getTimeRegion().contains(frame)); - const bool down_is = (this->m_down.isConnected() && - this->m_down.getFx()->getTimeRegion().contains(frame)); - /* ------ 両方とも切断の時処理しない ---------------------- */ - if (!up_is && !down_is) { - return; - } - /* ------ up接続かつdown切断の時 -------------------------- */ - if (up_is && !down_is) { - this->m_up->dryCompute(rect, frame, rs); - return; - } - /* ------ down接続時 -------------------------------------- */ - if (down_is) { - this->m_down->dryCompute(rect, frame, rs); - } - /* ------ up切断時 ---------------------------------------- */ - if (!up_is) { - return; - } - - /* ------ tileのgeometryを計算する ------------------------ */ - TRectD upBBox; - - if (upComputesWholeTile) { - upBBox = rect; - } else { - this->m_up->getBBox(frame, upBBox, rs); - upBBox *= rect; - makeRectCoherent(upBBox, rect.getP00()); - } - if ((upBBox.getLx() > 0.5) && (upBBox.getLy() > 0.5)) { - this->m_up->dryCompute(upBBox, frame, rs); - } -} -//------------------------------------------------------------ -#include /* std::ostringstream */ -#include "igs_color_blend.h" -namespace { -template -void tmpl_(TRasterPT dn_ras_out, const TRasterPT &up_ras, - const double up_opacity, const bool clipping_mask_sw) { - double maxi = static_cast(T::maxChannelValue); // 255or65535 - - assert(dn_ras_out->getSize() == up_ras->getSize()); - - for (int yy = 0; yy < dn_ras_out->getLy(); ++yy) { - T *out_pix = dn_ras_out->pixels(yy); - const T *const out_end = out_pix + dn_ras_out->getLx(); - const T *up_pix = up_ras->pixels(yy); - for (; out_pix < out_end; ++out_pix, ++up_pix) { - double upr = static_cast(up_pix->r) / maxi; - double upg = static_cast(up_pix->g) / maxi; - double upb = static_cast(up_pix->b) / maxi; - double upa = static_cast(up_pix->m) / maxi; - double dnr = static_cast(out_pix->r) / maxi; - double dng = static_cast(out_pix->g) / maxi; - double dnb = static_cast(out_pix->b) / maxi; - double dna = static_cast(out_pix->m) / maxi; - igs::color::hard_light(dnr, dng, dnb, dna, upr, upg, upb, upa, - clipping_mask_sw ? up_opacity * dna : up_opacity); - out_pix->r = static_cast(dnr * (maxi + 0.999999)); - out_pix->g = static_cast(dng * (maxi + 0.999999)); - out_pix->b = static_cast(dnb * (maxi + 0.999999)); - out_pix->m = static_cast(dna * (maxi + 0.999999)); - } - } -} -void fx_(TRasterP &dn_ras_out, const TRasterP &up_ras, const TPoint &pos, - const double up_opacity, const bool clipping_mask_sw) { - /* 交差したエリアを処理するようにする、いるのか??? */ - TRect outRect(dn_ras_out->getBounds()); - TRect upRect(up_ras->getBounds() + pos); - TRect intersection = outRect * upRect; - if (intersection.isEmpty()) return; - - TRasterP cRout = dn_ras_out->extract(intersection); - TRect rr = intersection - pos; - TRasterP cRup = up_ras->extract(rr); - - TRaster32P rout32 = cRout, rup32 = cRup; - TRaster64P rout64 = cRout, rup64 = cRup; - - if (rout32 && rup32) { - tmpl_(rout32, rup32, up_opacity, clipping_mask_sw); - } else if (rout64 && rup64) { - tmpl_(rout64, rup64, up_opacity, clipping_mask_sw); - } else { - throw TRopException("unsupported pixel type"); - } -} -} -void ino_blend_hard_light::doCompute(TTile &tile, double frame, - const TRenderSettings &rs) { - /* ------ 画像生成 ---------------------------------------- */ - TRasterP dn_ras, up_ras; - this->computeUpAndDown(tile, frame, rs, dn_ras, up_ras); - if (!dn_ras || !up_ras) { - return; - } - /* ------ 動作パラメータを得る ---------------------------- */ - const double up_opacity = - this->m_opacity->getValue(frame) / ino::param_range(); - /* ------ (app_begin)log記憶 ------------------------------ */ - const bool log_sw = ino::log_enable_sw(); - - if (log_sw) { - std::ostringstream os; - os << "params" - << " up_opacity " << up_opacity << " dn_tile w " << dn_ras->getLx() - << " wrap " << dn_ras->getWrap() << " h " << dn_ras->getLy() - << " pixbits " << ino::pixel_bits(dn_ras) << " up_tile w " - << up_ras->getLx() << " wrap " << up_ras->getWrap() << " h " - << up_ras->getLy() << " pixbits " << ino::pixel_bits(up_ras) - << " frame " << frame; - } - /* ------ fx処理 ------------------------------------------ */ - try { - if (dn_ras) { - dn_ras->lock(); - } - if (up_ras) { - up_ras->lock(); - } - fx_(dn_ras, up_ras, TPoint(), up_opacity, - this->m_clipping_mask->getValue()); - if (up_ras) { - up_ras->unlock(); - } - if (dn_ras) { - dn_ras->unlock(); - } - } - /* ------ error処理 --------------------------------------- */ - catch (std::exception &e) { - if (up_ras) { - up_ras->unlock(); - } - if (dn_ras) { - dn_ras->unlock(); - } - if (log_sw) { - std::string str("exception <"); - str += e.what(); - str += '>'; - } - throw; - } catch (...) { - if (up_ras) { - up_ras->unlock(); - } - if (dn_ras) { - dn_ras->unlock(); - } - if (log_sw) { - std::string str("other exception"); - } - throw; - } -} diff --git a/toonz/sources/stdfx/ino_blend_hard_mix.cpp b/toonz/sources/stdfx/ino_blend_hard_mix.cpp index bc2b5cb2..992bac7a 100644 --- a/toonz/sources/stdfx/ino_blend_hard_mix.cpp +++ b/toonz/sources/stdfx/ino_blend_hard_mix.cpp @@ -3,333 +3,19 @@ #include "stdfx.h" #include "ino_common.h" +#include "igs_color_blend.h" /* tnzbase --> Source Files --> tfx --> binaryFx.cppを参照 */ class ino_blend_hard_mix final : public TBlendForeBackRasterFx { FX_PLUGIN_DECLARATION(ino_blend_hard_mix) - TRasterFxPort m_up; - TRasterFxPort m_down; - TDoubleParamP m_opacity; - TBoolParamP m_clipping_mask; public: - ino_blend_hard_mix() - : m_opacity(1.0 * ino::param_range()), m_clipping_mask(true) { - addInputPort("Fore", this->m_up); - addInputPort("Back", this->m_down); - bindParam(this, "opacity", this->m_opacity); - bindParam(this, "clipping_mask", this->m_clipping_mask); - this->m_opacity->setValueRange(0, 1.0 * ino::param_range()); - } + ino_blend_hard_mix() : TBlendForeBackRasterFx(true) {} ~ino_blend_hard_mix() {} - bool canHandle(const TRenderSettings &rs, double frame) override { - return true; + void brendKernel(double& dnr, double& dng, double& dnb, double& dna, + const double upr, double upg, double upb, double upa, + const double up_opacity, + const bool alpha_rendering_sw = true) override { + igs::color::hard_mix(dnr, dng, dnb, dna, upr, upg, upb, upa, up_opacity); } - bool doGetBBox(double frame, TRectD &bBox, - const TRenderSettings &rs) override { - TRectD up_bx; - const bool up_sw = - (m_up.isConnected() ? m_up->doGetBBox(frame, up_bx, rs) : false); - TRectD dn_bx; - const bool dn_sw = - (m_down.isConnected() ? m_down->doGetBBox(frame, dn_bx, rs) : false); - if (up_sw && dn_sw) { - bBox = up_bx + dn_bx; - return !bBox.isEmpty(); - } else if (up_sw) { - bBox = up_bx; - return true; - } else if (dn_sw) { - bBox = dn_bx; - return true; - } else { - bBox = TRectD(); - return false; - } - } - // TRect getInvalidRect(const TRect &max) {return max;} - // void doSetParam(const std::string &name, const TParamP ¶m) {} - int getMemoryRequirement(const TRectD &rect, double frame, - const TRenderSettings &rs) override { - return TRasterFx::memorySize(rect, rs.m_bpp); - } - - void doDryCompute(TRectD &rect, double frame, - const TRenderSettings &rs) override { - this->dryComputeUpAndDown(rect, frame, rs, false); - } - void doCompute(TTile &tile, double frame, const TRenderSettings &rs) override; - void computeUpAndDown(TTile &tile, double frame, const TRenderSettings &rs, - TRasterP &dn_ras, TRasterP &up_ras, - bool upComputesWholeTile = false); - void dryComputeUpAndDown(TRectD &rect, double frame, - const TRenderSettings &rs, - bool upComputesWholeTile = false - /* - upComputesWholeTile は Screen, Min, Blendでtrueにして使用している。 - */ - ); }; FX_PLUGIN_IDENTIFIER(ino_blend_hard_mix, "inoHardMixFx"); -//------------------------------------------------------------ -namespace { -/* より大きな四角エリアにPixel整数値で密着する */ -void makeRectCoherent(TRectD &rect, const TPointD &pos) { - rect -= pos; - rect.x0 = tfloor(rect.x0); /* ((x)<(int)(x)? (int)(x)-1: (int)(x))*/ - rect.y0 = tfloor(rect.y0); - rect.x1 = tceil(rect.x1); /* ((int)(x)<(x)? (int)(x)+1: (int)(x))*/ - rect.y1 = tceil(rect.y1); - rect += pos; -} -} -void ino_blend_hard_mix::computeUpAndDown(TTile &tile, double frame, - const TRenderSettings &rs, - TRasterP &dn_ras, TRasterP &up_ras, - bool upComputesWholeTile) { - /* ------ サポートしていないPixelタイプはエラーを投げる --- */ - if (!((TRaster32P)tile.getRaster()) && !((TRaster64P)tile.getRaster())) { - throw TRopException("unsupported input pixel type"); - } - /* -m_down,m_upは繋がっている方があればそれを表示する -両方とも接続していれば合成処理する -表示スイッチを切ってあるならm_upを表示する -fxをreplaceすると、 - m_source --> m_up (=port0) - m_refernce --> m_down(=port1) -となる -*/ - const bool up_is = (this->m_up.isConnected() && - this->m_up.getFx()->getTimeRegion().contains(frame)); - const bool down_is = (this->m_down.isConnected() && - this->m_down.getFx()->getTimeRegion().contains(frame)); - /* ------ 両方とも切断の時処理しない ---------------------- */ - if (!up_is && !down_is) { - tile.getRaster()->clear(); - return; - } - /* ------ up接続かつdown切断の時 -------------------------- */ - if (up_is && !down_is) { - this->m_up->compute(tile, frame, rs); - return; - } - /* ------ down接続時 downのみ描画して... ------------------ */ - if (down_is) { - this->m_down->compute(tile, frame, rs); - } - /* ------ up切断時 ---------------------------------------- */ - if (!up_is) { - return; - } - - /* upと重なる部分を描画する */ - - /* ------ tileの範囲 -------------------------------------- */ - const TDimension tsz(tile.getRaster()->getSize()); /* 整数 */ - const TRectD tileRect(tile.m_pos, TDimensionD(tsz.lx, tsz.ly)); - TRectD upBBox; - if (upComputesWholeTile) { - upBBox = tileRect; - } /* tile全体を得る */ - else { /* 厳密なエリア... */ - this->m_up->getBBox(frame, upBBox, rs); - upBBox *= tileRect; /* upとtileの交差エリア */ - - /* より大きな四角エリアにPixel整数値で密着する */ - makeRectCoherent(upBBox, tile.m_pos); // double-->int grid - } - - TDimensionI upSize( /* TRectDをTDimensionIに変換 */ - tround(upBBox.getLx()) // getLx() = "x1>=x0?x1-x0:0" - , - tround(upBBox.getLy()) // getLy() = "y1>=y0?y1-y0:0" - ); - if ((upSize.lx <= 0) || (upSize.ly <= 0)) { - return; - } - - /* ------ upのメモリ確保と描画 ---------------------------- */ - TTile upTile; - this->m_up->allocateAndCompute(upTile, upBBox.getP00(), upSize, - tile.getRaster() /* 32/64bitsの判定に使う */ - , - frame, rs); - /* ------ upとdownのTRasterを得る ------------------------- */ - TRectI dnRect(upTile.getRaster()->getSize()); // TDimensionI(-) - - dnRect += convert(upTile.m_pos - tile.m_pos); /* uptile->tile原点 */ - /* - ここで問題はdoubleの位置を、四捨五入して整数値にしていること - 移動してから四捨五入ではないの??? - dnRectの元位置が整数位置なので、問題ないか... - */ - - dn_ras = upComputesWholeTile ? tile.getRaster() - : tile.getRaster()->extract(dnRect); - up_ras = upTile.getRaster(); - assert(dn_ras->getSize() == up_ras->getSize()); -} -void ino_blend_hard_mix::dryComputeUpAndDown(TRectD &rect, double frame, - const TRenderSettings &rs, - bool upComputesWholeTile) { - const bool up_is = (this->m_up.isConnected() && - this->m_up.getFx()->getTimeRegion().contains(frame)); - const bool down_is = (this->m_down.isConnected() && - this->m_down.getFx()->getTimeRegion().contains(frame)); - /* ------ 両方とも切断の時処理しない ---------------------- */ - if (!up_is && !down_is) { - return; - } - /* ------ up接続かつdown切断の時 -------------------------- */ - if (up_is && !down_is) { - this->m_up->dryCompute(rect, frame, rs); - return; - } - /* ------ down接続時 -------------------------------------- */ - if (down_is) { - this->m_down->dryCompute(rect, frame, rs); - } - /* ------ up切断時 ---------------------------------------- */ - if (!up_is) { - return; - } - - /* ------ tileのgeometryを計算する ------------------------ */ - TRectD upBBox; - - if (upComputesWholeTile) { - upBBox = rect; - } else { - this->m_up->getBBox(frame, upBBox, rs); - upBBox *= rect; - makeRectCoherent(upBBox, rect.getP00()); - } - if ((upBBox.getLx() > 0.5) && (upBBox.getLy() > 0.5)) { - this->m_up->dryCompute(upBBox, frame, rs); - } -} -//------------------------------------------------------------ -#include /* std::ostringstream */ -#include "igs_color_blend.h" -namespace { -template -void tmpl_(TRasterPT dn_ras_out, const TRasterPT &up_ras, - const double up_opacity, const bool clipping_mask_sw) { - double maxi = static_cast(T::maxChannelValue); // 255or65535 - - assert(dn_ras_out->getSize() == up_ras->getSize()); - - for (int yy = 0; yy < dn_ras_out->getLy(); ++yy) { - T *out_pix = dn_ras_out->pixels(yy); - const T *const out_end = out_pix + dn_ras_out->getLx(); - const T *up_pix = up_ras->pixels(yy); - for (; out_pix < out_end; ++out_pix, ++up_pix) { - double upr = static_cast(up_pix->r) / maxi; - double upg = static_cast(up_pix->g) / maxi; - double upb = static_cast(up_pix->b) / maxi; - double upa = static_cast(up_pix->m) / maxi; - double dnr = static_cast(out_pix->r) / maxi; - double dng = static_cast(out_pix->g) / maxi; - double dnb = static_cast(out_pix->b) / maxi; - double dna = static_cast(out_pix->m) / maxi; - igs::color::hard_mix(dnr, dng, dnb, dna, upr, upg, upb, upa, - clipping_mask_sw ? up_opacity * dna : up_opacity); - out_pix->r = static_cast(dnr * (maxi + 0.999999)); - out_pix->g = static_cast(dng * (maxi + 0.999999)); - out_pix->b = static_cast(dnb * (maxi + 0.999999)); - out_pix->m = static_cast(dna * (maxi + 0.999999)); - } - } -} -void fx_(TRasterP &dn_ras_out, const TRasterP &up_ras, const TPoint &pos, - const double up_opacity, const bool clipping_mask_sw) { - /* 交差したエリアを処理するようにする、いるのか??? */ - TRect outRect(dn_ras_out->getBounds()); - TRect upRect(up_ras->getBounds() + pos); - TRect intersection = outRect * upRect; - if (intersection.isEmpty()) return; - - TRasterP cRout = dn_ras_out->extract(intersection); - TRect rr = intersection - pos; - TRasterP cRup = up_ras->extract(rr); - - TRaster32P rout32 = cRout, rup32 = cRup; - TRaster64P rout64 = cRout, rup64 = cRup; - - if (rout32 && rup32) { - tmpl_(rout32, rup32, up_opacity, clipping_mask_sw); - } else if (rout64 && rup64) { - tmpl_(rout64, rup64, up_opacity, clipping_mask_sw); - } else { - throw TRopException("unsupported pixel type"); - } -} -} -void ino_blend_hard_mix::doCompute(TTile &tile, double frame, - const TRenderSettings &rs) { - /* ------ 画像生成 ---------------------------------------- */ - TRasterP dn_ras, up_ras; - this->computeUpAndDown(tile, frame, rs, dn_ras, up_ras); - if (!dn_ras || !up_ras) { - return; - } - /* ------ 動作パラメータを得る ---------------------------- */ - const double up_opacity = - this->m_opacity->getValue(frame) / ino::param_range(); - /* ------ (app_begin)log記憶 ------------------------------ */ - const bool log_sw = ino::log_enable_sw(); - - if (log_sw) { - std::ostringstream os; - os << "params" - << " up_opacity " << up_opacity << " dn_tile w " << dn_ras->getLx() - << " wrap " << dn_ras->getWrap() << " h " << dn_ras->getLy() - << " pixbits " << ino::pixel_bits(dn_ras) << " up_tile w " - << up_ras->getLx() << " wrap " << up_ras->getWrap() << " h " - << up_ras->getLy() << " pixbits " << ino::pixel_bits(up_ras) - << " frame " << frame; - } - /* ------ fx処理 ------------------------------------------ */ - try { - if (dn_ras) { - dn_ras->lock(); - } - if (up_ras) { - up_ras->lock(); - } - fx_(dn_ras, up_ras, TPoint(), up_opacity, - this->m_clipping_mask->getValue()); - if (up_ras) { - up_ras->unlock(); - } - if (dn_ras) { - dn_ras->unlock(); - } - } - /* ------ error処理 --------------------------------------- */ - catch (std::exception &e) { - if (up_ras) { - up_ras->unlock(); - } - if (dn_ras) { - dn_ras->unlock(); - } - if (log_sw) { - std::string str("exception <"); - str += e.what(); - str += '>'; - } - throw; - } catch (...) { - if (up_ras) { - up_ras->unlock(); - } - if (dn_ras) { - dn_ras->unlock(); - } - if (log_sw) { - std::string str("other exception"); - } - throw; - } -} diff --git a/toonz/sources/stdfx/ino_blend_lighten.cpp b/toonz/sources/stdfx/ino_blend_lighten.cpp index 5bb8bb90..a70810da 100644 --- a/toonz/sources/stdfx/ino_blend_lighten.cpp +++ b/toonz/sources/stdfx/ino_blend_lighten.cpp @@ -3,333 +3,19 @@ #include "stdfx.h" #include "ino_common.h" +#include "igs_color_blend.h" /* tnzbase --> Source Files --> tfx --> binaryFx.cppを参照 */ class ino_blend_lighten final : public TBlendForeBackRasterFx { FX_PLUGIN_DECLARATION(ino_blend_lighten) - TRasterFxPort m_up; - TRasterFxPort m_down; - TDoubleParamP m_opacity; - TBoolParamP m_clipping_mask; public: - ino_blend_lighten() - : m_opacity(1.0 * ino::param_range()), m_clipping_mask(false) { - addInputPort("Fore", this->m_up); - addInputPort("Back", this->m_down); - bindParam(this, "opacity", this->m_opacity); - bindParam(this, "clipping_mask", this->m_clipping_mask); - this->m_opacity->setValueRange(0, 1.0 * ino::param_range()); - } + ino_blend_lighten() : TBlendForeBackRasterFx(false) {} ~ino_blend_lighten() {} - bool canHandle(const TRenderSettings &rs, double frame) override { - return true; + void brendKernel(double& dnr, double& dng, double& dnb, double& dna, + const double upr, double upg, double upb, double upa, + const double up_opacity, + const bool alpha_rendering_sw = true) override { + igs::color::lighten(dnr, dng, dnb, dna, upr, upg, upb, upa, up_opacity); } - bool doGetBBox(double frame, TRectD &bBox, - const TRenderSettings &rs) override { - TRectD up_bx; - const bool up_sw = - (m_up.isConnected() ? m_up->doGetBBox(frame, up_bx, rs) : false); - TRectD dn_bx; - const bool dn_sw = - (m_down.isConnected() ? m_down->doGetBBox(frame, dn_bx, rs) : false); - if (up_sw && dn_sw) { - bBox = up_bx + dn_bx; - return !bBox.isEmpty(); - } else if (up_sw) { - bBox = up_bx; - return true; - } else if (dn_sw) { - bBox = dn_bx; - return true; - } else { - bBox = TRectD(); - return false; - } - } - // TRect getInvalidRect(const TRect &max) {return max;} - // void doSetParam(const std::string &name, const TParamP ¶m) {} - int getMemoryRequirement(const TRectD &rect, double frame, - const TRenderSettings &rs) override { - return TRasterFx::memorySize(rect, rs.m_bpp); - } - - void doDryCompute(TRectD &rect, double frame, - const TRenderSettings &rs) override { - this->dryComputeUpAndDown(rect, frame, rs, false); - } - void doCompute(TTile &tile, double frame, const TRenderSettings &rs) override; - void computeUpAndDown(TTile &tile, double frame, const TRenderSettings &rs, - TRasterP &dn_ras, TRasterP &up_ras, - bool upComputesWholeTile = false); - void dryComputeUpAndDown(TRectD &rect, double frame, - const TRenderSettings &rs, - bool upComputesWholeTile = false - /* - upComputesWholeTile は Screen, Min, Blendでtrueにして使用している。 - */ - ); }; FX_PLUGIN_IDENTIFIER(ino_blend_lighten, "inoLightenFx"); -//------------------------------------------------------------ -namespace { -/* より大きな四角エリアにPixel整数値で密着する */ -void makeRectCoherent(TRectD &rect, const TPointD &pos) { - rect -= pos; - rect.x0 = tfloor(rect.x0); /* ((x)<(int)(x)? (int)(x)-1: (int)(x))*/ - rect.y0 = tfloor(rect.y0); - rect.x1 = tceil(rect.x1); /* ((int)(x)<(x)? (int)(x)+1: (int)(x))*/ - rect.y1 = tceil(rect.y1); - rect += pos; -} -} -void ino_blend_lighten::computeUpAndDown(TTile &tile, double frame, - const TRenderSettings &rs, - TRasterP &dn_ras, TRasterP &up_ras, - bool upComputesWholeTile) { - /* ------ サポートしていないPixelタイプはエラーを投げる --- */ - if (!((TRaster32P)tile.getRaster()) && !((TRaster64P)tile.getRaster())) { - throw TRopException("unsupported input pixel type"); - } - /* -m_down,m_upは繋がっている方があればそれを表示する -両方とも接続していれば合成処理する -表示スイッチを切ってあるならm_upを表示する -fxをreplaceすると、 - m_source --> m_up (=port0) - m_refernce --> m_down(=port1) -となる -*/ - const bool up_is = (this->m_up.isConnected() && - this->m_up.getFx()->getTimeRegion().contains(frame)); - const bool down_is = (this->m_down.isConnected() && - this->m_down.getFx()->getTimeRegion().contains(frame)); - /* ------ 両方とも切断の時処理しない ---------------------- */ - if (!up_is && !down_is) { - tile.getRaster()->clear(); - return; - } - /* ------ up接続かつdown切断の時 -------------------------- */ - if (up_is && !down_is) { - this->m_up->compute(tile, frame, rs); - return; - } - /* ------ down接続時 downのみ描画して... ------------------ */ - if (down_is) { - this->m_down->compute(tile, frame, rs); - } - /* ------ up切断時 ---------------------------------------- */ - if (!up_is) { - return; - } - - /* upと重なる部分を描画する */ - - /* ------ tileの範囲 -------------------------------------- */ - const TDimension tsz(tile.getRaster()->getSize()); /* 整数 */ - const TRectD tileRect(tile.m_pos, TDimensionD(tsz.lx, tsz.ly)); - TRectD upBBox; - if (upComputesWholeTile) { - upBBox = tileRect; - } /* tile全体を得る */ - else { /* 厳密なエリア... */ - this->m_up->getBBox(frame, upBBox, rs); - upBBox *= tileRect; /* upとtileの交差エリア */ - - /* より大きな四角エリアにPixel整数値で密着する */ - makeRectCoherent(upBBox, tile.m_pos); // double-->int grid - } - - TDimensionI upSize( /* TRectDをTDimensionIに変換 */ - tround(upBBox.getLx()) // getLx() = "x1>=x0?x1-x0:0" - , - tround(upBBox.getLy()) // getLy() = "y1>=y0?y1-y0:0" - ); - if ((upSize.lx <= 0) || (upSize.ly <= 0)) { - return; - } - - /* ------ upのメモリ確保と描画 ---------------------------- */ - TTile upTile; - this->m_up->allocateAndCompute(upTile, upBBox.getP00(), upSize, - tile.getRaster() /* 32/64bitsの判定に使う */ - , - frame, rs); - /* ------ upとdownのTRasterを得る ------------------------- */ - TRectI dnRect(upTile.getRaster()->getSize()); // TDimensionI(-) - - dnRect += convert(upTile.m_pos - tile.m_pos); /* uptile->tile原点 */ - /* - ここで問題はdoubleの位置を、四捨五入して整数値にしていること - 移動してから四捨五入ではないの??? - dnRectの元位置が整数位置なので、問題ないか... - */ - - dn_ras = upComputesWholeTile ? tile.getRaster() - : tile.getRaster()->extract(dnRect); - up_ras = upTile.getRaster(); - assert(dn_ras->getSize() == up_ras->getSize()); -} -void ino_blend_lighten::dryComputeUpAndDown(TRectD &rect, double frame, - const TRenderSettings &rs, - bool upComputesWholeTile) { - const bool up_is = (this->m_up.isConnected() && - this->m_up.getFx()->getTimeRegion().contains(frame)); - const bool down_is = (this->m_down.isConnected() && - this->m_down.getFx()->getTimeRegion().contains(frame)); - /* ------ 両方とも切断の時処理しない ---------------------- */ - if (!up_is && !down_is) { - return; - } - /* ------ up接続かつdown切断の時 -------------------------- */ - if (up_is && !down_is) { - this->m_up->dryCompute(rect, frame, rs); - return; - } - /* ------ down接続時 -------------------------------------- */ - if (down_is) { - this->m_down->dryCompute(rect, frame, rs); - } - /* ------ up切断時 ---------------------------------------- */ - if (!up_is) { - return; - } - - /* ------ tileのgeometryを計算する ------------------------ */ - TRectD upBBox; - - if (upComputesWholeTile) { - upBBox = rect; - } else { - this->m_up->getBBox(frame, upBBox, rs); - upBBox *= rect; - makeRectCoherent(upBBox, rect.getP00()); - } - if ((upBBox.getLx() > 0.5) && (upBBox.getLy() > 0.5)) { - this->m_up->dryCompute(upBBox, frame, rs); - } -} -//------------------------------------------------------------ -#include /* std::ostringstream */ -#include "igs_color_blend.h" -namespace { -template -void tmpl_(TRasterPT dn_ras_out, const TRasterPT &up_ras, - const double up_opacity, const bool clipping_mask_sw) { - double maxi = static_cast(T::maxChannelValue); // 255or65535 - - assert(dn_ras_out->getSize() == up_ras->getSize()); - - for (int yy = 0; yy < dn_ras_out->getLy(); ++yy) { - T *out_pix = dn_ras_out->pixels(yy); - const T *const out_end = out_pix + dn_ras_out->getLx(); - const T *up_pix = up_ras->pixels(yy); - for (; out_pix < out_end; ++out_pix, ++up_pix) { - double upr = static_cast(up_pix->r) / maxi; - double upg = static_cast(up_pix->g) / maxi; - double upb = static_cast(up_pix->b) / maxi; - double upa = static_cast(up_pix->m) / maxi; - double dnr = static_cast(out_pix->r) / maxi; - double dng = static_cast(out_pix->g) / maxi; - double dnb = static_cast(out_pix->b) / maxi; - double dna = static_cast(out_pix->m) / maxi; - igs::color::lighten(dnr, dng, dnb, dna, upr, upg, upb, upa, - clipping_mask_sw ? up_opacity * dna : up_opacity); - out_pix->r = static_cast(dnr * (maxi + 0.999999)); - out_pix->g = static_cast(dng * (maxi + 0.999999)); - out_pix->b = static_cast(dnb * (maxi + 0.999999)); - out_pix->m = static_cast(dna * (maxi + 0.999999)); - } - } -} -void fx_(TRasterP &dn_ras_out, const TRasterP &up_ras, const TPoint &pos, - const double up_opacity, const bool clipping_mask_sw) { - /* 交差したエリアを処理するようにする、いるのか??? */ - TRect outRect(dn_ras_out->getBounds()); - TRect upRect(up_ras->getBounds() + pos); - TRect intersection = outRect * upRect; - if (intersection.isEmpty()) return; - - TRasterP cRout = dn_ras_out->extract(intersection); - TRect rr = intersection - pos; - TRasterP cRup = up_ras->extract(rr); - - TRaster32P rout32 = cRout, rup32 = cRup; - TRaster64P rout64 = cRout, rup64 = cRup; - - if (rout32 && rup32) { - tmpl_(rout32, rup32, up_opacity, clipping_mask_sw); - } else if (rout64 && rup64) { - tmpl_(rout64, rup64, up_opacity, clipping_mask_sw); - } else { - throw TRopException("unsupported pixel type"); - } -} -} -void ino_blend_lighten::doCompute(TTile &tile, double frame, - const TRenderSettings &rs) { - /* ------ 画像生成 ---------------------------------------- */ - TRasterP dn_ras, up_ras; - this->computeUpAndDown(tile, frame, rs, dn_ras, up_ras); - if (!dn_ras || !up_ras) { - return; - } - /* ------ 動作パラメータを得る ---------------------------- */ - const double up_opacity = - this->m_opacity->getValue(frame) / ino::param_range(); - /* ------ (app_begin)log記憶 ------------------------------ */ - const bool log_sw = ino::log_enable_sw(); - - if (log_sw) { - std::ostringstream os; - os << "params" - << " up_opacity " << up_opacity << " dn_tile w " << dn_ras->getLx() - << " wrap " << dn_ras->getWrap() << " h " << dn_ras->getLy() - << " pixbits " << ino::pixel_bits(dn_ras) << " up_tile w " - << up_ras->getLx() << " wrap " << up_ras->getWrap() << " h " - << up_ras->getLy() << " pixbits " << ino::pixel_bits(up_ras) - << " frame " << frame; - } - /* ------ fx処理 ------------------------------------------ */ - try { - if (dn_ras) { - dn_ras->lock(); - } - if (up_ras) { - up_ras->lock(); - } - fx_(dn_ras, up_ras, TPoint(), up_opacity, - this->m_clipping_mask->getValue()); - if (up_ras) { - up_ras->unlock(); - } - if (dn_ras) { - dn_ras->unlock(); - } - } - /* ------ error処理 --------------------------------------- */ - catch (std::exception &e) { - if (up_ras) { - up_ras->unlock(); - } - if (dn_ras) { - dn_ras->unlock(); - } - if (log_sw) { - std::string str("exception <"); - str += e.what(); - str += '>'; - } - throw; - } catch (...) { - if (up_ras) { - up_ras->unlock(); - } - if (dn_ras) { - dn_ras->unlock(); - } - if (log_sw) { - std::string str("other exception"); - } - throw; - } -} diff --git a/toonz/sources/stdfx/ino_blend_lighter_color.cpp b/toonz/sources/stdfx/ino_blend_lighter_color.cpp index b8d081e4..d491082c 100644 --- a/toonz/sources/stdfx/ino_blend_lighter_color.cpp +++ b/toonz/sources/stdfx/ino_blend_lighter_color.cpp @@ -3,335 +3,20 @@ #include "stdfx.h" #include "ino_common.h" +#include "igs_color_blend.h" /* tnzbase --> Source Files --> tfx --> binaryFx.cppを参照 */ class ino_blend_lighter_color final : public TBlendForeBackRasterFx { FX_PLUGIN_DECLARATION(ino_blend_lighter_color) - TRasterFxPort m_up; - TRasterFxPort m_down; - TDoubleParamP m_opacity; - TBoolParamP m_clipping_mask; public: - ino_blend_lighter_color() - : m_opacity(1.0 * ino::param_range()), m_clipping_mask(false) { - addInputPort("Fore", this->m_up); - addInputPort("Back", this->m_down); - bindParam(this, "opacity", this->m_opacity); - bindParam(this, "clipping_mask", this->m_clipping_mask); - this->m_opacity->setValueRange(0, 1.0 * ino::param_range()); - } + ino_blend_lighter_color() : TBlendForeBackRasterFx(false) {} ~ino_blend_lighter_color() {} - bool canHandle(const TRenderSettings &rs, double frame) override { - return true; + void brendKernel(double& dnr, double& dng, double& dnb, double& dna, + const double upr, double upg, double upb, double upa, + const double up_opacity, + const bool alpha_rendering_sw = true) override { + igs::color::lighter_color(dnr, dng, dnb, dna, upr, upg, upb, upa, + up_opacity); } - bool doGetBBox(double frame, TRectD &bBox, - const TRenderSettings &rs) override { - TRectD up_bx; - const bool up_sw = - (m_up.isConnected() ? m_up->doGetBBox(frame, up_bx, rs) : false); - TRectD dn_bx; - const bool dn_sw = - (m_down.isConnected() ? m_down->doGetBBox(frame, dn_bx, rs) : false); - if (up_sw && dn_sw) { - bBox = up_bx + dn_bx; - return !bBox.isEmpty(); - } else if (up_sw) { - bBox = up_bx; - return true; - } else if (dn_sw) { - bBox = dn_bx; - return true; - } else { - bBox = TRectD(); - return false; - } - } - // TRect getInvalidRect(const TRect &max) {return max;} - // void doSetParam(const std::string &name, const TParamP ¶m) {} - int getMemoryRequirement(const TRectD &rect, double frame, - const TRenderSettings &rs) override { - return TRasterFx::memorySize(rect, rs.m_bpp); - } - - void doDryCompute(TRectD &rect, double frame, - const TRenderSettings &rs) override { - this->dryComputeUpAndDown(rect, frame, rs, false); - } - void doCompute(TTile &tile, double frame, const TRenderSettings &rs) override; - void computeUpAndDown(TTile &tile, double frame, const TRenderSettings &rs, - TRasterP &dn_ras, TRasterP &up_ras, - bool upComputesWholeTile = false); - void dryComputeUpAndDown(TRectD &rect, double frame, - const TRenderSettings &rs, - bool upComputesWholeTile = false - /* - upComputesWholeTile は Screen, Min, Blendでtrueにして使用している。 - */ - ); }; FX_PLUGIN_IDENTIFIER(ino_blend_lighter_color, "inoLighterColorFx"); -//------------------------------------------------------------ -namespace { -/* より大きな四角エリアにPixel整数値で密着する */ -void makeRectCoherent(TRectD &rect, const TPointD &pos) { - rect -= pos; - rect.x0 = tfloor(rect.x0); /* ((x)<(int)(x)? (int)(x)-1: (int)(x))*/ - rect.y0 = tfloor(rect.y0); - rect.x1 = tceil(rect.x1); /* ((int)(x)<(x)? (int)(x)+1: (int)(x))*/ - rect.y1 = tceil(rect.y1); - rect += pos; -} -} -void ino_blend_lighter_color::computeUpAndDown(TTile &tile, double frame, - const TRenderSettings &rs, - TRasterP &dn_ras, - TRasterP &up_ras, - bool upComputesWholeTile) { - /* ------ サポートしていないPixelタイプはエラーを投げる --- */ - if (!((TRaster32P)tile.getRaster()) && !((TRaster64P)tile.getRaster())) { - throw TRopException("unsupported input pixel type"); - } - /* -m_down,m_upは繋がっている方があればそれを表示する -両方とも接続していれば合成処理する -表示スイッチを切ってあるならm_upを表示する -fxをreplaceすると、 - m_source --> m_up (=port0) - m_refernce --> m_down(=port1) -となる -*/ - const bool up_is = (this->m_up.isConnected() && - this->m_up.getFx()->getTimeRegion().contains(frame)); - const bool down_is = (this->m_down.isConnected() && - this->m_down.getFx()->getTimeRegion().contains(frame)); - /* ------ 両方とも切断の時処理しない ---------------------- */ - if (!up_is && !down_is) { - tile.getRaster()->clear(); - return; - } - /* ------ up接続かつdown切断の時 -------------------------- */ - if (up_is && !down_is) { - this->m_up->compute(tile, frame, rs); - return; - } - /* ------ down接続時 downのみ描画して... ------------------ */ - if (down_is) { - this->m_down->compute(tile, frame, rs); - } - /* ------ up切断時 ---------------------------------------- */ - if (!up_is) { - return; - } - - /* upと重なる部分を描画する */ - - /* ------ tileの範囲 -------------------------------------- */ - const TDimension tsz(tile.getRaster()->getSize()); /* 整数 */ - const TRectD tileRect(tile.m_pos, TDimensionD(tsz.lx, tsz.ly)); - TRectD upBBox; - if (upComputesWholeTile) { - upBBox = tileRect; - } /* tile全体を得る */ - else { /* 厳密なエリア... */ - this->m_up->getBBox(frame, upBBox, rs); - upBBox *= tileRect; /* upとtileの交差エリア */ - - /* より大きな四角エリアにPixel整数値で密着する */ - makeRectCoherent(upBBox, tile.m_pos); // double-->int grid - } - - TDimensionI upSize( /* TRectDをTDimensionIに変換 */ - tround(upBBox.getLx()) // getLx() = "x1>=x0?x1-x0:0" - , - tround(upBBox.getLy()) // getLy() = "y1>=y0?y1-y0:0" - ); - if ((upSize.lx <= 0) || (upSize.ly <= 0)) { - return; - } - - /* ------ upのメモリ確保と描画 ---------------------------- */ - TTile upTile; - this->m_up->allocateAndCompute(upTile, upBBox.getP00(), upSize, - tile.getRaster() /* 32/64bitsの判定に使う */ - , - frame, rs); - /* ------ upとdownのTRasterを得る ------------------------- */ - TRectI dnRect(upTile.getRaster()->getSize()); // TDimensionI(-) - - dnRect += convert(upTile.m_pos - tile.m_pos); /* uptile->tile原点 */ - /* - ここで問題はdoubleの位置を、四捨五入して整数値にしていること - 移動してから四捨五入ではないの??? - dnRectの元位置が整数位置なので、問題ないか... - */ - - dn_ras = upComputesWholeTile ? tile.getRaster() - : tile.getRaster()->extract(dnRect); - up_ras = upTile.getRaster(); - assert(dn_ras->getSize() == up_ras->getSize()); -} -void ino_blend_lighter_color::dryComputeUpAndDown(TRectD &rect, double frame, - const TRenderSettings &rs, - bool upComputesWholeTile) { - const bool up_is = (this->m_up.isConnected() && - this->m_up.getFx()->getTimeRegion().contains(frame)); - const bool down_is = (this->m_down.isConnected() && - this->m_down.getFx()->getTimeRegion().contains(frame)); - /* ------ 両方とも切断の時処理しない ---------------------- */ - if (!up_is && !down_is) { - return; - } - /* ------ up接続かつdown切断の時 -------------------------- */ - if (up_is && !down_is) { - this->m_up->dryCompute(rect, frame, rs); - return; - } - /* ------ down接続時 -------------------------------------- */ - if (down_is) { - this->m_down->dryCompute(rect, frame, rs); - } - /* ------ up切断時 ---------------------------------------- */ - if (!up_is) { - return; - } - - /* ------ tileのgeometryを計算する ------------------------ */ - TRectD upBBox; - - if (upComputesWholeTile) { - upBBox = rect; - } else { - this->m_up->getBBox(frame, upBBox, rs); - upBBox *= rect; - makeRectCoherent(upBBox, rect.getP00()); - } - if ((upBBox.getLx() > 0.5) && (upBBox.getLy() > 0.5)) { - this->m_up->dryCompute(upBBox, frame, rs); - } -} -//------------------------------------------------------------ -#include /* std::ostringstream */ -#include "igs_color_blend.h" -namespace { -template -void tmpl_(TRasterPT dn_ras_out, const TRasterPT &up_ras, - const double up_opacity, const bool clipping_mask_sw) { - double maxi = static_cast(T::maxChannelValue); // 255or65535 - - assert(dn_ras_out->getSize() == up_ras->getSize()); - - for (int yy = 0; yy < dn_ras_out->getLy(); ++yy) { - T *out_pix = dn_ras_out->pixels(yy); - const T *const out_end = out_pix + dn_ras_out->getLx(); - const T *up_pix = up_ras->pixels(yy); - for (; out_pix < out_end; ++out_pix, ++up_pix) { - double upr = static_cast(up_pix->r) / maxi; - double upg = static_cast(up_pix->g) / maxi; - double upb = static_cast(up_pix->b) / maxi; - double upa = static_cast(up_pix->m) / maxi; - double dnr = static_cast(out_pix->r) / maxi; - double dng = static_cast(out_pix->g) / maxi; - double dnb = static_cast(out_pix->b) / maxi; - double dna = static_cast(out_pix->m) / maxi; - igs::color::lighter_color( - dnr, dng, dnb, dna, upr, upg, upb, upa, - clipping_mask_sw ? up_opacity * dna : up_opacity); - out_pix->r = static_cast(dnr * (maxi + 0.999999)); - out_pix->g = static_cast(dng * (maxi + 0.999999)); - out_pix->b = static_cast(dnb * (maxi + 0.999999)); - out_pix->m = static_cast(dna * (maxi + 0.999999)); - } - } -} -void fx_(TRasterP &dn_ras_out, const TRasterP &up_ras, const TPoint &pos, - const double up_opacity, const bool clipping_mask_sw) { - /* 交差したエリアを処理するようにする、いるのか??? */ - TRect outRect(dn_ras_out->getBounds()); - TRect upRect(up_ras->getBounds() + pos); - TRect intersection = outRect * upRect; - if (intersection.isEmpty()) return; - - TRasterP cRout = dn_ras_out->extract(intersection); - TRect rr = intersection - pos; - TRasterP cRup = up_ras->extract(rr); - - TRaster32P rout32 = cRout, rup32 = cRup; - TRaster64P rout64 = cRout, rup64 = cRup; - - if (rout32 && rup32) { - tmpl_(rout32, rup32, up_opacity, clipping_mask_sw); - } else if (rout64 && rup64) { - tmpl_(rout64, rup64, up_opacity, clipping_mask_sw); - } else { - throw TRopException("unsupported pixel type"); - } -} -} -void ino_blend_lighter_color::doCompute(TTile &tile, double frame, - const TRenderSettings &rs) { - /* ------ 画像生成 ---------------------------------------- */ - TRasterP dn_ras, up_ras; - this->computeUpAndDown(tile, frame, rs, dn_ras, up_ras); - if (!dn_ras || !up_ras) { - return; - } - /* ------ 動作パラメータを得る ---------------------------- */ - const double up_opacity = - this->m_opacity->getValue(frame) / ino::param_range(); - /* ------ (app_begin)log記憶 ------------------------------ */ - const bool log_sw = ino::log_enable_sw(); - - if (log_sw) { - std::ostringstream os; - os << "params" - << " up_opacity " << up_opacity << " dn_tile w " << dn_ras->getLx() - << " wrap " << dn_ras->getWrap() << " h " << dn_ras->getLy() - << " pixbits " << ino::pixel_bits(dn_ras) << " up_tile w " - << up_ras->getLx() << " wrap " << up_ras->getWrap() << " h " - << up_ras->getLy() << " pixbits " << ino::pixel_bits(up_ras) - << " frame " << frame; - } - /* ------ fx処理 ------------------------------------------ */ - try { - if (dn_ras) { - dn_ras->lock(); - } - if (up_ras) { - up_ras->lock(); - } - fx_(dn_ras, up_ras, TPoint(), up_opacity, - this->m_clipping_mask->getValue()); - if (up_ras) { - up_ras->unlock(); - } - if (dn_ras) { - dn_ras->unlock(); - } - } - /* ------ error処理 --------------------------------------- */ - catch (std::exception &e) { - if (up_ras) { - up_ras->unlock(); - } - if (dn_ras) { - dn_ras->unlock(); - } - if (log_sw) { - std::string str("exception <"); - str += e.what(); - str += '>'; - } - throw; - } catch (...) { - if (up_ras) { - up_ras->unlock(); - } - if (dn_ras) { - dn_ras->unlock(); - } - if (log_sw) { - std::string str("other exception"); - } - throw; - } -} diff --git a/toonz/sources/stdfx/ino_blend_linear_burn.cpp b/toonz/sources/stdfx/ino_blend_linear_burn.cpp index d1e63ecd..7dffc0b1 100644 --- a/toonz/sources/stdfx/ino_blend_linear_burn.cpp +++ b/toonz/sources/stdfx/ino_blend_linear_burn.cpp @@ -3,333 +3,19 @@ #include "stdfx.h" #include "ino_common.h" +#include "igs_color_blend.h" /* tnzbase --> Source Files --> tfx --> binaryFx.cppを参照 */ class ino_blend_linear_burn final : public TBlendForeBackRasterFx { FX_PLUGIN_DECLARATION(ino_blend_linear_burn) - TRasterFxPort m_up; - TRasterFxPort m_down; - TDoubleParamP m_opacity; - TBoolParamP m_clipping_mask; public: - ino_blend_linear_burn() - : m_opacity(1.0 * ino::param_range()), m_clipping_mask(true) { - addInputPort("Fore", this->m_up); - addInputPort("Back", this->m_down); - bindParam(this, "opacity", this->m_opacity); - bindParam(this, "clipping_mask", this->m_clipping_mask); - this->m_opacity->setValueRange(0, 1.0 * ino::param_range()); - } + ino_blend_linear_burn() : TBlendForeBackRasterFx(true) {} ~ino_blend_linear_burn() {} - bool canHandle(const TRenderSettings &rs, double frame) override { - return true; + void brendKernel(double& dnr, double& dng, double& dnb, double& dna, + const double upr, double upg, double upb, double upa, + const double up_opacity, + const bool alpha_rendering_sw = true) override { + igs::color::linear_burn(dnr, dng, dnb, dna, upr, upg, upb, upa, up_opacity); } - bool doGetBBox(double frame, TRectD &bBox, - const TRenderSettings &rs) override { - TRectD up_bx; - const bool up_sw = - (m_up.isConnected() ? m_up->doGetBBox(frame, up_bx, rs) : false); - TRectD dn_bx; - const bool dn_sw = - (m_down.isConnected() ? m_down->doGetBBox(frame, dn_bx, rs) : false); - if (up_sw && dn_sw) { - bBox = up_bx + dn_bx; - return !bBox.isEmpty(); - } else if (up_sw) { - bBox = up_bx; - return true; - } else if (dn_sw) { - bBox = dn_bx; - return true; - } else { - bBox = TRectD(); - return false; - } - } - // TRect getInvalidRect(const TRect &max) {return max;} - // void doSetParam(const std::string &name, const TParamP ¶m) {} - int getMemoryRequirement(const TRectD &rect, double frame, - const TRenderSettings &rs) override { - return TRasterFx::memorySize(rect, rs.m_bpp); - } - - void doDryCompute(TRectD &rect, double frame, - const TRenderSettings &rs) override { - this->dryComputeUpAndDown(rect, frame, rs, false); - } - void doCompute(TTile &tile, double frame, const TRenderSettings &rs) override; - void computeUpAndDown(TTile &tile, double frame, const TRenderSettings &rs, - TRasterP &dn_ras, TRasterP &up_ras, - bool upComputesWholeTile = false); - void dryComputeUpAndDown(TRectD &rect, double frame, - const TRenderSettings &rs, - bool upComputesWholeTile = false - /* - upComputesWholeTile は Screen, Min, Blendでtrueにして使用している。 - */ - ); }; FX_PLUGIN_IDENTIFIER(ino_blend_linear_burn, "inoLinearBurnFx"); -//------------------------------------------------------------ -namespace { -/* より大きな四角エリアにPixel整数値で密着する */ -void makeRectCoherent(TRectD &rect, const TPointD &pos) { - rect -= pos; - rect.x0 = tfloor(rect.x0); /* ((x)<(int)(x)? (int)(x)-1: (int)(x))*/ - rect.y0 = tfloor(rect.y0); - rect.x1 = tceil(rect.x1); /* ((int)(x)<(x)? (int)(x)+1: (int)(x))*/ - rect.y1 = tceil(rect.y1); - rect += pos; -} -} -void ino_blend_linear_burn::computeUpAndDown(TTile &tile, double frame, - const TRenderSettings &rs, - TRasterP &dn_ras, TRasterP &up_ras, - bool upComputesWholeTile) { - /* ------ サポートしていないPixelタイプはエラーを投げる --- */ - if (!((TRaster32P)tile.getRaster()) && !((TRaster64P)tile.getRaster())) { - throw TRopException("unsupported input pixel type"); - } - /* -m_down,m_upは繋がっている方があればそれを表示する -両方とも接続していれば合成処理する -表示スイッチを切ってあるならm_upを表示する -fxをreplaceすると、 - m_source --> m_up (=port0) - m_refernce --> m_down(=port1) -となる -*/ - const bool up_is = (this->m_up.isConnected() && - this->m_up.getFx()->getTimeRegion().contains(frame)); - const bool down_is = (this->m_down.isConnected() && - this->m_down.getFx()->getTimeRegion().contains(frame)); - /* ------ 両方とも切断の時処理しない ---------------------- */ - if (!up_is && !down_is) { - tile.getRaster()->clear(); - return; - } - /* ------ up接続かつdown切断の時 -------------------------- */ - if (up_is && !down_is) { - this->m_up->compute(tile, frame, rs); - return; - } - /* ------ down接続時 downのみ描画して... ------------------ */ - if (down_is) { - this->m_down->compute(tile, frame, rs); - } - /* ------ up切断時 ---------------------------------------- */ - if (!up_is) { - return; - } - - /* upと重なる部分を描画する */ - - /* ------ tileの範囲 -------------------------------------- */ - const TDimension tsz(tile.getRaster()->getSize()); /* 整数 */ - const TRectD tileRect(tile.m_pos, TDimensionD(tsz.lx, tsz.ly)); - TRectD upBBox; - if (upComputesWholeTile) { - upBBox = tileRect; - } /* tile全体を得る */ - else { /* 厳密なエリア... */ - this->m_up->getBBox(frame, upBBox, rs); - upBBox *= tileRect; /* upとtileの交差エリア */ - - /* より大きな四角エリアにPixel整数値で密着する */ - makeRectCoherent(upBBox, tile.m_pos); // double-->int grid - } - - TDimensionI upSize( /* TRectDをTDimensionIに変換 */ - tround(upBBox.getLx()) // getLx() = "x1>=x0?x1-x0:0" - , - tround(upBBox.getLy()) // getLy() = "y1>=y0?y1-y0:0" - ); - if ((upSize.lx <= 0) || (upSize.ly <= 0)) { - return; - } - - /* ------ upのメモリ確保と描画 ---------------------------- */ - TTile upTile; - this->m_up->allocateAndCompute(upTile, upBBox.getP00(), upSize, - tile.getRaster() /* 32/64bitsの判定に使う */ - , - frame, rs); - /* ------ upとdownのTRasterを得る ------------------------- */ - TRectI dnRect(upTile.getRaster()->getSize()); // TDimensionI(-) - - dnRect += convert(upTile.m_pos - tile.m_pos); /* uptile->tile原点 */ - /* - ここで問題はdoubleの位置を、四捨五入して整数値にしていること - 移動してから四捨五入ではないの??? - dnRectの元位置が整数位置なので、問題ないか... - */ - - dn_ras = upComputesWholeTile ? tile.getRaster() - : tile.getRaster()->extract(dnRect); - up_ras = upTile.getRaster(); - assert(dn_ras->getSize() == up_ras->getSize()); -} -void ino_blend_linear_burn::dryComputeUpAndDown(TRectD &rect, double frame, - const TRenderSettings &rs, - bool upComputesWholeTile) { - const bool up_is = (this->m_up.isConnected() && - this->m_up.getFx()->getTimeRegion().contains(frame)); - const bool down_is = (this->m_down.isConnected() && - this->m_down.getFx()->getTimeRegion().contains(frame)); - /* ------ 両方とも切断の時処理しない ---------------------- */ - if (!up_is && !down_is) { - return; - } - /* ------ up接続かつdown切断の時 -------------------------- */ - if (up_is && !down_is) { - this->m_up->dryCompute(rect, frame, rs); - return; - } - /* ------ down接続時 -------------------------------------- */ - if (down_is) { - this->m_down->dryCompute(rect, frame, rs); - } - /* ------ up切断時 ---------------------------------------- */ - if (!up_is) { - return; - } - - /* ------ tileのgeometryを計算する ------------------------ */ - TRectD upBBox; - - if (upComputesWholeTile) { - upBBox = rect; - } else { - this->m_up->getBBox(frame, upBBox, rs); - upBBox *= rect; - makeRectCoherent(upBBox, rect.getP00()); - } - if ((upBBox.getLx() > 0.5) && (upBBox.getLy() > 0.5)) { - this->m_up->dryCompute(upBBox, frame, rs); - } -} -//------------------------------------------------------------ -#include /* std::ostringstream */ -#include "igs_color_blend.h" -namespace { -template -void tmpl_(TRasterPT dn_ras_out, const TRasterPT &up_ras, - const double up_opacity, const bool clipping_mask_sw) { - double maxi = static_cast(T::maxChannelValue); // 255or65535 - - assert(dn_ras_out->getSize() == up_ras->getSize()); - - for (int yy = 0; yy < dn_ras_out->getLy(); ++yy) { - T *out_pix = dn_ras_out->pixels(yy); - const T *const out_end = out_pix + dn_ras_out->getLx(); - const T *up_pix = up_ras->pixels(yy); - for (; out_pix < out_end; ++out_pix, ++up_pix) { - double upr = static_cast(up_pix->r) / maxi; - double upg = static_cast(up_pix->g) / maxi; - double upb = static_cast(up_pix->b) / maxi; - double upa = static_cast(up_pix->m) / maxi; - double dnr = static_cast(out_pix->r) / maxi; - double dng = static_cast(out_pix->g) / maxi; - double dnb = static_cast(out_pix->b) / maxi; - double dna = static_cast(out_pix->m) / maxi; - igs::color::linear_burn(dnr, dng, dnb, dna, upr, upg, upb, upa, - clipping_mask_sw ? up_opacity * dna : up_opacity); - out_pix->r = static_cast(dnr * (maxi + 0.999999)); - out_pix->g = static_cast(dng * (maxi + 0.999999)); - out_pix->b = static_cast(dnb * (maxi + 0.999999)); - out_pix->m = static_cast(dna * (maxi + 0.999999)); - } - } -} -void fx_(TRasterP &dn_ras_out, const TRasterP &up_ras, const TPoint &pos, - const double up_opacity, const bool clipping_mask_sw) { - /* 交差したエリアを処理するようにする、いるのか??? */ - TRect outRect(dn_ras_out->getBounds()); - TRect upRect(up_ras->getBounds() + pos); - TRect intersection = outRect * upRect; - if (intersection.isEmpty()) return; - - TRasterP cRout = dn_ras_out->extract(intersection); - TRect rr = intersection - pos; - TRasterP cRup = up_ras->extract(rr); - - TRaster32P rout32 = cRout, rup32 = cRup; - TRaster64P rout64 = cRout, rup64 = cRup; - - if (rout32 && rup32) { - tmpl_(rout32, rup32, up_opacity, clipping_mask_sw); - } else if (rout64 && rup64) { - tmpl_(rout64, rup64, up_opacity, clipping_mask_sw); - } else { - throw TRopException("unsupported pixel type"); - } -} -} -void ino_blend_linear_burn::doCompute(TTile &tile, double frame, - const TRenderSettings &rs) { - /* ------ 画像生成 ---------------------------------------- */ - TRasterP dn_ras, up_ras; - this->computeUpAndDown(tile, frame, rs, dn_ras, up_ras); - if (!dn_ras || !up_ras) { - return; - } - /* ------ 動作パラメータを得る ---------------------------- */ - const double up_opacity = - this->m_opacity->getValue(frame) / ino::param_range(); - /* ------ (app_begin)log記憶 ------------------------------ */ - const bool log_sw = ino::log_enable_sw(); - - if (log_sw) { - std::ostringstream os; - os << "params" - << " up_opacity " << up_opacity << " dn_tile w " << dn_ras->getLx() - << " wrap " << dn_ras->getWrap() << " h " << dn_ras->getLy() - << " pixbits " << ino::pixel_bits(dn_ras) << " up_tile w " - << up_ras->getLx() << " wrap " << up_ras->getWrap() << " h " - << up_ras->getLy() << " pixbits " << ino::pixel_bits(up_ras) - << " frame " << frame; - } - /* ------ fx処理 ------------------------------------------ */ - try { - if (dn_ras) { - dn_ras->lock(); - } - if (up_ras) { - up_ras->lock(); - } - fx_(dn_ras, up_ras, TPoint(), up_opacity, - this->m_clipping_mask->getValue()); - if (up_ras) { - up_ras->unlock(); - } - if (dn_ras) { - dn_ras->unlock(); - } - } - /* ------ error処理 --------------------------------------- */ - catch (std::exception &e) { - if (up_ras) { - up_ras->unlock(); - } - if (dn_ras) { - dn_ras->unlock(); - } - if (log_sw) { - std::string str("exception <"); - str += e.what(); - str += '>'; - } - throw; - } catch (...) { - if (up_ras) { - up_ras->unlock(); - } - if (dn_ras) { - dn_ras->unlock(); - } - if (log_sw) { - std::string str("other exception"); - } - throw; - } -} diff --git a/toonz/sources/stdfx/ino_blend_linear_dodge.cpp b/toonz/sources/stdfx/ino_blend_linear_dodge.cpp index 9e8598a2..aecbe552 100644 --- a/toonz/sources/stdfx/ino_blend_linear_dodge.cpp +++ b/toonz/sources/stdfx/ino_blend_linear_dodge.cpp @@ -3,335 +3,20 @@ #include "stdfx.h" #include "ino_common.h" +#include "igs_color_blend.h" /* tnzbase --> Source Files --> tfx --> binaryFx.cppを参照 */ class ino_blend_linear_dodge final : public TBlendForeBackRasterFx { FX_PLUGIN_DECLARATION(ino_blend_linear_dodge) - TRasterFxPort m_up; - TRasterFxPort m_down; - TDoubleParamP m_opacity; - TBoolParamP m_clipping_mask; public: - ino_blend_linear_dodge() - : m_opacity(1.0 * ino::param_range()), m_clipping_mask(true) { - addInputPort("Fore", this->m_up); - addInputPort("Back", this->m_down); - bindParam(this, "opacity", this->m_opacity); - bindParam(this, "clipping_mask", this->m_clipping_mask); - this->m_opacity->setValueRange(0, 1.0 * ino::param_range()); - } + ino_blend_linear_dodge() : TBlendForeBackRasterFx(true) {} ~ino_blend_linear_dodge() {} - bool canHandle(const TRenderSettings &rs, double frame) override { - return true; + void brendKernel(double& dnr, double& dng, double& dnb, double& dna, + const double upr, double upg, double upb, double upa, + const double up_opacity, + const bool alpha_rendering_sw = true) override { + igs::color::linear_dodge(dnr, dng, dnb, dna, upr, upg, upb, upa, + up_opacity); } - bool doGetBBox(double frame, TRectD &bBox, - const TRenderSettings &rs) override { - TRectD up_bx; - const bool up_sw = - (m_up.isConnected() ? m_up->doGetBBox(frame, up_bx, rs) : false); - TRectD dn_bx; - const bool dn_sw = - (m_down.isConnected() ? m_down->doGetBBox(frame, dn_bx, rs) : false); - if (up_sw && dn_sw) { - bBox = up_bx + dn_bx; - return !bBox.isEmpty(); - } else if (up_sw) { - bBox = up_bx; - return true; - } else if (dn_sw) { - bBox = dn_bx; - return true; - } else { - bBox = TRectD(); - return false; - } - } - // TRect getInvalidRect(const TRect &max) {return max;} - // void doSetParam(const std::string &name, const TParamP ¶m) {} - int getMemoryRequirement(const TRectD &rect, double frame, - const TRenderSettings &rs) override { - return TRasterFx::memorySize(rect, rs.m_bpp); - } - - void doDryCompute(TRectD &rect, double frame, - const TRenderSettings &rs) override { - this->dryComputeUpAndDown(rect, frame, rs, false); - } - void doCompute(TTile &tile, double frame, const TRenderSettings &rs) override; - void computeUpAndDown(TTile &tile, double frame, const TRenderSettings &rs, - TRasterP &dn_ras, TRasterP &up_ras, - bool upComputesWholeTile = false); - void dryComputeUpAndDown(TRectD &rect, double frame, - const TRenderSettings &rs, - bool upComputesWholeTile = false - /* - upComputesWholeTile は Screen, Min, Blendでtrueにして使用している。 - */ - ); }; FX_PLUGIN_IDENTIFIER(ino_blend_linear_dodge, "inoLinearDodgeFx"); -//------------------------------------------------------------ -namespace { -/* より大きな四角エリアにPixel整数値で密着する */ -void makeRectCoherent(TRectD &rect, const TPointD &pos) { - rect -= pos; - rect.x0 = tfloor(rect.x0); /* ((x)<(int)(x)? (int)(x)-1: (int)(x))*/ - rect.y0 = tfloor(rect.y0); - rect.x1 = tceil(rect.x1); /* ((int)(x)<(x)? (int)(x)+1: (int)(x))*/ - rect.y1 = tceil(rect.y1); - rect += pos; -} -} -void ino_blend_linear_dodge::computeUpAndDown(TTile &tile, double frame, - const TRenderSettings &rs, - TRasterP &dn_ras, - TRasterP &up_ras, - bool upComputesWholeTile) { - /* ------ サポートしていないPixelタイプはエラーを投げる --- */ - if (!((TRaster32P)tile.getRaster()) && !((TRaster64P)tile.getRaster())) { - throw TRopException("unsupported input pixel type"); - } - /* -m_down,m_upは繋がっている方があればそれを表示する -両方とも接続していれば合成処理する -表示スイッチを切ってあるならm_upを表示する -fxをreplaceすると、 - m_source --> m_up (=port0) - m_refernce --> m_down(=port1) -となる -*/ - const bool up_is = (this->m_up.isConnected() && - this->m_up.getFx()->getTimeRegion().contains(frame)); - const bool down_is = (this->m_down.isConnected() && - this->m_down.getFx()->getTimeRegion().contains(frame)); - /* ------ 両方とも切断の時処理しない ---------------------- */ - if (!up_is && !down_is) { - tile.getRaster()->clear(); - return; - } - /* ------ up接続かつdown切断の時 -------------------------- */ - if (up_is && !down_is) { - this->m_up->compute(tile, frame, rs); - return; - } - /* ------ down接続時 downのみ描画して... ------------------ */ - if (down_is) { - this->m_down->compute(tile, frame, rs); - } - /* ------ up切断時 ---------------------------------------- */ - if (!up_is) { - return; - } - - /* upと重なる部分を描画する */ - - /* ------ tileの範囲 -------------------------------------- */ - const TDimension tsz(tile.getRaster()->getSize()); /* 整数 */ - const TRectD tileRect(tile.m_pos, TDimensionD(tsz.lx, tsz.ly)); - TRectD upBBox; - if (upComputesWholeTile) { - upBBox = tileRect; - } /* tile全体を得る */ - else { /* 厳密なエリア... */ - this->m_up->getBBox(frame, upBBox, rs); - upBBox *= tileRect; /* upとtileの交差エリア */ - - /* より大きな四角エリアにPixel整数値で密着する */ - makeRectCoherent(upBBox, tile.m_pos); // double-->int grid - } - - TDimensionI upSize( /* TRectDをTDimensionIに変換 */ - tround(upBBox.getLx()) // getLx() = "x1>=x0?x1-x0:0" - , - tround(upBBox.getLy()) // getLy() = "y1>=y0?y1-y0:0" - ); - if ((upSize.lx <= 0) || (upSize.ly <= 0)) { - return; - } - - /* ------ upのメモリ確保と描画 ---------------------------- */ - TTile upTile; - this->m_up->allocateAndCompute(upTile, upBBox.getP00(), upSize, - tile.getRaster() /* 32/64bitsの判定に使う */ - , - frame, rs); - /* ------ upとdownのTRasterを得る ------------------------- */ - TRectI dnRect(upTile.getRaster()->getSize()); // TDimensionI(-) - - dnRect += convert(upTile.m_pos - tile.m_pos); /* uptile->tile原点 */ - /* - ここで問題はdoubleの位置を、四捨五入して整数値にしていること - 移動してから四捨五入ではないの??? - dnRectの元位置が整数位置なので、問題ないか... - */ - - dn_ras = upComputesWholeTile ? tile.getRaster() - : tile.getRaster()->extract(dnRect); - up_ras = upTile.getRaster(); - assert(dn_ras->getSize() == up_ras->getSize()); -} -void ino_blend_linear_dodge::dryComputeUpAndDown(TRectD &rect, double frame, - const TRenderSettings &rs, - bool upComputesWholeTile) { - const bool up_is = (this->m_up.isConnected() && - this->m_up.getFx()->getTimeRegion().contains(frame)); - const bool down_is = (this->m_down.isConnected() && - this->m_down.getFx()->getTimeRegion().contains(frame)); - /* ------ 両方とも切断の時処理しない ---------------------- */ - if (!up_is && !down_is) { - return; - } - /* ------ up接続かつdown切断の時 -------------------------- */ - if (up_is && !down_is) { - this->m_up->dryCompute(rect, frame, rs); - return; - } - /* ------ down接続時 -------------------------------------- */ - if (down_is) { - this->m_down->dryCompute(rect, frame, rs); - } - /* ------ up切断時 ---------------------------------------- */ - if (!up_is) { - return; - } - - /* ------ tileのgeometryを計算する ------------------------ */ - TRectD upBBox; - - if (upComputesWholeTile) { - upBBox = rect; - } else { - this->m_up->getBBox(frame, upBBox, rs); - upBBox *= rect; - makeRectCoherent(upBBox, rect.getP00()); - } - if ((upBBox.getLx() > 0.5) && (upBBox.getLy() > 0.5)) { - this->m_up->dryCompute(upBBox, frame, rs); - } -} -//------------------------------------------------------------ -#include /* std::ostringstream */ -#include "igs_color_blend.h" -namespace { -template -void tmpl_(TRasterPT dn_ras_out, const TRasterPT &up_ras, - const double up_opacity, const bool clipping_mask_sw) { - double maxi = static_cast(T::maxChannelValue); // 255or65535 - - assert(dn_ras_out->getSize() == up_ras->getSize()); - - for (int yy = 0; yy < dn_ras_out->getLy(); ++yy) { - T *out_pix = dn_ras_out->pixels(yy); - const T *const out_end = out_pix + dn_ras_out->getLx(); - const T *up_pix = up_ras->pixels(yy); - for (; out_pix < out_end; ++out_pix, ++up_pix) { - double upr = static_cast(up_pix->r) / maxi; - double upg = static_cast(up_pix->g) / maxi; - double upb = static_cast(up_pix->b) / maxi; - double upa = static_cast(up_pix->m) / maxi; - double dnr = static_cast(out_pix->r) / maxi; - double dng = static_cast(out_pix->g) / maxi; - double dnb = static_cast(out_pix->b) / maxi; - double dna = static_cast(out_pix->m) / maxi; - igs::color::linear_dodge( - dnr, dng, dnb, dna, upr, upg, upb, upa, - clipping_mask_sw ? up_opacity * dna : up_opacity); - out_pix->r = static_cast(dnr * (maxi + 0.999999)); - out_pix->g = static_cast(dng * (maxi + 0.999999)); - out_pix->b = static_cast(dnb * (maxi + 0.999999)); - out_pix->m = static_cast(dna * (maxi + 0.999999)); - } - } -} -void fx_(TRasterP &dn_ras_out, const TRasterP &up_ras, const TPoint &pos, - const double up_opacity, const bool clipping_mask_sw) { - /* 交差したエリアを処理するようにする、いるのか??? */ - TRect outRect(dn_ras_out->getBounds()); - TRect upRect(up_ras->getBounds() + pos); - TRect intersection = outRect * upRect; - if (intersection.isEmpty()) return; - - TRasterP cRout = dn_ras_out->extract(intersection); - TRect rr = intersection - pos; - TRasterP cRup = up_ras->extract(rr); - - TRaster32P rout32 = cRout, rup32 = cRup; - TRaster64P rout64 = cRout, rup64 = cRup; - - if (rout32 && rup32) { - tmpl_(rout32, rup32, up_opacity, clipping_mask_sw); - } else if (rout64 && rup64) { - tmpl_(rout64, rup64, up_opacity, clipping_mask_sw); - } else { - throw TRopException("unsupported pixel type"); - } -} -} -void ino_blend_linear_dodge::doCompute(TTile &tile, double frame, - const TRenderSettings &rs) { - /* ------ 画像生成 ---------------------------------------- */ - TRasterP dn_ras, up_ras; - this->computeUpAndDown(tile, frame, rs, dn_ras, up_ras); - if (!dn_ras || !up_ras) { - return; - } - /* ------ 動作パラメータを得る ---------------------------- */ - const double up_opacity = - this->m_opacity->getValue(frame) / ino::param_range(); - /* ------ (app_begin)log記憶 ------------------------------ */ - const bool log_sw = ino::log_enable_sw(); - - if (log_sw) { - std::ostringstream os; - os << "params" - << " up_opacity " << up_opacity << " dn_tile w " << dn_ras->getLx() - << " wrap " << dn_ras->getWrap() << " h " << dn_ras->getLy() - << " pixbits " << ino::pixel_bits(dn_ras) << " up_tile w " - << up_ras->getLx() << " wrap " << up_ras->getWrap() << " h " - << up_ras->getLy() << " pixbits " << ino::pixel_bits(up_ras) - << " frame " << frame; - } - /* ------ fx処理 ------------------------------------------ */ - try { - if (dn_ras) { - dn_ras->lock(); - } - if (up_ras) { - up_ras->lock(); - } - fx_(dn_ras, up_ras, TPoint(), up_opacity, - this->m_clipping_mask->getValue()); - if (up_ras) { - up_ras->unlock(); - } - if (dn_ras) { - dn_ras->unlock(); - } - } - /* ------ error処理 --------------------------------------- */ - catch (std::exception &e) { - if (up_ras) { - up_ras->unlock(); - } - if (dn_ras) { - dn_ras->unlock(); - } - if (log_sw) { - std::string str("exception <"); - str += e.what(); - str += '>'; - } - throw; - } catch (...) { - if (up_ras) { - up_ras->unlock(); - } - if (dn_ras) { - dn_ras->unlock(); - } - if (log_sw) { - std::string str("other exception"); - } - throw; - } -} diff --git a/toonz/sources/stdfx/ino_blend_linear_light.cpp b/toonz/sources/stdfx/ino_blend_linear_light.cpp index 3f7439c0..ec4083ef 100644 --- a/toonz/sources/stdfx/ino_blend_linear_light.cpp +++ b/toonz/sources/stdfx/ino_blend_linear_light.cpp @@ -3,335 +3,20 @@ #include "stdfx.h" #include "ino_common.h" +#include "igs_color_blend.h" /* tnzbase --> Source Files --> tfx --> binaryFx.cppを参照 */ class ino_blend_linear_light final : public TBlendForeBackRasterFx { FX_PLUGIN_DECLARATION(ino_blend_linear_light) - TRasterFxPort m_up; - TRasterFxPort m_down; - TDoubleParamP m_opacity; - TBoolParamP m_clipping_mask; public: - ino_blend_linear_light() - : m_opacity(1.0 * ino::param_range()), m_clipping_mask(true) { - addInputPort("Fore", this->m_up); - addInputPort("Back", this->m_down); - bindParam(this, "opacity", this->m_opacity); - bindParam(this, "clipping_mask", this->m_clipping_mask); - this->m_opacity->setValueRange(0, 1.0 * ino::param_range()); - } + ino_blend_linear_light() : TBlendForeBackRasterFx(true) {} ~ino_blend_linear_light() {} - bool canHandle(const TRenderSettings &rs, double frame) override { - return true; + void brendKernel(double& dnr, double& dng, double& dnb, double& dna, + const double upr, double upg, double upb, double upa, + const double up_opacity, + const bool alpha_rendering_sw = true) override { + igs::color::linear_light(dnr, dng, dnb, dna, upr, upg, upb, upa, + up_opacity); } - bool doGetBBox(double frame, TRectD &bBox, - const TRenderSettings &rs) override { - TRectD up_bx; - const bool up_sw = - (m_up.isConnected() ? m_up->doGetBBox(frame, up_bx, rs) : false); - TRectD dn_bx; - const bool dn_sw = - (m_down.isConnected() ? m_down->doGetBBox(frame, dn_bx, rs) : false); - if (up_sw && dn_sw) { - bBox = up_bx + dn_bx; - return !bBox.isEmpty(); - } else if (up_sw) { - bBox = up_bx; - return true; - } else if (dn_sw) { - bBox = dn_bx; - return true; - } else { - bBox = TRectD(); - return false; - } - } - // TRect getInvalidRect(const TRect &max) {return max;} - // void doSetParam(const std::string &name, const TParamP ¶m) {} - int getMemoryRequirement(const TRectD &rect, double frame, - const TRenderSettings &rs) override { - return TRasterFx::memorySize(rect, rs.m_bpp); - } - - void doDryCompute(TRectD &rect, double frame, - const TRenderSettings &rs) override { - this->dryComputeUpAndDown(rect, frame, rs, false); - } - void doCompute(TTile &tile, double frame, const TRenderSettings &rs) override; - void computeUpAndDown(TTile &tile, double frame, const TRenderSettings &rs, - TRasterP &dn_ras, TRasterP &up_ras, - bool upComputesWholeTile = false); - void dryComputeUpAndDown(TRectD &rect, double frame, - const TRenderSettings &rs, - bool upComputesWholeTile = false - /* - upComputesWholeTile は Screen, Min, Blendでtrueにして使用している。 - */ - ); }; FX_PLUGIN_IDENTIFIER(ino_blend_linear_light, "inoLinearLightFx"); -//------------------------------------------------------------ -namespace { -/* より大きな四角エリアにPixel整数値で密着する */ -void makeRectCoherent(TRectD &rect, const TPointD &pos) { - rect -= pos; - rect.x0 = tfloor(rect.x0); /* ((x)<(int)(x)? (int)(x)-1: (int)(x))*/ - rect.y0 = tfloor(rect.y0); - rect.x1 = tceil(rect.x1); /* ((int)(x)<(x)? (int)(x)+1: (int)(x))*/ - rect.y1 = tceil(rect.y1); - rect += pos; -} -} -void ino_blend_linear_light::computeUpAndDown(TTile &tile, double frame, - const TRenderSettings &rs, - TRasterP &dn_ras, - TRasterP &up_ras, - bool upComputesWholeTile) { - /* ------ サポートしていないPixelタイプはエラーを投げる --- */ - if (!((TRaster32P)tile.getRaster()) && !((TRaster64P)tile.getRaster())) { - throw TRopException("unsupported input pixel type"); - } - /* -m_down,m_upは繋がっている方があればそれを表示する -両方とも接続していれば合成処理する -表示スイッチを切ってあるならm_upを表示する -fxをreplaceすると、 - m_source --> m_up (=port0) - m_refernce --> m_down(=port1) -となる -*/ - const bool up_is = (this->m_up.isConnected() && - this->m_up.getFx()->getTimeRegion().contains(frame)); - const bool down_is = (this->m_down.isConnected() && - this->m_down.getFx()->getTimeRegion().contains(frame)); - /* ------ 両方とも切断の時処理しない ---------------------- */ - if (!up_is && !down_is) { - tile.getRaster()->clear(); - return; - } - /* ------ up接続かつdown切断の時 -------------------------- */ - if (up_is && !down_is) { - this->m_up->compute(tile, frame, rs); - return; - } - /* ------ down接続時 downのみ描画して... ------------------ */ - if (down_is) { - this->m_down->compute(tile, frame, rs); - } - /* ------ up切断時 ---------------------------------------- */ - if (!up_is) { - return; - } - - /* upと重なる部分を描画する */ - - /* ------ tileの範囲 -------------------------------------- */ - const TDimension tsz(tile.getRaster()->getSize()); /* 整数 */ - const TRectD tileRect(tile.m_pos, TDimensionD(tsz.lx, tsz.ly)); - TRectD upBBox; - if (upComputesWholeTile) { - upBBox = tileRect; - } /* tile全体を得る */ - else { /* 厳密なエリア... */ - this->m_up->getBBox(frame, upBBox, rs); - upBBox *= tileRect; /* upとtileの交差エリア */ - - /* より大きな四角エリアにPixel整数値で密着する */ - makeRectCoherent(upBBox, tile.m_pos); // double-->int grid - } - - TDimensionI upSize( /* TRectDをTDimensionIに変換 */ - tround(upBBox.getLx()) // getLx() = "x1>=x0?x1-x0:0" - , - tround(upBBox.getLy()) // getLy() = "y1>=y0?y1-y0:0" - ); - if ((upSize.lx <= 0) || (upSize.ly <= 0)) { - return; - } - - /* ------ upのメモリ確保と描画 ---------------------------- */ - TTile upTile; - this->m_up->allocateAndCompute(upTile, upBBox.getP00(), upSize, - tile.getRaster() /* 32/64bitsの判定に使う */ - , - frame, rs); - /* ------ upとdownのTRasterを得る ------------------------- */ - TRectI dnRect(upTile.getRaster()->getSize()); // TDimensionI(-) - - dnRect += convert(upTile.m_pos - tile.m_pos); /* uptile->tile原点 */ - /* - ここで問題はdoubleの位置を、四捨五入して整数値にしていること - 移動してから四捨五入ではないの??? - dnRectの元位置が整数位置なので、問題ないか... - */ - - dn_ras = upComputesWholeTile ? tile.getRaster() - : tile.getRaster()->extract(dnRect); - up_ras = upTile.getRaster(); - assert(dn_ras->getSize() == up_ras->getSize()); -} -void ino_blend_linear_light::dryComputeUpAndDown(TRectD &rect, double frame, - const TRenderSettings &rs, - bool upComputesWholeTile) { - const bool up_is = (this->m_up.isConnected() && - this->m_up.getFx()->getTimeRegion().contains(frame)); - const bool down_is = (this->m_down.isConnected() && - this->m_down.getFx()->getTimeRegion().contains(frame)); - /* ------ 両方とも切断の時処理しない ---------------------- */ - if (!up_is && !down_is) { - return; - } - /* ------ up接続かつdown切断の時 -------------------------- */ - if (up_is && !down_is) { - this->m_up->dryCompute(rect, frame, rs); - return; - } - /* ------ down接続時 -------------------------------------- */ - if (down_is) { - this->m_down->dryCompute(rect, frame, rs); - } - /* ------ up切断時 ---------------------------------------- */ - if (!up_is) { - return; - } - - /* ------ tileのgeometryを計算する ------------------------ */ - TRectD upBBox; - - if (upComputesWholeTile) { - upBBox = rect; - } else { - this->m_up->getBBox(frame, upBBox, rs); - upBBox *= rect; - makeRectCoherent(upBBox, rect.getP00()); - } - if ((upBBox.getLx() > 0.5) && (upBBox.getLy() > 0.5)) { - this->m_up->dryCompute(upBBox, frame, rs); - } -} -//------------------------------------------------------------ -#include /* std::ostringstream */ -#include "igs_color_blend.h" -namespace { -template -void tmpl_(TRasterPT dn_ras_out, const TRasterPT &up_ras, - const double up_opacity, const bool clipping_mask_sw) { - double maxi = static_cast(T::maxChannelValue); // 255or65535 - - assert(dn_ras_out->getSize() == up_ras->getSize()); - - for (int yy = 0; yy < dn_ras_out->getLy(); ++yy) { - T *out_pix = dn_ras_out->pixels(yy); - const T *const out_end = out_pix + dn_ras_out->getLx(); - const T *up_pix = up_ras->pixels(yy); - for (; out_pix < out_end; ++out_pix, ++up_pix) { - double upr = static_cast(up_pix->r) / maxi; - double upg = static_cast(up_pix->g) / maxi; - double upb = static_cast(up_pix->b) / maxi; - double upa = static_cast(up_pix->m) / maxi; - double dnr = static_cast(out_pix->r) / maxi; - double dng = static_cast(out_pix->g) / maxi; - double dnb = static_cast(out_pix->b) / maxi; - double dna = static_cast(out_pix->m) / maxi; - igs::color::linear_light( - dnr, dng, dnb, dna, upr, upg, upb, upa, - clipping_mask_sw ? up_opacity * dna : up_opacity); - out_pix->r = static_cast(dnr * (maxi + 0.999999)); - out_pix->g = static_cast(dng * (maxi + 0.999999)); - out_pix->b = static_cast(dnb * (maxi + 0.999999)); - out_pix->m = static_cast(dna * (maxi + 0.999999)); - } - } -} -void fx_(TRasterP &dn_ras_out, const TRasterP &up_ras, const TPoint &pos, - const double up_opacity, const bool clipping_mask_sw) { - /* 交差したエリアを処理するようにする、いるのか??? */ - TRect outRect(dn_ras_out->getBounds()); - TRect upRect(up_ras->getBounds() + pos); - TRect intersection = outRect * upRect; - if (intersection.isEmpty()) return; - - TRasterP cRout = dn_ras_out->extract(intersection); - TRect rr = intersection - pos; - TRasterP cRup = up_ras->extract(rr); - - TRaster32P rout32 = cRout, rup32 = cRup; - TRaster64P rout64 = cRout, rup64 = cRup; - - if (rout32 && rup32) { - tmpl_(rout32, rup32, up_opacity, clipping_mask_sw); - } else if (rout64 && rup64) { - tmpl_(rout64, rup64, up_opacity, clipping_mask_sw); - } else { - throw TRopException("unsupported pixel type"); - } -} -} -void ino_blend_linear_light::doCompute(TTile &tile, double frame, - const TRenderSettings &rs) { - /* ------ 画像生成 ---------------------------------------- */ - TRasterP dn_ras, up_ras; - this->computeUpAndDown(tile, frame, rs, dn_ras, up_ras); - if (!dn_ras || !up_ras) { - return; - } - /* ------ 動作パラメータを得る ---------------------------- */ - const double up_opacity = - this->m_opacity->getValue(frame) / ino::param_range(); - /* ------ (app_begin)log記憶 ------------------------------ */ - const bool log_sw = ino::log_enable_sw(); - - if (log_sw) { - std::ostringstream os; - os << "params" - << " up_opacity " << up_opacity << " dn_tile w " << dn_ras->getLx() - << " wrap " << dn_ras->getWrap() << " h " << dn_ras->getLy() - << " pixbits " << ino::pixel_bits(dn_ras) << " up_tile w " - << up_ras->getLx() << " wrap " << up_ras->getWrap() << " h " - << up_ras->getLy() << " pixbits " << ino::pixel_bits(up_ras) - << " frame " << frame; - } - /* ------ fx処理 ------------------------------------------ */ - try { - if (dn_ras) { - dn_ras->lock(); - } - if (up_ras) { - up_ras->lock(); - } - fx_(dn_ras, up_ras, TPoint(), up_opacity, - this->m_clipping_mask->getValue()); - if (up_ras) { - up_ras->unlock(); - } - if (dn_ras) { - dn_ras->unlock(); - } - } - /* ------ error処理 --------------------------------------- */ - catch (std::exception &e) { - if (up_ras) { - up_ras->unlock(); - } - if (dn_ras) { - dn_ras->unlock(); - } - if (log_sw) { - std::string str("exception <"); - str += e.what(); - str += '>'; - } - throw; - } catch (...) { - if (up_ras) { - up_ras->unlock(); - } - if (dn_ras) { - dn_ras->unlock(); - } - if (log_sw) { - std::string str("other exception"); - } - throw; - } -} diff --git a/toonz/sources/stdfx/ino_blend_multiply.cpp b/toonz/sources/stdfx/ino_blend_multiply.cpp index 88676ed8..16fb6714 100644 --- a/toonz/sources/stdfx/ino_blend_multiply.cpp +++ b/toonz/sources/stdfx/ino_blend_multiply.cpp @@ -3,333 +3,19 @@ #include "stdfx.h" #include "ino_common.h" +#include "igs_color_blend.h" /* tnzbase --> Source Files --> tfx --> binaryFx.cppを参照 */ class ino_blend_multiply final : public TBlendForeBackRasterFx { FX_PLUGIN_DECLARATION(ino_blend_multiply) - TRasterFxPort m_up; - TRasterFxPort m_down; - TDoubleParamP m_opacity; - TBoolParamP m_clipping_mask; public: - ino_blend_multiply() - : m_opacity(1.0 * ino::param_range()), m_clipping_mask(true) { - addInputPort("Fore", this->m_up); - addInputPort("Back", this->m_down); - bindParam(this, "opacity", this->m_opacity); - bindParam(this, "clipping_mask", this->m_clipping_mask); - this->m_opacity->setValueRange(0, 1.0 * ino::param_range()); - } + ino_blend_multiply() : TBlendForeBackRasterFx(true) {} ~ino_blend_multiply() {} - bool canHandle(const TRenderSettings &rs, double frame) override { - return true; + void brendKernel(double& dnr, double& dng, double& dnb, double& dna, + const double upr, double upg, double upb, double upa, + const double up_opacity, + const bool alpha_rendering_sw = true) override { + igs::color::multiply(dnr, dng, dnb, dna, upr, upg, upb, upa, up_opacity); } - bool doGetBBox(double frame, TRectD &bBox, - const TRenderSettings &rs) override { - TRectD up_bx; - const bool up_sw = - (m_up.isConnected() ? m_up->doGetBBox(frame, up_bx, rs) : false); - TRectD dn_bx; - const bool dn_sw = - (m_down.isConnected() ? m_down->doGetBBox(frame, dn_bx, rs) : false); - if (up_sw && dn_sw) { - bBox = up_bx + dn_bx; - return !bBox.isEmpty(); - } else if (up_sw) { - bBox = up_bx; - return true; - } else if (dn_sw) { - bBox = dn_bx; - return true; - } else { - bBox = TRectD(); - return false; - } - } - // TRect getInvalidRect(const TRect &max) {return max;} - // void doSetParam(const std::string &name, const TParamP ¶m) {} - int getMemoryRequirement(const TRectD &rect, double frame, - const TRenderSettings &rs) override { - return TRasterFx::memorySize(rect, rs.m_bpp); - } - - void doDryCompute(TRectD &rect, double frame, - const TRenderSettings &rs) override { - this->dryComputeUpAndDown(rect, frame, rs, false); - } - void doCompute(TTile &tile, double frame, const TRenderSettings &rs) override; - void computeUpAndDown(TTile &tile, double frame, const TRenderSettings &rs, - TRasterP &dn_ras, TRasterP &up_ras, - bool upComputesWholeTile = false); - void dryComputeUpAndDown(TRectD &rect, double frame, - const TRenderSettings &rs, - bool upComputesWholeTile = false - /* - upComputesWholeTile は Screen, Min, Blendでtrueにして使用している。 - */ - ); }; FX_PLUGIN_IDENTIFIER(ino_blend_multiply, "inoMultiplyFx"); -//------------------------------------------------------------ -namespace { -/* より大きな四角エリアにPixel整数値で密着する */ -void makeRectCoherent(TRectD &rect, const TPointD &pos) { - rect -= pos; - rect.x0 = tfloor(rect.x0); /* ((x)<(int)(x)? (int)(x)-1: (int)(x))*/ - rect.y0 = tfloor(rect.y0); - rect.x1 = tceil(rect.x1); /* ((int)(x)<(x)? (int)(x)+1: (int)(x))*/ - rect.y1 = tceil(rect.y1); - rect += pos; -} -} -void ino_blend_multiply::computeUpAndDown(TTile &tile, double frame, - const TRenderSettings &rs, - TRasterP &dn_ras, TRasterP &up_ras, - bool upComputesWholeTile) { - /* ------ サポートしていないPixelタイプはエラーを投げる --- */ - if (!((TRaster32P)tile.getRaster()) && !((TRaster64P)tile.getRaster())) { - throw TRopException("unsupported input pixel type"); - } - /* -m_down,m_upは繋がっている方があればそれを表示する -両方とも接続していれば合成処理する -表示スイッチを切ってあるならm_upを表示する -fxをreplaceすると、 - m_source --> m_up (=port0) - m_refernce --> m_down(=port1) -となる -*/ - const bool up_is = (this->m_up.isConnected() && - this->m_up.getFx()->getTimeRegion().contains(frame)); - const bool down_is = (this->m_down.isConnected() && - this->m_down.getFx()->getTimeRegion().contains(frame)); - /* ------ 両方とも切断の時処理しない ---------------------- */ - if (!up_is && !down_is) { - tile.getRaster()->clear(); - return; - } - /* ------ up接続かつdown切断の時 -------------------------- */ - if (up_is && !down_is) { - this->m_up->compute(tile, frame, rs); - return; - } - /* ------ down接続時 downのみ描画して... ------------------ */ - if (down_is) { - this->m_down->compute(tile, frame, rs); - } - /* ------ up切断時 ---------------------------------------- */ - if (!up_is) { - return; - } - - /* upと重なる部分を描画する */ - - /* ------ tileの範囲 -------------------------------------- */ - const TDimension tsz(tile.getRaster()->getSize()); /* 整数 */ - const TRectD tileRect(tile.m_pos, TDimensionD(tsz.lx, tsz.ly)); - TRectD upBBox; - if (upComputesWholeTile) { - upBBox = tileRect; - } /* tile全体を得る */ - else { /* 厳密なエリア... */ - this->m_up->getBBox(frame, upBBox, rs); - upBBox *= tileRect; /* upとtileの交差エリア */ - - /* より大きな四角エリアにPixel整数値で密着する */ - makeRectCoherent(upBBox, tile.m_pos); // double-->int grid - } - - TDimensionI upSize( /* TRectDをTDimensionIに変換 */ - tround(upBBox.getLx()) // getLx() = "x1>=x0?x1-x0:0" - , - tround(upBBox.getLy()) // getLy() = "y1>=y0?y1-y0:0" - ); - if ((upSize.lx <= 0) || (upSize.ly <= 0)) { - return; - } - - /* ------ upのメモリ確保と描画 ---------------------------- */ - TTile upTile; - this->m_up->allocateAndCompute(upTile, upBBox.getP00(), upSize, - tile.getRaster() /* 32/64bitsの判定に使う */ - , - frame, rs); - /* ------ upとdownのTRasterを得る ------------------------- */ - TRectI dnRect(upTile.getRaster()->getSize()); // TDimensionI(-) - - dnRect += convert(upTile.m_pos - tile.m_pos); /* uptile->tile原点 */ - /* - ここで問題はdoubleの位置を、四捨五入して整数値にしていること - 移動してから四捨五入ではないの??? - dnRectの元位置が整数位置なので、問題ないか... - */ - - dn_ras = upComputesWholeTile ? tile.getRaster() - : tile.getRaster()->extract(dnRect); - up_ras = upTile.getRaster(); - assert(dn_ras->getSize() == up_ras->getSize()); -} -void ino_blend_multiply::dryComputeUpAndDown(TRectD &rect, double frame, - const TRenderSettings &rs, - bool upComputesWholeTile) { - const bool up_is = (this->m_up.isConnected() && - this->m_up.getFx()->getTimeRegion().contains(frame)); - const bool down_is = (this->m_down.isConnected() && - this->m_down.getFx()->getTimeRegion().contains(frame)); - /* ------ 両方とも切断の時処理しない ---------------------- */ - if (!up_is && !down_is) { - return; - } - /* ------ up接続かつdown切断の時 -------------------------- */ - if (up_is && !down_is) { - this->m_up->dryCompute(rect, frame, rs); - return; - } - /* ------ down接続時 -------------------------------------- */ - if (down_is) { - this->m_down->dryCompute(rect, frame, rs); - } - /* ------ up切断時 ---------------------------------------- */ - if (!up_is) { - return; - } - - /* ------ tileのgeometryを計算する ------------------------ */ - TRectD upBBox; - - if (upComputesWholeTile) { - upBBox = rect; - } else { - this->m_up->getBBox(frame, upBBox, rs); - upBBox *= rect; - makeRectCoherent(upBBox, rect.getP00()); - } - if ((upBBox.getLx() > 0.5) && (upBBox.getLy() > 0.5)) { - this->m_up->dryCompute(upBBox, frame, rs); - } -} -//------------------------------------------------------------ -#include /* std::ostringstream */ -#include "igs_color_blend.h" -namespace { -template -void tmpl_(TRasterPT dn_ras_out, const TRasterPT &up_ras, - const double up_opacity, const bool clipping_mask_sw) { - double maxi = static_cast(T::maxChannelValue); // 255or65535 - - assert(dn_ras_out->getSize() == up_ras->getSize()); - - for (int yy = 0; yy < dn_ras_out->getLy(); ++yy) { - T *out_pix = dn_ras_out->pixels(yy); - const T *const out_end = out_pix + dn_ras_out->getLx(); - const T *up_pix = up_ras->pixels(yy); - for (; out_pix < out_end; ++out_pix, ++up_pix) { - double upr = static_cast(up_pix->r) / maxi; - double upg = static_cast(up_pix->g) / maxi; - double upb = static_cast(up_pix->b) / maxi; - double upa = static_cast(up_pix->m) / maxi; - double dnr = static_cast(out_pix->r) / maxi; - double dng = static_cast(out_pix->g) / maxi; - double dnb = static_cast(out_pix->b) / maxi; - double dna = static_cast(out_pix->m) / maxi; - igs::color::multiply(dnr, dng, dnb, dna, upr, upg, upb, upa, - clipping_mask_sw ? up_opacity * dna : up_opacity); - out_pix->r = static_cast(dnr * (maxi + 0.999999)); - out_pix->g = static_cast(dng * (maxi + 0.999999)); - out_pix->b = static_cast(dnb * (maxi + 0.999999)); - out_pix->m = static_cast(dna * (maxi + 0.999999)); - } - } -} -void fx_(TRasterP &dn_ras_out, const TRasterP &up_ras, const TPoint &pos, - const double up_opacity, const bool clipping_mask_sw) { - /* 交差したエリアを処理するようにする、いるのか??? */ - TRect outRect(dn_ras_out->getBounds()); - TRect upRect(up_ras->getBounds() + pos); - TRect intersection = outRect * upRect; - if (intersection.isEmpty()) return; - - TRasterP cRout = dn_ras_out->extract(intersection); - TRect rr = intersection - pos; - TRasterP cRup = up_ras->extract(rr); - - TRaster32P rout32 = cRout, rup32 = cRup; - TRaster64P rout64 = cRout, rup64 = cRup; - - if (rout32 && rup32) { - tmpl_(rout32, rup32, up_opacity, clipping_mask_sw); - } else if (rout64 && rup64) { - tmpl_(rout64, rup64, up_opacity, clipping_mask_sw); - } else { - throw TRopException("unsupported pixel type"); - } -} -} -void ino_blend_multiply::doCompute(TTile &tile, double frame, - const TRenderSettings &rs) { - /* ------ 画像生成 ---------------------------------------- */ - TRasterP dn_ras, up_ras; - this->computeUpAndDown(tile, frame, rs, dn_ras, up_ras); - if (!dn_ras || !up_ras) { - return; - } - /* ------ 動作パラメータを得る ---------------------------- */ - const double up_opacity = - this->m_opacity->getValue(frame) / ino::param_range(); - /* ------ (app_begin)log記憶 ------------------------------ */ - const bool log_sw = ino::log_enable_sw(); - - if (log_sw) { - std::ostringstream os; - os << "params" - << " up_opacity " << up_opacity << " dn_tile w " << dn_ras->getLx() - << " wrap " << dn_ras->getWrap() << " h " << dn_ras->getLy() - << " pixbits " << ino::pixel_bits(dn_ras) << " up_tile w " - << up_ras->getLx() << " wrap " << up_ras->getWrap() << " h " - << up_ras->getLy() << " pixbits " << ino::pixel_bits(up_ras) - << " frame " << frame; - } - /* ------ fx処理 ------------------------------------------ */ - try { - if (dn_ras) { - dn_ras->lock(); - } - if (up_ras) { - up_ras->lock(); - } - fx_(dn_ras, up_ras, TPoint(), up_opacity, - this->m_clipping_mask->getValue()); - if (up_ras) { - up_ras->unlock(); - } - if (dn_ras) { - dn_ras->unlock(); - } - } - /* ------ error処理 --------------------------------------- */ - catch (std::exception &e) { - if (up_ras) { - up_ras->unlock(); - } - if (dn_ras) { - dn_ras->unlock(); - } - if (log_sw) { - std::string str("exception <"); - str += e.what(); - str += '>'; - } - throw; - } catch (...) { - if (up_ras) { - up_ras->unlock(); - } - if (dn_ras) { - dn_ras->unlock(); - } - if (log_sw) { - std::string str("other exception"); - } - throw; - } -} diff --git a/toonz/sources/stdfx/ino_blend_over.cpp b/toonz/sources/stdfx/ino_blend_over.cpp index 84d36ff4..d8cd1adb 100644 --- a/toonz/sources/stdfx/ino_blend_over.cpp +++ b/toonz/sources/stdfx/ino_blend_over.cpp @@ -3,333 +3,19 @@ #include "stdfx.h" #include "ino_common.h" +#include "igs_color_blend.h" /* tnzbase --> Source Files --> tfx --> binaryFx.cppを参照 */ class ino_blend_over final : public TBlendForeBackRasterFx { FX_PLUGIN_DECLARATION(ino_blend_over) - TRasterFxPort m_up; - TRasterFxPort m_down; - TDoubleParamP m_opacity; - TBoolParamP m_clipping_mask; public: - ino_blend_over() - : m_opacity(1.0 * ino::param_range()), m_clipping_mask(false) { - addInputPort("Fore", this->m_up); - addInputPort("Back", this->m_down); - bindParam(this, "opacity", this->m_opacity); - bindParam(this, "clipping_mask", this->m_clipping_mask); - this->m_opacity->setValueRange(0, 1.0 * ino::param_range()); - } + ino_blend_over() : TBlendForeBackRasterFx(false) {} ~ino_blend_over() {} - bool canHandle(const TRenderSettings &rs, double frame) override { - return true; + void brendKernel(double& dnr, double& dng, double& dnb, double& dna, + const double upr, double upg, double upb, double upa, + const double up_opacity, + const bool alpha_rendering_sw = true) override { + igs::color::over(dnr, dng, dnb, dna, upr, upg, upb, upa, up_opacity); } - bool doGetBBox(double frame, TRectD &bBox, - const TRenderSettings &rs) override { - TRectD up_bx; - const bool up_sw = - (m_up.isConnected() ? m_up->doGetBBox(frame, up_bx, rs) : false); - TRectD dn_bx; - const bool dn_sw = - (m_down.isConnected() ? m_down->doGetBBox(frame, dn_bx, rs) : false); - if (up_sw && dn_sw) { - bBox = up_bx + dn_bx; - return !bBox.isEmpty(); - } else if (up_sw) { - bBox = up_bx; - return true; - } else if (dn_sw) { - bBox = dn_bx; - return true; - } else { - bBox = TRectD(); - return false; - } - } - // TRect getInvalidRect(const TRect &max) {return max;} - // void doSetParam(const std::string &name, const TParamP ¶m) {} - int getMemoryRequirement(const TRectD &rect, double frame, - const TRenderSettings &rs) override { - return TRasterFx::memorySize(rect, rs.m_bpp); - } - - void doDryCompute(TRectD &rect, double frame, - const TRenderSettings &rs) override { - this->dryComputeUpAndDown(rect, frame, rs, false); - } - void doCompute(TTile &tile, double frame, const TRenderSettings &rs) override; - void computeUpAndDown(TTile &tile, double frame, const TRenderSettings &rs, - TRasterP &dn_ras, TRasterP &up_ras, - bool upComputesWholeTile = false); - void dryComputeUpAndDown(TRectD &rect, double frame, - const TRenderSettings &rs, - bool upComputesWholeTile = false - /* - upComputesWholeTile は Screen, Min, Blendでtrueにして使用している。 - */ - ); }; FX_PLUGIN_IDENTIFIER(ino_blend_over, "inoOverFx"); -//------------------------------------------------------------ -namespace { -/* より大きな四角エリアにPixel整数値で密着する */ -void makeRectCoherent(TRectD &rect, const TPointD &pos) { - rect -= pos; - rect.x0 = tfloor(rect.x0); /* ((x)<(int)(x)? (int)(x)-1: (int)(x))*/ - rect.y0 = tfloor(rect.y0); - rect.x1 = tceil(rect.x1); /* ((int)(x)<(x)? (int)(x)+1: (int)(x))*/ - rect.y1 = tceil(rect.y1); - rect += pos; -} -} -void ino_blend_over::computeUpAndDown(TTile &tile, double frame, - const TRenderSettings &rs, - TRasterP &dn_ras, TRasterP &up_ras, - bool upComputesWholeTile) { - /* ------ サポートしていないPixelタイプはエラーを投げる --- */ - if (!((TRaster32P)tile.getRaster()) && !((TRaster64P)tile.getRaster())) { - throw TRopException("unsupported input pixel type"); - } - /* -m_down,m_upは繋がっている方があればそれを表示する -両方とも接続していれば合成処理する -表示スイッチを切ってあるならm_upを表示する -fxをreplaceすると、 - m_source --> m_up (=port0) - m_refernce --> m_down(=port1) -となる -*/ - const bool up_is = (this->m_up.isConnected() && - this->m_up.getFx()->getTimeRegion().contains(frame)); - const bool down_is = (this->m_down.isConnected() && - this->m_down.getFx()->getTimeRegion().contains(frame)); - /* ------ 両方とも切断の時処理しない ---------------------- */ - if (!up_is && !down_is) { - tile.getRaster()->clear(); - return; - } - /* ------ up接続かつdown切断の時 -------------------------- */ - if (up_is && !down_is) { - this->m_up->compute(tile, frame, rs); - return; - } - /* ------ down接続時 downのみ描画して... ------------------ */ - if (down_is) { - this->m_down->compute(tile, frame, rs); - } - /* ------ up切断時 ---------------------------------------- */ - if (!up_is) { - return; - } - - /* upと重なる部分を描画する */ - - /* ------ tileの範囲 -------------------------------------- */ - const TDimension tsz(tile.getRaster()->getSize()); /* 整数 */ - const TRectD tileRect(tile.m_pos, TDimensionD(tsz.lx, tsz.ly)); - TRectD upBBox; - if (upComputesWholeTile) { - upBBox = tileRect; - } /* tile全体を得る */ - else { /* 厳密なエリア... */ - this->m_up->getBBox(frame, upBBox, rs); - upBBox *= tileRect; /* upとtileの交差エリア */ - - /* より大きな四角エリアにPixel整数値で密着する */ - makeRectCoherent(upBBox, tile.m_pos); // double-->int grid - } - - TDimensionI upSize( /* TRectDをTDimensionIに変換 */ - tround(upBBox.getLx()) // getLx() = "x1>=x0?x1-x0:0" - , - tround(upBBox.getLy()) // getLy() = "y1>=y0?y1-y0:0" - ); - if ((upSize.lx <= 0) || (upSize.ly <= 0)) { - return; - } - - /* ------ upのメモリ確保と描画 ---------------------------- */ - TTile upTile; - this->m_up->allocateAndCompute(upTile, upBBox.getP00(), upSize, - tile.getRaster() /* 32/64bitsの判定に使う */ - , - frame, rs); - /* ------ upとdownのTRasterを得る ------------------------- */ - TRectI dnRect(upTile.getRaster()->getSize()); // TDimensionI(-) - - dnRect += convert(upTile.m_pos - tile.m_pos); /* uptile->tile原点 */ - /* - ここで問題はdoubleの位置を、四捨五入して整数値にしていること - 移動してから四捨五入ではないの??? - dnRectの元位置が整数位置なので、問題ないか... - */ - - dn_ras = upComputesWholeTile ? tile.getRaster() - : tile.getRaster()->extract(dnRect); - up_ras = upTile.getRaster(); - assert(dn_ras->getSize() == up_ras->getSize()); -} -void ino_blend_over::dryComputeUpAndDown(TRectD &rect, double frame, - const TRenderSettings &rs, - bool upComputesWholeTile) { - const bool up_is = (this->m_up.isConnected() && - this->m_up.getFx()->getTimeRegion().contains(frame)); - const bool down_is = (this->m_down.isConnected() && - this->m_down.getFx()->getTimeRegion().contains(frame)); - /* ------ 両方とも切断の時処理しない ---------------------- */ - if (!up_is && !down_is) { - return; - } - /* ------ up接続かつdown切断の時 -------------------------- */ - if (up_is && !down_is) { - this->m_up->dryCompute(rect, frame, rs); - return; - } - /* ------ down接続時 -------------------------------------- */ - if (down_is) { - this->m_down->dryCompute(rect, frame, rs); - } - /* ------ up切断時 ---------------------------------------- */ - if (!up_is) { - return; - } - - /* ------ tileのgeometryを計算する ------------------------ */ - TRectD upBBox; - - if (upComputesWholeTile) { - upBBox = rect; - } else { - this->m_up->getBBox(frame, upBBox, rs); - upBBox *= rect; - makeRectCoherent(upBBox, rect.getP00()); - } - if ((upBBox.getLx() > 0.5) && (upBBox.getLy() > 0.5)) { - this->m_up->dryCompute(upBBox, frame, rs); - } -} -//------------------------------------------------------------ -#include /* std::ostringstream */ -#include "igs_color_blend.h" -namespace { -template -void tmpl_(TRasterPT dn_ras_out, const TRasterPT &up_ras, - const double up_opacity, const bool clipping_mask_sw) { - double maxi = static_cast(T::maxChannelValue); // 255or65535 - - assert(dn_ras_out->getSize() == up_ras->getSize()); - - for (int yy = 0; yy < dn_ras_out->getLy(); ++yy) { - T *out_pix = dn_ras_out->pixels(yy); - const T *const out_end = out_pix + dn_ras_out->getLx(); - const T *up_pix = up_ras->pixels(yy); - for (; out_pix < out_end; ++out_pix, ++up_pix) { - double upr = static_cast(up_pix->r) / maxi; - double upg = static_cast(up_pix->g) / maxi; - double upb = static_cast(up_pix->b) / maxi; - double upa = static_cast(up_pix->m) / maxi; - double dnr = static_cast(out_pix->r) / maxi; - double dng = static_cast(out_pix->g) / maxi; - double dnb = static_cast(out_pix->b) / maxi; - double dna = static_cast(out_pix->m) / maxi; - igs::color::over(dnr, dng, dnb, dna, upr, upg, upb, upa, - clipping_mask_sw ? up_opacity * dna : up_opacity); - out_pix->r = static_cast(dnr * (maxi + 0.999999)); - out_pix->g = static_cast(dng * (maxi + 0.999999)); - out_pix->b = static_cast(dnb * (maxi + 0.999999)); - out_pix->m = static_cast(dna * (maxi + 0.999999)); - } - } -} -void fx_(TRasterP &dn_ras_out, const TRasterP &up_ras, const TPoint &pos, - const double up_opacity, const bool clipping_mask_sw) { - /* 交差したエリアを処理するようにする、いるのか??? */ - TRect outRect(dn_ras_out->getBounds()); - TRect upRect(up_ras->getBounds() + pos); - TRect intersection = outRect * upRect; - if (intersection.isEmpty()) return; - - TRasterP cRout = dn_ras_out->extract(intersection); - TRect rr = intersection - pos; - TRasterP cRup = up_ras->extract(rr); - - TRaster32P rout32 = cRout, rup32 = cRup; - TRaster64P rout64 = cRout, rup64 = cRup; - - if (rout32 && rup32) { - tmpl_(rout32, rup32, up_opacity, clipping_mask_sw); - } else if (rout64 && rup64) { - tmpl_(rout64, rup64, up_opacity, clipping_mask_sw); - } else { - throw TRopException("unsupported pixel type"); - } -} -} -void ino_blend_over::doCompute(TTile &tile, double frame, - const TRenderSettings &rs) { - /* ------ 画像生成 ---------------------------------------- */ - TRasterP dn_ras, up_ras; - this->computeUpAndDown(tile, frame, rs, dn_ras, up_ras); - if (!dn_ras || !up_ras) { - return; - } - /* ------ 動作パラメータを得る ---------------------------- */ - const double up_opacity = - this->m_opacity->getValue(frame) / ino::param_range(); - /* ------ (app_begin)log記憶 ------------------------------ */ - const bool log_sw = ino::log_enable_sw(); - - if (log_sw) { - std::ostringstream os; - os << "params" - << " up_opacity " << up_opacity << " dn_tile w " << dn_ras->getLx() - << " wrap " << dn_ras->getWrap() << " h " << dn_ras->getLy() - << " pixbits " << ino::pixel_bits(dn_ras) << " up_tile w " - << up_ras->getLx() << " wrap " << up_ras->getWrap() << " h " - << up_ras->getLy() << " pixbits " << ino::pixel_bits(up_ras) - << " frame " << frame; - } - /* ------ fx処理 ------------------------------------------ */ - try { - if (dn_ras) { - dn_ras->lock(); - } - if (up_ras) { - up_ras->lock(); - } - fx_(dn_ras, up_ras, TPoint(), up_opacity, - this->m_clipping_mask->getValue()); - if (up_ras) { - up_ras->unlock(); - } - if (dn_ras) { - dn_ras->unlock(); - } - } - /* ------ error処理 --------------------------------------- */ - catch (std::exception &e) { - if (up_ras) { - up_ras->unlock(); - } - if (dn_ras) { - dn_ras->unlock(); - } - if (log_sw) { - std::string str("exception <"); - str += e.what(); - str += '>'; - } - throw; - } catch (...) { - if (up_ras) { - up_ras->unlock(); - } - if (dn_ras) { - dn_ras->unlock(); - } - if (log_sw) { - std::string str("other exception"); - } - throw; - } -} diff --git a/toonz/sources/stdfx/ino_blend_overlay.cpp b/toonz/sources/stdfx/ino_blend_overlay.cpp index b695d169..be0e4c9f 100644 --- a/toonz/sources/stdfx/ino_blend_overlay.cpp +++ b/toonz/sources/stdfx/ino_blend_overlay.cpp @@ -3,333 +3,19 @@ #include "stdfx.h" #include "ino_common.h" +#include "igs_color_blend.h" /* tnzbase --> Source Files --> tfx --> binaryFx.cppを参照 */ class ino_blend_overlay final : public TBlendForeBackRasterFx { FX_PLUGIN_DECLARATION(ino_blend_overlay) - TRasterFxPort m_up; - TRasterFxPort m_down; - TDoubleParamP m_opacity; - TBoolParamP m_clipping_mask; public: - ino_blend_overlay() - : m_opacity(1.0 * ino::param_range()), m_clipping_mask(true) { - addInputPort("Fore", this->m_up); - addInputPort("Back", this->m_down); - bindParam(this, "opacity", this->m_opacity); - bindParam(this, "clipping_mask", this->m_clipping_mask); - this->m_opacity->setValueRange(0, 1.0 * ino::param_range()); - } + ino_blend_overlay() : TBlendForeBackRasterFx(true) {} ~ino_blend_overlay() {} - bool canHandle(const TRenderSettings &rs, double frame) override { - return true; + void brendKernel(double& dnr, double& dng, double& dnb, double& dna, + const double upr, double upg, double upb, double upa, + const double up_opacity, + const bool alpha_rendering_sw = true) override { + igs::color::overlay(dnr, dng, dnb, dna, upr, upg, upb, upa, up_opacity); } - bool doGetBBox(double frame, TRectD &bBox, - const TRenderSettings &rs) override { - TRectD up_bx; - const bool up_sw = - (m_up.isConnected() ? m_up->doGetBBox(frame, up_bx, rs) : false); - TRectD dn_bx; - const bool dn_sw = - (m_down.isConnected() ? m_down->doGetBBox(frame, dn_bx, rs) : false); - if (up_sw && dn_sw) { - bBox = up_bx + dn_bx; - return !bBox.isEmpty(); - } else if (up_sw) { - bBox = up_bx; - return true; - } else if (dn_sw) { - bBox = dn_bx; - return true; - } else { - bBox = TRectD(); - return false; - } - } - // TRect getInvalidRect(const TRect &max) {return max;} - // void doSetParam(const std::string &name, const TParamP ¶m) {} - int getMemoryRequirement(const TRectD &rect, double frame, - const TRenderSettings &rs) override { - return TRasterFx::memorySize(rect, rs.m_bpp); - } - - void doDryCompute(TRectD &rect, double frame, - const TRenderSettings &rs) override { - this->dryComputeUpAndDown(rect, frame, rs, false); - } - void doCompute(TTile &tile, double frame, const TRenderSettings &rs) override; - void computeUpAndDown(TTile &tile, double frame, const TRenderSettings &rs, - TRasterP &dn_ras, TRasterP &up_ras, - bool upComputesWholeTile = false); - void dryComputeUpAndDown(TRectD &rect, double frame, - const TRenderSettings &rs, - bool upComputesWholeTile = false - /* - upComputesWholeTile は Screen, Min, Blendでtrueにして使用している。 - */ - ); }; FX_PLUGIN_IDENTIFIER(ino_blend_overlay, "inoOverlayFx"); -//------------------------------------------------------------ -namespace { -/* より大きな四角エリアにPixel整数値で密着する */ -void makeRectCoherent(TRectD &rect, const TPointD &pos) { - rect -= pos; - rect.x0 = tfloor(rect.x0); /* ((x)<(int)(x)? (int)(x)-1: (int)(x))*/ - rect.y0 = tfloor(rect.y0); - rect.x1 = tceil(rect.x1); /* ((int)(x)<(x)? (int)(x)+1: (int)(x))*/ - rect.y1 = tceil(rect.y1); - rect += pos; -} -} -void ino_blend_overlay::computeUpAndDown(TTile &tile, double frame, - const TRenderSettings &rs, - TRasterP &dn_ras, TRasterP &up_ras, - bool upComputesWholeTile) { - /* ------ サポートしていないPixelタイプはエラーを投げる --- */ - if (!((TRaster32P)tile.getRaster()) && !((TRaster64P)tile.getRaster())) { - throw TRopException("unsupported input pixel type"); - } - /* -m_down,m_upは繋がっている方があればそれを表示する -両方とも接続していれば合成処理する -表示スイッチを切ってあるならm_upを表示する -fxをreplaceすると、 - m_source --> m_up (=port0) - m_refernce --> m_down(=port1) -となる -*/ - const bool up_is = (this->m_up.isConnected() && - this->m_up.getFx()->getTimeRegion().contains(frame)); - const bool down_is = (this->m_down.isConnected() && - this->m_down.getFx()->getTimeRegion().contains(frame)); - /* ------ 両方とも切断の時処理しない ---------------------- */ - if (!up_is && !down_is) { - tile.getRaster()->clear(); - return; - } - /* ------ up接続かつdown切断の時 -------------------------- */ - if (up_is && !down_is) { - this->m_up->compute(tile, frame, rs); - return; - } - /* ------ down接続時 downのみ描画して... ------------------ */ - if (down_is) { - this->m_down->compute(tile, frame, rs); - } - /* ------ up切断時 ---------------------------------------- */ - if (!up_is) { - return; - } - - /* upと重なる部分を描画する */ - - /* ------ tileの範囲 -------------------------------------- */ - const TDimension tsz(tile.getRaster()->getSize()); /* 整数 */ - const TRectD tileRect(tile.m_pos, TDimensionD(tsz.lx, tsz.ly)); - TRectD upBBox; - if (upComputesWholeTile) { - upBBox = tileRect; - } /* tile全体を得る */ - else { /* 厳密なエリア... */ - this->m_up->getBBox(frame, upBBox, rs); - upBBox *= tileRect; /* upとtileの交差エリア */ - - /* より大きな四角エリアにPixel整数値で密着する */ - makeRectCoherent(upBBox, tile.m_pos); // double-->int grid - } - - TDimensionI upSize( /* TRectDをTDimensionIに変換 */ - tround(upBBox.getLx()) // getLx() = "x1>=x0?x1-x0:0" - , - tround(upBBox.getLy()) // getLy() = "y1>=y0?y1-y0:0" - ); - if ((upSize.lx <= 0) || (upSize.ly <= 0)) { - return; - } - - /* ------ upのメモリ確保と描画 ---------------------------- */ - TTile upTile; - this->m_up->allocateAndCompute(upTile, upBBox.getP00(), upSize, - tile.getRaster() /* 32/64bitsの判定に使う */ - , - frame, rs); - /* ------ upとdownのTRasterを得る ------------------------- */ - TRectI dnRect(upTile.getRaster()->getSize()); // TDimensionI(-) - - dnRect += convert(upTile.m_pos - tile.m_pos); /* uptile->tile原点 */ - /* - ここで問題はdoubleの位置を、四捨五入して整数値にしていること - 移動してから四捨五入ではないの??? - dnRectの元位置が整数位置なので、問題ないか... - */ - - dn_ras = upComputesWholeTile ? tile.getRaster() - : tile.getRaster()->extract(dnRect); - up_ras = upTile.getRaster(); - assert(dn_ras->getSize() == up_ras->getSize()); -} -void ino_blend_overlay::dryComputeUpAndDown(TRectD &rect, double frame, - const TRenderSettings &rs, - bool upComputesWholeTile) { - const bool up_is = (this->m_up.isConnected() && - this->m_up.getFx()->getTimeRegion().contains(frame)); - const bool down_is = (this->m_down.isConnected() && - this->m_down.getFx()->getTimeRegion().contains(frame)); - /* ------ 両方とも切断の時処理しない ---------------------- */ - if (!up_is && !down_is) { - return; - } - /* ------ up接続かつdown切断の時 -------------------------- */ - if (up_is && !down_is) { - this->m_up->dryCompute(rect, frame, rs); - return; - } - /* ------ down接続時 -------------------------------------- */ - if (down_is) { - this->m_down->dryCompute(rect, frame, rs); - } - /* ------ up切断時 ---------------------------------------- */ - if (!up_is) { - return; - } - - /* ------ tileのgeometryを計算する ------------------------ */ - TRectD upBBox; - - if (upComputesWholeTile) { - upBBox = rect; - } else { - this->m_up->getBBox(frame, upBBox, rs); - upBBox *= rect; - makeRectCoherent(upBBox, rect.getP00()); - } - if ((upBBox.getLx() > 0.5) && (upBBox.getLy() > 0.5)) { - this->m_up->dryCompute(upBBox, frame, rs); - } -} -//------------------------------------------------------------ -#include /* std::ostringstream */ -#include "igs_color_blend.h" -namespace { -template -void tmpl_(TRasterPT dn_ras_out, const TRasterPT &up_ras, - const double up_opacity, const bool clipping_mask_sw) { - double maxi = static_cast(T::maxChannelValue); // 255or65535 - - assert(dn_ras_out->getSize() == up_ras->getSize()); - - for (int yy = 0; yy < dn_ras_out->getLy(); ++yy) { - T *out_pix = dn_ras_out->pixels(yy); - const T *const out_end = out_pix + dn_ras_out->getLx(); - const T *up_pix = up_ras->pixels(yy); - for (; out_pix < out_end; ++out_pix, ++up_pix) { - double upr = static_cast(up_pix->r) / maxi; - double upg = static_cast(up_pix->g) / maxi; - double upb = static_cast(up_pix->b) / maxi; - double upa = static_cast(up_pix->m) / maxi; - double dnr = static_cast(out_pix->r) / maxi; - double dng = static_cast(out_pix->g) / maxi; - double dnb = static_cast(out_pix->b) / maxi; - double dna = static_cast(out_pix->m) / maxi; - igs::color::overlay(dnr, dng, dnb, dna, upr, upg, upb, upa, - clipping_mask_sw ? up_opacity * dna : up_opacity); - out_pix->r = static_cast(dnr * (maxi + 0.999999)); - out_pix->g = static_cast(dng * (maxi + 0.999999)); - out_pix->b = static_cast(dnb * (maxi + 0.999999)); - out_pix->m = static_cast(dna * (maxi + 0.999999)); - } - } -} -void fx_(TRasterP &dn_ras_out, const TRasterP &up_ras, const TPoint &pos, - const double up_opacity, const bool clipping_mask_sw) { - /* 交差したエリアを処理するようにする、いるのか??? */ - TRect outRect(dn_ras_out->getBounds()); - TRect upRect(up_ras->getBounds() + pos); - TRect intersection = outRect * upRect; - if (intersection.isEmpty()) return; - - TRasterP cRout = dn_ras_out->extract(intersection); - TRect rr = intersection - pos; - TRasterP cRup = up_ras->extract(rr); - - TRaster32P rout32 = cRout, rup32 = cRup; - TRaster64P rout64 = cRout, rup64 = cRup; - - if (rout32 && rup32) { - tmpl_(rout32, rup32, up_opacity, clipping_mask_sw); - } else if (rout64 && rup64) { - tmpl_(rout64, rup64, up_opacity, clipping_mask_sw); - } else { - throw TRopException("unsupported pixel type"); - } -} -} -void ino_blend_overlay::doCompute(TTile &tile, double frame, - const TRenderSettings &rs) { - /* ------ 画像生成 ---------------------------------------- */ - TRasterP dn_ras, up_ras; - this->computeUpAndDown(tile, frame, rs, dn_ras, up_ras); - if (!dn_ras || !up_ras) { - return; - } - /* ------ 動作パラメータを得る ---------------------------- */ - const double up_opacity = - this->m_opacity->getValue(frame) / ino::param_range(); - /* ------ (app_begin)log記憶 ------------------------------ */ - const bool log_sw = ino::log_enable_sw(); - - if (log_sw) { - std::ostringstream os; - os << "params" - << " up_opacity " << up_opacity << " dn_tile w " << dn_ras->getLx() - << " wrap " << dn_ras->getWrap() << " h " << dn_ras->getLy() - << " pixbits " << ino::pixel_bits(dn_ras) << " up_tile w " - << up_ras->getLx() << " wrap " << up_ras->getWrap() << " h " - << up_ras->getLy() << " pixbits " << ino::pixel_bits(up_ras) - << " frame " << frame; - } - /* ------ fx処理 ------------------------------------------ */ - try { - if (dn_ras) { - dn_ras->lock(); - } - if (up_ras) { - up_ras->lock(); - } - fx_(dn_ras, up_ras, TPoint(), up_opacity, - this->m_clipping_mask->getValue()); - if (up_ras) { - up_ras->unlock(); - } - if (dn_ras) { - dn_ras->unlock(); - } - } - /* ------ error処理 --------------------------------------- */ - catch (std::exception &e) { - if (up_ras) { - up_ras->unlock(); - } - if (dn_ras) { - dn_ras->unlock(); - } - if (log_sw) { - std::string str("exception <"); - str += e.what(); - str += '>'; - } - throw; - } catch (...) { - if (up_ras) { - up_ras->unlock(); - } - if (dn_ras) { - dn_ras->unlock(); - } - if (log_sw) { - std::string str("other exception"); - } - throw; - } -} diff --git a/toonz/sources/stdfx/ino_blend_pin_light.cpp b/toonz/sources/stdfx/ino_blend_pin_light.cpp index a63de63a..fe9cd2b7 100644 --- a/toonz/sources/stdfx/ino_blend_pin_light.cpp +++ b/toonz/sources/stdfx/ino_blend_pin_light.cpp @@ -3,333 +3,19 @@ #include "stdfx.h" #include "ino_common.h" +#include "igs_color_blend.h" /* tnzbase --> Source Files --> tfx --> binaryFx.cppを参照 */ class ino_blend_pin_light final : public TBlendForeBackRasterFx { FX_PLUGIN_DECLARATION(ino_blend_pin_light) - TRasterFxPort m_up; - TRasterFxPort m_down; - TDoubleParamP m_opacity; - TBoolParamP m_clipping_mask; public: - ino_blend_pin_light() - : m_opacity(1.0 * ino::param_range()), m_clipping_mask(true) { - addInputPort("Fore", this->m_up); - addInputPort("Back", this->m_down); - bindParam(this, "opacity", this->m_opacity); - bindParam(this, "clipping_mask", this->m_clipping_mask); - this->m_opacity->setValueRange(0, 1.0 * ino::param_range()); - } + ino_blend_pin_light() : TBlendForeBackRasterFx(true) {} ~ino_blend_pin_light() {} - bool canHandle(const TRenderSettings &rs, double frame) override { - return true; + void brendKernel(double& dnr, double& dng, double& dnb, double& dna, + const double upr, double upg, double upb, double upa, + const double up_opacity, + const bool alpha_rendering_sw = true) override { + igs::color::pin_light(dnr, dng, dnb, dna, upr, upg, upb, upa, up_opacity); } - bool doGetBBox(double frame, TRectD &bBox, - const TRenderSettings &rs) override { - TRectD up_bx; - const bool up_sw = - (m_up.isConnected() ? m_up->doGetBBox(frame, up_bx, rs) : false); - TRectD dn_bx; - const bool dn_sw = - (m_down.isConnected() ? m_down->doGetBBox(frame, dn_bx, rs) : false); - if (up_sw && dn_sw) { - bBox = up_bx + dn_bx; - return !bBox.isEmpty(); - } else if (up_sw) { - bBox = up_bx; - return true; - } else if (dn_sw) { - bBox = dn_bx; - return true; - } else { - bBox = TRectD(); - return false; - } - } - // TRect getInvalidRect(const TRect &max) {return max;} - // void doSetParam(const std::string &name, const TParamP ¶m) {} - int getMemoryRequirement(const TRectD &rect, double frame, - const TRenderSettings &rs) override { - return TRasterFx::memorySize(rect, rs.m_bpp); - } - - void doDryCompute(TRectD &rect, double frame, - const TRenderSettings &rs) override { - this->dryComputeUpAndDown(rect, frame, rs, false); - } - void doCompute(TTile &tile, double frame, const TRenderSettings &rs) override; - void computeUpAndDown(TTile &tile, double frame, const TRenderSettings &rs, - TRasterP &dn_ras, TRasterP &up_ras, - bool upComputesWholeTile = false); - void dryComputeUpAndDown(TRectD &rect, double frame, - const TRenderSettings &rs, - bool upComputesWholeTile = false - /* - upComputesWholeTile は Screen, Min, Blendでtrueにして使用している。 - */ - ); }; FX_PLUGIN_IDENTIFIER(ino_blend_pin_light, "inoPinLightFx"); -//------------------------------------------------------------ -namespace { -/* より大きな四角エリアにPixel整数値で密着する */ -void makeRectCoherent(TRectD &rect, const TPointD &pos) { - rect -= pos; - rect.x0 = tfloor(rect.x0); /* ((x)<(int)(x)? (int)(x)-1: (int)(x))*/ - rect.y0 = tfloor(rect.y0); - rect.x1 = tceil(rect.x1); /* ((int)(x)<(x)? (int)(x)+1: (int)(x))*/ - rect.y1 = tceil(rect.y1); - rect += pos; -} -} -void ino_blend_pin_light::computeUpAndDown(TTile &tile, double frame, - const TRenderSettings &rs, - TRasterP &dn_ras, TRasterP &up_ras, - bool upComputesWholeTile) { - /* ------ サポートしていないPixelタイプはエラーを投げる --- */ - if (!((TRaster32P)tile.getRaster()) && !((TRaster64P)tile.getRaster())) { - throw TRopException("unsupported input pixel type"); - } - /* -m_down,m_upは繋がっている方があればそれを表示する -両方とも接続していれば合成処理する -表示スイッチを切ってあるならm_upを表示する -fxをreplaceすると、 - m_source --> m_up (=port0) - m_refernce --> m_down(=port1) -となる -*/ - const bool up_is = (this->m_up.isConnected() && - this->m_up.getFx()->getTimeRegion().contains(frame)); - const bool down_is = (this->m_down.isConnected() && - this->m_down.getFx()->getTimeRegion().contains(frame)); - /* ------ 両方とも切断の時処理しない ---------------------- */ - if (!up_is && !down_is) { - tile.getRaster()->clear(); - return; - } - /* ------ up接続かつdown切断の時 -------------------------- */ - if (up_is && !down_is) { - this->m_up->compute(tile, frame, rs); - return; - } - /* ------ down接続時 downのみ描画して... ------------------ */ - if (down_is) { - this->m_down->compute(tile, frame, rs); - } - /* ------ up切断時 ---------------------------------------- */ - if (!up_is) { - return; - } - - /* upと重なる部分を描画する */ - - /* ------ tileの範囲 -------------------------------------- */ - const TDimension tsz(tile.getRaster()->getSize()); /* 整数 */ - const TRectD tileRect(tile.m_pos, TDimensionD(tsz.lx, tsz.ly)); - TRectD upBBox; - if (upComputesWholeTile) { - upBBox = tileRect; - } /* tile全体を得る */ - else { /* 厳密なエリア... */ - this->m_up->getBBox(frame, upBBox, rs); - upBBox *= tileRect; /* upとtileの交差エリア */ - - /* より大きな四角エリアにPixel整数値で密着する */ - makeRectCoherent(upBBox, tile.m_pos); // double-->int grid - } - - TDimensionI upSize( /* TRectDをTDimensionIに変換 */ - tround(upBBox.getLx()) // getLx() = "x1>=x0?x1-x0:0" - , - tround(upBBox.getLy()) // getLy() = "y1>=y0?y1-y0:0" - ); - if ((upSize.lx <= 0) || (upSize.ly <= 0)) { - return; - } - - /* ------ upのメモリ確保と描画 ---------------------------- */ - TTile upTile; - this->m_up->allocateAndCompute(upTile, upBBox.getP00(), upSize, - tile.getRaster() /* 32/64bitsの判定に使う */ - , - frame, rs); - /* ------ upとdownのTRasterを得る ------------------------- */ - TRectI dnRect(upTile.getRaster()->getSize()); // TDimensionI(-) - - dnRect += convert(upTile.m_pos - tile.m_pos); /* uptile->tile原点 */ - /* - ここで問題はdoubleの位置を、四捨五入して整数値にしていること - 移動してから四捨五入ではないの??? - dnRectの元位置が整数位置なので、問題ないか... - */ - - dn_ras = upComputesWholeTile ? tile.getRaster() - : tile.getRaster()->extract(dnRect); - up_ras = upTile.getRaster(); - assert(dn_ras->getSize() == up_ras->getSize()); -} -void ino_blend_pin_light::dryComputeUpAndDown(TRectD &rect, double frame, - const TRenderSettings &rs, - bool upComputesWholeTile) { - const bool up_is = (this->m_up.isConnected() && - this->m_up.getFx()->getTimeRegion().contains(frame)); - const bool down_is = (this->m_down.isConnected() && - this->m_down.getFx()->getTimeRegion().contains(frame)); - /* ------ 両方とも切断の時処理しない ---------------------- */ - if (!up_is && !down_is) { - return; - } - /* ------ up接続かつdown切断の時 -------------------------- */ - if (up_is && !down_is) { - this->m_up->dryCompute(rect, frame, rs); - return; - } - /* ------ down接続時 -------------------------------------- */ - if (down_is) { - this->m_down->dryCompute(rect, frame, rs); - } - /* ------ up切断時 ---------------------------------------- */ - if (!up_is) { - return; - } - - /* ------ tileのgeometryを計算する ------------------------ */ - TRectD upBBox; - - if (upComputesWholeTile) { - upBBox = rect; - } else { - this->m_up->getBBox(frame, upBBox, rs); - upBBox *= rect; - makeRectCoherent(upBBox, rect.getP00()); - } - if ((upBBox.getLx() > 0.5) && (upBBox.getLy() > 0.5)) { - this->m_up->dryCompute(upBBox, frame, rs); - } -} -//------------------------------------------------------------ -#include /* std::ostringstream */ -#include "igs_color_blend.h" -namespace { -template -void tmpl_(TRasterPT dn_ras_out, const TRasterPT &up_ras, - const double up_opacity, const bool clipping_mask_sw) { - double maxi = static_cast(T::maxChannelValue); // 255or65535 - - assert(dn_ras_out->getSize() == up_ras->getSize()); - - for (int yy = 0; yy < dn_ras_out->getLy(); ++yy) { - T *out_pix = dn_ras_out->pixels(yy); - const T *const out_end = out_pix + dn_ras_out->getLx(); - const T *up_pix = up_ras->pixels(yy); - for (; out_pix < out_end; ++out_pix, ++up_pix) { - double upr = static_cast(up_pix->r) / maxi; - double upg = static_cast(up_pix->g) / maxi; - double upb = static_cast(up_pix->b) / maxi; - double upa = static_cast(up_pix->m) / maxi; - double dnr = static_cast(out_pix->r) / maxi; - double dng = static_cast(out_pix->g) / maxi; - double dnb = static_cast(out_pix->b) / maxi; - double dna = static_cast(out_pix->m) / maxi; - igs::color::pin_light(dnr, dng, dnb, dna, upr, upg, upb, upa, - clipping_mask_sw ? up_opacity * dna : up_opacity); - out_pix->r = static_cast(dnr * (maxi + 0.999999)); - out_pix->g = static_cast(dng * (maxi + 0.999999)); - out_pix->b = static_cast(dnb * (maxi + 0.999999)); - out_pix->m = static_cast(dna * (maxi + 0.999999)); - } - } -} -void fx_(TRasterP &dn_ras_out, const TRasterP &up_ras, const TPoint &pos, - const double up_opacity, const bool clipping_mask_sw) { - /* 交差したエリアを処理するようにする、いるのか??? */ - TRect outRect(dn_ras_out->getBounds()); - TRect upRect(up_ras->getBounds() + pos); - TRect intersection = outRect * upRect; - if (intersection.isEmpty()) return; - - TRasterP cRout = dn_ras_out->extract(intersection); - TRect rr = intersection - pos; - TRasterP cRup = up_ras->extract(rr); - - TRaster32P rout32 = cRout, rup32 = cRup; - TRaster64P rout64 = cRout, rup64 = cRup; - - if (rout32 && rup32) { - tmpl_(rout32, rup32, up_opacity, clipping_mask_sw); - } else if (rout64 && rup64) { - tmpl_(rout64, rup64, up_opacity, clipping_mask_sw); - } else { - throw TRopException("unsupported pixel type"); - } -} -} -void ino_blend_pin_light::doCompute(TTile &tile, double frame, - const TRenderSettings &rs) { - /* ------ 画像生成 ---------------------------------------- */ - TRasterP dn_ras, up_ras; - this->computeUpAndDown(tile, frame, rs, dn_ras, up_ras); - if (!dn_ras || !up_ras) { - return; - } - /* ------ 動作パラメータを得る ---------------------------- */ - const double up_opacity = - this->m_opacity->getValue(frame) / ino::param_range(); - /* ------ (app_begin)log記憶 ------------------------------ */ - const bool log_sw = ino::log_enable_sw(); - - if (log_sw) { - std::ostringstream os; - os << "params" - << " up_opacity " << up_opacity << " dn_tile w " << dn_ras->getLx() - << " wrap " << dn_ras->getWrap() << " h " << dn_ras->getLy() - << " pixbits " << ino::pixel_bits(dn_ras) << " up_tile w " - << up_ras->getLx() << " wrap " << up_ras->getWrap() << " h " - << up_ras->getLy() << " pixbits " << ino::pixel_bits(up_ras) - << " frame " << frame; - } - /* ------ fx処理 ------------------------------------------ */ - try { - if (dn_ras) { - dn_ras->lock(); - } - if (up_ras) { - up_ras->lock(); - } - fx_(dn_ras, up_ras, TPoint(), up_opacity, - this->m_clipping_mask->getValue()); - if (up_ras) { - up_ras->unlock(); - } - if (dn_ras) { - dn_ras->unlock(); - } - } - /* ------ error処理 --------------------------------------- */ - catch (std::exception &e) { - if (up_ras) { - up_ras->unlock(); - } - if (dn_ras) { - dn_ras->unlock(); - } - if (log_sw) { - std::string str("exception <"); - str += e.what(); - str += '>'; - } - throw; - } catch (...) { - if (up_ras) { - up_ras->unlock(); - } - if (dn_ras) { - dn_ras->unlock(); - } - if (log_sw) { - std::string str("other exception"); - } - throw; - } -} diff --git a/toonz/sources/stdfx/ino_blend_screen.cpp b/toonz/sources/stdfx/ino_blend_screen.cpp index c888480c..00b32b8d 100644 --- a/toonz/sources/stdfx/ino_blend_screen.cpp +++ b/toonz/sources/stdfx/ino_blend_screen.cpp @@ -3,333 +3,19 @@ #include "stdfx.h" #include "ino_common.h" +#include "igs_color_blend.h" /* tnzbase --> Source Files --> tfx --> binaryFx.cppを参照 */ class ino_blend_screen final : public TBlendForeBackRasterFx { FX_PLUGIN_DECLARATION(ino_blend_screen) - TRasterFxPort m_up; - TRasterFxPort m_down; - TDoubleParamP m_opacity; - TBoolParamP m_clipping_mask; public: - ino_blend_screen() - : m_opacity(1.0 * ino::param_range()), m_clipping_mask(true) { - addInputPort("Fore", this->m_up); - addInputPort("Back", this->m_down); - bindParam(this, "opacity", this->m_opacity); - bindParam(this, "clipping_mask", this->m_clipping_mask); - this->m_opacity->setValueRange(0, 1.0 * ino::param_range()); - } + ino_blend_screen() : TBlendForeBackRasterFx(true) {} ~ino_blend_screen() {} - bool canHandle(const TRenderSettings &rs, double frame) override { - return true; + void brendKernel(double& dnr, double& dng, double& dnb, double& dna, + const double upr, double upg, double upb, double upa, + const double up_opacity, + const bool alpha_rendering_sw = true) override { + igs::color::screen(dnr, dng, dnb, dna, upr, upg, upb, upa, up_opacity); } - bool doGetBBox(double frame, TRectD &bBox, - const TRenderSettings &rs) override { - TRectD up_bx; - const bool up_sw = - (m_up.isConnected() ? m_up->doGetBBox(frame, up_bx, rs) : false); - TRectD dn_bx; - const bool dn_sw = - (m_down.isConnected() ? m_down->doGetBBox(frame, dn_bx, rs) : false); - if (up_sw && dn_sw) { - bBox = up_bx + dn_bx; - return !bBox.isEmpty(); - } else if (up_sw) { - bBox = up_bx; - return true; - } else if (dn_sw) { - bBox = dn_bx; - return true; - } else { - bBox = TRectD(); - return false; - } - } - // TRect getInvalidRect(const TRect &max) {return max;} - // void doSetParam(const std::string &name, const TParamP ¶m) {} - int getMemoryRequirement(const TRectD &rect, double frame, - const TRenderSettings &rs) override { - return TRasterFx::memorySize(rect, rs.m_bpp); - } - - void doDryCompute(TRectD &rect, double frame, - const TRenderSettings &rs) override { - this->dryComputeUpAndDown(rect, frame, rs, false); - } - void doCompute(TTile &tile, double frame, const TRenderSettings &rs) override; - void computeUpAndDown(TTile &tile, double frame, const TRenderSettings &rs, - TRasterP &dn_ras, TRasterP &up_ras, - bool upComputesWholeTile = false); - void dryComputeUpAndDown(TRectD &rect, double frame, - const TRenderSettings &rs, - bool upComputesWholeTile = false - /* - upComputesWholeTile は Screen, Min, Blendでtrueにして使用している。 - */ - ); }; FX_PLUGIN_IDENTIFIER(ino_blend_screen, "inoScreenFx"); -//------------------------------------------------------------ -namespace { -/* より大きな四角エリアにPixel整数値で密着する */ -void makeRectCoherent(TRectD &rect, const TPointD &pos) { - rect -= pos; - rect.x0 = tfloor(rect.x0); /* ((x)<(int)(x)? (int)(x)-1: (int)(x))*/ - rect.y0 = tfloor(rect.y0); - rect.x1 = tceil(rect.x1); /* ((int)(x)<(x)? (int)(x)+1: (int)(x))*/ - rect.y1 = tceil(rect.y1); - rect += pos; -} -} -void ino_blend_screen::computeUpAndDown(TTile &tile, double frame, - const TRenderSettings &rs, - TRasterP &dn_ras, TRasterP &up_ras, - bool upComputesWholeTile) { - /* ------ サポートしていないPixelタイプはエラーを投げる --- */ - if (!((TRaster32P)tile.getRaster()) && !((TRaster64P)tile.getRaster())) { - throw TRopException("unsupported input pixel type"); - } - /* -m_down,m_upは繋がっている方があればそれを表示する -両方とも接続していれば合成処理する -表示スイッチを切ってあるならm_upを表示する -fxをreplaceすると、 - m_source --> m_up (=port0) - m_refernce --> m_down(=port1) -となる -*/ - const bool up_is = (this->m_up.isConnected() && - this->m_up.getFx()->getTimeRegion().contains(frame)); - const bool down_is = (this->m_down.isConnected() && - this->m_down.getFx()->getTimeRegion().contains(frame)); - /* ------ 両方とも切断の時処理しない ---------------------- */ - if (!up_is && !down_is) { - tile.getRaster()->clear(); - return; - } - /* ------ up接続かつdown切断の時 -------------------------- */ - if (up_is && !down_is) { - this->m_up->compute(tile, frame, rs); - return; - } - /* ------ down接続時 downのみ描画して... ------------------ */ - if (down_is) { - this->m_down->compute(tile, frame, rs); - } - /* ------ up切断時 ---------------------------------------- */ - if (!up_is) { - return; - } - - /* upと重なる部分を描画する */ - - /* ------ tileの範囲 -------------------------------------- */ - const TDimension tsz(tile.getRaster()->getSize()); /* 整数 */ - const TRectD tileRect(tile.m_pos, TDimensionD(tsz.lx, tsz.ly)); - TRectD upBBox; - if (upComputesWholeTile) { - upBBox = tileRect; - } /* tile全体を得る */ - else { /* 厳密なエリア... */ - this->m_up->getBBox(frame, upBBox, rs); - upBBox *= tileRect; /* upとtileの交差エリア */ - - /* より大きな四角エリアにPixel整数値で密着する */ - makeRectCoherent(upBBox, tile.m_pos); // double-->int grid - } - - TDimensionI upSize( /* TRectDをTDimensionIに変換 */ - tround(upBBox.getLx()) // getLx() = "x1>=x0?x1-x0:0" - , - tround(upBBox.getLy()) // getLy() = "y1>=y0?y1-y0:0" - ); - if ((upSize.lx <= 0) || (upSize.ly <= 0)) { - return; - } - - /* ------ upのメモリ確保と描画 ---------------------------- */ - TTile upTile; - this->m_up->allocateAndCompute(upTile, upBBox.getP00(), upSize, - tile.getRaster() /* 32/64bitsの判定に使う */ - , - frame, rs); - /* ------ upとdownのTRasterを得る ------------------------- */ - TRectI dnRect(upTile.getRaster()->getSize()); // TDimensionI(-) - - dnRect += convert(upTile.m_pos - tile.m_pos); /* uptile->tile原点 */ - /* - ここで問題はdoubleの位置を、四捨五入して整数値にしていること - 移動してから四捨五入ではないの??? - dnRectの元位置が整数位置なので、問題ないか... - */ - - dn_ras = upComputesWholeTile ? tile.getRaster() - : tile.getRaster()->extract(dnRect); - up_ras = upTile.getRaster(); - assert(dn_ras->getSize() == up_ras->getSize()); -} -void ino_blend_screen::dryComputeUpAndDown(TRectD &rect, double frame, - const TRenderSettings &rs, - bool upComputesWholeTile) { - const bool up_is = (this->m_up.isConnected() && - this->m_up.getFx()->getTimeRegion().contains(frame)); - const bool down_is = (this->m_down.isConnected() && - this->m_down.getFx()->getTimeRegion().contains(frame)); - /* ------ 両方とも切断の時処理しない ---------------------- */ - if (!up_is && !down_is) { - return; - } - /* ------ up接続かつdown切断の時 -------------------------- */ - if (up_is && !down_is) { - this->m_up->dryCompute(rect, frame, rs); - return; - } - /* ------ down接続時 -------------------------------------- */ - if (down_is) { - this->m_down->dryCompute(rect, frame, rs); - } - /* ------ up切断時 ---------------------------------------- */ - if (!up_is) { - return; - } - - /* ------ tileのgeometryを計算する ------------------------ */ - TRectD upBBox; - - if (upComputesWholeTile) { - upBBox = rect; - } else { - this->m_up->getBBox(frame, upBBox, rs); - upBBox *= rect; - makeRectCoherent(upBBox, rect.getP00()); - } - if ((upBBox.getLx() > 0.5) && (upBBox.getLy() > 0.5)) { - this->m_up->dryCompute(upBBox, frame, rs); - } -} -//------------------------------------------------------------ -#include /* std::ostringstream */ -#include "igs_color_blend.h" -namespace { -template -void tmpl_(TRasterPT dn_ras_out, const TRasterPT &up_ras, - const double up_opacity, const bool clipping_mask_sw) { - double maxi = static_cast(T::maxChannelValue); // 255or65535 - - assert(dn_ras_out->getSize() == up_ras->getSize()); - - for (int yy = 0; yy < dn_ras_out->getLy(); ++yy) { - T *out_pix = dn_ras_out->pixels(yy); - const T *const out_end = out_pix + dn_ras_out->getLx(); - const T *up_pix = up_ras->pixels(yy); - for (; out_pix < out_end; ++out_pix, ++up_pix) { - double upr = static_cast(up_pix->r) / maxi; - double upg = static_cast(up_pix->g) / maxi; - double upb = static_cast(up_pix->b) / maxi; - double upa = static_cast(up_pix->m) / maxi; - double dnr = static_cast(out_pix->r) / maxi; - double dng = static_cast(out_pix->g) / maxi; - double dnb = static_cast(out_pix->b) / maxi; - double dna = static_cast(out_pix->m) / maxi; - igs::color::screen(dnr, dng, dnb, dna, upr, upg, upb, upa, - clipping_mask_sw ? up_opacity * dna : up_opacity); - out_pix->r = static_cast(dnr * (maxi + 0.999999)); - out_pix->g = static_cast(dng * (maxi + 0.999999)); - out_pix->b = static_cast(dnb * (maxi + 0.999999)); - out_pix->m = static_cast(dna * (maxi + 0.999999)); - } - } -} -void fx_(TRasterP &dn_ras_out, const TRasterP &up_ras, const TPoint &pos, - const double up_opacity, const bool clipping_mask_sw) { - /* 交差したエリアを処理するようにする、いるのか??? */ - TRect outRect(dn_ras_out->getBounds()); - TRect upRect(up_ras->getBounds() + pos); - TRect intersection = outRect * upRect; - if (intersection.isEmpty()) return; - - TRasterP cRout = dn_ras_out->extract(intersection); - TRect rr = intersection - pos; - TRasterP cRup = up_ras->extract(rr); - - TRaster32P rout32 = cRout, rup32 = cRup; - TRaster64P rout64 = cRout, rup64 = cRup; - - if (rout32 && rup32) { - tmpl_(rout32, rup32, up_opacity, clipping_mask_sw); - } else if (rout64 && rup64) { - tmpl_(rout64, rup64, up_opacity, clipping_mask_sw); - } else { - throw TRopException("unsupported pixel type"); - } -} -} -void ino_blend_screen::doCompute(TTile &tile, double frame, - const TRenderSettings &rs) { - /* ------ 画像生成 ---------------------------------------- */ - TRasterP dn_ras, up_ras; - this->computeUpAndDown(tile, frame, rs, dn_ras, up_ras); - if (!dn_ras || !up_ras) { - return; - } - /* ------ 動作パラメータを得る ---------------------------- */ - const double up_opacity = - this->m_opacity->getValue(frame) / ino::param_range(); - /* ------ (app_begin)log記憶 ------------------------------ */ - const bool log_sw = ino::log_enable_sw(); - - if (log_sw) { - std::ostringstream os; - os << "params" - << " up_opacity " << up_opacity << " dn_tile w " << dn_ras->getLx() - << " wrap " << dn_ras->getWrap() << " h " << dn_ras->getLy() - << " pixbits " << ino::pixel_bits(dn_ras) << " up_tile w " - << up_ras->getLx() << " wrap " << up_ras->getWrap() << " h " - << up_ras->getLy() << " pixbits " << ino::pixel_bits(up_ras) - << " frame " << frame; - } - /* ------ fx処理 ------------------------------------------ */ - try { - if (dn_ras) { - dn_ras->lock(); - } - if (up_ras) { - up_ras->lock(); - } - fx_(dn_ras, up_ras, TPoint(), up_opacity, - this->m_clipping_mask->getValue()); - if (up_ras) { - up_ras->unlock(); - } - if (dn_ras) { - dn_ras->unlock(); - } - } - /* ------ error処理 --------------------------------------- */ - catch (std::exception &e) { - if (up_ras) { - up_ras->unlock(); - } - if (dn_ras) { - dn_ras->unlock(); - } - if (log_sw) { - std::string str("exception <"); - str += e.what(); - str += '>'; - } - throw; - } catch (...) { - if (up_ras) { - up_ras->unlock(); - } - if (dn_ras) { - dn_ras->unlock(); - } - if (log_sw) { - std::string str("other exception"); - } - throw; - } -} diff --git a/toonz/sources/stdfx/ino_blend_soft_light.cpp b/toonz/sources/stdfx/ino_blend_soft_light.cpp index def90f91..3865fb16 100644 --- a/toonz/sources/stdfx/ino_blend_soft_light.cpp +++ b/toonz/sources/stdfx/ino_blend_soft_light.cpp @@ -3,333 +3,19 @@ #include "stdfx.h" #include "ino_common.h" +#include "igs_color_blend.h" /* tnzbase --> Source Files --> tfx --> binaryFx.cppを参照 */ class ino_blend_soft_light final : public TBlendForeBackRasterFx { FX_PLUGIN_DECLARATION(ino_blend_soft_light) - TRasterFxPort m_up; - TRasterFxPort m_down; - TDoubleParamP m_opacity; - TBoolParamP m_clipping_mask; public: - ino_blend_soft_light() - : m_opacity(1.0 * ino::param_range()), m_clipping_mask(true) { - addInputPort("Fore", this->m_up); - addInputPort("Back", this->m_down); - bindParam(this, "opacity", this->m_opacity); - bindParam(this, "clipping_mask", this->m_clipping_mask); - this->m_opacity->setValueRange(0, 1.0 * ino::param_range()); - } + ino_blend_soft_light() : TBlendForeBackRasterFx(true) {} ~ino_blend_soft_light() {} - bool canHandle(const TRenderSettings &rs, double frame) override { - return true; + void brendKernel(double& dnr, double& dng, double& dnb, double& dna, + const double upr, double upg, double upb, double upa, + const double up_opacity, + const bool alpha_rendering_sw = true) override { + igs::color::soft_light(dnr, dng, dnb, dna, upr, upg, upb, upa, up_opacity); } - bool doGetBBox(double frame, TRectD &bBox, - const TRenderSettings &rs) override { - TRectD up_bx; - const bool up_sw = - (m_up.isConnected() ? m_up->doGetBBox(frame, up_bx, rs) : false); - TRectD dn_bx; - const bool dn_sw = - (m_down.isConnected() ? m_down->doGetBBox(frame, dn_bx, rs) : false); - if (up_sw && dn_sw) { - bBox = up_bx + dn_bx; - return !bBox.isEmpty(); - } else if (up_sw) { - bBox = up_bx; - return true; - } else if (dn_sw) { - bBox = dn_bx; - return true; - } else { - bBox = TRectD(); - return false; - } - } - // TRect getInvalidRect(const TRect &max) {return max;} - // void doSetParam(const std::string &name, const TParamP ¶m) {} - int getMemoryRequirement(const TRectD &rect, double frame, - const TRenderSettings &rs) override { - return TRasterFx::memorySize(rect, rs.m_bpp); - } - - void doDryCompute(TRectD &rect, double frame, - const TRenderSettings &rs) override { - this->dryComputeUpAndDown(rect, frame, rs, false); - } - void doCompute(TTile &tile, double frame, const TRenderSettings &rs) override; - void computeUpAndDown(TTile &tile, double frame, const TRenderSettings &rs, - TRasterP &dn_ras, TRasterP &up_ras, - bool upComputesWholeTile = false); - void dryComputeUpAndDown(TRectD &rect, double frame, - const TRenderSettings &rs, - bool upComputesWholeTile = false - /* - upComputesWholeTile は Screen, Min, Blendでtrueにして使用している。 - */ - ); }; FX_PLUGIN_IDENTIFIER(ino_blend_soft_light, "inoSoftLightFx"); -//------------------------------------------------------------ -namespace { -/* より大きな四角エリアにPixel整数値で密着する */ -void makeRectCoherent(TRectD &rect, const TPointD &pos) { - rect -= pos; - rect.x0 = tfloor(rect.x0); /* ((x)<(int)(x)? (int)(x)-1: (int)(x))*/ - rect.y0 = tfloor(rect.y0); - rect.x1 = tceil(rect.x1); /* ((int)(x)<(x)? (int)(x)+1: (int)(x))*/ - rect.y1 = tceil(rect.y1); - rect += pos; -} -} -void ino_blend_soft_light::computeUpAndDown(TTile &tile, double frame, - const TRenderSettings &rs, - TRasterP &dn_ras, TRasterP &up_ras, - bool upComputesWholeTile) { - /* ------ サポートしていないPixelタイプはエラーを投げる --- */ - if (!((TRaster32P)tile.getRaster()) && !((TRaster64P)tile.getRaster())) { - throw TRopException("unsupported input pixel type"); - } - /* -m_down,m_upは繋がっている方があればそれを表示する -両方とも接続していれば合成処理する -表示スイッチを切ってあるならm_upを表示する -fxをreplaceすると、 - m_source --> m_up (=port0) - m_refernce --> m_down(=port1) -となる -*/ - const bool up_is = (this->m_up.isConnected() && - this->m_up.getFx()->getTimeRegion().contains(frame)); - const bool down_is = (this->m_down.isConnected() && - this->m_down.getFx()->getTimeRegion().contains(frame)); - /* ------ 両方とも切断の時処理しない ---------------------- */ - if (!up_is && !down_is) { - tile.getRaster()->clear(); - return; - } - /* ------ up接続かつdown切断の時 -------------------------- */ - if (up_is && !down_is) { - this->m_up->compute(tile, frame, rs); - return; - } - /* ------ down接続時 downのみ描画して... ------------------ */ - if (down_is) { - this->m_down->compute(tile, frame, rs); - } - /* ------ up切断時 ---------------------------------------- */ - if (!up_is) { - return; - } - - /* upと重なる部分を描画する */ - - /* ------ tileの範囲 -------------------------------------- */ - const TDimension tsz(tile.getRaster()->getSize()); /* 整数 */ - const TRectD tileRect(tile.m_pos, TDimensionD(tsz.lx, tsz.ly)); - TRectD upBBox; - if (upComputesWholeTile) { - upBBox = tileRect; - } /* tile全体を得る */ - else { /* 厳密なエリア... */ - this->m_up->getBBox(frame, upBBox, rs); - upBBox *= tileRect; /* upとtileの交差エリア */ - - /* より大きな四角エリアにPixel整数値で密着する */ - makeRectCoherent(upBBox, tile.m_pos); // double-->int grid - } - - TDimensionI upSize( /* TRectDをTDimensionIに変換 */ - tround(upBBox.getLx()) // getLx() = "x1>=x0?x1-x0:0" - , - tround(upBBox.getLy()) // getLy() = "y1>=y0?y1-y0:0" - ); - if ((upSize.lx <= 0) || (upSize.ly <= 0)) { - return; - } - - /* ------ upのメモリ確保と描画 ---------------------------- */ - TTile upTile; - this->m_up->allocateAndCompute(upTile, upBBox.getP00(), upSize, - tile.getRaster() /* 32/64bitsの判定に使う */ - , - frame, rs); - /* ------ upとdownのTRasterを得る ------------------------- */ - TRectI dnRect(upTile.getRaster()->getSize()); // TDimensionI(-) - - dnRect += convert(upTile.m_pos - tile.m_pos); /* uptile->tile原点 */ - /* - ここで問題はdoubleの位置を、四捨五入して整数値にしていること - 移動してから四捨五入ではないの??? - dnRectの元位置が整数位置なので、問題ないか... - */ - - dn_ras = upComputesWholeTile ? tile.getRaster() - : tile.getRaster()->extract(dnRect); - up_ras = upTile.getRaster(); - assert(dn_ras->getSize() == up_ras->getSize()); -} -void ino_blend_soft_light::dryComputeUpAndDown(TRectD &rect, double frame, - const TRenderSettings &rs, - bool upComputesWholeTile) { - const bool up_is = (this->m_up.isConnected() && - this->m_up.getFx()->getTimeRegion().contains(frame)); - const bool down_is = (this->m_down.isConnected() && - this->m_down.getFx()->getTimeRegion().contains(frame)); - /* ------ 両方とも切断の時処理しない ---------------------- */ - if (!up_is && !down_is) { - return; - } - /* ------ up接続かつdown切断の時 -------------------------- */ - if (up_is && !down_is) { - this->m_up->dryCompute(rect, frame, rs); - return; - } - /* ------ down接続時 -------------------------------------- */ - if (down_is) { - this->m_down->dryCompute(rect, frame, rs); - } - /* ------ up切断時 ---------------------------------------- */ - if (!up_is) { - return; - } - - /* ------ tileのgeometryを計算する ------------------------ */ - TRectD upBBox; - - if (upComputesWholeTile) { - upBBox = rect; - } else { - this->m_up->getBBox(frame, upBBox, rs); - upBBox *= rect; - makeRectCoherent(upBBox, rect.getP00()); - } - if ((upBBox.getLx() > 0.5) && (upBBox.getLy() > 0.5)) { - this->m_up->dryCompute(upBBox, frame, rs); - } -} -//------------------------------------------------------------ -#include /* std::ostringstream */ -#include "igs_color_blend.h" -namespace { -template -void tmpl_(TRasterPT dn_ras_out, const TRasterPT &up_ras, - const double up_opacity, const bool clipping_mask_sw) { - double maxi = static_cast(T::maxChannelValue); // 255or65535 - - assert(dn_ras_out->getSize() == up_ras->getSize()); - - for (int yy = 0; yy < dn_ras_out->getLy(); ++yy) { - T *out_pix = dn_ras_out->pixels(yy); - const T *const out_end = out_pix + dn_ras_out->getLx(); - const T *up_pix = up_ras->pixels(yy); - for (; out_pix < out_end; ++out_pix, ++up_pix) { - double upr = static_cast(up_pix->r) / maxi; - double upg = static_cast(up_pix->g) / maxi; - double upb = static_cast(up_pix->b) / maxi; - double upa = static_cast(up_pix->m) / maxi; - double dnr = static_cast(out_pix->r) / maxi; - double dng = static_cast(out_pix->g) / maxi; - double dnb = static_cast(out_pix->b) / maxi; - double dna = static_cast(out_pix->m) / maxi; - igs::color::soft_light(dnr, dng, dnb, dna, upr, upg, upb, upa, - clipping_mask_sw ? up_opacity * dna : up_opacity); - out_pix->r = static_cast(dnr * (maxi + 0.999999)); - out_pix->g = static_cast(dng * (maxi + 0.999999)); - out_pix->b = static_cast(dnb * (maxi + 0.999999)); - out_pix->m = static_cast(dna * (maxi + 0.999999)); - } - } -} -void fx_(TRasterP &dn_ras_out, const TRasterP &up_ras, const TPoint &pos, - const double up_opacity, const bool clipping_mask_sw) { - /* 交差したエリアを処理するようにする、いるのか??? */ - TRect outRect(dn_ras_out->getBounds()); - TRect upRect(up_ras->getBounds() + pos); - TRect intersection = outRect * upRect; - if (intersection.isEmpty()) return; - - TRasterP cRout = dn_ras_out->extract(intersection); - TRect rr = intersection - pos; - TRasterP cRup = up_ras->extract(rr); - - TRaster32P rout32 = cRout, rup32 = cRup; - TRaster64P rout64 = cRout, rup64 = cRup; - - if (rout32 && rup32) { - tmpl_(rout32, rup32, up_opacity, clipping_mask_sw); - } else if (rout64 && rup64) { - tmpl_(rout64, rup64, up_opacity, clipping_mask_sw); - } else { - throw TRopException("unsupported pixel type"); - } -} -} -void ino_blend_soft_light::doCompute(TTile &tile, double frame, - const TRenderSettings &rs) { - /* ------ 画像生成 ---------------------------------------- */ - TRasterP dn_ras, up_ras; - this->computeUpAndDown(tile, frame, rs, dn_ras, up_ras); - if (!dn_ras || !up_ras) { - return; - } - /* ------ 動作パラメータを得る ---------------------------- */ - const double up_opacity = - this->m_opacity->getValue(frame) / ino::param_range(); - /* ------ (app_begin)log記憶 ------------------------------ */ - const bool log_sw = ino::log_enable_sw(); - - if (log_sw) { - std::ostringstream os; - os << "params" - << " up_opacity " << up_opacity << " dn_tile w " << dn_ras->getLx() - << " wrap " << dn_ras->getWrap() << " h " << dn_ras->getLy() - << " pixbits " << ino::pixel_bits(dn_ras) << " up_tile w " - << up_ras->getLx() << " wrap " << up_ras->getWrap() << " h " - << up_ras->getLy() << " pixbits " << ino::pixel_bits(up_ras) - << " frame " << frame; - } - /* ------ fx処理 ------------------------------------------ */ - try { - if (dn_ras) { - dn_ras->lock(); - } - if (up_ras) { - up_ras->lock(); - } - fx_(dn_ras, up_ras, TPoint(), up_opacity, - this->m_clipping_mask->getValue()); - if (up_ras) { - up_ras->unlock(); - } - if (dn_ras) { - dn_ras->unlock(); - } - } - /* ------ error処理 --------------------------------------- */ - catch (std::exception &e) { - if (up_ras) { - up_ras->unlock(); - } - if (dn_ras) { - dn_ras->unlock(); - } - if (log_sw) { - std::string str("exception <"); - str += e.what(); - str += '>'; - } - throw; - } catch (...) { - if (up_ras) { - up_ras->unlock(); - } - if (dn_ras) { - dn_ras->unlock(); - } - if (log_sw) { - std::string str("other exception"); - } - throw; - } -} diff --git a/toonz/sources/stdfx/ino_blend_subtract.cpp b/toonz/sources/stdfx/ino_blend_subtract.cpp index b2dfee93..e3f52f62 100644 --- a/toonz/sources/stdfx/ino_blend_subtract.cpp +++ b/toonz/sources/stdfx/ino_blend_subtract.cpp @@ -3,342 +3,21 @@ #include "stdfx.h" #include "ino_common.h" +#include "igs_color_blend.h" + /* tnzbase --> Source Files --> tfx --> binaryFx.cppを参照 */ class ino_blend_subtract final : public TBlendForeBackRasterFx { FX_PLUGIN_DECLARATION(ino_blend_subtract) - TRasterFxPort m_up; - TRasterFxPort m_down; - TDoubleParamP m_opacity; - TBoolParamP m_clipping_mask; - TBoolParamP m_alpha_rendering; - public: ino_blend_subtract() - : m_opacity(1.0 * ino::param_range()) - , m_clipping_mask(true) - , m_alpha_rendering(true) { - addInputPort("Fore", this->m_up); - addInputPort("Back", this->m_down); - bindParam(this, "opacity", this->m_opacity); - bindParam(this, "clipping_mask", this->m_clipping_mask); - bindParam(this, "alpha_rendering", this->m_alpha_rendering); - this->m_opacity->setValueRange(0, 1.0 * ino::param_range()); - } + : TBlendForeBackRasterFx(true, true) {} // with alpha_rendering switch ~ino_blend_subtract() {} - bool canHandle(const TRenderSettings &rs, double frame) override { - return true; + void brendKernel(double& dnr, double& dng, double& dnb, double& dna, + const double upr, double upg, double upb, double upa, + const double up_opacity, + const bool alpha_rendering_sw = true) override { + igs::color::subtract(dnr, dng, dnb, dna, upr, upg, upb, upa, up_opacity, + alpha_rendering_sw); } - bool doGetBBox(double frame, TRectD &bBox, - const TRenderSettings &rs) override { - TRectD up_bx; - const bool up_sw = - (m_up.isConnected() ? m_up->doGetBBox(frame, up_bx, rs) : false); - TRectD dn_bx; - const bool dn_sw = - (m_down.isConnected() ? m_down->doGetBBox(frame, dn_bx, rs) : false); - if (up_sw && dn_sw) { - bBox = up_bx + dn_bx; - return !bBox.isEmpty(); - } else if (up_sw) { - bBox = up_bx; - return true; - } else if (dn_sw) { - bBox = dn_bx; - return true; - } else { - bBox = TRectD(); - return false; - } - } - // TRect getInvalidRect(const TRect &max) {return max;} - // void doSetParam(const std::string &name, const TParamP ¶m) {} - int getMemoryRequirement(const TRectD &rect, double frame, - const TRenderSettings &rs) override { - return TRasterFx::memorySize(rect, rs.m_bpp); - } - - void doDryCompute(TRectD &rect, double frame, - const TRenderSettings &rs) override { - this->dryComputeUpAndDown(rect, frame, rs, false); - } - void doCompute(TTile &tile, double frame, const TRenderSettings &rs) override; - void computeUpAndDown(TTile &tile, double frame, const TRenderSettings &rs, - TRasterP &dn_ras, TRasterP &up_ras, - bool upComputesWholeTile = false); - void dryComputeUpAndDown(TRectD &rect, double frame, - const TRenderSettings &rs, - bool upComputesWholeTile = false - /* - upComputesWholeTile は Screen, Min, Blendでtrueにして使用している。 - */ - ); }; FX_PLUGIN_IDENTIFIER(ino_blend_subtract, "inoSubtractFx"); -//------------------------------------------------------------ -namespace { -/* より大きな四角エリアにPixel整数値で密着する */ -void makeRectCoherent(TRectD &rect, const TPointD &pos) { - rect -= pos; - rect.x0 = tfloor(rect.x0); /* ((x)<(int)(x)? (int)(x)-1: (int)(x))*/ - rect.y0 = tfloor(rect.y0); - rect.x1 = tceil(rect.x1); /* ((int)(x)<(x)? (int)(x)+1: (int)(x))*/ - rect.y1 = tceil(rect.y1); - rect += pos; -} -} -void ino_blend_subtract::computeUpAndDown(TTile &tile, double frame, - const TRenderSettings &rs, - TRasterP &dn_ras, TRasterP &up_ras, - bool upComputesWholeTile) { - /* ------ サポートしていないPixelタイプはエラーを投げる --- */ - if (!((TRaster32P)tile.getRaster()) && !((TRaster64P)tile.getRaster())) { - throw TRopException("unsupported input pixel type"); - } - /* -m_down,m_upは繋がっている方があればそれを表示する -両方とも接続していれば合成処理する -表示スイッチを切ってあるならm_upを表示する -fxをreplaceすると、 - m_source --> m_up (=port0) - m_refernce --> m_down(=port1) -となる -*/ - const bool up_is = (this->m_up.isConnected() && - this->m_up.getFx()->getTimeRegion().contains(frame)); - const bool down_is = (this->m_down.isConnected() && - this->m_down.getFx()->getTimeRegion().contains(frame)); - /* ------ 両方とも切断の時処理しない ---------------------- */ - if (!up_is && !down_is) { - tile.getRaster()->clear(); - return; - } - /* ------ up接続かつdown切断の時 -------------------------- */ - if (up_is && !down_is) { - this->m_up->compute(tile, frame, rs); - return; - } - /* ------ down接続時 downのみ描画して... ------------------ */ - if (down_is) { - this->m_down->compute(tile, frame, rs); - } - /* ------ up切断時 ---------------------------------------- */ - if (!up_is) { - return; - } - - /* upと重なる部分を描画する */ - - /* ------ tileの範囲 -------------------------------------- */ - const TDimension tsz(tile.getRaster()->getSize()); /* 整数 */ - const TRectD tileRect(tile.m_pos, TDimensionD(tsz.lx, tsz.ly)); - TRectD upBBox; - if (upComputesWholeTile) { - upBBox = tileRect; - } /* tile全体を得る */ - else { /* 厳密なエリア... */ - this->m_up->getBBox(frame, upBBox, rs); - upBBox *= tileRect; /* upとtileの交差エリア */ - - /* より大きな四角エリアにPixel整数値で密着する */ - makeRectCoherent(upBBox, tile.m_pos); // double-->int grid - } - - TDimensionI upSize( /* TRectDをTDimensionIに変換 */ - tround(upBBox.getLx()) // getLx() = "x1>=x0?x1-x0:0" - , - tround(upBBox.getLy()) // getLy() = "y1>=y0?y1-y0:0" - ); - if ((upSize.lx <= 0) || (upSize.ly <= 0)) { - return; - } - - /* ------ upのメモリ確保と描画 ---------------------------- */ - TTile upTile; - this->m_up->allocateAndCompute(upTile, upBBox.getP00(), upSize, - tile.getRaster() /* 32/64bitsの判定に使う */ - , - frame, rs); - /* ------ upとdownのTRasterを得る ------------------------- */ - TRectI dnRect(upTile.getRaster()->getSize()); // TDimensionI(-) - - dnRect += convert(upTile.m_pos - tile.m_pos); /* uptile->tile原点 */ - /* - ここで問題はdoubleの位置を、四捨五入して整数値にしていること - 移動してから四捨五入ではないの??? - dnRectの元位置が整数位置なので、問題ないか... - */ - - dn_ras = upComputesWholeTile ? tile.getRaster() - : tile.getRaster()->extract(dnRect); - up_ras = upTile.getRaster(); - assert(dn_ras->getSize() == up_ras->getSize()); -} -void ino_blend_subtract::dryComputeUpAndDown(TRectD &rect, double frame, - const TRenderSettings &rs, - bool upComputesWholeTile) { - const bool up_is = (this->m_up.isConnected() && - this->m_up.getFx()->getTimeRegion().contains(frame)); - const bool down_is = (this->m_down.isConnected() && - this->m_down.getFx()->getTimeRegion().contains(frame)); - /* ------ 両方とも切断の時処理しない ---------------------- */ - if (!up_is && !down_is) { - return; - } - /* ------ up接続かつdown切断の時 -------------------------- */ - if (up_is && !down_is) { - this->m_up->dryCompute(rect, frame, rs); - return; - } - /* ------ down接続時 -------------------------------------- */ - if (down_is) { - this->m_down->dryCompute(rect, frame, rs); - } - /* ------ up切断時 ---------------------------------------- */ - if (!up_is) { - return; - } - - /* ------ tileのgeometryを計算する ------------------------ */ - TRectD upBBox; - - if (upComputesWholeTile) { - upBBox = rect; - } else { - this->m_up->getBBox(frame, upBBox, rs); - upBBox *= rect; - makeRectCoherent(upBBox, rect.getP00()); - } - if ((upBBox.getLx() > 0.5) && (upBBox.getLy() > 0.5)) { - this->m_up->dryCompute(upBBox, frame, rs); - } -} -//------------------------------------------------------------ -#include /* std::ostringstream */ -#include "igs_color_blend.h" -namespace { -template -void tmpl_(TRasterPT dn_ras_out, const TRasterPT &up_ras, - const double up_opacity, const bool clipping_mask_sw, - const bool alpha_rendering_sw) { - double maxi = static_cast(T::maxChannelValue); // 255or65535 - - assert(dn_ras_out->getSize() == up_ras->getSize()); - - for (int yy = 0; yy < dn_ras_out->getLy(); ++yy) { - T *out_pix = dn_ras_out->pixels(yy); - const T *const out_end = out_pix + dn_ras_out->getLx(); - const T *up_pix = up_ras->pixels(yy); - for (; out_pix < out_end; ++out_pix, ++up_pix) { - double upr = static_cast(up_pix->r) / maxi; - double upg = static_cast(up_pix->g) / maxi; - double upb = static_cast(up_pix->b) / maxi; - double upa = static_cast(up_pix->m) / maxi; - double dnr = static_cast(out_pix->r) / maxi; - double dng = static_cast(out_pix->g) / maxi; - double dnb = static_cast(out_pix->b) / maxi; - double dna = static_cast(out_pix->m) / maxi; - igs::color::subtract(dnr, dng, dnb, dna, upr, upg, upb, upa, - clipping_mask_sw ? up_opacity * dna : up_opacity, - alpha_rendering_sw); - out_pix->r = static_cast(dnr * (maxi + 0.999999)); - out_pix->g = static_cast(dng * (maxi + 0.999999)); - out_pix->b = static_cast(dnb * (maxi + 0.999999)); - out_pix->m = static_cast(dna * (maxi + 0.999999)); - } - } -} -void fx_(TRasterP &dn_ras_out, const TRasterP &up_ras, const TPoint &pos, - const double up_opacity, const bool clipping_mask_sw, - const bool alpha_rendering_sw) { - /* 交差したエリアを処理するようにする、いるのか??? */ - TRect outRect(dn_ras_out->getBounds()); - TRect upRect(up_ras->getBounds() + pos); - TRect intersection = outRect * upRect; - if (intersection.isEmpty()) return; - - TRasterP cRout = dn_ras_out->extract(intersection); - TRect rr = intersection - pos; - TRasterP cRup = up_ras->extract(rr); - - TRaster32P rout32 = cRout, rup32 = cRup; - TRaster64P rout64 = cRout, rup64 = cRup; - - if (rout32 && rup32) { - tmpl_(rout32, rup32, up_opacity, clipping_mask_sw, - alpha_rendering_sw); - } else if (rout64 && rup64) { - tmpl_(rout64, rup64, up_opacity, clipping_mask_sw, - alpha_rendering_sw); - } else { - throw TRopException("unsupported pixel type"); - } -} -} -void ino_blend_subtract::doCompute(TTile &tile, double frame, - const TRenderSettings &rs) { - /* ------ 画像生成 ---------------------------------------- */ - TRasterP dn_ras, up_ras; - this->computeUpAndDown(tile, frame, rs, dn_ras, up_ras); - if (!dn_ras || !up_ras) { - return; - } - /* ------ 動作パラメータを得る ---------------------------- */ - const double up_opacity = - this->m_opacity->getValue(frame) / ino::param_range(); - /* ------ (app_begin)log記憶 ------------------------------ */ - const bool log_sw = ino::log_enable_sw(); - - if (log_sw) { - std::ostringstream os; - os << "params" - << " up_opacity " << up_opacity << " dn_tile w " << dn_ras->getLx() - << " wrap " << dn_ras->getWrap() << " h " << dn_ras->getLy() - << " pixbits " << ino::pixel_bits(dn_ras) << " up_tile w " - << up_ras->getLx() << " wrap " << up_ras->getWrap() << " h " - << up_ras->getLy() << " pixbits " << ino::pixel_bits(up_ras) - << " frame " << frame; - } - /* ------ fx処理 ------------------------------------------ */ - try { - if (dn_ras) { - dn_ras->lock(); - } - if (up_ras) { - up_ras->lock(); - } - fx_(dn_ras, up_ras, TPoint(), up_opacity, this->m_clipping_mask->getValue(), - this->m_alpha_rendering->getValue()); - if (up_ras) { - up_ras->unlock(); - } - if (dn_ras) { - dn_ras->unlock(); - } - } - /* ------ error処理 --------------------------------------- */ - catch (std::exception &e) { - if (up_ras) { - up_ras->unlock(); - } - if (dn_ras) { - dn_ras->unlock(); - } - if (log_sw) { - std::string str("exception <"); - str += e.what(); - str += '>'; - } - throw; - } catch (...) { - if (up_ras) { - up_ras->unlock(); - } - if (dn_ras) { - dn_ras->unlock(); - } - if (log_sw) { - std::string str("other exception"); - } - throw; - } -} diff --git a/toonz/sources/stdfx/ino_blend_vivid_light.cpp b/toonz/sources/stdfx/ino_blend_vivid_light.cpp index 3a93893d..918e6f93 100644 --- a/toonz/sources/stdfx/ino_blend_vivid_light.cpp +++ b/toonz/sources/stdfx/ino_blend_vivid_light.cpp @@ -3,333 +3,19 @@ #include "stdfx.h" #include "ino_common.h" +#include "igs_color_blend.h" /* tnzbase --> Source Files --> tfx --> binaryFx.cppを参照 */ class ino_blend_vivid_light final : public TBlendForeBackRasterFx { FX_PLUGIN_DECLARATION(ino_blend_vivid_light) - TRasterFxPort m_up; - TRasterFxPort m_down; - TDoubleParamP m_opacity; - TBoolParamP m_clipping_mask; public: - ino_blend_vivid_light() - : m_opacity(1.0 * ino::param_range()), m_clipping_mask(true) { - addInputPort("Fore", this->m_up); - addInputPort("Back", this->m_down); - bindParam(this, "opacity", this->m_opacity); - bindParam(this, "clipping_mask", this->m_clipping_mask); - this->m_opacity->setValueRange(0, 1.0 * ino::param_range()); - } + ino_blend_vivid_light() : TBlendForeBackRasterFx(true) {} ~ino_blend_vivid_light() {} - bool canHandle(const TRenderSettings &rs, double frame) override { - return true; + void brendKernel(double& dnr, double& dng, double& dnb, double& dna, + const double upr, double upg, double upb, double upa, + const double up_opacity, + const bool alpha_rendering_sw = true) override { + igs::color::vivid_light(dnr, dng, dnb, dna, upr, upg, upb, upa, up_opacity); } - bool doGetBBox(double frame, TRectD &bBox, - const TRenderSettings &rs) override { - TRectD up_bx; - const bool up_sw = - (m_up.isConnected() ? m_up->doGetBBox(frame, up_bx, rs) : false); - TRectD dn_bx; - const bool dn_sw = - (m_down.isConnected() ? m_down->doGetBBox(frame, dn_bx, rs) : false); - if (up_sw && dn_sw) { - bBox = up_bx + dn_bx; - return !bBox.isEmpty(); - } else if (up_sw) { - bBox = up_bx; - return true; - } else if (dn_sw) { - bBox = dn_bx; - return true; - } else { - bBox = TRectD(); - return false; - } - } - // TRect getInvalidRect(const TRect &max) {return max;} - // void doSetParam(const std::string &name, const TParamP ¶m) {} - int getMemoryRequirement(const TRectD &rect, double frame, - const TRenderSettings &rs) override { - return TRasterFx::memorySize(rect, rs.m_bpp); - } - - void doDryCompute(TRectD &rect, double frame, - const TRenderSettings &rs) override { - this->dryComputeUpAndDown(rect, frame, rs, false); - } - void doCompute(TTile &tile, double frame, const TRenderSettings &rs) override; - void computeUpAndDown(TTile &tile, double frame, const TRenderSettings &rs, - TRasterP &dn_ras, TRasterP &up_ras, - bool upComputesWholeTile = false); - void dryComputeUpAndDown(TRectD &rect, double frame, - const TRenderSettings &rs, - bool upComputesWholeTile = false - /* - upComputesWholeTile は Screen, Min, Blendでtrueにして使用している。 - */ - ); }; FX_PLUGIN_IDENTIFIER(ino_blend_vivid_light, "inoVividLightFx"); -//------------------------------------------------------------ -namespace { -/* より大きな四角エリアにPixel整数値で密着する */ -void makeRectCoherent(TRectD &rect, const TPointD &pos) { - rect -= pos; - rect.x0 = tfloor(rect.x0); /* ((x)<(int)(x)? (int)(x)-1: (int)(x))*/ - rect.y0 = tfloor(rect.y0); - rect.x1 = tceil(rect.x1); /* ((int)(x)<(x)? (int)(x)+1: (int)(x))*/ - rect.y1 = tceil(rect.y1); - rect += pos; -} -} -void ino_blend_vivid_light::computeUpAndDown(TTile &tile, double frame, - const TRenderSettings &rs, - TRasterP &dn_ras, TRasterP &up_ras, - bool upComputesWholeTile) { - /* ------ サポートしていないPixelタイプはエラーを投げる --- */ - if (!((TRaster32P)tile.getRaster()) && !((TRaster64P)tile.getRaster())) { - throw TRopException("unsupported input pixel type"); - } - /* -m_down,m_upは繋がっている方があればそれを表示する -両方とも接続していれば合成処理する -表示スイッチを切ってあるならm_upを表示する -fxをreplaceすると、 - m_source --> m_up (=port0) - m_refernce --> m_down(=port1) -となる -*/ - const bool up_is = (this->m_up.isConnected() && - this->m_up.getFx()->getTimeRegion().contains(frame)); - const bool down_is = (this->m_down.isConnected() && - this->m_down.getFx()->getTimeRegion().contains(frame)); - /* ------ 両方とも切断の時処理しない ---------------------- */ - if (!up_is && !down_is) { - tile.getRaster()->clear(); - return; - } - /* ------ up接続かつdown切断の時 -------------------------- */ - if (up_is && !down_is) { - this->m_up->compute(tile, frame, rs); - return; - } - /* ------ down接続時 downのみ描画して... ------------------ */ - if (down_is) { - this->m_down->compute(tile, frame, rs); - } - /* ------ up切断時 ---------------------------------------- */ - if (!up_is) { - return; - } - - /* upと重なる部分を描画する */ - - /* ------ tileの範囲 -------------------------------------- */ - const TDimension tsz(tile.getRaster()->getSize()); /* 整数 */ - const TRectD tileRect(tile.m_pos, TDimensionD(tsz.lx, tsz.ly)); - TRectD upBBox; - if (upComputesWholeTile) { - upBBox = tileRect; - } /* tile全体を得る */ - else { /* 厳密なエリア... */ - this->m_up->getBBox(frame, upBBox, rs); - upBBox *= tileRect; /* upとtileの交差エリア */ - - /* より大きな四角エリアにPixel整数値で密着する */ - makeRectCoherent(upBBox, tile.m_pos); // double-->int grid - } - - TDimensionI upSize( /* TRectDをTDimensionIに変換 */ - tround(upBBox.getLx()) // getLx() = "x1>=x0?x1-x0:0" - , - tround(upBBox.getLy()) // getLy() = "y1>=y0?y1-y0:0" - ); - if ((upSize.lx <= 0) || (upSize.ly <= 0)) { - return; - } - - /* ------ upのメモリ確保と描画 ---------------------------- */ - TTile upTile; - this->m_up->allocateAndCompute(upTile, upBBox.getP00(), upSize, - tile.getRaster() /* 32/64bitsの判定に使う */ - , - frame, rs); - /* ------ upとdownのTRasterを得る ------------------------- */ - TRectI dnRect(upTile.getRaster()->getSize()); // TDimensionI(-) - - dnRect += convert(upTile.m_pos - tile.m_pos); /* uptile->tile原点 */ - /* - ここで問題はdoubleの位置を、四捨五入して整数値にしていること - 移動してから四捨五入ではないの??? - dnRectの元位置が整数位置なので、問題ないか... - */ - - dn_ras = upComputesWholeTile ? tile.getRaster() - : tile.getRaster()->extract(dnRect); - up_ras = upTile.getRaster(); - assert(dn_ras->getSize() == up_ras->getSize()); -} -void ino_blend_vivid_light::dryComputeUpAndDown(TRectD &rect, double frame, - const TRenderSettings &rs, - bool upComputesWholeTile) { - const bool up_is = (this->m_up.isConnected() && - this->m_up.getFx()->getTimeRegion().contains(frame)); - const bool down_is = (this->m_down.isConnected() && - this->m_down.getFx()->getTimeRegion().contains(frame)); - /* ------ 両方とも切断の時処理しない ---------------------- */ - if (!up_is && !down_is) { - return; - } - /* ------ up接続かつdown切断の時 -------------------------- */ - if (up_is && !down_is) { - this->m_up->dryCompute(rect, frame, rs); - return; - } - /* ------ down接続時 -------------------------------------- */ - if (down_is) { - this->m_down->dryCompute(rect, frame, rs); - } - /* ------ up切断時 ---------------------------------------- */ - if (!up_is) { - return; - } - - /* ------ tileのgeometryを計算する ------------------------ */ - TRectD upBBox; - - if (upComputesWholeTile) { - upBBox = rect; - } else { - this->m_up->getBBox(frame, upBBox, rs); - upBBox *= rect; - makeRectCoherent(upBBox, rect.getP00()); - } - if ((upBBox.getLx() > 0.5) && (upBBox.getLy() > 0.5)) { - this->m_up->dryCompute(upBBox, frame, rs); - } -} -//------------------------------------------------------------ -#include /* std::ostringstream */ -#include "igs_color_blend.h" -namespace { -template -void tmpl_(TRasterPT dn_ras_out, const TRasterPT &up_ras, - const double up_opacity, const bool clipping_mask_sw) { - double maxi = static_cast(T::maxChannelValue); // 255or65535 - - assert(dn_ras_out->getSize() == up_ras->getSize()); - - for (int yy = 0; yy < dn_ras_out->getLy(); ++yy) { - T *out_pix = dn_ras_out->pixels(yy); - const T *const out_end = out_pix + dn_ras_out->getLx(); - const T *up_pix = up_ras->pixels(yy); - for (; out_pix < out_end; ++out_pix, ++up_pix) { - double upr = static_cast(up_pix->r) / maxi; - double upg = static_cast(up_pix->g) / maxi; - double upb = static_cast(up_pix->b) / maxi; - double upa = static_cast(up_pix->m) / maxi; - double dnr = static_cast(out_pix->r) / maxi; - double dng = static_cast(out_pix->g) / maxi; - double dnb = static_cast(out_pix->b) / maxi; - double dna = static_cast(out_pix->m) / maxi; - igs::color::vivid_light(dnr, dng, dnb, dna, upr, upg, upb, upa, - clipping_mask_sw ? up_opacity * dna : up_opacity); - out_pix->r = static_cast(dnr * (maxi + 0.999999)); - out_pix->g = static_cast(dng * (maxi + 0.999999)); - out_pix->b = static_cast(dnb * (maxi + 0.999999)); - out_pix->m = static_cast(dna * (maxi + 0.999999)); - } - } -} -void fx_(TRasterP &dn_ras_out, const TRasterP &up_ras, const TPoint &pos, - const double up_opacity, const bool clipping_mask_sw) { - /* 交差したエリアを処理するようにする、いるのか??? */ - TRect outRect(dn_ras_out->getBounds()); - TRect upRect(up_ras->getBounds() + pos); - TRect intersection = outRect * upRect; - if (intersection.isEmpty()) return; - - TRasterP cRout = dn_ras_out->extract(intersection); - TRect rr = intersection - pos; - TRasterP cRup = up_ras->extract(rr); - - TRaster32P rout32 = cRout, rup32 = cRup; - TRaster64P rout64 = cRout, rup64 = cRup; - - if (rout32 && rup32) { - tmpl_(rout32, rup32, up_opacity, clipping_mask_sw); - } else if (rout64 && rup64) { - tmpl_(rout64, rup64, up_opacity, clipping_mask_sw); - } else { - throw TRopException("unsupported pixel type"); - } -} -} -void ino_blend_vivid_light::doCompute(TTile &tile, double frame, - const TRenderSettings &rs) { - /* ------ 画像生成 ---------------------------------------- */ - TRasterP dn_ras, up_ras; - this->computeUpAndDown(tile, frame, rs, dn_ras, up_ras); - if (!dn_ras || !up_ras) { - return; - } - /* ------ 動作パラメータを得る ---------------------------- */ - const double up_opacity = - this->m_opacity->getValue(frame) / ino::param_range(); - /* ------ (app_begin)log記憶 ------------------------------ */ - const bool log_sw = ino::log_enable_sw(); - - if (log_sw) { - std::ostringstream os; - os << "params" - << " up_opacity " << up_opacity << " dn_tile w " << dn_ras->getLx() - << " wrap " << dn_ras->getWrap() << " h " << dn_ras->getLy() - << " pixbits " << ino::pixel_bits(dn_ras) << " up_tile w " - << up_ras->getLx() << " wrap " << up_ras->getWrap() << " h " - << up_ras->getLy() << " pixbits " << ino::pixel_bits(up_ras) - << " frame " << frame; - } - /* ------ fx処理 ------------------------------------------ */ - try { - if (dn_ras) { - dn_ras->lock(); - } - if (up_ras) { - up_ras->lock(); - } - fx_(dn_ras, up_ras, TPoint(), up_opacity, - this->m_clipping_mask->getValue()); - if (up_ras) { - up_ras->unlock(); - } - if (dn_ras) { - dn_ras->unlock(); - } - } - /* ------ error処理 --------------------------------------- */ - catch (std::exception &e) { - if (up_ras) { - up_ras->unlock(); - } - if (dn_ras) { - dn_ras->unlock(); - } - if (log_sw) { - std::string str("exception <"); - str += e.what(); - str += '>'; - } - throw; - } catch (...) { - if (up_ras) { - up_ras->unlock(); - } - if (dn_ras) { - dn_ras->unlock(); - } - if (log_sw) { - std::string str("other exception"); - } - throw; - } -} diff --git a/toonz/sources/stdfx/ino_common.cpp b/toonz/sources/stdfx/ino_common.cpp index 9314aa87..6d739701 100644 --- a/toonz/sources/stdfx/ino_common.cpp +++ b/toonz/sources/stdfx/ino_common.cpp @@ -2,6 +2,9 @@ #include "tsystem.h" #include "ino_common.h" +#include "tfxparam.h" + +#include /* std::ostringstream */ /* copy and paste from igs_ifx_common.h */ @@ -10,18 +13,18 @@ namespace image { namespace rgba { enum num { blu = 0, gre, red, alp, siz }; } -} -} +} // namespace image +} // namespace igs //------------------------------------------------------------ namespace { // T is TPixel32 or TPixel64 // U is unsigned char or unsigned short template -void ras_to_arr_(const TRasterPT ras, U *arr, const int channels) { +void ras_to_arr_(const TRasterPT ras, U* arr, const int channels) { using namespace igs::image::rgba; for (int yy = 0; yy < ras->getLy(); ++yy) { - const T *ras_sl = ras->pixels(yy); + const T* ras_sl = ras->pixels(yy); for (int xx = 0; xx < ras->getLx(); ++xx, arr += channels) { if (red < channels) { arr[red] = ras_sl[xx].r; @@ -39,9 +42,9 @@ void ras_to_arr_(const TRasterPT ras, U *arr, const int channels) { } } template -void arr_to_ras_(const U *arr, const int channels, TRasterPT ras, +void arr_to_ras_(const U* arr, const int channels, TRasterPT ras, const int margin // default is 0 - ) { +) { arr += (ras->getLx() + margin + margin) * margin * channels + margin * channels; @@ -49,8 +52,8 @@ void arr_to_ras_(const U *arr, const int channels, TRasterPT ras, for (int yy = 0; yy < ras->getLy(); ++yy, arr += (ras->getLx() + margin + margin) * channels) { - const U *arrx = arr; - T *ras_sl = ras->pixels(yy); + const U* arrx = arr; + T* ras_sl = ras->pixels(yy); for (int xx = 0; xx < ras->getLx(); ++xx, arrx += channels) { if (red < channels) { ras_sl[xx].r = arrx[red]; @@ -67,38 +70,38 @@ void arr_to_ras_(const U *arr, const int channels, TRasterPT ras, } } } -} +} // namespace //-------------------- void ino::ras_to_arr(const TRasterP in_ras, const int channels, - unsigned char *out_arr) { + unsigned char* out_arr) { if ((TRaster32P)in_ras) { ras_to_arr_(in_ras, out_arr, channels); } else if ((TRaster64P)in_ras) { ras_to_arr_( - in_ras, reinterpret_cast(out_arr), channels); + in_ras, reinterpret_cast(out_arr), channels); } } -void ino::arr_to_ras(const unsigned char *in_arr, const int channels, +void ino::arr_to_ras(const unsigned char* in_arr, const int channels, TRasterP out_ras, const int margin) { if ((TRaster32P)out_ras) { arr_to_ras_(in_arr, channels, out_ras, margin); } else if ((TRaster64P)out_ras) { arr_to_ras_( - reinterpret_cast(in_arr), channels, out_ras, + reinterpret_cast(in_arr), channels, out_ras, margin); } } //-------------------- void ino::ras_to_vec(const TRasterP in_ras, const int channels, - std::vector &out_vec) { + std::vector& out_vec) { out_vec.resize( in_ras->getLy() * in_ras->getLx() * channels * (((TRaster64P)in_ras) ? sizeof(unsigned short) : sizeof(unsigned char))); ino::ras_to_arr(in_ras, channels, &out_vec.at(0)); } -void ino::vec_to_ras(std::vector &in_vec, const int channels, +void ino::vec_to_ras(std::vector& in_vec, const int channels, TRasterP out_ras, const int margin // default is 0 - ) { +) { ino::arr_to_ras(&in_vec.at(0), channels, out_ras, margin); in_vec.clear(); } @@ -131,7 +134,7 @@ void ino::Lx_to_wrap( TRasterP ras ) { namespace { bool enable_sw_ = true; bool check_sw_ = true; -} +} // namespace bool ino::log_enable_sw(void) { if (check_sw_) { TFileStatus file( @@ -145,3 +148,460 @@ bool ino::log_enable_sw(void) { } return enable_sw_; } + +//------------------------------------------------------------ +namespace { +/* より大きな四角エリアにPixel整数値で密着する */ +void makeRectCoherent(TRectD& rect, const TPointD& pos) { + rect -= pos; + rect.x0 = tfloor(rect.x0); /* ((x)<(int)(x)? (int)(x)-1: (int)(x))*/ + rect.y0 = tfloor(rect.y0); + rect.x1 = tceil(rect.x1); /* ((int)(x)<(x)? (int)(x)+1: (int)(x))*/ + rect.y1 = tceil(rect.y1); + rect += pos; +} + +inline void to_xyz(double* xyz, double const* bgr) { + xyz[0] = 0.6069 * bgr[2] + 0.1735 * bgr[1] + 0.2003 * bgr[0]; // X + xyz[1] = 0.2989 * bgr[2] + 0.5866 * bgr[1] + 0.1145 * bgr[0]; // Y + xyz[2] = 0.0000 * bgr[2] + 0.0661 * bgr[1] + 1.1162 * bgr[0]; // Z +} + +inline void to_bgr(double* bgr, double const* xyz) { + bgr[0] = +0.0585 * xyz[0] - 0.1187 * xyz[1] + 0.9017 * xyz[2]; // blue + bgr[1] = -0.9844 * xyz[0] + 1.9985 * xyz[1] - 0.0279 * xyz[2]; // green + bgr[2] = +1.9104 * xyz[0] - 0.5338 * xyz[1] - 0.2891 * xyz[2]; // red +} + +// convert sRGB color space to power space +template +inline T to_linear_color_space(T nonlinear_color, T exposure, T gamma) { + // return -std::log(T(1) - std::pow(nonlinear_color, gamma)) / exposure; + return std::pow(nonlinear_color, gamma) / exposure; +} +// convert power space to sRGB color space +template +inline T to_nonlinear_color_space(T linear_color, T exposure, T gamma) { + // return std::pow(T(1) - std::exp(-exposure * linear_color), T(1) / gamma); + return std::pow(linear_color * exposure, T(1) / gamma); +} + +template +const T& clamp(const T& v, const T& lo, const T& hi) { + assert(!(hi < lo)); + return (v < lo) ? lo : (hi < v) ? hi : v; +} +} // namespace +//------------------------------------------------------------ + +TBlendForeBackRasterFx::TBlendForeBackRasterFx(bool clipping_mask, + bool has_alpha_option) + : m_opacity(1.0 * ino::param_range()) + , m_clipping_mask(clipping_mask) + , m_linear(false) + , m_gamma(2.2) + , m_premultiplied(true) { + addInputPort("Fore", this->m_up); + addInputPort("Back", this->m_down); + bindParam(this, "opacity", this->m_opacity); + bindParam(this, "clipping_mask", this->m_clipping_mask); + bindParam(this, "linear", this->m_linear); + bindParam(this, "gamma", this->m_gamma); + bindParam(this, "premultiplied", this->m_premultiplied); + this->m_opacity->setValueRange(0, 1.0 * ino::param_range()); + this->m_gamma->setValueRange(0.2, 5.0); + + if (has_alpha_option) { + m_alpha_rendering = TBoolParamP(true); + bindParam(this, "alpha_rendering", this->m_alpha_rendering); + } +} +//------------------------------------------------------------ + +bool TBlendForeBackRasterFx::doGetBBox(double frame, TRectD& bBox, + const TRenderSettings& rs) { + TRectD up_bx; + const bool up_sw = + (m_up.isConnected() ? m_up->doGetBBox(frame, up_bx, rs) : false); + TRectD dn_bx; + const bool dn_sw = + (m_down.isConnected() ? m_down->doGetBBox(frame, dn_bx, rs) : false); + if (up_sw && dn_sw) { + bBox = up_bx + dn_bx; + return !bBox.isEmpty(); + } else if (up_sw) { + bBox = up_bx; + return true; + } else if (dn_sw) { + bBox = dn_bx; + return true; + } else { + bBox = TRectD(); + return false; + } +} +//------------------------------------------------------------ + +void TBlendForeBackRasterFx::dryComputeUpAndDown(TRectD& rect, double frame, + const TRenderSettings& rs, + bool upComputesWholeTile) { + const bool up_is = (this->m_up.isConnected() && + this->m_up.getFx()->getTimeRegion().contains(frame)); + const bool down_is = (this->m_down.isConnected() && + this->m_down.getFx()->getTimeRegion().contains(frame)); + /* ------ 両方とも切断の時処理しない ---------------------- */ + if (!up_is && !down_is) { + return; + } + /* ------ up接続かつdown切断の時 -------------------------- */ + if (up_is && !down_is) { + this->m_up->dryCompute(rect, frame, rs); + return; + } + /* ------ down接続時 -------------------------------------- */ + if (down_is) { + this->m_down->dryCompute(rect, frame, rs); + } + /* ------ up切断時 ---------------------------------------- */ + if (!up_is) { + return; + } + + /* ------ tileのgeometryを計算する ------------------------ */ + TRectD upBBox; + + if (upComputesWholeTile) { + upBBox = rect; + } else { + this->m_up->getBBox(frame, upBBox, rs); + upBBox *= rect; + makeRectCoherent(upBBox, rect.getP00()); + } + if ((upBBox.getLx() > 0.5) && (upBBox.getLy() > 0.5)) { + this->m_up->dryCompute(upBBox, frame, rs); + } +} + +//------------------------------------------------------------ +void TBlendForeBackRasterFx::doCompute(TTile& tile, double frame, + const TRenderSettings& rs) { + /* ------ 画像生成 ---------------------------------------- */ + TRasterP dn_ras, up_ras; + this->computeUpAndDown(tile, frame, rs, dn_ras, up_ras); + if (!dn_ras || !up_ras) { + return; + } + /* ------ 動作パラメータを得る ---------------------------- */ + const double up_opacity = + this->m_opacity->getValue(frame) / ino::param_range(); + const double gamma = this->m_gamma->getValue(frame); + /* ------ (app_begin)log記憶 ------------------------------ */ + const bool log_sw = ino::log_enable_sw(); + + if (log_sw) { + std::ostringstream os; + os << "params" + << " up_opacity " << up_opacity << " dn_tile w " << dn_ras->getLx() + << " wrap " << dn_ras->getWrap() << " h " << dn_ras->getLy() + << " pixbits " << ino::pixel_bits(dn_ras) << " up_tile w " + << up_ras->getLx() << " wrap " << up_ras->getWrap() << " h " + << up_ras->getLy() << " pixbits " << ino::pixel_bits(up_ras) + << " frame " << frame; + } + /* ------ fx処理 ------------------------------------------ */ + try { + if (dn_ras) { + dn_ras->lock(); + } + if (up_ras) { + up_ras->lock(); + } + doComputeFx(dn_ras, up_ras, TPoint(), up_opacity, gamma); + // fx_(dn_ras, up_ras, TPoint(), up_opacity, + // this->m_clipping_mask->getValue(), + // this->m_linear->getValue(), gamma, this->m_premultiplied->getValue()); + if (up_ras) { + up_ras->unlock(); + } + if (dn_ras) { + dn_ras->unlock(); + } + } + /* ------ error処理 --------------------------------------- */ + catch (std::exception& e) { + if (up_ras) { + up_ras->unlock(); + } + if (dn_ras) { + dn_ras->unlock(); + } + if (log_sw) { + std::string str("exception <"); + str += e.what(); + str += '>'; + } + throw; + } catch (...) { + if (up_ras) { + up_ras->unlock(); + } + if (dn_ras) { + dn_ras->unlock(); + } + if (log_sw) { + std::string str("other exception"); + } + throw; + } +} + +//------------------------------------------------------------ +void TBlendForeBackRasterFx::doComputeFx(TRasterP& dn_ras_out, + const TRasterP& up_ras, + const TPoint& pos, + const double up_opacity, + const double gamma) { + /* 交差したエリアを処理するようにする、いるのか??? */ + TRect outRect(dn_ras_out->getBounds()); + TRect upRect(up_ras->getBounds() + pos); + TRect intersection = outRect * upRect; + if (intersection.isEmpty()) return; + + TRasterP cRout = dn_ras_out->extract(intersection); + TRect rr = intersection - pos; + TRasterP cRup = up_ras->extract(rr); + + TRaster32P rout32 = cRout, rup32 = cRup; + TRaster64P rout64 = cRout, rup64 = cRup; + + bool linear_sw = this->m_linear->getValue(); + + if (rout32 && rup32) { + if (linear_sw) + linearTmpl(rout32, rup32, up_opacity, gamma); + // linearAdd(rout32, rup32, up_opacity, clipping_mask_sw, + // gamma, premultiplied_sw); + else + nonlinearTmpl(rout32, rup32, up_opacity); + // tmpl_(rout32, rup32, up_opacity, clipping_mask_sw); + } else if (rout64 && rup64) { + if (linear_sw) + linearTmpl(rout64, rup64, up_opacity, gamma); + else + nonlinearTmpl(rout64, rup64, up_opacity); + } else { + throw TRopException("unsupported pixel type"); + } +} + +//------------------------------------------------------------ +template +void TBlendForeBackRasterFx::nonlinearTmpl(TRasterPT dn_ras_out, + const TRasterPT& up_ras, + const double up_opacity) { + bool clipping_mask_sw = this->m_clipping_mask->getValue(); + bool alpha_rendering_sw = (m_alpha_rendering.getPointer()) + ? this->m_alpha_rendering->getValue() + : true; + + double maxi = static_cast(T::maxChannelValue); // 255or65535 + + assert(dn_ras_out->getSize() == up_ras->getSize()); + + for (int yy = 0; yy < dn_ras_out->getLy(); ++yy) { + T* out_pix = dn_ras_out->pixels(yy); + const T* const out_end = out_pix + dn_ras_out->getLx(); + const T* up_pix = up_ras->pixels(yy); + for (; out_pix < out_end; ++out_pix, ++up_pix) { + double upr = static_cast(up_pix->r) / maxi; + double upg = static_cast(up_pix->g) / maxi; + double upb = static_cast(up_pix->b) / maxi; + double upa = static_cast(up_pix->m) / maxi; + double dnr = static_cast(out_pix->r) / maxi; + double dng = static_cast(out_pix->g) / maxi; + double dnb = static_cast(out_pix->b) / maxi; + double dna = static_cast(out_pix->m) / maxi; + brendKernel(dnr, dng, dnb, dna, upr, upg, upb, upa, + clipping_mask_sw ? up_opacity * dna : up_opacity, + alpha_rendering_sw); + out_pix->r = static_cast(dnr * (maxi + 0.999999)); + out_pix->g = static_cast(dng * (maxi + 0.999999)); + out_pix->b = static_cast(dnb * (maxi + 0.999999)); + out_pix->m = static_cast(dna * (maxi + 0.999999)); + } + } +} + +//------------------------------------------------------------ +template +void TBlendForeBackRasterFx::linearTmpl(TRasterPT dn_ras_out, + const TRasterPT& up_ras, + const double up_opacity, + const double gamma) { + bool clipping_mask_sw = this->m_clipping_mask->getValue(); + bool alpha_rendering_sw = (m_alpha_rendering.getPointer()) + ? this->m_alpha_rendering->getValue() + : true; + bool premultiplied_sw = this->m_premultiplied->getValue(); + double maxi = static_cast(T::maxChannelValue); // 255or65535 + double limit = (maxi + 0.5) / (maxi + 1.0); + + assert(dn_ras_out->getSize() == up_ras->getSize()); + + for (int yy = 0; yy < dn_ras_out->getLy(); ++yy) { + T* out_pix = dn_ras_out->pixels(yy); + const T* const out_end = out_pix + dn_ras_out->getLx(); + const T* up_pix = up_ras->pixels(yy); + for (; out_pix < out_end; ++out_pix, ++up_pix) { + if (up_pix->m <= 0 || up_opacity <= 0) { + continue; + } + + double dna = static_cast(out_pix->m) / maxi; + double tmp_opacity = clipping_mask_sw ? up_opacity * dna : up_opacity; + if (tmp_opacity <= 0) continue; + + double dnBGR[3]; + dnBGR[0] = static_cast(out_pix->b) / maxi; + dnBGR[1] = static_cast(out_pix->g) / maxi; + dnBGR[2] = static_cast(out_pix->r) / maxi; + double dnXYZ[3] = {0.0, 0.0, 0.0}; + if (dna > 0.0) { + for (int c = 0; c < 3; c++) { + if (premultiplied_sw) + dnBGR[c] = to_linear_color_space(dnBGR[c] / dna, 1.0, gamma) * dna; + else + dnBGR[c] = to_linear_color_space(dnBGR[c], 1.0, gamma); + } + to_xyz(dnXYZ, dnBGR); + } + + double upBGR[3]; + upBGR[0] = static_cast(up_pix->b) / maxi; + upBGR[1] = static_cast(up_pix->g) / maxi; + upBGR[2] = static_cast(up_pix->r) / maxi; + double upa = static_cast(up_pix->m) / maxi; + for (int c = 0; c < 3; c++) { + if (premultiplied_sw) + upBGR[c] = to_linear_color_space(upBGR[c] / upa, 1.0, gamma) * upa; + else + upBGR[c] = to_linear_color_space(upBGR[c], 1.0, gamma); + } + + double upXYZ[3]; + to_xyz(upXYZ, upBGR); + + brendKernel(dnXYZ[0], dnXYZ[1], dnXYZ[2], dna, upXYZ[0], upXYZ[1], + upXYZ[2], upa, tmp_opacity, alpha_rendering_sw); + + to_bgr(dnBGR, dnXYZ); + + // premultiply the result + double nonlinear_b = + to_nonlinear_color_space(dnBGR[0] / dna, 1.0, gamma) * dna; + double nonlinear_g = + to_nonlinear_color_space(dnBGR[1] / dna, 1.0, gamma) * dna; + double nonlinear_r = + to_nonlinear_color_space(dnBGR[2] / dna, 1.0, gamma) * dna; + + out_pix->r = + static_cast(clamp(nonlinear_r, 0.0, 1.0) * (maxi + 0.999999)); + out_pix->g = + static_cast(clamp(nonlinear_g, 0.0, 1.0) * (maxi + 0.999999)); + out_pix->b = + static_cast(clamp(nonlinear_b, 0.0, 1.0) * (maxi + 0.999999)); + out_pix->m = static_cast(dna * (maxi + 0.999999)); + } + } +} + +//------------------------------------------------------------ + +void TBlendForeBackRasterFx::computeUpAndDown(TTile& tile, double frame, + const TRenderSettings& rs, + TRasterP& dn_ras, + TRasterP& up_ras, + bool upComputesWholeTile) { + /* ------ サポートしていないPixelタイプはエラーを投げる --- */ + if (!((TRaster32P)tile.getRaster()) && !((TRaster64P)tile.getRaster())) { + throw TRopException("unsupported input pixel type"); + } + /* +m_down,m_upは繋がっている方があればそれを表示する +両方とも接続していれば合成処理する +表示スイッチを切ってあるならm_upを表示する +fxをreplaceすると、 + m_source --> m_up (=port0) + m_refernce --> m_down(=port1) +となる +*/ + const bool up_is = (this->m_up.isConnected() && + this->m_up.getFx()->getTimeRegion().contains(frame)); + const bool down_is = (this->m_down.isConnected() && + this->m_down.getFx()->getTimeRegion().contains(frame)); + /* ------ 両方とも切断の時処理しない ---------------------- */ + if (!up_is && !down_is) { + tile.getRaster()->clear(); + return; + } + /* ------ up接続かつdown切断の時 -------------------------- */ + if (up_is && !down_is) { + this->m_up->compute(tile, frame, rs); + return; + } + /* ------ down接続時 downのみ描画して... ------------------ */ + if (down_is) { + this->m_down->compute(tile, frame, rs); + } + /* ------ up切断時 ---------------------------------------- */ + if (!up_is) { + return; + } + + /* upと重なる部分を描画する */ + + /* ------ tileの範囲 -------------------------------------- */ + const TDimension tsz(tile.getRaster()->getSize()); /* 整数 */ + const TRectD tileRect(tile.m_pos, TDimensionD(tsz.lx, tsz.ly)); + TRectD upBBox; + if (upComputesWholeTile) { + upBBox = tileRect; + } /* tile全体を得る */ + else { /* 厳密なエリア... */ + this->m_up->getBBox(frame, upBBox, rs); + upBBox *= tileRect; /* upとtileの交差エリア */ + + /* より大きな四角エリアにPixel整数値で密着する */ + makeRectCoherent(upBBox, tile.m_pos); // double-->int grid + } + + TDimensionI upSize( /* TRectDをTDimensionIに変換 */ + tround(upBBox.getLx()) // getLx() = "x1>=x0?x1-x0:0" + , + tround(upBBox.getLy()) // getLy() = "y1>=y0?y1-y0:0" + ); + if ((upSize.lx <= 0) || (upSize.ly <= 0)) { + return; + } + + /* ------ upのメモリ確保と描画 ---------------------------- */ + TTile upTile; + this->m_up->allocateAndCompute(upTile, upBBox.getP00(), upSize, + tile.getRaster() /* 32/64bitsの判定に使う */ + , + frame, rs); + /* ------ upとdownのTRasterを得る ------------------------- */ + TRectI dnRect(upTile.getRaster()->getSize()); // TDimensionI(-) + + dnRect += convert(upTile.m_pos - tile.m_pos); /* uptile->tile原点 */ + /* + ここで問題はdoubleの位置を、四捨五入して整数値にしていること + 移動してから四捨五入ではないの??? + dnRectの元位置が整数位置なので、問題ないか... + */ + + dn_ras = upComputesWholeTile ? tile.getRaster() + : tile.getRaster()->extract(dnRect); + up_ras = upTile.getRaster(); + assert(dn_ras->getSize() == up_ras->getSize()); +} \ No newline at end of file diff --git a/toonz/sources/stdfx/ino_common.h b/toonz/sources/stdfx/ino_common.h index a7a0eab9..e4efb101 100644 --- a/toonz/sources/stdfx/ino_common.h +++ b/toonz/sources/stdfx/ino_common.h @@ -10,12 +10,12 @@ namespace ino { /* 一時バッファとの変換機能 */ void ras_to_arr(const TRasterP in_ras, const int channels, - unsigned char *out_arr); -void arr_to_ras(const unsigned char *in_arr, const int channels, + unsigned char* out_arr); +void arr_to_ras(const unsigned char* in_arr, const int channels, TRasterP out_ras, const int margin); void ras_to_vec(const TRasterP ras, const int channels, - std::vector &vec); -void vec_to_ras(std::vector &vec, const int channels, + std::vector& vec); +void vec_to_ras(std::vector& vec, const int channels, TRasterP ras, const int margin = 0); // void Lx_to_wrap( TRasterP ras ); @@ -37,10 +37,69 @@ inline int pixel_bits(const TRasterP ras) { // inline double pixel_per_mm(void) { return 640. / 12. / 25.4; } inline double pixel_per_mm(void) { return 1.; } // inline double pixel_per_inch(void) { return 640. / 12.; } -} +} // namespace ino class TBlendForeBackRasterFx : public TRasterFx { +protected: + TRasterFxPort m_up; + TRasterFxPort m_down; + TDoubleParamP m_opacity; + TBoolParamP m_clipping_mask; + + TBoolParamP m_linear; + TDoubleParamP m_gamma; + + // If the pixel is premultiplied, divide color data by the alpha before + // converting from the colorspace, and then multiply by the alpha afterwards. + // This will correct the color of the semi-transparent pixels in most cases. + TBoolParamP m_premultiplied; + + TBoolParamP m_alpha_rendering; // optional + + void dryComputeUpAndDown(TRectD& rect, double frame, + const TRenderSettings& rs, + bool upComputesWholeTile = false); + + void doComputeFx(TRasterP& dn_ras_out, const TRasterP& up_ras, + const TPoint& pos, const double up_opacity, + const double gamma); + + template + void nonlinearTmpl(TRasterPT dn_ras_out, const TRasterPT& up_ras, + const double up_opacity); + + template + void linearTmpl(TRasterPT dn_ras_out, const TRasterPT& up_ras, + const double up_opacity, const double gamma); + + virtual void brendKernel(double& dnr, double& dng, double& dnb, double& dna, + const double up_, double upg, double upb, double upa, + const double upopacity, + const bool alpha_rendering_sw = true) = 0; + + void computeUpAndDown(TTile& tile, double frame, const TRenderSettings& rs, + TRasterP& dn_ras, TRasterP& up_ras, + bool upComputesWholeTile = false); + public: + TBlendForeBackRasterFx(bool clipping_mask, bool has_alpha_option = false); + + bool canHandle(const TRenderSettings& rs, double frame) override { + return true; + } + bool doGetBBox(double frame, TRectD& bBox, + const TRenderSettings& rs) override; + int getMemoryRequirement(const TRectD& rect, double frame, + const TRenderSettings& rs) override { + return TRasterFx::memorySize(rect, rs.m_bpp); + } + void doDryCompute(TRectD& rect, double frame, + const TRenderSettings& rs) override { + this->dryComputeUpAndDown(rect, frame, rs, false); + } + + void doCompute(TTile& tile, double frame, const TRenderSettings& rs) override; + /* FX nodeが無効のときの、表示port番号 */ int getPreferredInputPort() override { return 1; }