2016-03-19 06:57:51 +13:00
|
|
|
#include <sstream> /* std::ostringstream */
|
|
|
|
/* Not use boost at toonz-6.1 */
|
|
|
|
// #include <boost/shared_array.hpp> /* boost::shared_array<> */
|
|
|
|
#include "tfxparam.h"
|
|
|
|
#include "stdfx.h"
|
|
|
|
|
|
|
|
#include "ino_common.h"
|
|
|
|
//------------------------------------------------------------
|
2016-06-29 18:17:12 +12:00
|
|
|
class ino_channel_selector final : public TStandardRasterFx {
|
2016-06-15 18:43:10 +12:00
|
|
|
FX_PLUGIN_DECLARATION(ino_channel_selector)
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
TRasterFxPort m_source1;
|
|
|
|
TRasterFxPort m_source2;
|
|
|
|
TRasterFxPort m_source3;
|
|
|
|
TRasterFxPort m_source4;
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
TIntParamP m_red_source;
|
|
|
|
TIntParamP m_gre_source;
|
|
|
|
TIntParamP m_blu_source;
|
|
|
|
TIntParamP m_alp_source;
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
TIntEnumParamP m_red_channel;
|
|
|
|
TIntEnumParamP m_gre_channel;
|
|
|
|
TIntEnumParamP m_blu_channel;
|
|
|
|
TIntEnumParamP m_alp_channel;
|
2016-03-19 06:57:51 +13:00
|
|
|
|
|
|
|
public:
|
2016-06-15 18:43:10 +12:00
|
|
|
ino_channel_selector()
|
|
|
|
: m_red_source(1)
|
|
|
|
, m_gre_source(1)
|
|
|
|
, m_blu_source(1)
|
|
|
|
, m_alp_source(1)
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
, m_red_channel(new TIntEnumParam(0, "Red"))
|
|
|
|
, m_gre_channel(new TIntEnumParam(1, "Green"))
|
|
|
|
, m_blu_channel(new TIntEnumParam(2, "Blue"))
|
|
|
|
, m_alp_channel(new TIntEnumParam(3, "Alpha")) {
|
|
|
|
addInputPort("Source1", this->m_source1);
|
|
|
|
addInputPort("Source2", this->m_source2);
|
|
|
|
addInputPort("Source3", this->m_source3);
|
|
|
|
addInputPort("Source4", this->m_source4);
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
bindParam(this, "red_source", this->m_red_source);
|
|
|
|
bindParam(this, "green_source", this->m_gre_source);
|
|
|
|
bindParam(this, "blue_source", this->m_blu_source);
|
|
|
|
bindParam(this, "alpha_source", this->m_alp_source);
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
bindParam(this, "red_channel", this->m_red_channel);
|
|
|
|
bindParam(this, "green_channel", this->m_gre_channel);
|
|
|
|
bindParam(this, "blue_channel", this->m_blu_channel);
|
|
|
|
bindParam(this, "alpha_channel", this->m_alp_channel);
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
this->m_red_channel->addItem(1, "Green");
|
|
|
|
this->m_red_channel->addItem(2, "Blue");
|
|
|
|
this->m_red_channel->addItem(3, "Alpha");
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
this->m_gre_channel->addItem(0, "Red");
|
|
|
|
this->m_gre_channel->addItem(2, "Blue");
|
|
|
|
this->m_gre_channel->addItem(3, "Alpha");
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
this->m_blu_channel->addItem(0, "Red");
|
|
|
|
this->m_blu_channel->addItem(1, "Green");
|
|
|
|
this->m_blu_channel->addItem(3, "Alpha");
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
this->m_alp_channel->addItem(0, "Red");
|
|
|
|
this->m_alp_channel->addItem(1, "Green");
|
|
|
|
this->m_alp_channel->addItem(2, "Blue");
|
|
|
|
}
|
2016-06-20 14:23:05 +12:00
|
|
|
bool doGetBBox(double frame, TRectD &bBox,
|
|
|
|
const TRenderSettings &info) override {
|
2016-06-15 18:43:10 +12:00
|
|
|
for (int ii = 0; ii < this->getInputPortCount(); ++ii) {
|
|
|
|
std::string nm = this->getInputPortName(ii);
|
|
|
|
TRasterFxPort *tmp_port = (TRasterFxPort *)this->getInputPort(nm);
|
|
|
|
if (tmp_port->isConnected()) {
|
|
|
|
return (*tmp_port)->doGetBBox(frame, bBox, info);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
bBox = TRectD();
|
|
|
|
return false;
|
|
|
|
}
|
2016-06-20 14:23:05 +12:00
|
|
|
bool canHandle(const TRenderSettings &info, double frame) override {
|
|
|
|
return true;
|
|
|
|
}
|
2016-06-19 20:06:29 +12:00
|
|
|
void doCompute(TTile &tile, double frame, const TRenderSettings &ri) override;
|
2016-03-19 06:57:51 +13:00
|
|
|
};
|
|
|
|
FX_PLUGIN_IDENTIFIER(ino_channel_selector, "inoChannelSelectorFx");
|
|
|
|
//--------------------------------------------------------------------
|
|
|
|
// #include "igs_channel_selector.h"
|
2016-06-15 18:43:10 +12:00
|
|
|
namespace {
|
2016-03-19 06:57:51 +13:00
|
|
|
template <typename IN_PIXEL, typename OUT_PIXEL>
|
2016-06-15 18:43:10 +12:00
|
|
|
void fx_template(const TRasterPT<IN_PIXEL> in_ras, const int in_sel,
|
|
|
|
const TRasterPT<OUT_PIXEL> out_ras, const int out_sel) {
|
|
|
|
for (int yy = 0; yy < out_ras->getLy(); ++yy) {
|
|
|
|
IN_PIXEL *sl_in = in_ras->pixels(yy);
|
|
|
|
OUT_PIXEL *sl_out = out_ras->pixels(yy);
|
|
|
|
for (int xx = 0; xx < out_ras->getLx(); ++xx, ++sl_in, ++sl_out) {
|
|
|
|
int val = 0;
|
|
|
|
switch (in_sel) {
|
|
|
|
case 0:
|
|
|
|
val = sl_in->r;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
val = sl_in->g;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
val = sl_in->b;
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
val = sl_in->m;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
switch (out_sel) {
|
|
|
|
case 0:
|
|
|
|
sl_out->r = val;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
sl_out->g = val;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
sl_out->b = val;
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
sl_out->m = val;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
2016-06-15 18:43:10 +12:00
|
|
|
void fx_(const TRasterP in_ras, const int in_sel, TRasterP out_ras,
|
|
|
|
const int out_sel) {
|
|
|
|
if ((TRaster32P)in_ras && (TRaster32P)out_ras) {
|
|
|
|
fx_template<TPixel32, TPixel32>(in_ras, in_sel, out_ras, out_sel);
|
|
|
|
} else if ((TRaster64P)in_ras && (TRaster64P)out_ras) {
|
|
|
|
fx_template<TPixel64, TPixel64>(in_ras, in_sel, out_ras, out_sel);
|
|
|
|
}
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
}
|
|
|
|
//------------------------------------------------------------
|
2016-06-15 18:43:10 +12:00
|
|
|
void ino_channel_selector::doCompute(TTile &tile, double frame,
|
|
|
|
const TRenderSettings &ri) {
|
|
|
|
/* ------ サポートしていないPixelタイプはエラーを投げる --- */
|
|
|
|
if (!((TRaster32P)tile.getRaster()) && !((TRaster64P)tile.getRaster())) {
|
|
|
|
throw TRopException("unsupported input pixel type");
|
|
|
|
}
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
/* ------ 動作パラメータを得る ---------------------------- */
|
|
|
|
const int red_source = this->m_red_source->getValue() - 1;
|
|
|
|
const int gre_source = this->m_gre_source->getValue() - 1;
|
|
|
|
const int blu_source = this->m_blu_source->getValue() - 1;
|
|
|
|
const int alp_source = this->m_alp_source->getValue() - 1;
|
|
|
|
const int red_channel = this->m_red_channel->getValue();
|
|
|
|
const int gre_channel = this->m_gre_channel->getValue();
|
|
|
|
const int blu_channel = this->m_blu_channel->getValue();
|
|
|
|
const int alp_channel = this->m_alp_channel->getValue();
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
/* ------ 画像位置とサイズ -------------------------------- */
|
|
|
|
/***const TRectD rect = TRectD( tile.m_pos, TDimensionD(
|
|
|
|
tile.getRaster()->getLx()
|
|
|
|
, tile.getRaster()->getLy()
|
|
|
|
));
|
|
|
|
const TPointD poin = TPointD(rect.getP00());
|
|
|
|
const TDimension dime = TDimension(
|
|
|
|
(int)(rect.getLx()+0.5)
|
|
|
|
,(int)(rect.getLy()+0.5)
|
|
|
|
);***/
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
/* ------ 塗りつぶしクリア -------------------------------- */
|
|
|
|
tile.getRaster()->clear();
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
/* ------ 入力画像を接続していなければ処理しない ---------- */
|
|
|
|
if (this->getInputPortCount() <= 0) {
|
|
|
|
return;
|
|
|
|
}
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
/* ------ 入力画像の参照を確保 ---------------------------- */
|
|
|
|
// TTile *source_tiles = new TTile[this->getInputPortCount()];
|
|
|
|
// int *source_sw = new int[this->getInputPortCount()];
|
|
|
|
// TRasterP *ras_a = new TRasterP[this->getInputPortCount()];
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
/* Not use boost at toonz-6.1 */
|
|
|
|
/******
|
|
|
|
boost::shared_array<TTile>
|
|
|
|
source_tiles(new TTile[this->getInputPortCount()]);
|
|
|
|
boost::shared_array<int>
|
|
|
|
source_sw(new int[this->getInputPortCount()]);
|
|
|
|
boost::shared_array<TRasterP>
|
|
|
|
ras_a(new TRasterP[this->getInputPortCount()]);
|
2016-03-19 06:57:51 +13:00
|
|
|
******/
|
2016-06-15 18:43:10 +12:00
|
|
|
/* Array item(TRasterFxPort) number is 4(fix) in this code */
|
|
|
|
TTile source_tiles[4];
|
|
|
|
int source_sw[4];
|
|
|
|
TRasterP ras_a[4];
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
int ras_s = 0;
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
/* ------ 画像生成 ---------------------------------------- */
|
|
|
|
for (int ii = 0; ii < this->getInputPortCount(); ++ii) {
|
|
|
|
std::string nm = this->getInputPortName(ii);
|
|
|
|
TRasterFxPort *tmp_port = (TRasterFxPort *)this->getInputPort(nm);
|
|
|
|
if (tmp_port->isConnected() && ((ii == red_source) || (ii == gre_source) ||
|
|
|
|
(ii == blu_source) || (ii == alp_source))) {
|
|
|
|
(*tmp_port)->allocateAndCompute(
|
|
|
|
source_tiles[ii]
|
|
|
|
//,poin,dime
|
|
|
|
,
|
|
|
|
tile.m_pos /* 位置 */
|
|
|
|
,
|
|
|
|
TDimension(/* サイズ */
|
|
|
|
tile.getRaster()->getLx(), tile.getRaster()->getLy()),
|
|
|
|
tile.getRaster() /* sampling */
|
|
|
|
,
|
|
|
|
frame, ri);
|
|
|
|
source_sw[ii] = 1;
|
|
|
|
ras_a[ras_s++] = source_tiles[ii].getRaster();
|
|
|
|
} else
|
|
|
|
source_sw[ii] = 0;
|
|
|
|
}
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
TRasterP red_ras = 0;
|
|
|
|
TRasterP gre_ras = 0;
|
|
|
|
TRasterP blu_ras = 0;
|
|
|
|
TRasterP alp_ras = 0;
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
if ((0 <= red_source) && (red_source < this->getInputPortCount()) &&
|
|
|
|
source_sw[red_source]) {
|
|
|
|
red_ras = source_tiles[red_source].getRaster();
|
|
|
|
}
|
|
|
|
if ((0 <= gre_source) && (gre_source < this->getInputPortCount()) &&
|
|
|
|
source_sw[gre_source]) {
|
|
|
|
gre_ras = source_tiles[gre_source].getRaster();
|
|
|
|
}
|
|
|
|
if ((0 <= blu_source) && (blu_source < this->getInputPortCount()) &&
|
|
|
|
source_sw[blu_source]) {
|
|
|
|
blu_ras = source_tiles[blu_source].getRaster();
|
|
|
|
}
|
|
|
|
if ((0 <= alp_source) && (alp_source < this->getInputPortCount()) &&
|
|
|
|
source_sw[alp_source]) {
|
|
|
|
alp_ras = source_tiles[alp_source].getRaster();
|
|
|
|
}
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
/* ------ (app_begin)log記憶 ------------------------------ */
|
|
|
|
const bool log_sw = ino::log_enable_sw();
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
if (log_sw) {
|
|
|
|
std::ostringstream os;
|
|
|
|
os << "red"
|
|
|
|
<< " s " << red_source << " c " << red_channel << " green"
|
|
|
|
<< " s " << gre_source << " c " << gre_channel << " blue"
|
|
|
|
<< " s " << blu_source << " c " << blu_channel << " alpha"
|
|
|
|
<< " s " << alp_source << " c " << alp_channel << " tile w "
|
|
|
|
<< tile.getRaster()->getLx() << " h " << tile.getRaster()->getLy()
|
|
|
|
<< " b " << ino::pixel_bits(tile.getRaster());
|
|
|
|
os << " s_count " << this->getInputPortCount();
|
|
|
|
for (int ii = 0; ii < this->getInputPortCount(); ++ii) {
|
|
|
|
if (source_sw[ii]) {
|
|
|
|
os << " tile" << ii << " w " << source_tiles[ii].getRaster()->getLx()
|
|
|
|
<< " h " << source_tiles[ii].getRaster()->getLy() << " b "
|
|
|
|
<< ino::pixel_bits(source_tiles[ii].getRaster());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
os << " frame " << frame;
|
|
|
|
}
|
|
|
|
/* ------ 入力画像の参照開放 ------------------------------ */
|
|
|
|
// delete [] source_sw;
|
|
|
|
// delete [] source_tiles;
|
|
|
|
/* ------ fx処理 ------------------------------------------ */
|
|
|
|
try {
|
|
|
|
tile.getRaster()->lock();
|
|
|
|
for (int ii = 0; ii < ras_s; ++ii) {
|
|
|
|
ras_a[ii]->lock();
|
|
|
|
}
|
|
|
|
if (red_ras) {
|
|
|
|
fx_(red_ras, red_channel, tile.getRaster(), 0);
|
|
|
|
}
|
|
|
|
if (gre_ras) {
|
|
|
|
fx_(gre_ras, gre_channel, tile.getRaster(), 1);
|
|
|
|
}
|
|
|
|
if (blu_ras) {
|
|
|
|
fx_(blu_ras, blu_channel, tile.getRaster(), 2);
|
|
|
|
}
|
|
|
|
if (alp_ras) {
|
|
|
|
fx_(alp_ras, alp_channel, tile.getRaster(), 3);
|
|
|
|
}
|
|
|
|
for (int ii = ras_s - 1; 0 <= ii; --ii) {
|
|
|
|
ras_a[ii]->unlock();
|
|
|
|
}
|
|
|
|
tile.getRaster()->unlock();
|
|
|
|
}
|
|
|
|
/* ------ error処理 --------------------------------------- */
|
|
|
|
catch (std::bad_alloc &e) {
|
|
|
|
for (int ii = ras_s - 1; 0 <= ii; --ii) {
|
|
|
|
ras_a[ii]->unlock();
|
|
|
|
}
|
|
|
|
tile.getRaster()->unlock();
|
|
|
|
if (log_sw) {
|
|
|
|
std::string str("std::bad_alloc <");
|
|
|
|
str += e.what();
|
|
|
|
str += '>';
|
|
|
|
}
|
|
|
|
// delete [] ras_a;
|
|
|
|
throw;
|
|
|
|
} catch (std::exception &e) {
|
|
|
|
for (int ii = ras_s - 1; 0 <= ii; --ii) {
|
|
|
|
ras_a[ii]->unlock();
|
|
|
|
}
|
|
|
|
tile.getRaster()->unlock();
|
|
|
|
if (log_sw) {
|
|
|
|
std::string str("exception <");
|
|
|
|
str += e.what();
|
|
|
|
str += '>';
|
|
|
|
}
|
|
|
|
// delete [] ras_a;
|
|
|
|
throw;
|
|
|
|
} catch (...) {
|
|
|
|
for (int ii = ras_s - 1; 0 <= ii; --ii) {
|
|
|
|
ras_a[ii]->unlock();
|
|
|
|
}
|
|
|
|
tile.getRaster()->unlock();
|
|
|
|
if (log_sw) {
|
|
|
|
std::string str("other exception");
|
|
|
|
}
|
|
|
|
// delete [] ras_a;
|
|
|
|
throw;
|
|
|
|
}
|
|
|
|
// delete [] ras_a;
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|