#include #include #include #include #include #include #include "pixelop.hpp" #include #include #include #ifdef _MSC_VER // Visual Studio is not supported __restrict for reference #define RESTRICT #else #define RESTRICT __restrict #endif extern "C" { TOONZ_EXPORT int toonz_plugin_init(toonz::host_interface_t *hostif); TOONZ_EXPORT void toonz_plugin_exit(); } toonz::host_interface_t *ifactory_ = NULL; int toonz_plugin_init(toonz::host_interface_t *hostif) { printf("toonz_plugin_init()\n"); ifactory_ = hostif; return TOONZ_OK; } void toonz_plugin_exit() { printf("toonz_plugin_exit()\n"); } ToonzRect conv2rect(toonz::rect_t &&r) { return ToonzRect(r.x0, r.y0, r.x1, r.y1); } toonz::rect_t conv2rect(ToonzRect &&r) { return toonz::rect_t{r.x0, r.y0, r.x1, r.y1}; } ToonzRect conv2rect(const toonz::rect_t &r) { return ToonzRect(r.x0, r.y0, r.x1, r.y1); } toonz::rect_t conv2rect(const ToonzRect &r) { return toonz::rect_t{r.x0, r.y0, r.x1, r.y1}; } template void dump_value(const T &v) { printf("value: type:%s {%d}\n", typeid(T).name(), v); } template <> void dump_value(const toonz_param_traits_double_t::iovaluetype &v) { printf("value: type:%s {%g}\n", typeid(toonz_param_traits_double_t::iovaluetype).name(), v); } template <> void dump_value(const toonz_param_traits_range_t::iovaluetype &v) { printf("value: type:%s {%g, %g}\n", typeid(toonz_param_traits_range_t::iovaluetype).name(), v.a, v.b); } template <> void dump_value(const toonz_param_traits_point_t::iovaluetype &v) { printf("value: type:%s {%g, %g}\n", typeid(toonz_param_traits_point_t::iovaluetype).name(), v.x, v.y); } template <> void dump_value(const toonz_param_traits_color_t::iovaluetype &v) { printf("value: type:%s {%d, %d, %d, %d}\n", typeid(toonz_param_traits_color_t::iovaluetype).name(), v.c0, v.c1, v.c2, v.m); } template <> void dump_value(const toonz_param_traits_spectrum_t::iovaluetype &v) { printf("value: type:%s {%g, %g, %g, %g, %g}\n", typeid(toonz_param_traits_spectrum_t::iovaluetype).name(), v.w, v.c0, v.c1, v.c2, v.m); } template <> void dump_value(const toonz_param_traits_tonecurve_t::iovaluetype &v) { printf("value: type:%s {%g, %g, %d, %d}\n", typeid(toonz_param_traits_tonecurve_t::iovaluetype).name(), v.x, v.y, v.channel, v.interp); } template bool get_and_check(toonz::node_handle_t node, const char *nm, double frame, double opt = 0) { auto nodeif = grab_interf(TOONZ_UUID_NODE); auto pif = grab_interf(TOONZ_UUID_PARAM); toonz_param_handle_t p1; int ret; ret = nodeif->get_param(node, nm, &p1); printf("get_param(%s): ret:%d\n", nm, ret); int type = 0; int cnt = 0; pif->get_type(p1, frame, &type, &cnt); printf("parameter(ret:%d): name:%s (type:%d count:%d) expect:(type:%d) typesize:%ld\n", ret, nm, type, cnt, T::E, sizeof(typename T::iovaluetype)); if (type != T::E) return false; typename T::iovaluetype v; ret = pif->get_value(p1, frame, &cnt, &v); printf("get_value: ret:%d count:%d\n", ret, cnt); dump_value(v); return true; } template <> bool get_and_check(toonz::node_handle_t node, const char *nm, double frame, double opt) { auto nodeif = grab_interf(TOONZ_UUID_NODE); auto pif = grab_interf(TOONZ_UUID_PARAM); toonz_param_handle_t p1; int ret; ret = nodeif->get_param(node, nm, &p1); printf("get_param(%s): ret:%d\n", nm, ret); int type = 0; int cnt = 0; ret = pif->get_type(p1, frame, &type, &cnt); printf("parameter(ret:%d): name:%s (type:%d count:%d) expect:(type:%d) typesize:-\n", ret, nm, type, cnt, toonz_param_traits_string_t::E); if (type != toonz_param_traits_string_t::E) return false; std::vector v(cnt); ret = pif->get_value(p1, frame, &cnt, v.data()); printf("get_value: ret:%d count:%d\n", ret, cnt); //dump_value< toonz_param_traits_string_t::iovaluetype* >(v); printf("value: type:%s {%s}\n", typeid(toonz_param_traits_string_t::iovaluetype).name(), v.begin()); return true; } template <> bool get_and_check(toonz::node_handle_t node, const char *nm, double frame, double opt) { auto nodeif = grab_interf(TOONZ_UUID_NODE); auto pif = grab_interf(TOONZ_UUID_PARAM); toonz_param_handle_t p1; int ret; ret = nodeif->get_param(node, nm, &p1); printf("get_param(%s): ret:%d\n", nm, ret); int type = 0; int cnt = 0; ret = pif->get_type(p1, frame, &type, &cnt); printf("parameter(ret:%d): name:%s (type:%d count:%d) expect:(type:%d) typesize:-\n", ret, nm, type, cnt, toonz_param_traits_spectrum_t::E); if (type != toonz_param_traits_spectrum_t::E) return false; toonz_param_traits_spectrum_t::iovaluetype v; v.w = opt; ret = pif->get_value(p1, frame, &cnt, &v); printf("get_value: ret:%d count:%d\n", ret, cnt); dump_value(v); return true; } template <> bool get_and_check(toonz::node_handle_t node, const char *nm, double frame, double opt) { auto nodeif = grab_interf(TOONZ_UUID_NODE); auto pif = grab_interf(TOONZ_UUID_PARAM); toonz_param_handle_t p1; int ret; ret = nodeif->get_param(node, nm, &p1); printf("get_param(%s): ret:%d\n", nm, ret); int type = 0; int cnt = 0; ret = pif->get_type(p1, frame, &type, &cnt); printf("parameter)(ret:%d): name:%s (type:%d count:%d) expect:(type:%d) sz:-\n", ret, nm, type, cnt, toonz_param_traits_tonecurve_t::E); if (type != toonz_param_traits_tonecurve_t::E) return false; std::vector v(cnt); ret = pif->get_value(p1, frame, &cnt, v.data()); printf("get_value: ret:%d count:%d\n", ret, cnt); for (int i = 0; i < cnt; i++) { dump_value(v[i]); } return true; } void do_compute(toonz::node_handle_t node, const toonz::rendering_setting_t *rs, double frame, toonz::tile_handle_t tile) { printf("do_compute(): node:%p tile:%p frame:%g\n", node, tile, frame); toonz::port_handle_t port = nullptr; { auto nodeif = grab_interf(TOONZ_UUID_NODE); if (nodeif) { int ret = nodeif->get_input_port(node, "IPort", &port); if (ret) printf("do_compute(): get_input_port: ret:%d\n", ret); // test get_and_check(node, "first", frame); get_and_check(node, "second", frame); get_and_check(node, "third", frame); get_and_check(node, "fourth", frame); get_and_check(node, "fifth", frame); get_and_check(node, "sixth", frame); get_and_check(node, "seventh", frame); get_and_check(node, "eighth", frame); get_and_check(node, "ninth", frame, 0.5); get_and_check(node, "tenth", frame); get_and_check(node, "unknown", frame); toonz::param_handle_t str; nodeif->get_param(node, "eighth", &str); toonz::param_handle_t notstr; nodeif->get_param(node, "seventh", ¬str); toonz::param_handle_t spec; nodeif->get_param(node, "ninth", &spec); auto pif = grab_interf(TOONZ_UUID_PARAM); if (pif) { int t, l; pif->get_type(str, frame, &t, &l); int sz; std::vector shortage_buf(l / 2 + 1); int ret = pif->get_string_value(str, &sz, l / 2 + 1, shortage_buf.data()); printf("get_string_value(string): {%s} (length:%d) ret:%d\n", shortage_buf.data(), sz, ret); ret = pif->get_string_value(notstr, &sz, l / 2 + 1, shortage_buf.data()); // must be error printf("get_string_value(not string): sz:%d ret:%d\n", sz, ret); // size must be not changed pif->get_type(spec, frame, &t, &l); toonz_param_spectrum_t spc; ret = pif->get_spectrum_value(spec, frame, 0, &spc); printf("get_spectrum_value(spec): ret:%d\n", ret); dump_value(spc); ret = pif->get_spectrum_value(str, frame, 0, &spc); printf("get_spectrum_value(str): ret:%d\n", ret); // must be error } } } int blur = 1; auto tileif = grab_interf(TOONZ_UUID_TILE); auto portif = grab_interf(TOONZ_UUID_PORT); if (port && tileif && portif) { toonz::fxnode_handle_t fx; portif->get_fx(port, &fx); auto fxif = grab_interf(TOONZ_UUID_FXNODE); if (fxif) { /* evaluate upstream's flow */ toonz::rect_t rect; tileif->get_rectangle(tile, &rect); toonz::rect_t inRect = conv2rect(conv2rect(rect).enlarge(blur, blur)); toonz::tile_handle_t result = nullptr; tileif->create(&result); fxif->compute_to_tile(fx, rs, frame, &inRect, tile, result); /* evaluate the fx */ int x = rect.x0; int y = rect.y0; int lx = rect.x1 - rect.x0; int ly = rect.y1 - rect.y0; int sstride, dstride; tileif->get_raw_stride(result, &sstride); tileif->get_raw_stride(tile, &dstride); int selement_type, delement_type; tileif->get_element_type(result, &delement_type); tileif->get_element_type(tile, &selement_type); uint8_t *saddr, *daddr; tileif->get_raw_address_unsafe(result, reinterpret_cast(&saddr)); tileif->get_raw_address_unsafe(tile, reinterpret_cast(&daddr)); printf("%f %f %f %f\n", rect.x0, rect.y0, rect.x1, rect.y1); printf("-+ x:%d y:%d lx:%d ly:%d\n", x, y, lx, ly); printf(" + src tile: addr:%p stride:%d type:%d\n", saddr, sstride, selement_type); printf(" + dst tile: addr:%p stride:%d type:%d\n", daddr, dstride, delement_type); // need compatibility check for formats hv_kernel(daddr, saddr + sstride + 4, lx, ly, dstride, sstride, [](uint8_t v[4], const uint8_t *p, int stride, int xinbytes, int yinbytes) { uint32_t l00 = *reinterpret_cast(p + -stride - 4); uint32_t l10 = *reinterpret_cast(p + -stride); uint32_t l20 = *reinterpret_cast(p + -stride + 4); uint32_t l01 = *reinterpret_cast(p - 4); uint32_t l11 = *reinterpret_cast(p); uint32_t l21 = *reinterpret_cast(p + 4); uint32_t l02 = *reinterpret_cast(p + stride - 4); uint32_t l12 = *reinterpret_cast(p + stride); uint32_t l22 = *reinterpret_cast(p + stride + 4); uint32_t r = 0, g = 0, b = 0, m = 0; //printf("col:0x%08x [%d, %d]\n", l11, xinbytes, yinbytes); /* TODO: toonz の TPixel は char r, g, b, m; のように持っているのでそのまま uin32_t だとエンディアンが変わる. toonz ビルド時の configuration はコンパイル時に参照できるようにしておくべきだ. */ m += ((l00 >> 24) & 0xff); m += ((l10 >> 24) & 0xff); m += ((l20 >> 24) & 0xff); m += ((l01 >> 24) & 0xff); m += ((l11 >> 24) & 0xff); m += ((l21 >> 24) & 0xff); m += ((l02 >> 24) & 0xff); m += ((l12 >> 24) & 0xff); m += ((l22 >> 24) & 0xff); b += ((l00 >> 16) & 0xff); b += ((l10 >> 16) & 0xff); b += ((l20 >> 16) & 0xff); b += ((l01 >> 16) & 0xff); b += ((l11 >> 16) & 0xff); b += ((l21 >> 16) & 0xff); b += ((l02 >> 16) & 0xff); b += ((l12 >> 16) & 0xff); b += ((l22 >> 16) & 0xff); g += ((l00 >> 8) & 0xff); g += ((l10 >> 8) & 0xff); g += ((l20 >> 8) & 0xff); g += ((l01 >> 8) & 0xff); g += ((l11 >> 8) & 0xff); g += ((l21 >> 8) & 0xff); g += ((l02 >> 8) & 0xff); g += ((l12 >> 8) & 0xff); g += ((l22 >> 8) & 0xff); r += ((l00 >> 0) & 0xff); r += ((l10 >> 0) & 0xff); r += ((l20 >> 0) & 0xff); r += ((l01 >> 0) & 0xff); r += ((l11 >> 0) & 0xff); r += ((l21 >> 0) & 0xff); r += ((l02 >> 0) & 0xff); r += ((l12 >> 0) & 0xff); r += ((l22 >> 0) & 0xff); v[0] = static_cast(r / 9); v[1] = static_cast(g / 9); v[2] = static_cast(b / 9); v[3] = static_cast(m / 9); }); } } } int do_get_bbox(toonz::node_handle_t node, const toonz::rendering_setting_t *rs, double frame, toonz::rect_t *rect) { printf("do_get_bbox(): node:%p\n", node); bool modified = false; toonz::port_handle_t port = nullptr; { auto nodeif = grab_interf(TOONZ_UUID_NODE); if (nodeif) { int ret = nodeif->get_input_port(node, "IPort", &port); printf("do_get_bbox(): get_input_port:%d\n", ret); } } auto portif = grab_interf(TOONZ_UUID_PORT); if (port && portif) { int con = 0; portif->is_connected(port, &con); if (con) { toonz::fxnode_handle_t fx; portif->get_fx(port, &fx); auto fxif = grab_interf(TOONZ_UUID_FXNODE); if (fxif) { int ret = 0; /* この引数の順番つらいなぁ, fx, rs, frame, rect の順だよね */ fxif->get_bbox(fx, rs, frame, rect, &ret); /* 画素単位の値を現在の座標系に合わせる */ toonz::affine_t a = rs->affine; double det = a.a11 * a.a22 - a.a12 * a.a21; double scale = sqrt(fabs(det)); double blur = 1.0 / scale; ToonzRect r = conv2rect(*rect); r = r.enlarge(blur, blur); *rect = conv2rect(std::move(r)); modified = true; } } } return modified; } param_desc_t params0_[] = { param_desc_ctor("first", "1st", {1.0 /* default */, -1.0 /* min */, 1.0 /* max */}, "description of the first param"), param_desc_ctor("second", "2nd", {{48.0, 64.0} /* default */, {0.0, 180.0} /* min-max */}), param_desc_ctor("third", "3rd", {0xff, 0xff, 0xff, 0xff} /* white */), param_desc_ctor("fourth", "4th", {{64, -64} /* default */, {-200, 200} /* min */, {-200, +200} /* max */}), }; const char *strtbl_[] = {"tokyo", "osaka", "nagoya"}; param_desc_t params1_[] = { param_desc_ctor("fifth", "5th", {2, 3, strtbl_}), param_desc_ctor("sixth", "6th", {2, -10, 10}, "this is integer"), param_desc_ctor("seventh", "7th", {1}), }; toonz_param_traits_spectrum_t::valuetype points_[] = {{0.0, 1.0, 0.0, 0.0, 1.0}, {0.5, 0.5, 0.0, 0.5, 1.0}, {1.0, 0.0, 0.0, 0.5, 1.0}}; param_desc_t params2_[] = { param_desc_ctor("eighth", "8th", {"this is sample message"}), param_desc_ctor("ninth", "9th", {0.1, 3, points_}), param_desc_ctor("tenth", "10th", {/* tonecurve has no default */}), }; toonz_param_group_t groups0_[] = { param_group_ctor("Group1", sizeof(params0_) / sizeof(param_desc_t), params0_), param_group_ctor("Group2", sizeof(params1_) / sizeof(param_desc_t), params1_), param_group_ctor("Group3", sizeof(params2_) / sizeof(param_desc_t), params2_), }; toonz_param_page_t pages_[] = { param_page_ctor("Properties", sizeof(groups0_) / sizeof(toonz_param_group_t), groups0_), }; int node_setup(toonz::node_handle_t node) { printf("blur: setup(): node:%p\n", node); auto setup = grab_interf(TOONZ_UUID_SETUP); if (setup) { int errcode = 0; void *entry = NULL; int ret = setup->set_parameter_pages_with_error(node, sizeof(pages_) / sizeof(toonz_param_page_t), pages_, &errcode, &entry); if (ret) { printf("setup error:0x%x reason:0x%x entry:%p\n", ret, errcode, entry); } setup->add_input_port(node, "IPort", TOONZ_PORT_TYPE_RASTER); } return 0; } int node_create(toonz::node_handle_t node) { printf("blur: create(): node:%p\n", node); return TOONZ_OK; } int node_destroy(toonz::node_handle_t node) { printf("destroy():node:%p\n", node); return TOONZ_OK; } int can_handle(toonz_node_handle_t node, const toonz_rendering_setting_t *rs, double frame) { printf("%s:\n", __FUNCTION__); return TOONZ_OK; } size_t get_memory_requirement(toonz_node_handle_t node, const toonz_rendering_setting_t *rs, double frame, const toonz_rect_t *rect) { printf("%s:\n", __FUNCTION__); return TOONZ_OK; } void on_new_frame(toonz_node_handle_t node, const toonz_rendering_setting_t *rs, double frame) { printf("%s:\n", __FUNCTION__); } void on_end_frame(toonz_node_handle_t node, const toonz_rendering_setting_t *rs, double frame) { printf("%s:\n", __FUNCTION__); } toonz_nodal_rasterfx_handler_t_ toonz_plugin_node_handler = { {1, 0}, // ver do_compute, // do_compute do_get_bbox, // do_get_bbox can_handle, // can_handle get_memory_requirement, // get_memory_requirement on_new_frame, // on_new_frame on_end_frame, // on_end_frame node_create, // create node_destroy, // destroy node_setup}; extern "C" { TOONZ_PLUGIN_PROBE_BEGIN(TOONZ_IF_VER(1, 0)) TOONZ_PLUGIN_PROBE_DEFINE(TOONZ_PLUGIN_VER(1, 0), "blur-plugin" /* name */, "dwango" /* vendor */, "libblur.plugin" /* identifier */, "a blur plugin for test", "http://dwango.co.jp/", TOONZ_PLUGIN_CLASS_POSTPROCESS_SLAB, &toonz_plugin_node_handler) TOONZ_PLUGIN_PROBE_END; }