linear option for all layer blending ino fxs
This commit is contained in:
parent
3b3c1b2fa1
commit
cbfde43fb8
46 changed files with 894 additions and 7242 deletions
|
@ -846,67 +846,130 @@
|
|||
<item>"STD_inoColorBurnFx" "Color Burn Ino" </item>
|
||||
<item>"STD_inoColorBurnFx.opacity" "Opacity" </item>
|
||||
<item>"STD_inoColorBurnFx.clipping_mask" "Clipping Mask" </item>
|
||||
<item>"STD_inoColorBurnFx.linear" "Linear Color Space" </item>
|
||||
<item>"STD_inoColorBurnFx.gamma" "Gamma" </item>
|
||||
<item>"STD_inoColorBurnFx.premultiplied" "Source is Premultiplied" </item>
|
||||
<item>"STD_inoColorDodgeFx" "Color Dodge Ino" </item>
|
||||
<item>"STD_inoColorDodgeFx.opacity" "Opacity" </item>
|
||||
<item>"STD_inoColorDodgeFx.clipping_mask" "Clipping Mask" </item>
|
||||
<item>"STD_inoColorDodgeFx.linear" "Linear Color Space" </item>
|
||||
<item>"STD_inoColorDodgeFx.gamma" "Gamma" </item>
|
||||
<item>"STD_inoColorDodgeFx.premultiplied" "Source is Premultiplied" </item>
|
||||
<item>"STD_inoCrossDissolveFx" "Cross Dissolve Ino" </item>
|
||||
<item>"STD_inoCrossDissolveFx.opacity" "Opacity" </item>
|
||||
<item>"STD_inoCrossDissolveFx.clipping_mask" "Clipping Mask" </item>
|
||||
<item>"STD_inoCrossDissolveFx.linear" "Linear Color Space" </item>
|
||||
<item>"STD_inoCrossDissolveFx.gamma" "Gamma" </item>
|
||||
<item>"STD_inoCrossDissolveFx.premultiplied" "Source is Premultiplied" </item>
|
||||
<item>"STD_inoDarkenFx" "Darken Ino" </item>
|
||||
<item>"STD_inoDarkenFx.opacity" "Opacity" </item>
|
||||
<item>"STD_inoDarkenFx.clipping_mask" "Clipping Mask" </item>
|
||||
<item>"STD_inoDarkenFx.linear" "Linear Color Space" </item>
|
||||
<item>"STD_inoDarkenFx.gamma" "Gamma" </item>
|
||||
<item>"STD_inoDarkenFx.premultiplied" "Source is Premultiplied" </item>
|
||||
<item>"STD_inoDarkerColorFx" "Darker Color Ino" </item>
|
||||
<item>"STD_inoDarkerColorFx.opacity" "Opacity" </item>
|
||||
<item>"STD_inoDarkerColorFx.clipping_mask" "Clipping Mask" </item>
|
||||
<item>"STD_inoDarkerColorFx.linear" "Linear Color Space" </item>
|
||||
<item>"STD_inoDarkerColorFx.gamma" "Gamma" </item>
|
||||
<item>"STD_inoDarkerColorFx.premultiplied" "Source is Premultiplied" </item>
|
||||
<item>"STD_inoDivideFx" "Divide Ino" </item>
|
||||
<item>"STD_inoDivideFx.opacity" "Opacity" </item>
|
||||
<item>"STD_inoDivideFx.clipping_mask" "Clipping Mask" </item>
|
||||
<item>"STD_inoDivideFx.linear" "Linear Color Space" </item>
|
||||
<item>"STD_inoDivideFx.gamma" "Gamma" </item>
|
||||
<item>"STD_inoDivideFx.premultiplied" "Source is Premultiplied" </item>
|
||||
<item>"STD_inoHardLightFx" "Hard Light Ino" </item>
|
||||
<item>"STD_inoHardLightFx.opacity" "Opacity" </item>
|
||||
<item>"STD_inoHardLightFx.clipping_mask" "Clipping Mask" </item>
|
||||
<item>"STD_inoHardLightFx.linear" "Linear Color Space" </item>
|
||||
<item>"STD_inoHardLightFx.gamma" "Gamma" </item>
|
||||
<item>"STD_inoHardLightFx.premultiplied" "Source is Premultiplied" </item>
|
||||
<item>"STD_inoHardMixFx" "Hard Mix Ino" </item>
|
||||
<item>"STD_inoHardMixFx.opacity" "Opacity" </item>
|
||||
<item>"STD_inoHardMixFx.clipping_mask" "Clipping Mask" </item>
|
||||
<item>"STD_inoHardMixFx.linear" "Linear Color Space" </item>
|
||||
<item>"STD_inoHardMixFx.gamma" "Gamma" </item>
|
||||
<item>"STD_inoHardMixFx.premultiplied" "Source is Premultiplied" </item>
|
||||
<item>"STD_inoLightenFx" "Lighten Ino" </item>
|
||||
<item>"STD_inoLightenFx.opacity" "Opacity" </item>
|
||||
<item>"STD_inoLightenFx.clipping_mask" "Clipping Mask" </item>
|
||||
<item>"STD_inoLightenFx.linear" "Linear Color Space" </item>
|
||||
<item>"STD_inoLightenFx.gamma" "Gamma" </item>
|
||||
<item>"STD_inoLightenFx.premultiplied" "Source is Premultiplied" </item>
|
||||
<item>"STD_inoLighterColorFx" "Lighter Color Ino" </item>
|
||||
<item>"STD_inoLighterColorFx.opacity" "Opacity" </item>
|
||||
<item>"STD_inoLighterColorFx.clipping_mask" "Clipping Mask" </item>
|
||||
<item>"STD_inoLighterColorFx.linear" "Linear Color Space" </item>
|
||||
<item>"STD_inoLighterColorFx.gamma" "Gamma" </item>
|
||||
<item>"STD_inoLighterColorFx.premultiplied" "Source is Premultiplied" </item>
|
||||
<item>"STD_inoLinearBurnFx" "Linear Burn Ino" </item>
|
||||
<item>"STD_inoLinearBurnFx.opacity" "Opacity" </item>
|
||||
<item>"STD_inoLinearBurnFx.clipping_mask" "Clipping Mask" </item>
|
||||
<item>"STD_inoLinearBurnFx.linear" "Linear Color Space" </item>
|
||||
<item>"STD_inoLinearBurnFx.gamma" "Gamma" </item>
|
||||
<item>"STD_inoLinearBurnFx.premultiplied" "Source is Premultiplied" </item>
|
||||
<item>"STD_inoLinearDodgeFx" "Linear Dodge Ino" </item>
|
||||
<item>"STD_inoLinearDodgeFx.opacity" "Opacity" </item>
|
||||
<item>"STD_inoLinearDodgeFx.clipping_mask" "Clipping Mask" </item>
|
||||
<item>"STD_inoLinearDodgeFx.linear" "Linear Color Space" </item>
|
||||
<item>"STD_inoLinearDodgeFx.gamma" "Gamma" </item>
|
||||
<item>"STD_inoLinearDodgeFx.premultiplied" "Source is Premultiplied" </item>
|
||||
<item>"STD_inoLinearLightFx" "Linear Light Ino" </item>
|
||||
<item>"STD_inoLinearLightFx.opacity" "Opacity" </item>
|
||||
<item>"STD_inoLinearLightFx.clipping_mask" "Clipping Mask" </item>
|
||||
<item>"STD_inoLinearLightFx.linear" "Linear Color Space" </item>
|
||||
<item>"STD_inoLinearLightFx.gamma" "Gamma" </item>
|
||||
<item>"STD_inoLinearLightFx.premultiplied" "Source is Premultiplied" </item>
|
||||
<item>"STD_inoMultiplyFx" "Multiply Ino" </item>
|
||||
<item>"STD_inoMultiplyFx.opacity" "Opacity" </item>
|
||||
<item>"STD_inoMultiplyFx.clipping_mask" "Clipping Mask" </item>
|
||||
<item>"STD_inoMultiplyFx.linear" "Linear Color Space" </item>
|
||||
<item>"STD_inoMultiplyFx.gamma" "Gamma" </item>
|
||||
<item>"STD_inoMultiplyFx.premultiplied" "Source is Premultiplied" </item>
|
||||
<item>"STD_inoOverFx" "Over Ino" </item>
|
||||
<item>"STD_inoOverFx.opacity" "Opacity" </item>
|
||||
<item>"STD_inoOverFx.clipping_mask" "Clipping Mask" </item>
|
||||
<item>"STD_inoOverFx.linear" "Linear Color Space" </item>
|
||||
<item>"STD_inoOverFx.gamma" "Gamma" </item>
|
||||
<item>"STD_inoOverFx.premultiplied" "Source is Premultiplied" </item>
|
||||
<item>"STD_inoOverlayFx" "Overlay Ino" </item>
|
||||
<item>"STD_inoOverlayFx.opacity" "Opacity" </item>
|
||||
<item>"STD_inoOverlayFx.clipping_mask" "Clipping Mask" </item>
|
||||
<item>"STD_inoOverlayFx.linear" "Linear Color Space" </item>
|
||||
<item>"STD_inoOverlayFx.gamma" "Gamma" </item>
|
||||
<item>"STD_inoOverlayFx.premultiplied" "Source is Premultiplied" </item>
|
||||
<item>"STD_inoPinLightFx" "Pin Light Ino" </item>
|
||||
<item>"STD_inoPinLightFx.opacity" "Opacity" </item>
|
||||
<item>"STD_inoPinLightFx.clipping_mask" "Clipping Mask" </item>
|
||||
<item>"STD_inoPinLightFx.linear" "Linear Color Space" </item>
|
||||
<item>"STD_inoPinLightFx.gamma" "Gamma" </item>
|
||||
<item>"STD_inoPinLightFx.premultiplied" "Source is Premultiplied" </item>
|
||||
<item>"STD_inoScreenFx" "Screen Ino" </item>
|
||||
<item>"STD_inoScreenFx.opacity" "Opacity" </item>
|
||||
<item>"STD_inoScreenFx.clipping_mask" "Clipping Mask" </item>
|
||||
<item>"STD_inoScreenFx.linear" "Linear Color Space" </item>
|
||||
<item>"STD_inoScreenFx.gamma" "Gamma" </item>
|
||||
<item>"STD_inoScreenFx.premultiplied" "Source is Premultiplied" </item>
|
||||
<item>"STD_inoSoftLightFx" "Soft Light Ino" </item>
|
||||
<item>"STD_inoSoftLightFx.opacity" "Opacity" </item>
|
||||
<item>"STD_inoSoftLightFx.clipping_mask" "Clipping Mask" </item>
|
||||
<item>"STD_inoSoftLightFx.linear" "Linear Color Space" </item>
|
||||
<item>"STD_inoSoftLightFx.gamma" "Gamma" </item>
|
||||
<item>"STD_inoSoftLightFx.premultiplied" "Source is Premultiplied" </item>
|
||||
<item>"STD_inoSubtractFx" "Subtract Ino" </item>
|
||||
<item>"STD_inoSubtractFx.opacity" "Opacity" </item>
|
||||
<item>"STD_inoSubtractFx.clipping_mask" "Clipping Mask" </item>
|
||||
<item>"STD_inoSubtractFx.alpha_rendering" "Alpha Rendering" </item>
|
||||
<item>"STD_inoSubtractFx.linear" "Linear Color Space" </item>
|
||||
<item>"STD_inoSubtractFx.gamma" "Gamma" </item>
|
||||
<item>"STD_inoSubtractFx.premultiplied" "Source is Premultiplied" </item>
|
||||
<item>"STD_inoVividLightFx" "Vivid Light Ino" </item>
|
||||
<item>"STD_inoVividLightFx.opacity" "Opacity" </item>
|
||||
<item>"STD_inoVividLightFx.clipping_mask" "Clipping Mask" </item>
|
||||
<item>"STD_inoVividLightFx.linear" "Linear Color Space" </item>
|
||||
<item>"STD_inoVividLightFx.gamma" "Gamma" </item>
|
||||
<item>"STD_inoVividLightFx.premultiplied" "Source is Premultiplied" </item>
|
||||
<item>"STD_inoBlurFx" "Blur Ino" </item>
|
||||
<item>"STD_inoBlurFx.radius" "Radius" </item>
|
||||
<item>"STD_inoBlurFx.reference" "Reference" </item>
|
||||
|
|
|
@ -2,5 +2,11 @@
|
|||
<page name="Color Burn Ino">
|
||||
<control>opacity</control>
|
||||
<control>clipping_mask</control>
|
||||
<separator/>
|
||||
<control>linear</control>
|
||||
<vbox modeSensitive="linear" mode="1">
|
||||
<control>gamma</control>
|
||||
<control>premultiplied</control>
|
||||
</vbox>
|
||||
</page>
|
||||
</fxlayout>
|
||||
|
|
|
@ -2,5 +2,11 @@
|
|||
<page name="Color Dodge Ino">
|
||||
<control>opacity</control>
|
||||
<control>clipping_mask</control>
|
||||
<separator/>
|
||||
<control>linear</control>
|
||||
<vbox modeSensitive="linear" mode="1">
|
||||
<control>gamma</control>
|
||||
<control>premultiplied</control>
|
||||
</vbox>
|
||||
</page>
|
||||
</fxlayout>
|
||||
|
|
|
@ -2,5 +2,11 @@
|
|||
<page name="Cross Dissolve Ino">
|
||||
<control>opacity</control>
|
||||
<control>clipping_mask</control>
|
||||
<separator/>
|
||||
<control>linear</control>
|
||||
<vbox modeSensitive="linear" mode="1">
|
||||
<control>gamma</control>
|
||||
<control>premultiplied</control>
|
||||
</vbox>
|
||||
</page>
|
||||
</fxlayout>
|
||||
|
|
|
@ -2,5 +2,11 @@
|
|||
<page name="Darken Ino">
|
||||
<control>opacity</control>
|
||||
<control>clipping_mask</control>
|
||||
<separator/>
|
||||
<control>linear</control>
|
||||
<vbox modeSensitive="linear" mode="1">
|
||||
<control>gamma</control>
|
||||
<control>premultiplied</control>
|
||||
</vbox>
|
||||
</page>
|
||||
</fxlayout>
|
||||
|
|
|
@ -2,5 +2,11 @@
|
|||
<page name="Darker Color Ino">
|
||||
<control>opacity</control>
|
||||
<control>clipping_mask</control>
|
||||
<separator/>
|
||||
<control>linear</control>
|
||||
<vbox modeSensitive="linear" mode="1">
|
||||
<control>gamma</control>
|
||||
<control>premultiplied</control>
|
||||
</vbox>
|
||||
</page>
|
||||
</fxlayout>
|
||||
|
|
|
@ -2,5 +2,11 @@
|
|||
<page name="Divide Ino">
|
||||
<control>opacity</control>
|
||||
<control>clipping_mask</control>
|
||||
<separator/>
|
||||
<control>linear</control>
|
||||
<vbox modeSensitive="linear" mode="1">
|
||||
<control>gamma</control>
|
||||
<control>premultiplied</control>
|
||||
</vbox>
|
||||
</page>
|
||||
</fxlayout>
|
||||
|
|
|
@ -2,5 +2,11 @@
|
|||
<page name="Hard Light Ino">
|
||||
<control>opacity</control>
|
||||
<control>clipping_mask</control>
|
||||
<separator/>
|
||||
<control>linear</control>
|
||||
<vbox modeSensitive="linear" mode="1">
|
||||
<control>gamma</control>
|
||||
<control>premultiplied</control>
|
||||
</vbox>
|
||||
</page>
|
||||
</fxlayout>
|
||||
|
|
|
@ -2,5 +2,11 @@
|
|||
<page name="Hard Mix Ino">
|
||||
<control>opacity</control>
|
||||
<control>clipping_mask</control>
|
||||
<separator/>
|
||||
<control>linear</control>
|
||||
<vbox modeSensitive="linear" mode="1">
|
||||
<control>gamma</control>
|
||||
<control>premultiplied</control>
|
||||
</vbox>
|
||||
</page>
|
||||
</fxlayout>
|
||||
|
|
|
@ -2,5 +2,11 @@
|
|||
<page name="Lighten Ino">
|
||||
<control>opacity</control>
|
||||
<control>clipping_mask</control>
|
||||
<separator/>
|
||||
<control>linear</control>
|
||||
<vbox modeSensitive="linear" mode="1">
|
||||
<control>gamma</control>
|
||||
<control>premultiplied</control>
|
||||
</vbox>
|
||||
</page>
|
||||
</fxlayout>
|
||||
|
|
|
@ -2,5 +2,11 @@
|
|||
<page name="Lighter Color Ino">
|
||||
<control>opacity</control>
|
||||
<control>clipping_mask</control>
|
||||
<separator/>
|
||||
<control>linear</control>
|
||||
<vbox modeSensitive="linear" mode="1">
|
||||
<control>gamma</control>
|
||||
<control>premultiplied</control>
|
||||
</vbox>
|
||||
</page>
|
||||
</fxlayout>
|
||||
|
|
|
@ -2,5 +2,11 @@
|
|||
<page name="Linear Burn Ino">
|
||||
<control>opacity</control>
|
||||
<control>clipping_mask</control>
|
||||
<separator/>
|
||||
<control>linear</control>
|
||||
<vbox modeSensitive="linear" mode="1">
|
||||
<control>gamma</control>
|
||||
<control>premultiplied</control>
|
||||
</vbox>
|
||||
</page>
|
||||
</fxlayout>
|
||||
|
|
|
@ -2,5 +2,11 @@
|
|||
<page name="Linear Dodge Ino">
|
||||
<control>opacity</control>
|
||||
<control>clipping_mask</control>
|
||||
<separator/>
|
||||
<control>linear</control>
|
||||
<vbox modeSensitive="linear" mode="1">
|
||||
<control>gamma</control>
|
||||
<control>premultiplied</control>
|
||||
</vbox>
|
||||
</page>
|
||||
</fxlayout>
|
||||
|
|
|
@ -2,5 +2,11 @@
|
|||
<page name="Linear Light Ino">
|
||||
<control>opacity</control>
|
||||
<control>clipping_mask</control>
|
||||
<separator/>
|
||||
<control>linear</control>
|
||||
<vbox modeSensitive="linear" mode="1">
|
||||
<control>gamma</control>
|
||||
<control>premultiplied</control>
|
||||
</vbox>
|
||||
</page>
|
||||
</fxlayout>
|
||||
|
|
|
@ -2,5 +2,11 @@
|
|||
<page name="Multiply Ino">
|
||||
<control>opacity</control>
|
||||
<control>clipping_mask</control>
|
||||
<separator/>
|
||||
<control>linear</control>
|
||||
<vbox modeSensitive="linear" mode="1">
|
||||
<control>gamma</control>
|
||||
<control>premultiplied</control>
|
||||
</vbox>
|
||||
</page>
|
||||
</fxlayout>
|
||||
|
|
|
@ -2,5 +2,11 @@
|
|||
<page name="Over Ino">
|
||||
<control>opacity</control>
|
||||
<control>clipping_mask</control>
|
||||
<separator/>
|
||||
<control>linear</control>
|
||||
<vbox modeSensitive="linear" mode="1">
|
||||
<control>gamma</control>
|
||||
<control>premultiplied</control>
|
||||
</vbox>
|
||||
</page>
|
||||
</fxlayout>
|
||||
|
|
|
@ -2,5 +2,11 @@
|
|||
<page name="Overlay Ino">
|
||||
<control>opacity</control>
|
||||
<control>clipping_mask</control>
|
||||
<separator/>
|
||||
<control>linear</control>
|
||||
<vbox modeSensitive="linear" mode="1">
|
||||
<control>gamma</control>
|
||||
<control>premultiplied</control>
|
||||
</vbox>
|
||||
</page>
|
||||
</fxlayout>
|
||||
|
|
|
@ -2,5 +2,11 @@
|
|||
<page name="Pin Light Ino">
|
||||
<control>opacity</control>
|
||||
<control>clipping_mask</control>
|
||||
<separator/>
|
||||
<control>linear</control>
|
||||
<vbox modeSensitive="linear" mode="1">
|
||||
<control>gamma</control>
|
||||
<control>premultiplied</control>
|
||||
</vbox>
|
||||
</page>
|
||||
</fxlayout>
|
||||
|
|
|
@ -2,5 +2,11 @@
|
|||
<page name="Screen Ino">
|
||||
<control>opacity</control>
|
||||
<control>clipping_mask</control>
|
||||
<separator/>
|
||||
<control>linear</control>
|
||||
<vbox modeSensitive="linear" mode="1">
|
||||
<control>gamma</control>
|
||||
<control>premultiplied</control>
|
||||
</vbox>
|
||||
</page>
|
||||
</fxlayout>
|
||||
|
|
|
@ -2,5 +2,11 @@
|
|||
<page name="Soft Light Ino">
|
||||
<control>opacity</control>
|
||||
<control>clipping_mask</control>
|
||||
<separator/>
|
||||
<control>linear</control>
|
||||
<vbox modeSensitive="linear" mode="1">
|
||||
<control>gamma</control>
|
||||
<control>premultiplied</control>
|
||||
</vbox>
|
||||
</page>
|
||||
</fxlayout>
|
||||
|
|
|
@ -3,5 +3,11 @@
|
|||
<control>opacity</control>
|
||||
<control>clipping_mask</control>
|
||||
<control>alpha_rendering</control>
|
||||
<separator/>
|
||||
<control>linear</control>
|
||||
<vbox modeSensitive="linear" mode="1">
|
||||
<control>gamma</control>
|
||||
<control>premultiplied</control>
|
||||
</vbox>
|
||||
</page>
|
||||
</fxlayout>
|
||||
|
|
|
@ -2,5 +2,11 @@
|
|||
<page name="Vivid Light Ino">
|
||||
<control>opacity</control>
|
||||
<control>clipping_mask</control>
|
||||
<separator/>
|
||||
<control>linear</control>
|
||||
<vbox modeSensitive="linear" mode="1">
|
||||
<control>gamma</control>
|
||||
<control>premultiplied</control>
|
||||
</vbox>
|
||||
</page>
|
||||
</fxlayout>
|
||||
|
|
|
@ -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 <typename T = double>
|
||||
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 <typename T = double>
|
||||
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 <class T = double>
|
||||
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 <sstream> /* std::ostringstream */
|
||||
#include "igs_color_blend.h"
|
||||
namespace {
|
||||
template <class T, class Q>
|
||||
void tmpl_(TRasterPT<T> dn_ras_out, const TRasterPT<T> &up_ras,
|
||||
const double up_opacity, const bool clipping_mask_sw) {
|
||||
double maxi = static_cast<double>(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<double>(up_pix->r) / maxi;
|
||||
double upg = static_cast<double>(up_pix->g) / maxi;
|
||||
double upb = static_cast<double>(up_pix->b) / maxi;
|
||||
double upa = static_cast<double>(up_pix->m) / maxi;
|
||||
double dnr = static_cast<double>(out_pix->r) / maxi;
|
||||
double dng = static_cast<double>(out_pix->g) / maxi;
|
||||
double dnb = static_cast<double>(out_pix->b) / maxi;
|
||||
double dna = static_cast<double>(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<Q>(dnr * (maxi + 0.999999));
|
||||
out_pix->g = static_cast<Q>(dng * (maxi + 0.999999));
|
||||
out_pix->b = static_cast<Q>(dnb * (maxi + 0.999999));
|
||||
out_pix->m = static_cast<Q>(dna * (maxi + 0.999999));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, class Q>
|
||||
void linearAdd(TRasterPT<T> dn_ras_out, const TRasterPT<T> &up_ras,
|
||||
const double up_opacity, const bool clipping_mask_sw,
|
||||
const double gamma, const bool premultiplied_sw) {
|
||||
double maxi = static_cast<double>(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<double>(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<double>(out_pix->b) / maxi;
|
||||
dnBGR[1] = static_cast<double>(out_pix->g) / maxi;
|
||||
dnBGR[2] = static_cast<double>(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<double>(up_pix->b) / maxi;
|
||||
upBGR[1] = static_cast<double>(up_pix->g) / maxi;
|
||||
upBGR[2] = static_cast<double>(up_pix->r) / maxi;
|
||||
double upa = static_cast<double>(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<Q>(clamp(nonlinear_r, 0.0, 1.0) * (maxi + 0.999999));
|
||||
out_pix->g =
|
||||
static_cast<Q>(clamp(nonlinear_g, 0.0, 1.0) * (maxi + 0.999999));
|
||||
out_pix->b =
|
||||
static_cast<Q>(clamp(nonlinear_b, 0.0, 1.0) * (maxi + 0.999999));
|
||||
out_pix->m = static_cast<Q>(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<TPixel32, UCHAR>(rout32, rup32, up_opacity, clipping_mask_sw,
|
||||
gamma, premultiplied_sw);
|
||||
else
|
||||
tmpl_<TPixel32, UCHAR>(rout32, rup32, up_opacity, clipping_mask_sw);
|
||||
} else if (rout64 && rup64) {
|
||||
if (linear_sw)
|
||||
linearAdd<TPixel64, USHORT>(rout64, rup64, up_opacity, clipping_mask_sw,
|
||||
gamma, premultiplied_sw);
|
||||
else
|
||||
tmpl_<TPixel64, USHORT>(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");
|
|
@ -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 <sstream> /* std::ostringstream */
|
||||
#include "igs_color_blend.h"
|
||||
namespace {
|
||||
template <class T, class Q>
|
||||
void tmpl_(TRasterPT<T> dn_ras_out, const TRasterPT<T> &up_ras,
|
||||
const double up_opacity, const bool clipping_mask_sw) {
|
||||
double maxi = static_cast<double>(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<double>(up_pix->r) / maxi;
|
||||
double upg = static_cast<double>(up_pix->g) / maxi;
|
||||
double upb = static_cast<double>(up_pix->b) / maxi;
|
||||
double upa = static_cast<double>(up_pix->m) / maxi;
|
||||
double dnr = static_cast<double>(out_pix->r) / maxi;
|
||||
double dng = static_cast<double>(out_pix->g) / maxi;
|
||||
double dnb = static_cast<double>(out_pix->b) / maxi;
|
||||
double dna = static_cast<double>(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<Q>(dnr * (maxi + 0.999999));
|
||||
out_pix->g = static_cast<Q>(dng * (maxi + 0.999999));
|
||||
out_pix->b = static_cast<Q>(dnb * (maxi + 0.999999));
|
||||
out_pix->m = static_cast<Q>(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_<TPixel32, UCHAR>(rout32, rup32, up_opacity, clipping_mask_sw);
|
||||
} else if (rout64 && rup64) {
|
||||
tmpl_<TPixel64, USHORT>(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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 <sstream> /* std::ostringstream */
|
||||
#include "igs_color_blend.h"
|
||||
namespace {
|
||||
template <class T, class Q>
|
||||
void tmpl_(TRasterPT<T> dn_ras_out, const TRasterPT<T> &up_ras,
|
||||
const double up_opacity, const bool clipping_mask_sw) {
|
||||
double maxi = static_cast<double>(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<double>(up_pix->r) / maxi;
|
||||
double upg = static_cast<double>(up_pix->g) / maxi;
|
||||
double upb = static_cast<double>(up_pix->b) / maxi;
|
||||
double upa = static_cast<double>(up_pix->m) / maxi;
|
||||
double dnr = static_cast<double>(out_pix->r) / maxi;
|
||||
double dng = static_cast<double>(out_pix->g) / maxi;
|
||||
double dnb = static_cast<double>(out_pix->b) / maxi;
|
||||
double dna = static_cast<double>(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<Q>(dnr * (maxi + 0.999999));
|
||||
out_pix->g = static_cast<Q>(dng * (maxi + 0.999999));
|
||||
out_pix->b = static_cast<Q>(dnb * (maxi + 0.999999));
|
||||
out_pix->m = static_cast<Q>(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_<TPixel32, UCHAR>(rout32, rup32, up_opacity, clipping_mask_sw);
|
||||
} else if (rout64 && rup64) {
|
||||
tmpl_<TPixel64, USHORT>(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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 <sstream> /* std::ostringstream */
|
||||
#include "igs_color_blend.h"
|
||||
namespace {
|
||||
template <class T, class Q>
|
||||
void tmpl_(TRasterPT<T> dn_ras_out, const TRasterPT<T> &up_ras,
|
||||
const double up_opacity, const bool clipping_mask_sw) {
|
||||
double maxi = static_cast<double>(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<double>(up_pix->r) / maxi;
|
||||
double upg = static_cast<double>(up_pix->g) / maxi;
|
||||
double upb = static_cast<double>(up_pix->b) / maxi;
|
||||
double upa = static_cast<double>(up_pix->m) / maxi;
|
||||
double dnr = static_cast<double>(out_pix->r) / maxi;
|
||||
double dng = static_cast<double>(out_pix->g) / maxi;
|
||||
double dnb = static_cast<double>(out_pix->b) / maxi;
|
||||
double dna = static_cast<double>(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<Q>(dnr * (maxi + 0.999999));
|
||||
out_pix->g = static_cast<Q>(dng * (maxi + 0.999999));
|
||||
out_pix->b = static_cast<Q>(dnb * (maxi + 0.999999));
|
||||
out_pix->m = static_cast<Q>(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_<TPixel32, UCHAR>(rout32, rup32, up_opacity, clipping_mask_sw);
|
||||
} else if (rout64 && rup64) {
|
||||
tmpl_<TPixel64, USHORT>(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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 <sstream> /* std::ostringstream */
|
||||
#include "igs_color_blend.h"
|
||||
namespace {
|
||||
template <class T, class Q>
|
||||
void tmpl_(TRasterPT<T> dn_ras_out, const TRasterPT<T> &up_ras,
|
||||
const double up_opacity, const bool clipping_mask_sw) {
|
||||
double maxi = static_cast<double>(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<double>(up_pix->r) / maxi;
|
||||
double upg = static_cast<double>(up_pix->g) / maxi;
|
||||
double upb = static_cast<double>(up_pix->b) / maxi;
|
||||
double upa = static_cast<double>(up_pix->m) / maxi;
|
||||
double dnr = static_cast<double>(out_pix->r) / maxi;
|
||||
double dng = static_cast<double>(out_pix->g) / maxi;
|
||||
double dnb = static_cast<double>(out_pix->b) / maxi;
|
||||
double dna = static_cast<double>(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<Q>(dnr * (maxi + 0.999999));
|
||||
out_pix->g = static_cast<Q>(dng * (maxi + 0.999999));
|
||||
out_pix->b = static_cast<Q>(dnb * (maxi + 0.999999));
|
||||
out_pix->m = static_cast<Q>(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_<TPixel32, UCHAR>(rout32, rup32, up_opacity, clipping_mask_sw);
|
||||
} else if (rout64 && rup64) {
|
||||
tmpl_<TPixel64, USHORT>(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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 <sstream> /* std::ostringstream */
|
||||
#include "igs_color_blend.h"
|
||||
namespace {
|
||||
template <class T, class Q>
|
||||
void tmpl_(TRasterPT<T> dn_ras_out, const TRasterPT<T> &up_ras,
|
||||
const double up_opacity, const bool clipping_mask_sw) {
|
||||
double maxi = static_cast<double>(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<double>(up_pix->r) / maxi;
|
||||
double upg = static_cast<double>(up_pix->g) / maxi;
|
||||
double upb = static_cast<double>(up_pix->b) / maxi;
|
||||
double upa = static_cast<double>(up_pix->m) / maxi;
|
||||
double dnr = static_cast<double>(out_pix->r) / maxi;
|
||||
double dng = static_cast<double>(out_pix->g) / maxi;
|
||||
double dnb = static_cast<double>(out_pix->b) / maxi;
|
||||
double dna = static_cast<double>(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<Q>(dnr * (maxi + 0.999999));
|
||||
out_pix->g = static_cast<Q>(dng * (maxi + 0.999999));
|
||||
out_pix->b = static_cast<Q>(dnb * (maxi + 0.999999));
|
||||
out_pix->m = static_cast<Q>(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_<TPixel32, UCHAR>(rout32, rup32, up_opacity, clipping_mask_sw);
|
||||
} else if (rout64 && rup64) {
|
||||
tmpl_<TPixel64, USHORT>(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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 <sstream> /* std::ostringstream */
|
||||
#include "igs_color_blend.h"
|
||||
namespace {
|
||||
template <class T, class Q>
|
||||
void tmpl_(TRasterPT<T> dn_ras_out, const TRasterPT<T> &up_ras,
|
||||
const double up_opacity, const bool clipping_mask_sw) {
|
||||
double maxi = static_cast<double>(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<double>(up_pix->r) / maxi;
|
||||
double upg = static_cast<double>(up_pix->g) / maxi;
|
||||
double upb = static_cast<double>(up_pix->b) / maxi;
|
||||
double upa = static_cast<double>(up_pix->m) / maxi;
|
||||
double dnr = static_cast<double>(out_pix->r) / maxi;
|
||||
double dng = static_cast<double>(out_pix->g) / maxi;
|
||||
double dnb = static_cast<double>(out_pix->b) / maxi;
|
||||
double dna = static_cast<double>(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<Q>(dnr * (maxi + 0.999999));
|
||||
out_pix->g = static_cast<Q>(dng * (maxi + 0.999999));
|
||||
out_pix->b = static_cast<Q>(dnb * (maxi + 0.999999));
|
||||
out_pix->m = static_cast<Q>(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_<TPixel32, UCHAR>(rout32, rup32, up_opacity, clipping_mask_sw);
|
||||
} else if (rout64 && rup64) {
|
||||
tmpl_<TPixel64, USHORT>(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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 <sstream> /* std::ostringstream */
|
||||
#include "igs_color_blend.h"
|
||||
namespace {
|
||||
template <class T, class Q>
|
||||
void tmpl_(TRasterPT<T> dn_ras_out, const TRasterPT<T> &up_ras,
|
||||
const double up_opacity, const bool clipping_mask_sw) {
|
||||
double maxi = static_cast<double>(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<double>(up_pix->r) / maxi;
|
||||
double upg = static_cast<double>(up_pix->g) / maxi;
|
||||
double upb = static_cast<double>(up_pix->b) / maxi;
|
||||
double upa = static_cast<double>(up_pix->m) / maxi;
|
||||
double dnr = static_cast<double>(out_pix->r) / maxi;
|
||||
double dng = static_cast<double>(out_pix->g) / maxi;
|
||||
double dnb = static_cast<double>(out_pix->b) / maxi;
|
||||
double dna = static_cast<double>(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<Q>(dnr * (maxi + 0.999999));
|
||||
out_pix->g = static_cast<Q>(dng * (maxi + 0.999999));
|
||||
out_pix->b = static_cast<Q>(dnb * (maxi + 0.999999));
|
||||
out_pix->m = static_cast<Q>(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_<TPixel32, UCHAR>(rout32, rup32, up_opacity, clipping_mask_sw);
|
||||
} else if (rout64 && rup64) {
|
||||
tmpl_<TPixel64, USHORT>(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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 <sstream> /* std::ostringstream */
|
||||
#include "igs_color_blend.h"
|
||||
namespace {
|
||||
template <class T, class Q>
|
||||
void tmpl_(TRasterPT<T> dn_ras_out, const TRasterPT<T> &up_ras,
|
||||
const double up_opacity, const bool clipping_mask_sw) {
|
||||
double maxi = static_cast<double>(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<double>(up_pix->r) / maxi;
|
||||
double upg = static_cast<double>(up_pix->g) / maxi;
|
||||
double upb = static_cast<double>(up_pix->b) / maxi;
|
||||
double upa = static_cast<double>(up_pix->m) / maxi;
|
||||
double dnr = static_cast<double>(out_pix->r) / maxi;
|
||||
double dng = static_cast<double>(out_pix->g) / maxi;
|
||||
double dnb = static_cast<double>(out_pix->b) / maxi;
|
||||
double dna = static_cast<double>(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<Q>(dnr * (maxi + 0.999999));
|
||||
out_pix->g = static_cast<Q>(dng * (maxi + 0.999999));
|
||||
out_pix->b = static_cast<Q>(dnb * (maxi + 0.999999));
|
||||
out_pix->m = static_cast<Q>(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_<TPixel32, UCHAR>(rout32, rup32, up_opacity, clipping_mask_sw);
|
||||
} else if (rout64 && rup64) {
|
||||
tmpl_<TPixel64, USHORT>(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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 <sstream> /* std::ostringstream */
|
||||
#include "igs_color_blend.h"
|
||||
namespace {
|
||||
template <class T, class Q>
|
||||
void tmpl_(TRasterPT<T> dn_ras_out, const TRasterPT<T> &up_ras,
|
||||
const double up_opacity, const bool clipping_mask_sw) {
|
||||
double maxi = static_cast<double>(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<double>(up_pix->r) / maxi;
|
||||
double upg = static_cast<double>(up_pix->g) / maxi;
|
||||
double upb = static_cast<double>(up_pix->b) / maxi;
|
||||
double upa = static_cast<double>(up_pix->m) / maxi;
|
||||
double dnr = static_cast<double>(out_pix->r) / maxi;
|
||||
double dng = static_cast<double>(out_pix->g) / maxi;
|
||||
double dnb = static_cast<double>(out_pix->b) / maxi;
|
||||
double dna = static_cast<double>(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<Q>(dnr * (maxi + 0.999999));
|
||||
out_pix->g = static_cast<Q>(dng * (maxi + 0.999999));
|
||||
out_pix->b = static_cast<Q>(dnb * (maxi + 0.999999));
|
||||
out_pix->m = static_cast<Q>(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_<TPixel32, UCHAR>(rout32, rup32, up_opacity, clipping_mask_sw);
|
||||
} else if (rout64 && rup64) {
|
||||
tmpl_<TPixel64, USHORT>(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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 <sstream> /* std::ostringstream */
|
||||
#include "igs_color_blend.h"
|
||||
namespace {
|
||||
template <class T, class Q>
|
||||
void tmpl_(TRasterPT<T> dn_ras_out, const TRasterPT<T> &up_ras,
|
||||
const double up_opacity, const bool clipping_mask_sw) {
|
||||
double maxi = static_cast<double>(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<double>(up_pix->r) / maxi;
|
||||
double upg = static_cast<double>(up_pix->g) / maxi;
|
||||
double upb = static_cast<double>(up_pix->b) / maxi;
|
||||
double upa = static_cast<double>(up_pix->m) / maxi;
|
||||
double dnr = static_cast<double>(out_pix->r) / maxi;
|
||||
double dng = static_cast<double>(out_pix->g) / maxi;
|
||||
double dnb = static_cast<double>(out_pix->b) / maxi;
|
||||
double dna = static_cast<double>(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<Q>(dnr * (maxi + 0.999999));
|
||||
out_pix->g = static_cast<Q>(dng * (maxi + 0.999999));
|
||||
out_pix->b = static_cast<Q>(dnb * (maxi + 0.999999));
|
||||
out_pix->m = static_cast<Q>(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_<TPixel32, UCHAR>(rout32, rup32, up_opacity, clipping_mask_sw);
|
||||
} else if (rout64 && rup64) {
|
||||
tmpl_<TPixel64, USHORT>(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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 <sstream> /* std::ostringstream */
|
||||
#include "igs_color_blend.h"
|
||||
namespace {
|
||||
template <class T, class Q>
|
||||
void tmpl_(TRasterPT<T> dn_ras_out, const TRasterPT<T> &up_ras,
|
||||
const double up_opacity, const bool clipping_mask_sw) {
|
||||
double maxi = static_cast<double>(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<double>(up_pix->r) / maxi;
|
||||
double upg = static_cast<double>(up_pix->g) / maxi;
|
||||
double upb = static_cast<double>(up_pix->b) / maxi;
|
||||
double upa = static_cast<double>(up_pix->m) / maxi;
|
||||
double dnr = static_cast<double>(out_pix->r) / maxi;
|
||||
double dng = static_cast<double>(out_pix->g) / maxi;
|
||||
double dnb = static_cast<double>(out_pix->b) / maxi;
|
||||
double dna = static_cast<double>(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<Q>(dnr * (maxi + 0.999999));
|
||||
out_pix->g = static_cast<Q>(dng * (maxi + 0.999999));
|
||||
out_pix->b = static_cast<Q>(dnb * (maxi + 0.999999));
|
||||
out_pix->m = static_cast<Q>(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_<TPixel32, UCHAR>(rout32, rup32, up_opacity, clipping_mask_sw);
|
||||
} else if (rout64 && rup64) {
|
||||
tmpl_<TPixel64, USHORT>(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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 <sstream> /* std::ostringstream */
|
||||
#include "igs_color_blend.h"
|
||||
namespace {
|
||||
template <class T, class Q>
|
||||
void tmpl_(TRasterPT<T> dn_ras_out, const TRasterPT<T> &up_ras,
|
||||
const double up_opacity, const bool clipping_mask_sw) {
|
||||
double maxi = static_cast<double>(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<double>(up_pix->r) / maxi;
|
||||
double upg = static_cast<double>(up_pix->g) / maxi;
|
||||
double upb = static_cast<double>(up_pix->b) / maxi;
|
||||
double upa = static_cast<double>(up_pix->m) / maxi;
|
||||
double dnr = static_cast<double>(out_pix->r) / maxi;
|
||||
double dng = static_cast<double>(out_pix->g) / maxi;
|
||||
double dnb = static_cast<double>(out_pix->b) / maxi;
|
||||
double dna = static_cast<double>(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<Q>(dnr * (maxi + 0.999999));
|
||||
out_pix->g = static_cast<Q>(dng * (maxi + 0.999999));
|
||||
out_pix->b = static_cast<Q>(dnb * (maxi + 0.999999));
|
||||
out_pix->m = static_cast<Q>(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_<TPixel32, UCHAR>(rout32, rup32, up_opacity, clipping_mask_sw);
|
||||
} else if (rout64 && rup64) {
|
||||
tmpl_<TPixel64, USHORT>(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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 <sstream> /* std::ostringstream */
|
||||
#include "igs_color_blend.h"
|
||||
namespace {
|
||||
template <class T, class Q>
|
||||
void tmpl_(TRasterPT<T> dn_ras_out, const TRasterPT<T> &up_ras,
|
||||
const double up_opacity, const bool clipping_mask_sw) {
|
||||
double maxi = static_cast<double>(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<double>(up_pix->r) / maxi;
|
||||
double upg = static_cast<double>(up_pix->g) / maxi;
|
||||
double upb = static_cast<double>(up_pix->b) / maxi;
|
||||
double upa = static_cast<double>(up_pix->m) / maxi;
|
||||
double dnr = static_cast<double>(out_pix->r) / maxi;
|
||||
double dng = static_cast<double>(out_pix->g) / maxi;
|
||||
double dnb = static_cast<double>(out_pix->b) / maxi;
|
||||
double dna = static_cast<double>(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<Q>(dnr * (maxi + 0.999999));
|
||||
out_pix->g = static_cast<Q>(dng * (maxi + 0.999999));
|
||||
out_pix->b = static_cast<Q>(dnb * (maxi + 0.999999));
|
||||
out_pix->m = static_cast<Q>(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_<TPixel32, UCHAR>(rout32, rup32, up_opacity, clipping_mask_sw);
|
||||
} else if (rout64 && rup64) {
|
||||
tmpl_<TPixel64, USHORT>(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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 <sstream> /* std::ostringstream */
|
||||
#include "igs_color_blend.h"
|
||||
namespace {
|
||||
template <class T, class Q>
|
||||
void tmpl_(TRasterPT<T> dn_ras_out, const TRasterPT<T> &up_ras,
|
||||
const double up_opacity, const bool clipping_mask_sw) {
|
||||
double maxi = static_cast<double>(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<double>(up_pix->r) / maxi;
|
||||
double upg = static_cast<double>(up_pix->g) / maxi;
|
||||
double upb = static_cast<double>(up_pix->b) / maxi;
|
||||
double upa = static_cast<double>(up_pix->m) / maxi;
|
||||
double dnr = static_cast<double>(out_pix->r) / maxi;
|
||||
double dng = static_cast<double>(out_pix->g) / maxi;
|
||||
double dnb = static_cast<double>(out_pix->b) / maxi;
|
||||
double dna = static_cast<double>(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<Q>(dnr * (maxi + 0.999999));
|
||||
out_pix->g = static_cast<Q>(dng * (maxi + 0.999999));
|
||||
out_pix->b = static_cast<Q>(dnb * (maxi + 0.999999));
|
||||
out_pix->m = static_cast<Q>(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_<TPixel32, UCHAR>(rout32, rup32, up_opacity, clipping_mask_sw);
|
||||
} else if (rout64 && rup64) {
|
||||
tmpl_<TPixel64, USHORT>(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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 <sstream> /* std::ostringstream */
|
||||
#include "igs_color_blend.h"
|
||||
namespace {
|
||||
template <class T, class Q>
|
||||
void tmpl_(TRasterPT<T> dn_ras_out, const TRasterPT<T> &up_ras,
|
||||
const double up_opacity, const bool clipping_mask_sw) {
|
||||
double maxi = static_cast<double>(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<double>(up_pix->r) / maxi;
|
||||
double upg = static_cast<double>(up_pix->g) / maxi;
|
||||
double upb = static_cast<double>(up_pix->b) / maxi;
|
||||
double upa = static_cast<double>(up_pix->m) / maxi;
|
||||
double dnr = static_cast<double>(out_pix->r) / maxi;
|
||||
double dng = static_cast<double>(out_pix->g) / maxi;
|
||||
double dnb = static_cast<double>(out_pix->b) / maxi;
|
||||
double dna = static_cast<double>(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<Q>(dnr * (maxi + 0.999999));
|
||||
out_pix->g = static_cast<Q>(dng * (maxi + 0.999999));
|
||||
out_pix->b = static_cast<Q>(dnb * (maxi + 0.999999));
|
||||
out_pix->m = static_cast<Q>(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_<TPixel32, UCHAR>(rout32, rup32, up_opacity, clipping_mask_sw);
|
||||
} else if (rout64 && rup64) {
|
||||
tmpl_<TPixel64, USHORT>(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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 <sstream> /* std::ostringstream */
|
||||
#include "igs_color_blend.h"
|
||||
namespace {
|
||||
template <class T, class Q>
|
||||
void tmpl_(TRasterPT<T> dn_ras_out, const TRasterPT<T> &up_ras,
|
||||
const double up_opacity, const bool clipping_mask_sw) {
|
||||
double maxi = static_cast<double>(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<double>(up_pix->r) / maxi;
|
||||
double upg = static_cast<double>(up_pix->g) / maxi;
|
||||
double upb = static_cast<double>(up_pix->b) / maxi;
|
||||
double upa = static_cast<double>(up_pix->m) / maxi;
|
||||
double dnr = static_cast<double>(out_pix->r) / maxi;
|
||||
double dng = static_cast<double>(out_pix->g) / maxi;
|
||||
double dnb = static_cast<double>(out_pix->b) / maxi;
|
||||
double dna = static_cast<double>(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<Q>(dnr * (maxi + 0.999999));
|
||||
out_pix->g = static_cast<Q>(dng * (maxi + 0.999999));
|
||||
out_pix->b = static_cast<Q>(dnb * (maxi + 0.999999));
|
||||
out_pix->m = static_cast<Q>(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_<TPixel32, UCHAR>(rout32, rup32, up_opacity, clipping_mask_sw);
|
||||
} else if (rout64 && rup64) {
|
||||
tmpl_<TPixel64, USHORT>(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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 <sstream> /* std::ostringstream */
|
||||
#include "igs_color_blend.h"
|
||||
namespace {
|
||||
template <class T, class Q>
|
||||
void tmpl_(TRasterPT<T> dn_ras_out, const TRasterPT<T> &up_ras,
|
||||
const double up_opacity, const bool clipping_mask_sw) {
|
||||
double maxi = static_cast<double>(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<double>(up_pix->r) / maxi;
|
||||
double upg = static_cast<double>(up_pix->g) / maxi;
|
||||
double upb = static_cast<double>(up_pix->b) / maxi;
|
||||
double upa = static_cast<double>(up_pix->m) / maxi;
|
||||
double dnr = static_cast<double>(out_pix->r) / maxi;
|
||||
double dng = static_cast<double>(out_pix->g) / maxi;
|
||||
double dnb = static_cast<double>(out_pix->b) / maxi;
|
||||
double dna = static_cast<double>(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<Q>(dnr * (maxi + 0.999999));
|
||||
out_pix->g = static_cast<Q>(dng * (maxi + 0.999999));
|
||||
out_pix->b = static_cast<Q>(dnb * (maxi + 0.999999));
|
||||
out_pix->m = static_cast<Q>(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_<TPixel32, UCHAR>(rout32, rup32, up_opacity, clipping_mask_sw);
|
||||
} else if (rout64 && rup64) {
|
||||
tmpl_<TPixel64, USHORT>(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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 <sstream> /* std::ostringstream */
|
||||
#include "igs_color_blend.h"
|
||||
namespace {
|
||||
template <class T, class Q>
|
||||
void tmpl_(TRasterPT<T> dn_ras_out, const TRasterPT<T> &up_ras,
|
||||
const double up_opacity, const bool clipping_mask_sw) {
|
||||
double maxi = static_cast<double>(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<double>(up_pix->r) / maxi;
|
||||
double upg = static_cast<double>(up_pix->g) / maxi;
|
||||
double upb = static_cast<double>(up_pix->b) / maxi;
|
||||
double upa = static_cast<double>(up_pix->m) / maxi;
|
||||
double dnr = static_cast<double>(out_pix->r) / maxi;
|
||||
double dng = static_cast<double>(out_pix->g) / maxi;
|
||||
double dnb = static_cast<double>(out_pix->b) / maxi;
|
||||
double dna = static_cast<double>(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<Q>(dnr * (maxi + 0.999999));
|
||||
out_pix->g = static_cast<Q>(dng * (maxi + 0.999999));
|
||||
out_pix->b = static_cast<Q>(dnb * (maxi + 0.999999));
|
||||
out_pix->m = static_cast<Q>(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_<TPixel32, UCHAR>(rout32, rup32, up_opacity, clipping_mask_sw);
|
||||
} else if (rout64 && rup64) {
|
||||
tmpl_<TPixel64, USHORT>(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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 <sstream> /* std::ostringstream */
|
||||
#include "igs_color_blend.h"
|
||||
namespace {
|
||||
template <class T, class Q>
|
||||
void tmpl_(TRasterPT<T> dn_ras_out, const TRasterPT<T> &up_ras,
|
||||
const double up_opacity, const bool clipping_mask_sw) {
|
||||
double maxi = static_cast<double>(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<double>(up_pix->r) / maxi;
|
||||
double upg = static_cast<double>(up_pix->g) / maxi;
|
||||
double upb = static_cast<double>(up_pix->b) / maxi;
|
||||
double upa = static_cast<double>(up_pix->m) / maxi;
|
||||
double dnr = static_cast<double>(out_pix->r) / maxi;
|
||||
double dng = static_cast<double>(out_pix->g) / maxi;
|
||||
double dnb = static_cast<double>(out_pix->b) / maxi;
|
||||
double dna = static_cast<double>(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<Q>(dnr * (maxi + 0.999999));
|
||||
out_pix->g = static_cast<Q>(dng * (maxi + 0.999999));
|
||||
out_pix->b = static_cast<Q>(dnb * (maxi + 0.999999));
|
||||
out_pix->m = static_cast<Q>(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_<TPixel32, UCHAR>(rout32, rup32, up_opacity, clipping_mask_sw);
|
||||
} else if (rout64 && rup64) {
|
||||
tmpl_<TPixel64, USHORT>(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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 <sstream> /* std::ostringstream */
|
||||
#include "igs_color_blend.h"
|
||||
namespace {
|
||||
template <class T, class Q>
|
||||
void tmpl_(TRasterPT<T> dn_ras_out, const TRasterPT<T> &up_ras,
|
||||
const double up_opacity, const bool clipping_mask_sw,
|
||||
const bool alpha_rendering_sw) {
|
||||
double maxi = static_cast<double>(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<double>(up_pix->r) / maxi;
|
||||
double upg = static_cast<double>(up_pix->g) / maxi;
|
||||
double upb = static_cast<double>(up_pix->b) / maxi;
|
||||
double upa = static_cast<double>(up_pix->m) / maxi;
|
||||
double dnr = static_cast<double>(out_pix->r) / maxi;
|
||||
double dng = static_cast<double>(out_pix->g) / maxi;
|
||||
double dnb = static_cast<double>(out_pix->b) / maxi;
|
||||
double dna = static_cast<double>(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<Q>(dnr * (maxi + 0.999999));
|
||||
out_pix->g = static_cast<Q>(dng * (maxi + 0.999999));
|
||||
out_pix->b = static_cast<Q>(dnb * (maxi + 0.999999));
|
||||
out_pix->m = static_cast<Q>(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_<TPixel32, UCHAR>(rout32, rup32, up_opacity, clipping_mask_sw,
|
||||
alpha_rendering_sw);
|
||||
} else if (rout64 && rup64) {
|
||||
tmpl_<TPixel64, USHORT>(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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 <sstream> /* std::ostringstream */
|
||||
#include "igs_color_blend.h"
|
||||
namespace {
|
||||
template <class T, class Q>
|
||||
void tmpl_(TRasterPT<T> dn_ras_out, const TRasterPT<T> &up_ras,
|
||||
const double up_opacity, const bool clipping_mask_sw) {
|
||||
double maxi = static_cast<double>(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<double>(up_pix->r) / maxi;
|
||||
double upg = static_cast<double>(up_pix->g) / maxi;
|
||||
double upb = static_cast<double>(up_pix->b) / maxi;
|
||||
double upa = static_cast<double>(up_pix->m) / maxi;
|
||||
double dnr = static_cast<double>(out_pix->r) / maxi;
|
||||
double dng = static_cast<double>(out_pix->g) / maxi;
|
||||
double dnb = static_cast<double>(out_pix->b) / maxi;
|
||||
double dna = static_cast<double>(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<Q>(dnr * (maxi + 0.999999));
|
||||
out_pix->g = static_cast<Q>(dng * (maxi + 0.999999));
|
||||
out_pix->b = static_cast<Q>(dnb * (maxi + 0.999999));
|
||||
out_pix->m = static_cast<Q>(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_<TPixel32, UCHAR>(rout32, rup32, up_opacity, clipping_mask_sw);
|
||||
} else if (rout64 && rup64) {
|
||||
tmpl_<TPixel64, USHORT>(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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,9 @@
|
|||
#include "tsystem.h"
|
||||
|
||||
#include "ino_common.h"
|
||||
#include "tfxparam.h"
|
||||
|
||||
#include <sstream> /* 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 <class T, class U>
|
||||
void ras_to_arr_(const TRasterPT<T> ras, U *arr, const int channels) {
|
||||
void ras_to_arr_(const TRasterPT<T> 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<T> ras, U *arr, const int channels) {
|
|||
}
|
||||
}
|
||||
template <class U, class T>
|
||||
void arr_to_ras_(const U *arr, const int channels, TRasterPT<T> ras,
|
||||
void arr_to_ras_(const U* arr, const int channels, TRasterPT<T> 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<T> 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<T> 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_<TPixel32, unsigned char>(in_ras, out_arr, channels);
|
||||
} else if ((TRaster64P)in_ras) {
|
||||
ras_to_arr_<TPixel64, unsigned short>(
|
||||
in_ras, reinterpret_cast<unsigned short *>(out_arr), channels);
|
||||
in_ras, reinterpret_cast<unsigned short*>(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_<unsigned char, TPixel32>(in_arr, channels, out_ras, margin);
|
||||
} else if ((TRaster64P)out_ras) {
|
||||
arr_to_ras_<unsigned short, TPixel64>(
|
||||
reinterpret_cast<const unsigned short *>(in_arr), channels, out_ras,
|
||||
reinterpret_cast<const unsigned short*>(in_arr), channels, out_ras,
|
||||
margin);
|
||||
}
|
||||
}
|
||||
//--------------------
|
||||
void ino::ras_to_vec(const TRasterP in_ras, const int channels,
|
||||
std::vector<unsigned char> &out_vec) {
|
||||
std::vector<unsigned char>& 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<unsigned char> &in_vec, const int channels,
|
||||
void ino::vec_to_ras(std::vector<unsigned char>& 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 <typename T = double>
|
||||
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 <typename T = double>
|
||||
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 <class T = double>
|
||||
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<TPixel32, UCHAR>(rout32, rup32, up_opacity, gamma);
|
||||
// linearAdd<TPixel32, UCHAR>(rout32, rup32, up_opacity, clipping_mask_sw,
|
||||
// gamma, premultiplied_sw);
|
||||
else
|
||||
nonlinearTmpl<TPixel32, UCHAR>(rout32, rup32, up_opacity);
|
||||
// tmpl_<TPixel32, UCHAR>(rout32, rup32, up_opacity, clipping_mask_sw);
|
||||
} else if (rout64 && rup64) {
|
||||
if (linear_sw)
|
||||
linearTmpl<TPixel64, USHORT>(rout64, rup64, up_opacity, gamma);
|
||||
else
|
||||
nonlinearTmpl<TPixel64, USHORT>(rout64, rup64, up_opacity);
|
||||
} else {
|
||||
throw TRopException("unsupported pixel type");
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------
|
||||
template <class T, class Q>
|
||||
void TBlendForeBackRasterFx::nonlinearTmpl(TRasterPT<T> dn_ras_out,
|
||||
const TRasterPT<T>& 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<double>(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<double>(up_pix->r) / maxi;
|
||||
double upg = static_cast<double>(up_pix->g) / maxi;
|
||||
double upb = static_cast<double>(up_pix->b) / maxi;
|
||||
double upa = static_cast<double>(up_pix->m) / maxi;
|
||||
double dnr = static_cast<double>(out_pix->r) / maxi;
|
||||
double dng = static_cast<double>(out_pix->g) / maxi;
|
||||
double dnb = static_cast<double>(out_pix->b) / maxi;
|
||||
double dna = static_cast<double>(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<Q>(dnr * (maxi + 0.999999));
|
||||
out_pix->g = static_cast<Q>(dng * (maxi + 0.999999));
|
||||
out_pix->b = static_cast<Q>(dnb * (maxi + 0.999999));
|
||||
out_pix->m = static_cast<Q>(dna * (maxi + 0.999999));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------
|
||||
template <class T, class Q>
|
||||
void TBlendForeBackRasterFx::linearTmpl(TRasterPT<T> dn_ras_out,
|
||||
const TRasterPT<T>& 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<double>(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<double>(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<double>(out_pix->b) / maxi;
|
||||
dnBGR[1] = static_cast<double>(out_pix->g) / maxi;
|
||||
dnBGR[2] = static_cast<double>(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<double>(up_pix->b) / maxi;
|
||||
upBGR[1] = static_cast<double>(up_pix->g) / maxi;
|
||||
upBGR[2] = static_cast<double>(up_pix->r) / maxi;
|
||||
double upa = static_cast<double>(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<Q>(clamp(nonlinear_r, 0.0, 1.0) * (maxi + 0.999999));
|
||||
out_pix->g =
|
||||
static_cast<Q>(clamp(nonlinear_g, 0.0, 1.0) * (maxi + 0.999999));
|
||||
out_pix->b =
|
||||
static_cast<Q>(clamp(nonlinear_b, 0.0, 1.0) * (maxi + 0.999999));
|
||||
out_pix->m = static_cast<Q>(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());
|
||||
}
|
|
@ -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<unsigned char> &vec);
|
||||
void vec_to_ras(std::vector<unsigned char> &vec, const int channels,
|
||||
std::vector<unsigned char>& vec);
|
||||
void vec_to_ras(std::vector<unsigned char>& 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 <class T, class Q>
|
||||
void nonlinearTmpl(TRasterPT<T> dn_ras_out, const TRasterPT<T>& up_ras,
|
||||
const double up_opacity);
|
||||
|
||||
template <class T, class Q>
|
||||
void linearTmpl(TRasterPT<T> dn_ras_out, const TRasterPT<T>& 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; }
|
||||
|
||||
|
|
Loading…
Reference in a new issue