Synchronize changes with trunk:
- Revert some unneeded code-style changes which were done in tomato - Remove classic compositor's keying node exec callback. It was too outdated and not sure if we shall support two versions of compositors. - Revert changes made to some other nodes which were needed to make classic compositor's keying node working.
This commit is contained in:
@@ -6155,7 +6155,7 @@ static void direct_link_movieTracks(FileData *fd, ListBase *tracksbase)
|
||||
MovieTrackingTrack *track;
|
||||
|
||||
link_list(fd, tracksbase);
|
||||
|
||||
|
||||
for (track = tracksbase->first; track; track = track->next) {
|
||||
track->markers = newdataadr(fd, track->markers);
|
||||
}
|
||||
|
||||
@@ -223,9 +223,6 @@ void IIR_gauss(CompBuf* src, float sigma, int chan, int xy);
|
||||
#define CMP_SCALE_MAX 12000
|
||||
|
||||
CompBuf* node_composit_transform(CompBuf *cbuf, float x, float y, float angle, float scale, int filter_type);
|
||||
void node_composit_blur_single_image(bNode *node, int filtertype, int sizex, int sizey, CompBuf *new, CompBuf *img, float scale);
|
||||
void node_composite_morpho_dilate(CompBuf *cbuf);
|
||||
void node_composite_morpho_erode(CompBuf *cbuf);
|
||||
float *node_composit_get_float_buffer(RenderData *rd, ImBuf *ibuf, int *alloc);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -85,8 +85,9 @@ static float *make_bloomtab(int rad)
|
||||
}
|
||||
|
||||
/* both input images of same type, either 4 or 1 channel */
|
||||
void node_composit_blur_single_image(bNode *node, int filtertype, int sizex, int sizey, CompBuf *new, CompBuf *img, float scale)
|
||||
static void blur_single_image(bNode *node, CompBuf *new, CompBuf *img, float scale)
|
||||
{
|
||||
NodeBlurData *nbd= node->storage;
|
||||
CompBuf *work;
|
||||
register float sum, val;
|
||||
float rval, gval, bval, aval;
|
||||
@@ -100,17 +101,17 @@ void node_composit_blur_single_image(bNode *node, int filtertype, int sizex, int
|
||||
work= alloc_compbuf(imgx, imgy, img->type, 1); /* allocs */
|
||||
|
||||
/* horizontal */
|
||||
if (sizex == 0) {
|
||||
if (nbd->sizex == 0) {
|
||||
memcpy(work->rect, img->rect, sizeof(float) * img->type * imgx * imgy);
|
||||
}
|
||||
else {
|
||||
rad = scale*(float)sizex;
|
||||
rad = scale*(float)nbd->sizex;
|
||||
if (rad>imgx/2)
|
||||
rad= imgx/2;
|
||||
else if (rad<1)
|
||||
rad= 1;
|
||||
|
||||
gausstab= make_gausstab(filtertype, rad);
|
||||
gausstab= make_gausstab(nbd->filtertype, rad);
|
||||
gausstabcent= gausstab+rad;
|
||||
|
||||
for (y = 0; y < imgy; y++) {
|
||||
@@ -151,17 +152,17 @@ void node_composit_blur_single_image(bNode *node, int filtertype, int sizex, int
|
||||
MEM_freeN(gausstab);
|
||||
}
|
||||
|
||||
if (sizey == 0) {
|
||||
if (nbd->sizey == 0) {
|
||||
memcpy(new->rect, work->rect, sizeof(float) * img->type * imgx * imgy);
|
||||
}
|
||||
else {
|
||||
rad = scale*(float)sizey;
|
||||
rad = scale*(float)nbd->sizey;
|
||||
if (rad>imgy/2)
|
||||
rad= imgy/2;
|
||||
else if (rad<1)
|
||||
rad= 1;
|
||||
|
||||
gausstab= make_gausstab(filtertype, rad);
|
||||
gausstab= make_gausstab(nbd->filtertype, rad);
|
||||
gausstabcent= gausstab+rad;
|
||||
|
||||
bigstep = pix*imgx;
|
||||
@@ -206,13 +207,6 @@ void node_composit_blur_single_image(bNode *node, int filtertype, int sizex, int
|
||||
free_compbuf(work);
|
||||
}
|
||||
|
||||
static void blur_single_image(bNode *node, CompBuf *new, CompBuf *img, float scale)
|
||||
{
|
||||
NodeBlurData *nbd = node->storage;
|
||||
|
||||
node_composit_blur_single_image(node, nbd->filtertype, nbd->sizex, nbd->sizey, new, img, scale);
|
||||
}
|
||||
|
||||
/* reference has to be mapped 0-1, and equal in size */
|
||||
static void bloom_with_reference(CompBuf *new, CompBuf *img, CompBuf *UNUSED(ref), float UNUSED(fac), NodeBlurData *nbd)
|
||||
{
|
||||
|
||||
@@ -44,7 +44,7 @@ static bNodeSocketTemplate cmp_node_dilateerode_out[]= {
|
||||
{ -1, 0, "" }
|
||||
};
|
||||
|
||||
void node_composite_morpho_dilate(CompBuf *cbuf)
|
||||
static void morpho_dilate(CompBuf *cbuf)
|
||||
{
|
||||
int x, y;
|
||||
float *p, *rectf = cbuf->rect;
|
||||
@@ -78,7 +78,7 @@ void node_composite_morpho_dilate(CompBuf *cbuf)
|
||||
}
|
||||
}
|
||||
|
||||
void node_composite_morpho_erode(CompBuf *cbuf)
|
||||
static void morpho_erode(CompBuf *cbuf)
|
||||
{
|
||||
int x, y;
|
||||
float *p, *rectf = cbuf->rect;
|
||||
@@ -133,11 +133,11 @@ static void node_composit_exec_dilateerode(void *UNUSED(data), bNode *node, bNod
|
||||
|
||||
if (node->custom2 > 0) { // positive, dilate
|
||||
for (i = 0; i < node->custom2; i++)
|
||||
node_composite_morpho_dilate(stackbuf);
|
||||
morpho_dilate(stackbuf);
|
||||
}
|
||||
else if (node->custom2 < 0) { // negative, erode
|
||||
for (i = 0; i > node->custom2; i--)
|
||||
node_composite_morpho_erode(stackbuf);
|
||||
morpho_erode(stackbuf);
|
||||
}
|
||||
|
||||
if (cbuf!=in[0]->data)
|
||||
|
||||
@@ -58,137 +58,8 @@ static bNodeSocketTemplate cmp_node_keying_out[] = {
|
||||
{ -1, 0, "" }
|
||||
};
|
||||
|
||||
static int get_pixel_primary_channel(float *pixel)
|
||||
static void exec(void *UNUSED(data), bNode *UNUSED(node), bNodeStack **UNUSED(in), bNodeStack **UNUSED(out))
|
||||
{
|
||||
float max_value = MAX3(pixel[0], pixel[1], pixel[2]);
|
||||
|
||||
if (max_value == pixel[0])
|
||||
return 0;
|
||||
else if (max_value == pixel[1])
|
||||
return 1;
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
static float get_pixel_saturation(float *pixel, float screen_balance)
|
||||
{
|
||||
float min = MIN3(pixel[0], pixel[1], pixel[2]);
|
||||
float max = MAX3(pixel[0], pixel[1], pixel[2]);
|
||||
float mid = pixel[0] + pixel[1] + pixel[2] - min - max;
|
||||
float val = (1.0f - screen_balance) * min + screen_balance * mid;
|
||||
|
||||
return max - val;
|
||||
}
|
||||
|
||||
static void despil_pixel(float *out, float *pixel, float *screen, float screen_gain)
|
||||
{
|
||||
int screen_primary_channel = get_pixel_primary_channel(screen);
|
||||
float average_value, amount;
|
||||
|
||||
average_value = (pixel[0] + pixel[1] + pixel[2] - pixel[screen_primary_channel]) / 2.0f;
|
||||
amount = pixel[screen_primary_channel] - average_value;
|
||||
|
||||
if (screen_gain * amount > 0) {
|
||||
out[screen_primary_channel] = pixel[screen_primary_channel] - screen_gain * amount;
|
||||
}
|
||||
}
|
||||
|
||||
static void do_key(bNode *node, float *out, float *pixel, float *screen)
|
||||
{
|
||||
NodeKeyingData *data = node->storage;
|
||||
|
||||
float screen_balance = 0.5f;
|
||||
float despill_factor = data->despill_factor;
|
||||
float clip_black = data->clip_black;
|
||||
float clip_white = data->clip_white;
|
||||
|
||||
float saturation = get_pixel_saturation(pixel, screen_balance);
|
||||
float screen_saturation = get_pixel_saturation(screen, screen_balance);
|
||||
int primary_channel = get_pixel_primary_channel(pixel);
|
||||
int screen_primary_channel = get_pixel_primary_channel(screen);
|
||||
|
||||
if (primary_channel != screen_primary_channel) {
|
||||
/* different main channel means pixel is on foreground,
|
||||
* but screen color still need to be despilled from it */
|
||||
despil_pixel(out, pixel, screen, despill_factor);
|
||||
out[3] = 1.0f;
|
||||
}
|
||||
else if (saturation >= screen_saturation) {
|
||||
/* saturation of main channel is more than screen, definitely a background */
|
||||
out[0] = 0.0f;
|
||||
out[1] = 0.0f;
|
||||
out[2] = 0.0f;
|
||||
out[3] = 0.0f;
|
||||
}
|
||||
else {
|
||||
float distance;
|
||||
|
||||
despil_pixel(out, pixel, screen, despill_factor);
|
||||
|
||||
distance = 1.0f - saturation / screen_saturation;
|
||||
|
||||
out[3] = distance;
|
||||
|
||||
if (out[3] < clip_black)
|
||||
out[3] = 0.0f;
|
||||
else if (out[3] >= clip_white)
|
||||
out[3] = 1.0f;
|
||||
else
|
||||
out[3] = (out[3] - clip_black) / (clip_white - clip_black);
|
||||
}
|
||||
}
|
||||
|
||||
static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
|
||||
{
|
||||
if (in[0]->data) {
|
||||
NodeKeyingData *keying_data = node->storage;
|
||||
CompBuf *cbuf = typecheck_compbuf(in[0]->data, CB_RGBA);
|
||||
CompBuf *keybuf, *mattebuf;
|
||||
|
||||
keybuf = dupalloc_compbuf(cbuf);
|
||||
|
||||
/* single color is used for screen detection */
|
||||
composit2_pixel_processor(node, keybuf, cbuf, in[0]->vec, in[1]->data, in[1]->vec, do_key, CB_RGBA, CB_VAL);
|
||||
|
||||
/* create a matte from alpha channel */
|
||||
mattebuf = valbuf_from_rgbabuf(keybuf, CHAN_A);
|
||||
|
||||
/* apply dilate/erode if needed */
|
||||
if (keying_data->dilate_distance != 0) {
|
||||
int i;
|
||||
|
||||
if (keying_data->dilate_distance > 0) {
|
||||
for (i = 0; i < keying_data->dilate_distance; i++)
|
||||
node_composite_morpho_dilate(mattebuf);
|
||||
}
|
||||
else {
|
||||
for (i = 0; i < -keying_data->dilate_distance; i++)
|
||||
node_composite_morpho_erode(mattebuf);
|
||||
}
|
||||
}
|
||||
|
||||
if (keying_data->blur_post > 0.0f) {
|
||||
/* post-blur of matte */
|
||||
CompBuf *newmatte = alloc_compbuf(mattebuf->x, mattebuf->y, mattebuf->type, TRUE);
|
||||
int size = keying_data->blur_post;
|
||||
|
||||
node_composit_blur_single_image(node, R_FILTER_BOX, size, size, newmatte, mattebuf, 1.0f);
|
||||
|
||||
free_compbuf(mattebuf);
|
||||
mattebuf = newmatte;
|
||||
|
||||
/* apply blurred matte on output buffer alpha */
|
||||
valbuf_to_rgbabuf(mattebuf, keybuf, CHAN_A);
|
||||
}
|
||||
|
||||
out[0]->data = keybuf;
|
||||
out[1]->data = mattebuf;
|
||||
|
||||
generate_preview(data, node, keybuf);
|
||||
|
||||
if (cbuf!=in[0]->data)
|
||||
free_compbuf(cbuf);
|
||||
}
|
||||
}
|
||||
|
||||
static void node_composit_init_keying(bNodeTree *UNUSED(ntree), bNode* node, bNodeTemplate *UNUSED(ntemp))
|
||||
|
||||
Reference in New Issue
Block a user