Changeset View
Changeset View
Standalone View
Standalone View
source/blender/compositor/operations/COM_DoubleEdgeMaskOperation.cc
| Show All 19 Lines | |||||
| #include "BLI_math.h" | #include "BLI_math.h" | ||||
| #include "COM_DoubleEdgeMaskOperation.h" | #include "COM_DoubleEdgeMaskOperation.h" | ||||
| #include "DNA_node_types.h" | #include "DNA_node_types.h" | ||||
| #include "MEM_guardedalloc.h" | #include "MEM_guardedalloc.h" | ||||
| namespace blender::compositor { | namespace blender::compositor { | ||||
| // this part has been copied from the double edge mask | /* This part has been copied from the double edge mask. */ | ||||
| static void do_adjacentKeepBorders(unsigned int t, | static void do_adjacentKeepBorders(unsigned int t, | ||||
| unsigned int rw, | unsigned int rw, | ||||
| const unsigned int *limask, | const unsigned int *limask, | ||||
| const unsigned int *lomask, | const unsigned int *lomask, | ||||
| unsigned int *lres, | unsigned int *lres, | ||||
| float *res, | float *res, | ||||
| unsigned int *rsize) | unsigned int *rsize) | ||||
| { | { | ||||
| int x; | int x; | ||||
| unsigned int isz = 0; // inner edge size | unsigned int isz = 0; /* Inner edge size. */ | ||||
| unsigned int osz = 0; // outer edge size | unsigned int osz = 0; /* Outer edge size. */ | ||||
| unsigned int gsz = 0; // gradient fill area size | unsigned int gsz = 0; /* Gradient fill area size. */ | ||||
| /* Test the four corners */ | /* Test the four corners */ | ||||
| /* upper left corner */ | /* Upper left corner. */ | ||||
| x = t - rw + 1; | x = t - rw + 1; | ||||
| // test if inner mask is filled | /* Test if inner mask is filled. */ | ||||
| if (limask[x]) { | if (limask[x]) { | ||||
| // test if pixel underneath, or to the right, are empty in the inner mask, | /* Test if pixel underneath, or to the right, are empty in the inner mask, | ||||
| // but filled in the outer mask | * but filled in the outer mask. */ | ||||
| if ((!limask[x - rw] && lomask[x - rw]) || (!limask[x + 1] && lomask[x + 1])) { | if ((!limask[x - rw] && lomask[x - rw]) || (!limask[x + 1] && lomask[x + 1])) { | ||||
| isz++; // increment inner edge size | isz++; /* Increment inner edge size. */ | ||||
| lres[x] = 4; // flag pixel as inner edge | lres[x] = 4; /* Flag pixel as inner edge. */ | ||||
| } | } | ||||
| else { | else { | ||||
| res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge | res[x] = 1.0f; /* Pixel is just part of inner mask, and it's not an edge. */ | ||||
| } | } | ||||
| } | } | ||||
| else if (lomask[x]) { // inner mask was empty, test if outer mask is filled | else if (lomask[x]) { /* Inner mask was empty, test if outer mask is filled. */ | ||||
| osz++; // increment outer edge size | osz++; /* Increment outer edge size. */ | ||||
| lres[x] = 3; // flag pixel as outer edge | lres[x] = 3; /* Flag pixel as outer edge. */ | ||||
| } | } | ||||
| /* upper right corner */ | /* Upper right corner. */ | ||||
| x = t; | x = t; | ||||
| // test if inner mask is filled | /* Test if inner mask is filled. */ | ||||
| if (limask[x]) { | if (limask[x]) { | ||||
| // test if pixel underneath, or to the left, are empty in the inner mask, | /* Test if pixel underneath, or to the left, are empty in the inner mask, | ||||
| // but filled in the outer mask | * but filled in the outer mask. */ | ||||
| if ((!limask[x - rw] && lomask[x - rw]) || (!limask[x - 1] && lomask[x - 1])) { | if ((!limask[x - rw] && lomask[x - rw]) || (!limask[x - 1] && lomask[x - 1])) { | ||||
| isz++; // increment inner edge size | isz++; /* Increment inner edge size. */ | ||||
| lres[x] = 4; // flag pixel as inner edge | lres[x] = 4; /* Flag pixel as inner edge. */ | ||||
| } | } | ||||
| else { | else { | ||||
| res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge | res[x] = 1.0f; /* Pixel is just part of inner mask, and it's not an edge. */ | ||||
| } | } | ||||
| } | } | ||||
| else if (lomask[x]) { // inner mask was empty, test if outer mask is filled | else if (lomask[x]) { /* Inner mask was empty, test if outer mask is filled. */ | ||||
| osz++; // increment outer edge size | osz++; /* Increment outer edge size. */ | ||||
| lres[x] = 3; // flag pixel as outer edge | lres[x] = 3; /* Flag pixel as outer edge. */ | ||||
| } | } | ||||
| /* lower left corner */ | /* Lower left corner. */ | ||||
| x = 0; | x = 0; | ||||
| // test if inner mask is filled | /* Test if inner mask is filled. */ | ||||
| if (limask[x]) { | if (limask[x]) { | ||||
| // test if pixel above, or to the right, are empty in the inner mask, | /* Test if pixel above, or to the right, are empty in the inner mask, | ||||
| // but filled in the outer mask | * but filled in the outer mask. */ | ||||
| if ((!limask[x + rw] && lomask[x + rw]) || (!limask[x + 1] && lomask[x + 1])) { | if ((!limask[x + rw] && lomask[x + rw]) || (!limask[x + 1] && lomask[x + 1])) { | ||||
| isz++; // increment inner edge size | isz++; /* Increment inner edge size. */ | ||||
| lres[x] = 4; // flag pixel as inner edge | lres[x] = 4; /* Flag pixel as inner edge. */ | ||||
| } | } | ||||
| else { | else { | ||||
| res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge | res[x] = 1.0f; /* Pixel is just part of inner mask, and it's not an edge. */ | ||||
| } | } | ||||
| } | } | ||||
| else if (lomask[x]) { // inner mask was empty, test if outer mask is filled | else if (lomask[x]) { /* Inner mask was empty, test if outer mask is filled. */ | ||||
| osz++; // increment outer edge size | osz++; /* Increment outer edge size. */ | ||||
| lres[x] = 3; // flag pixel as outer edge | lres[x] = 3; /* Flag pixel as outer edge. */ | ||||
| } | } | ||||
| /* lower right corner */ | /* Lower right corner. */ | ||||
| x = rw - 1; | x = rw - 1; | ||||
| // test if inner mask is filled | /* Test if inner mask is filled. */ | ||||
| if (limask[x]) { | if (limask[x]) { | ||||
| // test if pixel above, or to the left, are empty in the inner mask, | /* Test if pixel above, or to the left, are empty in the inner mask, | ||||
| // but filled in the outer mask | * but filled in the outer mask. */ | ||||
| if ((!limask[x + rw] && lomask[x + rw]) || (!limask[x - 1] && lomask[x - 1])) { | if ((!limask[x + rw] && lomask[x + rw]) || (!limask[x - 1] && lomask[x - 1])) { | ||||
| isz++; // increment inner edge size | isz++; /* Increment inner edge size. */ | ||||
| lres[x] = 4; // flag pixel as inner edge | lres[x] = 4; /* Flag pixel as inner edge. */ | ||||
| } | } | ||||
| else { | else { | ||||
| res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge | res[x] = 1.0f; /* Pixel is just part of inner mask, and it's not an edge. */ | ||||
| } | } | ||||
| } | } | ||||
| else if (lomask[x]) { // inner mask was empty, test if outer mask is filled | else if (lomask[x]) { /* Inner mask was empty, test if outer mask is filled. */ | ||||
| osz++; // increment outer edge size | osz++; /* Increment outer edge size. */ | ||||
| lres[x] = 3; // flag pixel as outer edge | lres[x] = 3; /* Flag pixel as outer edge. */ | ||||
| } | } | ||||
| /* Test the TOP row of pixels in buffer, except corners */ | /* Test the TOP row of pixels in buffer, except corners */ | ||||
| for (x = t - 1; x >= (t - rw) + 2; x--) { | for (x = t - 1; x >= (t - rw) + 2; x--) { | ||||
| // test if inner mask is filled | /* Test if inner mask is filled. */ | ||||
| if (limask[x]) { | if (limask[x]) { | ||||
| // test if pixel to the right, or to the left, are empty in the inner mask, | /* Test if pixel to the right, or to the left, are empty in the inner mask, | ||||
| // but filled in the outer mask | * but filled in the outer mask. */ | ||||
| if ((!limask[x - 1] && lomask[x - 1]) || (!limask[x + 1] && lomask[x + 1])) { | if ((!limask[x - 1] && lomask[x - 1]) || (!limask[x + 1] && lomask[x + 1])) { | ||||
| isz++; // increment inner edge size | isz++; /* Increment inner edge size. */ | ||||
| lres[x] = 4; // flag pixel as inner edge | lres[x] = 4; /* Flag pixel as inner edge. */ | ||||
| } | } | ||||
| else { | else { | ||||
| res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge | res[x] = 1.0f; /* Pixel is just part of inner mask, and it's not an edge. */ | ||||
| } | } | ||||
| } | } | ||||
| else if (lomask[x]) { // inner mask was empty, test if outer mask is filled | else if (lomask[x]) { /* Inner mask was empty, test if outer mask is filled. */ | ||||
| osz++; // increment outer edge size | osz++; /* Increment outer edge size. */ | ||||
| lres[x] = 3; // flag pixel as outer edge | lres[x] = 3; /* Flag pixel as outer edge. */ | ||||
| } | } | ||||
| } | } | ||||
| /* Test the BOTTOM row of pixels in buffer, except corners */ | /* Test the BOTTOM row of pixels in buffer, except corners */ | ||||
| for (x = rw - 2; x; x--) { | for (x = rw - 2; x; x--) { | ||||
| // test if inner mask is filled | /* Test if inner mask is filled. */ | ||||
| if (limask[x]) { | if (limask[x]) { | ||||
| // test if pixel to the right, or to the left, are empty in the inner mask, | /* Test if pixel to the right, or to the left, are empty in the inner mask, | ||||
| // but filled in the outer mask | * but filled in the outer mask. */ | ||||
| if ((!limask[x - 1] && lomask[x - 1]) || (!limask[x + 1] && lomask[x + 1])) { | if ((!limask[x - 1] && lomask[x - 1]) || (!limask[x + 1] && lomask[x + 1])) { | ||||
| isz++; // increment inner edge size | isz++; /* Increment inner edge size. */ | ||||
| lres[x] = 4; // flag pixel as inner edge | lres[x] = 4; /* Flag pixel as inner edge. */ | ||||
| } | } | ||||
| else { | else { | ||||
| res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge | res[x] = 1.0f; /* Pixel is just part of inner mask, and it's not an edge. */ | ||||
| } | } | ||||
| } | } | ||||
| else if (lomask[x]) { // inner mask was empty, test if outer mask is filled | else if (lomask[x]) { /* Inner mask was empty, test if outer mask is filled. */ | ||||
| osz++; // increment outer edge size | osz++; /* Increment outer edge size. */ | ||||
| lres[x] = 3; // flag pixel as outer edge | lres[x] = 3; /* Flag pixel as outer edge. */ | ||||
| } | } | ||||
| } | } | ||||
| /* Test the LEFT edge of pixels in buffer, except corners */ | /* Test the LEFT edge of pixels in buffer, except corners */ | ||||
| for (x = t - (rw << 1) + 1; x >= rw; x -= rw) { | for (x = t - (rw << 1) + 1; x >= rw; x -= rw) { | ||||
| // test if inner mask is filled | /* Test if inner mask is filled. */ | ||||
| if (limask[x]) { | if (limask[x]) { | ||||
| // test if pixel underneath, or above, are empty in the inner mask, | /* Test if pixel underneath, or above, are empty in the inner mask, | ||||
| // but filled in the outer mask | * but filled in the outer mask. */ | ||||
| if ((!limask[x - rw] && lomask[x - rw]) || (!limask[x + rw] && lomask[x + rw])) { | if ((!limask[x - rw] && lomask[x - rw]) || (!limask[x + rw] && lomask[x + rw])) { | ||||
| isz++; // increment inner edge size | isz++; /* Increment inner edge size. */ | ||||
| lres[x] = 4; // flag pixel as inner edge | lres[x] = 4; /* Flag pixel as inner edge. */ | ||||
| } | } | ||||
| else { | else { | ||||
| res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge | res[x] = 1.0f; /* Pixel is just part of inner mask, and it's not an edge. */ | ||||
| } | } | ||||
| } | } | ||||
| else if (lomask[x]) { // inner mask was empty, test if outer mask is filled | else if (lomask[x]) { /* Inner mask was empty, test if outer mask is filled. */ | ||||
| osz++; // increment outer edge size | osz++; /* Increment outer edge size. */ | ||||
| lres[x] = 3; // flag pixel as outer edge | lres[x] = 3; /* Flag pixel as outer edge. */ | ||||
| } | } | ||||
| } | } | ||||
| /* Test the RIGHT edge of pixels in buffer, except corners */ | /* Test the RIGHT edge of pixels in buffer, except corners */ | ||||
| for (x = t - rw; x > rw; x -= rw) { | for (x = t - rw; x > rw; x -= rw) { | ||||
| // test if inner mask is filled | /* Test if inner mask is filled. */ | ||||
| if (limask[x]) { | if (limask[x]) { | ||||
| // test if pixel underneath, or above, are empty in the inner mask, | /* Test if pixel underneath, or above, are empty in the inner mask, | ||||
| // but filled in the outer mask | * but filled in the outer mask. */ | ||||
| if ((!limask[x - rw] && lomask[x - rw]) || (!limask[x + rw] && lomask[x + rw])) { | if ((!limask[x - rw] && lomask[x - rw]) || (!limask[x + rw] && lomask[x + rw])) { | ||||
| isz++; // increment inner edge size | isz++; /* Increment inner edge size. */ | ||||
| lres[x] = 4; // flag pixel as inner edge | lres[x] = 4; /* Flag pixel as inner edge. */ | ||||
| } | } | ||||
| else { | else { | ||||
| res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge | res[x] = 1.0f; /* Pixel is just part of inner mask, and it's not an edge. */ | ||||
| } | } | ||||
| } | } | ||||
| else if (lomask[x]) { // inner mask was empty, test if outer mask is filled | else if (lomask[x]) { /* Inner mask was empty, test if outer mask is filled. */ | ||||
| osz++; // increment outer edge size | osz++; /* Increment outer edge size. */ | ||||
| lres[x] = 3; // flag pixel as outer edge | lres[x] = 3; /* Flag pixel as outer edge. */ | ||||
| } | } | ||||
| } | } | ||||
| rsize[0] = isz; // fill in our return sizes for edges + fill | rsize[0] = isz; /* Fill in our return sizes for edges + fill. */ | ||||
| rsize[1] = osz; | rsize[1] = osz; | ||||
| rsize[2] = gsz; | rsize[2] = gsz; | ||||
| } | } | ||||
| static void do_adjacentBleedBorders(unsigned int t, | static void do_adjacentBleedBorders(unsigned int t, | ||||
| unsigned int rw, | unsigned int rw, | ||||
| const unsigned int *limask, | const unsigned int *limask, | ||||
| const unsigned int *lomask, | const unsigned int *lomask, | ||||
| unsigned int *lres, | unsigned int *lres, | ||||
| float *res, | float *res, | ||||
| unsigned int *rsize) | unsigned int *rsize) | ||||
| { | { | ||||
| int x; | int x; | ||||
| unsigned int isz = 0; // inner edge size | unsigned int isz = 0; /* Inner edge size. */ | ||||
| unsigned int osz = 0; // outer edge size | unsigned int osz = 0; /* Outer edge size. */ | ||||
| unsigned int gsz = 0; // gradient fill area size | unsigned int gsz = 0; /* Gradient fill area size. */ | ||||
| /* Test the four corners */ | /* Test the four corners */ | ||||
| /* upper left corner */ | /* Upper left corner. */ | ||||
| x = t - rw + 1; | x = t - rw + 1; | ||||
| // test if inner mask is filled | /* Test if inner mask is filled. */ | ||||
| if (limask[x]) { | if (limask[x]) { | ||||
| // test if pixel underneath, or to the right, are empty in the inner mask, | /* Test if pixel underneath, or to the right, are empty in the inner mask, | ||||
| // but filled in the outer mask | * but filled in the outer mask. */ | ||||
| if ((!limask[x - rw] && lomask[x - rw]) || (!limask[x + 1] && lomask[x + 1])) { | if ((!limask[x - rw] && lomask[x - rw]) || (!limask[x + 1] && lomask[x + 1])) { | ||||
| isz++; // increment inner edge size | isz++; /* Increment inner edge size. */ | ||||
| lres[x] = 4; // flag pixel as inner edge | lres[x] = 4; /* Flag pixel as inner edge. */ | ||||
| } | } | ||||
| else { | else { | ||||
| res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge | res[x] = 1.0f; /* Pixel is just part of inner mask, and it's not an edge. */ | ||||
| } | } | ||||
| } | } | ||||
| else if (lomask[x]) { // inner mask was empty, test if outer mask is filled | else if (lomask[x]) { /* Inner mask was empty, test if outer mask is filled. */ | ||||
| if (!lomask[x - rw] || | if (!lomask[x - rw] || | ||||
| !lomask[x + 1]) { // test if outer mask is empty underneath or to the right | !lomask[x + 1]) { /* Test if outer mask is empty underneath or to the right. */ | ||||
| osz++; // increment outer edge size | osz++; /* Increment outer edge size. */ | ||||
| lres[x] = 3; // flag pixel as outer edge | lres[x] = 3; /* Flag pixel as outer edge. */ | ||||
| } | } | ||||
| else { | else { | ||||
| gsz++; // increment the gradient pixel count | gsz++; /* Increment the gradient pixel count. */ | ||||
| lres[x] = 2; // flag pixel as gradient | lres[x] = 2; /* Flag pixel as gradient. */ | ||||
| } | } | ||||
| } | } | ||||
| /* upper right corner */ | /* Upper right corner. */ | ||||
| x = t; | x = t; | ||||
| // test if inner mask is filled | /* Test if inner mask is filled. */ | ||||
| if (limask[x]) { | if (limask[x]) { | ||||
| // test if pixel underneath, or to the left, are empty in the inner mask, | /* Test if pixel underneath, or to the left, are empty in the inner mask, | ||||
| // but filled in the outer mask | * but filled in the outer mask. */ | ||||
| if ((!limask[x - rw] && lomask[x - rw]) || (!limask[x - 1] && lomask[x - 1])) { | if ((!limask[x - rw] && lomask[x - rw]) || (!limask[x - 1] && lomask[x - 1])) { | ||||
| isz++; // increment inner edge size | isz++; /* Increment inner edge size. */ | ||||
| lres[x] = 4; // flag pixel as inner edge | lres[x] = 4; /* Flag pixel as inner edge. */ | ||||
| } | } | ||||
| else { | else { | ||||
| res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge | res[x] = 1.0f; /* Pixel is just part of inner mask, and it's not an edge. */ | ||||
| } | } | ||||
| } | } | ||||
| else if (lomask[x]) { // inner mask was empty, test if outer mask is filled | else if (lomask[x]) { /* Inner mask was empty, test if outer mask is filled. */ | ||||
| if (!lomask[x - rw] || | if (!lomask[x - rw] || | ||||
| !lomask[x - 1]) { // test if outer mask is empty underneath or to the left | !lomask[x - 1]) { /* Test if outer mask is empty underneath or to the left. */ | ||||
| osz++; // increment outer edge size | osz++; /* Increment outer edge size. */ | ||||
| lres[x] = 3; // flag pixel as outer edge | lres[x] = 3; /* Flag pixel as outer edge. */ | ||||
| } | } | ||||
| else { | else { | ||||
| gsz++; // increment the gradient pixel count | gsz++; /* Increment the gradient pixel count. */ | ||||
| lres[x] = 2; // flag pixel as gradient | lres[x] = 2; /* Flag pixel as gradient. */ | ||||
| } | } | ||||
| } | } | ||||
| /* lower left corner */ | /* Lower left corner. */ | ||||
| x = 0; | x = 0; | ||||
| // test if inner mask is filled | /* Test if inner mask is filled. */ | ||||
| if (limask[x]) { | if (limask[x]) { | ||||
| // test if pixel above, or to the right, are empty in the inner mask, | /* Test if pixel above, or to the right, are empty in the inner mask, | ||||
| // but filled in the outer mask | * But filled in the outer mask. */ | ||||
| if ((!limask[x + rw] && lomask[x + rw]) || (!limask[x + 1] && lomask[x + 1])) { | if ((!limask[x + rw] && lomask[x + rw]) || (!limask[x + 1] && lomask[x + 1])) { | ||||
| isz++; // increment inner edge size | isz++; /* Increment inner edge size. */ | ||||
| lres[x] = 4; // flag pixel as inner edge | lres[x] = 4; /* Flag pixel as inner edge. */ | ||||
| } | } | ||||
| else { | else { | ||||
| res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge | res[x] = 1.0f; /* Pixel is just part of inner mask, and it's not an edge. */ | ||||
| } | } | ||||
| } | } | ||||
| else if (lomask[x]) { // inner mask was empty, test if outer mask is filled | else if (lomask[x]) { /* Inner mask was empty, test if outer mask is filled. */ | ||||
| if (!lomask[x + rw] || !lomask[x + 1]) { // test if outer mask is empty above or to the right | if (!lomask[x + rw] || | ||||
| osz++; // increment outer edge size | !lomask[x + 1]) { /* Test if outer mask is empty above or to the right. */ | ||||
| lres[x] = 3; // flag pixel as outer edge | osz++; /* Increment outer edge size. */ | ||||
| lres[x] = 3; /* Flag pixel as outer edge. */ | |||||
| } | } | ||||
| else { | else { | ||||
| gsz++; // increment the gradient pixel count | gsz++; /* Increment the gradient pixel count. */ | ||||
| lres[x] = 2; // flag pixel as gradient | lres[x] = 2; /* Flag pixel as gradient. */ | ||||
| } | } | ||||
| } | } | ||||
| /* lower right corner */ | /* Lower right corner. */ | ||||
| x = rw - 1; | x = rw - 1; | ||||
| // test if inner mask is filled | /* Test if inner mask is filled. */ | ||||
| if (limask[x]) { | if (limask[x]) { | ||||
| // test if pixel above, or to the left, are empty in the inner mask, | /* Test if pixel above, or to the left, are empty in the inner mask, | ||||
| // but filled in the outer mask | * but filled in the outer mask. */ | ||||
| if ((!limask[x + rw] && lomask[x + rw]) || (!limask[x - 1] && lomask[x - 1])) { | if ((!limask[x + rw] && lomask[x + rw]) || (!limask[x - 1] && lomask[x - 1])) { | ||||
| isz++; // increment inner edge size | isz++; /* Increment inner edge size. */ | ||||
| lres[x] = 4; // flag pixel as inner edge | lres[x] = 4; /* Flag pixel as inner edge. */ | ||||
| } | } | ||||
| else { | else { | ||||
| res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge | res[x] = 1.0f; /* Pixel is just part of inner mask, and it's not an edge. */ | ||||
| } | } | ||||
| } | } | ||||
| else if (lomask[x]) { // inner mask was empty, test if outer mask is filled | else if (lomask[x]) { /* Inner mask was empty, test if outer mask is filled. */ | ||||
| if (!lomask[x + rw] || !lomask[x - 1]) { // test if outer mask is empty above or to the left | if (!lomask[x + rw] || | ||||
| osz++; // increment outer edge size | !lomask[x - 1]) { /* Test if outer mask is empty above or to the left. */ | ||||
| lres[x] = 3; // flag pixel as outer edge | osz++; /* Increment outer edge size. */ | ||||
| lres[x] = 3; /* Flag pixel as outer edge. */ | |||||
| } | } | ||||
| else { | else { | ||||
| gsz++; // increment the gradient pixel count | gsz++; /* Increment the gradient pixel count. */ | ||||
| lres[x] = 2; // flag pixel as gradient | lres[x] = 2; /* Flag pixel as gradient. */ | ||||
| } | } | ||||
| } | } | ||||
| /* Test the TOP row of pixels in buffer, except corners */ | /* Test the TOP row of pixels in buffer, except corners */ | ||||
| for (x = t - 1; x >= (t - rw) + 2; x--) { | for (x = t - 1; x >= (t - rw) + 2; x--) { | ||||
| // test if inner mask is filled | /* Test if inner mask is filled. */ | ||||
| if (limask[x]) { | if (limask[x]) { | ||||
| // test if pixel to the left, or to the right, are empty in the inner mask, | /* Test if pixel to the left, or to the right, are empty in the inner mask, | ||||
| // but filled in the outer mask | * but filled in the outer mask. */ | ||||
| if ((!limask[x - 1] && lomask[x - 1]) || (!limask[x + 1] && lomask[x + 1])) { | if ((!limask[x - 1] && lomask[x - 1]) || (!limask[x + 1] && lomask[x + 1])) { | ||||
| isz++; // increment inner edge size | isz++; /* Increment inner edge size. */ | ||||
| lres[x] = 4; // flag pixel as inner edge | lres[x] = 4; /* Flag pixel as inner edge. */ | ||||
| } | } | ||||
| else { | else { | ||||
| res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge | res[x] = 1.0f; /* Pixel is just part of inner mask, and it's not an edge. */ | ||||
| } | } | ||||
| } | } | ||||
| else if (lomask[x]) { // inner mask was empty, test if outer mask is filled | else if (lomask[x]) { /* Inner mask was empty, test if outer mask is filled. */ | ||||
| if (!lomask[x - 1] || | if (!lomask[x - 1] || | ||||
| !lomask[x + 1]) { // test if outer mask is empty to the left or to the right | !lomask[x + 1]) { /* Test if outer mask is empty to the left or to the right. */ | ||||
| osz++; // increment outer edge size | osz++; /* Increment outer edge size. */ | ||||
| lres[x] = 3; // flag pixel as outer edge | lres[x] = 3; /* Flag pixel as outer edge. */ | ||||
| } | } | ||||
| else { | else { | ||||
| gsz++; // increment the gradient pixel count | gsz++; /* Increment the gradient pixel count. */ | ||||
| lres[x] = 2; // flag pixel as gradient | lres[x] = 2; /* Flag pixel as gradient. */ | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /* Test the BOTTOM row of pixels in buffer, except corners */ | /* Test the BOTTOM row of pixels in buffer, except corners */ | ||||
| for (x = rw - 2; x; x--) { | for (x = rw - 2; x; x--) { | ||||
| // test if inner mask is filled | /* Test if inner mask is filled. */ | ||||
| if (limask[x]) { | if (limask[x]) { | ||||
| // test if pixel to the left, or to the right, are empty in the inner mask, | /* Test if pixel to the left, or to the right, are empty in the inner mask, | ||||
| // but filled in the outer mask | * but filled in the outer mask. */ | ||||
| if ((!limask[x - 1] && lomask[x - 1]) || (!limask[x + 1] && lomask[x + 1])) { | if ((!limask[x - 1] && lomask[x - 1]) || (!limask[x + 1] && lomask[x + 1])) { | ||||
| isz++; // increment inner edge size | isz++; /* Increment inner edge size. */ | ||||
| lres[x] = 4; // flag pixel as inner edge | lres[x] = 4; /* Flag pixel as inner edge. */ | ||||
| } | } | ||||
| else { | else { | ||||
| res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge | res[x] = 1.0f; /* Pixel is just part of inner mask, and it's not an edge. */ | ||||
| } | } | ||||
| } | } | ||||
| else if (lomask[x]) { // inner mask was empty, test if outer mask is filled | else if (lomask[x]) { /* Inner mask was empty, test if outer mask is filled. */ | ||||
| if (!lomask[x - 1] || | if (!lomask[x - 1] || | ||||
| !lomask[x + 1]) { // test if outer mask is empty to the left or to the right | !lomask[x + 1]) { /* Test if outer mask is empty to the left or to the right. */ | ||||
| osz++; // increment outer edge size | osz++; /* Increment outer edge size. */ | ||||
| lres[x] = 3; // flag pixel as outer edge | lres[x] = 3; /* Flag pixel as outer edge. */ | ||||
| } | } | ||||
| else { | else { | ||||
| gsz++; // increment the gradient pixel count | gsz++; /* Increment the gradient pixel count. */ | ||||
| lres[x] = 2; // flag pixel as gradient | lres[x] = 2; /* Flag pixel as gradient. */ | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /* Test the LEFT edge of pixels in buffer, except corners */ | /* Test the LEFT edge of pixels in buffer, except corners */ | ||||
| for (x = t - (rw << 1) + 1; x >= rw; x -= rw) { | for (x = t - (rw << 1) + 1; x >= rw; x -= rw) { | ||||
| // test if inner mask is filled | /* Test if inner mask is filled. */ | ||||
| if (limask[x]) { | if (limask[x]) { | ||||
| // test if pixel underneath, or above, are empty in the inner mask, | /* Test if pixel underneath, or above, are empty in the inner mask, | ||||
| // but filled in the outer mask | * but filled in the outer mask. */ | ||||
| if ((!limask[x - rw] && lomask[x - rw]) || (!limask[x + rw] && lomask[x + rw])) { | if ((!limask[x - rw] && lomask[x - rw]) || (!limask[x + rw] && lomask[x + rw])) { | ||||
| isz++; // increment inner edge size | isz++; /* Increment inner edge size. */ | ||||
| lres[x] = 4; // flag pixel as inner edge | lres[x] = 4; /* Flag pixel as inner edge. */ | ||||
| } | } | ||||
| else { | else { | ||||
| res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge | res[x] = 1.0f; /* Pixel is just part of inner mask, and it's not an edge. */ | ||||
| } | } | ||||
| } | } | ||||
| else if (lomask[x]) { // inner mask was empty, test if outer mask is filled | else if (lomask[x]) { /* Inner mask was empty, test if outer mask is filled. */ | ||||
| if (!lomask[x - rw] || !lomask[x + rw]) { // test if outer mask is empty underneath or above | if (!lomask[x - rw] || | ||||
| osz++; // increment outer edge size | !lomask[x + rw]) { /* Test if outer mask is empty underneath or above. */ | ||||
| lres[x] = 3; // flag pixel as outer edge | osz++; /* Increment outer edge size. */ | ||||
| lres[x] = 3; /* Flag pixel as outer edge. */ | |||||
| } | } | ||||
| else { | else { | ||||
| gsz++; // increment the gradient pixel count | gsz++; /* Increment the gradient pixel count. */ | ||||
| lres[x] = 2; // flag pixel as gradient | lres[x] = 2; /* Flag pixel as gradient. */ | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /* Test the RIGHT edge of pixels in buffer, except corners */ | /* Test the RIGHT edge of pixels in buffer, except corners */ | ||||
| for (x = t - rw; x > rw; x -= rw) { | for (x = t - rw; x > rw; x -= rw) { | ||||
| // test if inner mask is filled | /* Test if inner mask is filled. */ | ||||
| if (limask[x]) { | if (limask[x]) { | ||||
| // test if pixel underneath, or above, are empty in the inner mask, | /* Test if pixel underneath, or above, are empty in the inner mask, | ||||
| // but filled in the outer mask | * But filled in the outer mask. */ | ||||
| if ((!limask[x - rw] && lomask[x - rw]) || (!limask[x + rw] && lomask[x + rw])) { | if ((!limask[x - rw] && lomask[x - rw]) || (!limask[x + rw] && lomask[x + rw])) { | ||||
| isz++; // increment inner edge size | isz++; /* Increment inner edge size. */ | ||||
| lres[x] = 4; // flag pixel as inner edge | lres[x] = 4; /* Flag pixel as inner edge. */ | ||||
| } | } | ||||
| else { | else { | ||||
| res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge | res[x] = 1.0f; /* Pixel is just part of inner mask, and it's not an edge. */ | ||||
| } | } | ||||
| } | } | ||||
| else if (lomask[x]) { // inner mask was empty, test if outer mask is filled | else if (lomask[x]) { /* Inner mask was empty, test if outer mask is filled. */ | ||||
| if (!lomask[x - rw] || !lomask[x + rw]) { // test if outer mask is empty underneath or above | if (!lomask[x - rw] || | ||||
| osz++; // increment outer edge size | !lomask[x + rw]) { /* Test if outer mask is empty underneath or above. */ | ||||
| lres[x] = 3; // flag pixel as outer edge | osz++; /* Increment outer edge size. */ | ||||
| lres[x] = 3; /* Flag pixel as outer edge. */ | |||||
| } | } | ||||
| else { | else { | ||||
| gsz++; // increment the gradient pixel count | gsz++; /* Increment the gradient pixel count. */ | ||||
| lres[x] = 2; // flag pixel as gradient | lres[x] = 2; /* Flag pixel as gradient. */ | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| rsize[0] = isz; // fill in our return sizes for edges + fill | rsize[0] = isz; /* Fill in our return sizes for edges + fill. */ | ||||
| rsize[1] = osz; | rsize[1] = osz; | ||||
| rsize[2] = gsz; | rsize[2] = gsz; | ||||
| } | } | ||||
| static void do_allKeepBorders(unsigned int t, | static void do_allKeepBorders(unsigned int t, | ||||
| unsigned int rw, | unsigned int rw, | ||||
| const unsigned int *limask, | const unsigned int *limask, | ||||
| const unsigned int *lomask, | const unsigned int *lomask, | ||||
| unsigned int *lres, | unsigned int *lres, | ||||
| float *res, | float *res, | ||||
| unsigned int *rsize) | unsigned int *rsize) | ||||
| { | { | ||||
| int x; | int x; | ||||
| unsigned int isz = 0; // inner edge size | unsigned int isz = 0; /* Inner edge size. */ | ||||
| unsigned int osz = 0; // outer edge size | unsigned int osz = 0; /* Outer edge size. */ | ||||
| unsigned int gsz = 0; // gradient fill area size | unsigned int gsz = 0; /* Gradient fill area size. */ | ||||
| /* Test the four corners */ | /* Test the four corners. */ | ||||
| /* upper left corner */ | /* Upper left corner. */ | ||||
| x = t - rw + 1; | x = t - rw + 1; | ||||
| // test if inner mask is filled | /* Test if inner mask is filled. */ | ||||
| if (limask[x]) { | if (limask[x]) { | ||||
| // test if the inner mask is empty underneath or to the right | /* Test if the inner mask is empty underneath or to the right. */ | ||||
| if (!limask[x - rw] || !limask[x + 1]) { | if (!limask[x - rw] || !limask[x + 1]) { | ||||
| isz++; // increment inner edge size | isz++; /* Increment inner edge size. */ | ||||
| lres[x] = 4; // flag pixel as inner edge | lres[x] = 4; /* Flag pixel as inner edge. */ | ||||
| } | } | ||||
| else { | else { | ||||
| res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge | res[x] = 1.0f; /* Pixel is just part of inner mask, and it's not an edge. */ | ||||
| } | } | ||||
| } | } | ||||
| else if (lomask[x]) { // inner mask was empty, test if outer mask is filled | else if (lomask[x]) { /* Inner mask was empty, test if outer mask is filled. */ | ||||
| osz++; // increment outer edge size | osz++; /* Increment outer edge size. */ | ||||
| lres[x] = 3; // flag pixel as outer edge | lres[x] = 3; /* Flag pixel as outer edge. */ | ||||
| } | } | ||||
| /* upper right corner */ | /* Upper right corner. */ | ||||
| x = t; | x = t; | ||||
| // test if inner mask is filled | /* Test if inner mask is filled. */ | ||||
| if (limask[x]) { | if (limask[x]) { | ||||
| // test if the inner mask is empty underneath or to the left | /* Test if the inner mask is empty underneath or to the left. */ | ||||
| if (!limask[x - rw] || !limask[x - 1]) { | if (!limask[x - rw] || !limask[x - 1]) { | ||||
| isz++; // increment inner edge size | isz++; /* Increment inner edge size. */ | ||||
| lres[x] = 4; // flag pixel as inner edge | lres[x] = 4; /* Flag pixel as inner edge. */ | ||||
| } | } | ||||
| else { | else { | ||||
| res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge | res[x] = 1.0f; /* Pixel is just part of inner mask, and it's not an edge. */ | ||||
| } | } | ||||
| } | } | ||||
| else if (lomask[x]) { // inner mask was empty, test if outer mask is filled | else if (lomask[x]) { /* Inner mask was empty, test if outer mask is filled. */ | ||||
| osz++; // increment outer edge size | osz++; /* Increment outer edge size. */ | ||||
| lres[x] = 3; // flag pixel as outer edge | lres[x] = 3; /* Flag pixel as outer edge. */ | ||||
| } | } | ||||
| /* lower left corner */ | /* Lower left corner. */ | ||||
| x = 0; | x = 0; | ||||
| // test if inner mask is filled | /* Test if inner mask is filled. */ | ||||
| if (limask[x]) { | if (limask[x]) { | ||||
| // test if inner mask is empty above or to the right | /* Test if inner mask is empty above or to the right. */ | ||||
| if (!limask[x + rw] || !limask[x + 1]) { | if (!limask[x + rw] || !limask[x + 1]) { | ||||
| isz++; // increment inner edge size | isz++; /* Increment inner edge size. */ | ||||
| lres[x] = 4; // flag pixel as inner edge | lres[x] = 4; /* Flag pixel as inner edge. */ | ||||
| } | } | ||||
| else { | else { | ||||
| res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge | res[x] = 1.0f; /* Pixel is just part of inner mask, and it's not an edge. */ | ||||
| } | } | ||||
| } | } | ||||
| else if (lomask[x]) { // inner mask was empty, test if outer mask is filled | else if (lomask[x]) { /* Inner mask was empty, test if outer mask is filled. */ | ||||
| osz++; // increment outer edge size | osz++; /* Increment outer edge size. */ | ||||
| lres[x] = 3; // flag pixel as outer edge | lres[x] = 3; /* Flag pixel as outer edge. */ | ||||
| } | } | ||||
| /* lower right corner */ | /* Lower right corner. */ | ||||
| x = rw - 1; | x = rw - 1; | ||||
| // test if inner mask is filled | /* Test if inner mask is filled. */ | ||||
| if (limask[x]) { | if (limask[x]) { | ||||
| // test if inner mask is empty above or to the left | /* Test if inner mask is empty above or to the left. */ | ||||
| if (!limask[x + rw] || !limask[x - 1]) { | if (!limask[x + rw] || !limask[x - 1]) { | ||||
| isz++; // increment inner edge size | isz++; /* Increment inner edge size. */ | ||||
| lres[x] = 4; // flag pixel as inner edge | lres[x] = 4; /* Flag pixel as inner edge. */ | ||||
| } | } | ||||
| else { | else { | ||||
| res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge | res[x] = 1.0f; /* Pixel is just part of inner mask, and it's not an edge. */ | ||||
| } | } | ||||
| } | } | ||||
| else if (lomask[x]) { // inner mask was empty, test if outer mask is filled | else if (lomask[x]) { /* Inner mask was empty, test if outer mask is filled. */ | ||||
| osz++; // increment outer edge size | osz++; /* Increment outer edge size. */ | ||||
| lres[x] = 3; // flag pixel as outer edge | lres[x] = 3; /* Flag pixel as outer edge. */ | ||||
| } | } | ||||
| /* Test the TOP row of pixels in buffer, except corners */ | /* Test the TOP row of pixels in buffer, except corners */ | ||||
| for (x = t - 1; x >= (t - rw) + 2; x--) { | for (x = t - 1; x >= (t - rw) + 2; x--) { | ||||
| // test if inner mask is filled | /* Test if inner mask is filled. */ | ||||
| if (limask[x]) { | if (limask[x]) { | ||||
| // test if inner mask is empty to the left or to the right | /* Test if inner mask is empty to the left or to the right. */ | ||||
| if (!limask[x - 1] || !limask[x + 1]) { | if (!limask[x - 1] || !limask[x + 1]) { | ||||
| isz++; // increment inner edge size | isz++; /* Increment inner edge size. */ | ||||
| lres[x] = 4; // flag pixel as inner edge | lres[x] = 4; /* Flag pixel as inner edge. */ | ||||
| } | } | ||||
| else { | else { | ||||
| res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge | res[x] = 1.0f; /* Pixel is just part of inner mask, and it's not an edge. */ | ||||
| } | } | ||||
| } | } | ||||
| else if (lomask[x]) { // inner mask was empty, test if outer mask is filled | else if (lomask[x]) { /* Inner mask was empty, test if outer mask is filled. */ | ||||
| osz++; // increment outer edge size | osz++; /* Increment outer edge size. */ | ||||
| lres[x] = 3; // flag pixel as outer edge | lres[x] = 3; /* Flag pixel as outer edge. */ | ||||
| } | } | ||||
| } | } | ||||
| /* Test the BOTTOM row of pixels in buffer, except corners */ | /* Test the BOTTOM row of pixels in buffer, except corners */ | ||||
| for (x = rw - 2; x; x--) { | for (x = rw - 2; x; x--) { | ||||
| // test if inner mask is filled | /* Test if inner mask is filled. */ | ||||
| if (limask[x]) { | if (limask[x]) { | ||||
| // test if inner mask is empty to the left or to the right | /* Test if inner mask is empty to the left or to the right. */ | ||||
| if (!limask[x - 1] || !limask[x + 1]) { | if (!limask[x - 1] || !limask[x + 1]) { | ||||
| isz++; // increment inner edge size | isz++; /* Increment inner edge size. */ | ||||
| lres[x] = 4; // flag pixel as inner edge | lres[x] = 4; /* Flag pixel as inner edge. */ | ||||
| } | } | ||||
| else { | else { | ||||
| res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge | res[x] = 1.0f; /* Pixel is just part of inner mask, and it's not an edge. */ | ||||
| } | } | ||||
| } | } | ||||
| else if (lomask[x]) { // inner mask was empty, test if outer mask is filled | else if (lomask[x]) { /* Inner mask was empty, test if outer mask is filled. */ | ||||
| osz++; // increment outer edge size | osz++; /* Increment outer edge size. */ | ||||
| lres[x] = 3; // flag pixel as outer edge | lres[x] = 3; /* Flag pixel as outer edge. */ | ||||
| } | } | ||||
| } | } | ||||
| /* Test the LEFT edge of pixels in buffer, except corners */ | /* Test the LEFT edge of pixels in buffer, except corners */ | ||||
| for (x = t - (rw << 1) + 1; x >= rw; x -= rw) { | for (x = t - (rw << 1) + 1; x >= rw; x -= rw) { | ||||
| // test if inner mask is filled | /* Test if inner mask is filled. */ | ||||
| if (limask[x]) { | if (limask[x]) { | ||||
| // test if inner mask is empty underneath or above | /* Test if inner mask is empty underneath or above. */ | ||||
| if (!limask[x - rw] || !limask[x + rw]) { | if (!limask[x - rw] || !limask[x + rw]) { | ||||
| isz++; // increment inner edge size | isz++; /* Increment inner edge size. */ | ||||
| lres[x] = 4; // flag pixel as inner edge | lres[x] = 4; /* Flag pixel as inner edge. */ | ||||
| } | } | ||||
| else { | else { | ||||
| res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge | res[x] = 1.0f; /* Pixel is just part of inner mask, and it's not an edge. */ | ||||
| } | } | ||||
| } | } | ||||
| else if (lomask[x]) { // inner mask was empty, test if outer mask is filled | else if (lomask[x]) { /* Inner mask was empty, test if outer mask is filled. */ | ||||
| osz++; // increment outer edge size | osz++; /* Increment outer edge size. */ | ||||
| lres[x] = 3; // flag pixel as outer edge | lres[x] = 3; /* Flag pixel as outer edge. */ | ||||
| } | } | ||||
| } | } | ||||
| /* Test the RIGHT edge of pixels in buffer, except corners */ | /* Test the RIGHT edge of pixels in buffer, except corners */ | ||||
| for (x = t - rw; x > rw; x -= rw) { | for (x = t - rw; x > rw; x -= rw) { | ||||
| // test if inner mask is filled | /* Test if inner mask is filled. */ | ||||
| if (limask[x]) { | if (limask[x]) { | ||||
| // test if inner mask is empty underneath or above | /* Test if inner mask is empty underneath or above. */ | ||||
| if (!limask[x - rw] || !limask[x + rw]) { | if (!limask[x - rw] || !limask[x + rw]) { | ||||
| isz++; // increment inner edge size | isz++; /* Increment inner edge size. */ | ||||
| lres[x] = 4; // flag pixel as inner edge | lres[x] = 4; /* Flag pixel as inner edge. */ | ||||
| } | } | ||||
| else { | else { | ||||
| res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge | res[x] = 1.0f; /* Pixel is just part of inner mask, and it's not an edge. */ | ||||
| } | } | ||||
| } | } | ||||
| else if (lomask[x]) { // inner mask was empty, test if outer mask is filled | else if (lomask[x]) { /* Inner mask was empty, test if outer mask is filled. */ | ||||
| osz++; // increment outer edge size | osz++; /* Increment outer edge size. */ | ||||
| lres[x] = 3; // flag pixel as outer edge | lres[x] = 3; /* Flag pixel as outer edge. */ | ||||
| } | } | ||||
| } | } | ||||
| rsize[0] = isz; // fill in our return sizes for edges + fill | rsize[0] = isz; /* Fill in our return sizes for edges + fill. */ | ||||
| rsize[1] = osz; | rsize[1] = osz; | ||||
| rsize[2] = gsz; | rsize[2] = gsz; | ||||
| } | } | ||||
| static void do_allBleedBorders(unsigned int t, | static void do_allBleedBorders(unsigned int t, | ||||
| unsigned int rw, | unsigned int rw, | ||||
| const unsigned int *limask, | const unsigned int *limask, | ||||
| const unsigned int *lomask, | const unsigned int *lomask, | ||||
| unsigned int *lres, | unsigned int *lres, | ||||
| float *res, | float *res, | ||||
| unsigned int *rsize) | unsigned int *rsize) | ||||
| { | { | ||||
| int x; | int x; | ||||
| unsigned int isz = 0; // inner edge size | unsigned int isz = 0; /* Inner edge size. */ | ||||
| unsigned int osz = 0; // outer edge size | unsigned int osz = 0; /* Outer edge size. */ | ||||
| unsigned int gsz = 0; // gradient fill area size | unsigned int gsz = 0; /* Gradient fill area size. */ | ||||
| /* Test the four corners */ | /* Test the four corners */ | ||||
| /* upper left corner */ | /* Upper left corner. */ | ||||
| x = t - rw + 1; | x = t - rw + 1; | ||||
| // test if inner mask is filled | /* Test if inner mask is filled. */ | ||||
| if (limask[x]) { | if (limask[x]) { | ||||
| // test if the inner mask is empty underneath or to the right | /* Test if the inner mask is empty underneath or to the right. */ | ||||
| if (!limask[x - rw] || !limask[x + 1]) { | if (!limask[x - rw] || !limask[x + 1]) { | ||||
| isz++; // increment inner edge size | isz++; /* Increment inner edge size. */ | ||||
| lres[x] = 4; // flag pixel as inner edge | lres[x] = 4; /* Flag pixel as inner edge. */ | ||||
| } | } | ||||
| else { | else { | ||||
| res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge | res[x] = 1.0f; /* Pixel is just part of inner mask, and it's not an edge. */ | ||||
| } | } | ||||
| } | } | ||||
| else if (lomask[x]) { // inner mask was empty, test if outer mask is filled | else if (lomask[x]) { /* Inner mask was empty, test if outer mask is filled. */ | ||||
| if (!lomask[x - rw] || | if (!lomask[x - rw] || | ||||
| !lomask[x + 1]) { // test if outer mask is empty underneath or to the right | !lomask[x + 1]) { /* Test if outer mask is empty underneath or to the right. */ | ||||
| osz++; // increment outer edge size | osz++; /* Increment outer edge size. */ | ||||
| lres[x] = 3; // flag pixel as outer edge | lres[x] = 3; /* Flag pixel as outer edge. */ | ||||
| } | } | ||||
| else { | else { | ||||
| gsz++; // increment the gradient pixel count | gsz++; /* Increment the gradient pixel count. */ | ||||
| lres[x] = 2; // flag pixel as gradient | lres[x] = 2; /* Flag pixel as gradient. */ | ||||
| } | } | ||||
| } | } | ||||
| /* upper right corner */ | /* Upper right corner. */ | ||||
| x = t; | x = t; | ||||
| // test if inner mask is filled | /* Test if inner mask is filled. */ | ||||
| if (limask[x]) { | if (limask[x]) { | ||||
| // test if the inner mask is empty underneath or to the left | /* Test if the inner mask is empty underneath or to the left. */ | ||||
| if (!limask[x - rw] || !limask[x - 1]) { | if (!limask[x - rw] || !limask[x - 1]) { | ||||
| isz++; // increment inner edge size | isz++; /* Increment inner edge size. */ | ||||
| lres[x] = 4; // flag pixel as inner edge | lres[x] = 4; /* Flag pixel as inner edge. */ | ||||
| } | } | ||||
| else { | else { | ||||
| res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge | res[x] = 1.0f; /* Pixel is just part of inner mask, and it's not an edge. */ | ||||
| } | } | ||||
| } | } | ||||
| else if (lomask[x]) { // inner mask was empty, test if outer mask is filled | else if (lomask[x]) { /* Inner mask was empty, test if outer mask is filled. */ | ||||
| if (!lomask[x - rw] || !lomask[x - 1]) { // test if outer mask is empty above or to the left | if (!lomask[x - rw] || | ||||
| osz++; // increment outer edge size | !lomask[x - 1]) { /* Test if outer mask is empty above or to the left. */ | ||||
| lres[x] = 3; // flag pixel as outer edge | osz++; /* Increment outer edge size. */ | ||||
| lres[x] = 3; /* Flag pixel as outer edge. */ | |||||
| } | } | ||||
| else { | else { | ||||
| gsz++; // increment the gradient pixel count | gsz++; /* Increment the gradient pixel count. */ | ||||
| lres[x] = 2; // flag pixel as gradient | lres[x] = 2; /* Flag pixel as gradient. */ | ||||
| } | } | ||||
| } | } | ||||
| /* lower left corner */ | /* Lower left corner. */ | ||||
| x = 0; | x = 0; | ||||
| // test if inner mask is filled | /* Test if inner mask is filled. */ | ||||
| if (limask[x]) { | if (limask[x]) { | ||||
| // test if inner mask is empty above or to the right | /* Test if inner mask is empty above or to the right. */ | ||||
| if (!limask[x + rw] || !limask[x + 1]) { | if (!limask[x + rw] || !limask[x + 1]) { | ||||
| isz++; // increment inner edge size | isz++; /* Increment inner edge size. */ | ||||
| lres[x] = 4; // flag pixel as inner edge | lres[x] = 4; /* Flag pixel as inner edge. */ | ||||
| } | } | ||||
| else { | else { | ||||
| res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge | res[x] = 1.0f; /* Pixel is just part of inner mask, and it's not an edge. */ | ||||
| } | } | ||||
| } | } | ||||
| else if (lomask[x]) { // inner mask was empty, test if outer mask is filled | else if (lomask[x]) { /* Inner mask was empty, test if outer mask is filled. */ | ||||
| if (!lomask[x + rw] || | if (!lomask[x + rw] || | ||||
| !lomask[x + 1]) { // test if outer mask is empty underneath or to the right | !lomask[x + 1]) { /* Test if outer mask is empty underneath or to the right. */ | ||||
| osz++; // increment outer edge size | osz++; /* Increment outer edge size. */ | ||||
| lres[x] = 3; // flag pixel as outer edge | lres[x] = 3; /* Flag pixel as outer edge. */ | ||||
| } | } | ||||
| else { | else { | ||||
| gsz++; // increment the gradient pixel count | gsz++; /* Increment the gradient pixel count. */ | ||||
| lres[x] = 2; // flag pixel as gradient | lres[x] = 2; /* Flag pixel as gradient. */ | ||||
| } | } | ||||
| } | } | ||||
| /* lower right corner */ | /* Lower right corner. */ | ||||
| x = rw - 1; | x = rw - 1; | ||||
| // test if inner mask is filled | /* Test if inner mask is filled. */ | ||||
| if (limask[x]) { | if (limask[x]) { | ||||
| // test if inner mask is empty above or to the left | /* Test if inner mask is empty above or to the left. */ | ||||
| if (!limask[x + rw] || !limask[x - 1]) { | if (!limask[x + rw] || !limask[x - 1]) { | ||||
| isz++; // increment inner edge size | isz++; /* Increment inner edge size. */ | ||||
| lres[x] = 4; // flag pixel as inner edge | lres[x] = 4; /* Flag pixel as inner edge. */ | ||||
| } | } | ||||
| else { | else { | ||||
| res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge | res[x] = 1.0f; /* Pixel is just part of inner mask, and it's not an edge. */ | ||||
| } | } | ||||
| } | } | ||||
| else if (lomask[x]) { // inner mask was empty, test if outer mask is filled | else if (lomask[x]) { /* Inner mask was empty, test if outer mask is filled. */ | ||||
| if (!lomask[x + rw] || | if (!lomask[x + rw] || | ||||
| !lomask[x - 1]) { // test if outer mask is empty underneath or to the left | !lomask[x - 1]) { /* Test if outer mask is empty underneath or to the left. */ | ||||
| osz++; // increment outer edge size | osz++; /* Increment outer edge size. */ | ||||
| lres[x] = 3; // flag pixel as outer edge | lres[x] = 3; /* Flag pixel as outer edge. */ | ||||
| } | } | ||||
| else { | else { | ||||
| gsz++; // increment the gradient pixel count | gsz++; /* Increment the gradient pixel count. */ | ||||
| lres[x] = 2; // flag pixel as gradient | lres[x] = 2; /* Flag pixel as gradient. */ | ||||
| } | } | ||||
| } | } | ||||
| /* Test the TOP row of pixels in buffer, except corners */ | /* Test the TOP row of pixels in buffer, except corners */ | ||||
| for (x = t - 1; x >= (t - rw) + 2; x--) { | for (x = t - 1; x >= (t - rw) + 2; x--) { | ||||
| // test if inner mask is filled | /* Test if inner mask is filled. */ | ||||
| if (limask[x]) { | if (limask[x]) { | ||||
| // test if inner mask is empty to the left or to the right | /* Test if inner mask is empty to the left or to the right. */ | ||||
| if (!limask[x - 1] || !limask[x + 1]) { | if (!limask[x - 1] || !limask[x + 1]) { | ||||
| isz++; // increment inner edge size | isz++; /* Increment inner edge size. */ | ||||
| lres[x] = 4; // flag pixel as inner edge | lres[x] = 4; /* Flag pixel as inner edge. */ | ||||
| } | } | ||||
| else { | else { | ||||
| res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge | res[x] = 1.0f; /* Pixel is just part of inner mask, and it's not an edge. */ | ||||
| } | } | ||||
| } | } | ||||
| else if (lomask[x]) { // inner mask was empty, test if outer mask is filled | else if (lomask[x]) { /* Inner mask was empty, test if outer mask is filled. */ | ||||
| if (!lomask[x - 1] || | if (!lomask[x - 1] || | ||||
| !lomask[x + 1]) { // test if outer mask is empty to the left or to the right | !lomask[x + 1]) { /* Test if outer mask is empty to the left or to the right. */ | ||||
| osz++; // increment outer edge size | osz++; /* Increment outer edge size. */ | ||||
| lres[x] = 3; // flag pixel as outer edge | lres[x] = 3; /* Flag pixel as outer edge. */ | ||||
| } | } | ||||
| else { | else { | ||||
| gsz++; // increment the gradient pixel count | gsz++; /* Increment the gradient pixel count. */ | ||||
| lres[x] = 2; // flag pixel as gradient | lres[x] = 2; /* Flag pixel as gradient. */ | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /* Test the BOTTOM row of pixels in buffer, except corners */ | /* Test the BOTTOM row of pixels in buffer, except corners */ | ||||
| for (x = rw - 2; x; x--) { | for (x = rw - 2; x; x--) { | ||||
| // test if inner mask is filled | /* Test if inner mask is filled. */ | ||||
| if (limask[x]) { | if (limask[x]) { | ||||
| // test if inner mask is empty to the left or to the right | /* Test if inner mask is empty to the left or to the right. */ | ||||
| if (!limask[x - 1] || !limask[x + 1]) { | if (!limask[x - 1] || !limask[x + 1]) { | ||||
| isz++; // increment inner edge size | isz++; /* Increment inner edge size. */ | ||||
| lres[x] = 4; // flag pixel as inner edge | lres[x] = 4; /* Flag pixel as inner edge. */ | ||||
| } | } | ||||
| else { | else { | ||||
| res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge | res[x] = 1.0f; /* Pixel is just part of inner mask, and it's not an edge. */ | ||||
| } | } | ||||
| } | } | ||||
| else if (lomask[x]) { // inner mask was empty, test if outer mask is filled | else if (lomask[x]) { /* Inner mask was empty, test if outer mask is filled. */ | ||||
| if (!lomask[x - 1] || | if (!lomask[x - 1] || | ||||
| !lomask[x + 1]) { // test if outer mask is empty to the left or to the right | !lomask[x + 1]) { /* Test if outer mask is empty to the left or to the right. */ | ||||
| osz++; // increment outer edge size | osz++; /* Increment outer edge size. */ | ||||
| lres[x] = 3; // flag pixel as outer edge | lres[x] = 3; /* Flag pixel as outer edge. */ | ||||
| } | } | ||||
| else { | else { | ||||
| gsz++; // increment the gradient pixel count | gsz++; /* Increment the gradient pixel count. */ | ||||
| lres[x] = 2; // flag pixel as gradient | lres[x] = 2; /* Flag pixel as gradient. */ | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /* Test the LEFT edge of pixels in buffer, except corners */ | /* Test the LEFT edge of pixels in buffer, except corners */ | ||||
| for (x = t - (rw << 1) + 1; x >= rw; x -= rw) { | for (x = t - (rw << 1) + 1; x >= rw; x -= rw) { | ||||
| // test if inner mask is filled | /* Test if inner mask is filled. */ | ||||
| if (limask[x]) { | if (limask[x]) { | ||||
| // test if inner mask is empty underneath or above | /* Test if inner mask is empty underneath or above. */ | ||||
| if (!limask[x - rw] || !limask[x + rw]) { | if (!limask[x - rw] || !limask[x + rw]) { | ||||
| isz++; // increment inner edge size | isz++; /* Increment inner edge size. */ | ||||
| lres[x] = 4; // flag pixel as inner edge | lres[x] = 4; /* Flag pixel as inner edge. */ | ||||
| } | } | ||||
| else { | else { | ||||
| res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge | res[x] = 1.0f; /* Pixel is just part of inner mask, and it's not an edge. */ | ||||
| } | } | ||||
| } | } | ||||
| else if (lomask[x]) { // inner mask was empty, test if outer mask is filled | else if (lomask[x]) { /* Inner mask was empty, test if outer mask is filled. */ | ||||
| if (!lomask[x - rw] || !lomask[x + rw]) { // test if outer mask is empty underneath or above | if (!lomask[x - rw] || | ||||
| osz++; // increment outer edge size | !lomask[x + rw]) { /* Test if outer mask is empty underneath or above. */ | ||||
| lres[x] = 3; // flag pixel as outer edge | osz++; /* Increment outer edge size. */ | ||||
| lres[x] = 3; /* Flag pixel as outer edge. */ | |||||
| } | } | ||||
| else { | else { | ||||
| gsz++; // increment the gradient pixel count | gsz++; /* Increment the gradient pixel count. */ | ||||
| lres[x] = 2; // flag pixel as gradient | lres[x] = 2; /* Flag pixel as gradient. */ | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /* Test the RIGHT edge of pixels in buffer, except corners */ | /* Test the RIGHT edge of pixels in buffer, except corners */ | ||||
| for (x = t - rw; x > rw; x -= rw) { | for (x = t - rw; x > rw; x -= rw) { | ||||
| // test if inner mask is filled | /* Test if inner mask is filled. */ | ||||
| if (limask[x]) { | if (limask[x]) { | ||||
| // test if inner mask is empty underneath or above | /* Test if inner mask is empty underneath or above. */ | ||||
| if (!limask[x - rw] || !limask[x + rw]) { | if (!limask[x - rw] || !limask[x + rw]) { | ||||
| isz++; // increment inner edge size | isz++; /* Increment inner edge size. */ | ||||
| lres[x] = 4; // flag pixel as inner edge | lres[x] = 4; /* Flag pixel as inner edge. */ | ||||
| } | } | ||||
| else { | else { | ||||
| res[x] = 1.0f; // pixel is just part of inner mask, and it's not an edge | res[x] = 1.0f; /* Pixel is just part of inner mask, and it's not an edge. */ | ||||
| } | } | ||||
| } | } | ||||
| else if (lomask[x]) { // inner mask was empty, test if outer mask is filled | else if (lomask[x]) { /* Inner mask was empty, test if outer mask is filled. */ | ||||
| if (!lomask[x - rw] || !lomask[x + rw]) { // test if outer mask is empty underneath or above | if (!lomask[x - rw] || | ||||
| osz++; // increment outer edge size | !lomask[x + rw]) { /* Test if outer mask is empty underneath or above. */ | ||||
| lres[x] = 3; // flag pixel as outer edge | osz++; /* Increment outer edge size. */ | ||||
| lres[x] = 3; /* Flag pixel as outer edge. */ | |||||
| } | } | ||||
| else { | else { | ||||
| gsz++; // increment the gradient pixel count | gsz++; /* Increment the gradient pixel count. */ | ||||
| lres[x] = 2; // flag pixel as gradient | lres[x] = 2; /* Flag pixel as gradient. */ | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| rsize[0] = isz; // fill in our return sizes for edges + fill | rsize[0] = isz; /* Fill in our return sizes for edges + fill. */ | ||||
| rsize[1] = osz; | rsize[1] = osz; | ||||
| rsize[2] = gsz; | rsize[2] = gsz; | ||||
| } | } | ||||
| static void do_allEdgeDetection(unsigned int t, | static void do_allEdgeDetection(unsigned int t, | ||||
| unsigned int rw, | unsigned int rw, | ||||
| const unsigned int *limask, | const unsigned int *limask, | ||||
| const unsigned int *lomask, | const unsigned int *lomask, | ||||
| unsigned int *lres, | unsigned int *lres, | ||||
| float *res, | float *res, | ||||
| unsigned int *rsize, | unsigned int *rsize, | ||||
| unsigned int in_isz, | unsigned int in_isz, | ||||
| unsigned int in_osz, | unsigned int in_osz, | ||||
| unsigned int in_gsz) | unsigned int in_gsz) | ||||
| { | { | ||||
| int x; // x = pixel loop counter | int x; /* Pixel loop counter. */ | ||||
| int a; // a = pixel loop counter | int a; /* Pixel loop counter. */ | ||||
| int dx; // dx = delta x | int dx; /* Delta x. */ | ||||
| int pix_prevRow; // pix_prevRow = pixel one row behind the one we are testing in a loop | int pix_prevRow; /* Pixel one row behind the one we are testing in a loop. */ | ||||
| int pix_nextRow; // pix_nextRow = pixel one row in front of the one we are testing in a loop | int pix_nextRow; /* Pixel one row in front of the one we are testing in a loop. */ | ||||
| int pix_prevCol; // pix_prevCol = pixel one column behind the one we are testing in a loop | int pix_prevCol; /* Pixel one column behind the one we are testing in a loop. */ | ||||
| int pix_nextCol; // pix_nextCol = pixel one column in front of the one we are testing in a loop | int pix_nextCol; /* Pixel one column in front of the one we are testing in a loop. */ | ||||
| /* Test all rows between the FIRST and LAST rows, excluding left and right edges */ | /* Test all rows between the FIRST and LAST rows, excluding left and right edges */ | ||||
| for (x = (t - rw) + 1, dx = x - (rw - 2); dx > rw; x -= rw, dx -= rw) { | for (x = (t - rw) + 1, dx = x - (rw - 2); dx > rw; x -= rw, dx -= rw) { | ||||
| a = x - 2; | a = x - 2; | ||||
| pix_prevRow = a + rw; | pix_prevRow = a + rw; | ||||
| pix_nextRow = a - rw; | pix_nextRow = a - rw; | ||||
| pix_prevCol = a + 1; | pix_prevCol = a + 1; | ||||
| pix_nextCol = a - 1; | pix_nextCol = a - 1; | ||||
| while (a > dx - 2) { | while (a > dx - 2) { | ||||
| if (!limask[a]) { // if the inner mask is empty | if (!limask[a]) { /* If the inner mask is empty. */ | ||||
| if (lomask[a]) { // if the outer mask is full | if (lomask[a]) { /* If the outer mask is full. */ | ||||
| /* | /* | ||||
| * Next we test all 4 directions around the current pixel: next/prev/up/down | * Next we test all 4 directions around the current pixel: next/prev/up/down | ||||
| * The test ensures that the outer mask is empty and that the inner mask | * The test ensures that the outer mask is empty and that the inner mask | ||||
| * is also empty. If both conditions are true for any one of the 4 adjacent pixels | * is also empty. If both conditions are true for any one of the 4 adjacent pixels | ||||
| * then the current pixel is counted as being a true outer edge pixel. | * then the current pixel is counted as being a true outer edge pixel. | ||||
| */ | */ | ||||
| if ((!lomask[pix_nextCol] && !limask[pix_nextCol]) || | if ((!lomask[pix_nextCol] && !limask[pix_nextCol]) || | ||||
| (!lomask[pix_prevCol] && !limask[pix_prevCol]) || | (!lomask[pix_prevCol] && !limask[pix_prevCol]) || | ||||
| (!lomask[pix_nextRow] && !limask[pix_nextRow]) || | (!lomask[pix_nextRow] && !limask[pix_nextRow]) || | ||||
| (!lomask[pix_prevRow] && !limask[pix_prevRow])) { | (!lomask[pix_prevRow] && !limask[pix_prevRow])) { | ||||
| in_osz++; // increment the outer boundary pixel count | in_osz++; /* Increment the outer boundary pixel count. */ | ||||
| lres[a] = 3; // flag pixel as part of outer edge | lres[a] = 3; /* Flag pixel as part of outer edge. */ | ||||
| } | } | ||||
| else { // it's not a boundary pixel, but it is a gradient pixel | else { /* It's not a boundary pixel, but it is a gradient pixel. */ | ||||
| in_gsz++; // increment the gradient pixel count | in_gsz++; /* Increment the gradient pixel count. */ | ||||
| lres[a] = 2; // flag pixel as gradient | lres[a] = 2; /* Flag pixel as gradient. */ | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| if (!limask[pix_nextCol] || !limask[pix_prevCol] || !limask[pix_nextRow] || | if (!limask[pix_nextCol] || !limask[pix_prevCol] || !limask[pix_nextRow] || | ||||
| !limask[pix_prevRow]) { | !limask[pix_prevRow]) { | ||||
| in_isz++; // increment the inner boundary pixel count | in_isz++; /* Increment the inner boundary pixel count. */ | ||||
| lres[a] = 4; // flag pixel as part of inner edge | lres[a] = 4; /* Flag pixel as part of inner edge. */ | ||||
| } | } | ||||
| else { | else { | ||||
| res[a] = 1.0f; // pixel is part of inner mask, but not at an edge | res[a] = 1.0f; /* Pixel is part of inner mask, but not at an edge. */ | ||||
| } | } | ||||
| } | } | ||||
| a--; | a--; | ||||
| pix_prevRow--; | pix_prevRow--; | ||||
| pix_nextRow--; | pix_nextRow--; | ||||
| pix_prevCol--; | pix_prevCol--; | ||||
| pix_nextCol--; | pix_nextCol--; | ||||
| } | } | ||||
| } | } | ||||
| rsize[0] = in_isz; // fill in our return sizes for edges + fill | rsize[0] = in_isz; /* Fill in our return sizes for edges + fill. */ | ||||
| rsize[1] = in_osz; | rsize[1] = in_osz; | ||||
| rsize[2] = in_gsz; | rsize[2] = in_gsz; | ||||
| } | } | ||||
| static void do_adjacentEdgeDetection(unsigned int t, | static void do_adjacentEdgeDetection(unsigned int t, | ||||
| unsigned int rw, | unsigned int rw, | ||||
| const unsigned int *limask, | const unsigned int *limask, | ||||
| const unsigned int *lomask, | const unsigned int *lomask, | ||||
| unsigned int *lres, | unsigned int *lres, | ||||
| float *res, | float *res, | ||||
| unsigned int *rsize, | unsigned int *rsize, | ||||
| unsigned int in_isz, | unsigned int in_isz, | ||||
| unsigned int in_osz, | unsigned int in_osz, | ||||
| unsigned int in_gsz) | unsigned int in_gsz) | ||||
| { | { | ||||
| int x; // x = pixel loop counter | int x; /* Pixel loop counter. */ | ||||
| int a; // a = pixel loop counter | int a; /* Pixel loop counter. */ | ||||
| int dx; // dx = delta x | int dx; /* Delta x. */ | ||||
| int pix_prevRow; // pix_prevRow = pixel one row behind the one we are testing in a loop | int pix_prevRow; /* Pixel one row behind the one we are testing in a loop. */ | ||||
| int pix_nextRow; // pix_nextRow = pixel one row in front of the one we are testing in a loop | int pix_nextRow; /* Pixel one row in front of the one we are testing in a loop. */ | ||||
| int pix_prevCol; // pix_prevCol = pixel one column behind the one we are testing in a loop | int pix_prevCol; /* Pixel one column behind the one we are testing in a loop. */ | ||||
| int pix_nextCol; // pix_nextCol = pixel one column in front of the one we are testing in a loop | int pix_nextCol; /* Pixel one column in front of the one we are testing in a loop. */ | ||||
| /* Test all rows between the FIRST and LAST rows, excluding left and right edges */ | /* Test all rows between the FIRST and LAST rows, excluding left and right edges */ | ||||
| for (x = (t - rw) + 1, dx = x - (rw - 2); dx > rw; x -= rw, dx -= rw) { | for (x = (t - rw) + 1, dx = x - (rw - 2); dx > rw; x -= rw, dx -= rw) { | ||||
| a = x - 2; | a = x - 2; | ||||
| pix_prevRow = a + rw; | pix_prevRow = a + rw; | ||||
| pix_nextRow = a - rw; | pix_nextRow = a - rw; | ||||
| pix_prevCol = a + 1; | pix_prevCol = a + 1; | ||||
| pix_nextCol = a - 1; | pix_nextCol = a - 1; | ||||
| while (a > dx - 2) { | while (a > dx - 2) { | ||||
| if (!limask[a]) { // if the inner mask is empty | if (!limask[a]) { /* If the inner mask is empty. */ | ||||
| if (lomask[a]) { // if the outer mask is full | if (lomask[a]) { /* If the outer mask is full. */ | ||||
| /* | /* | ||||
| * Next we test all 4 directions around the current pixel: next/prev/up/down | * Next we test all 4 directions around the current pixel: next/prev/up/down | ||||
| * The test ensures that the outer mask is empty and that the inner mask | * The test ensures that the outer mask is empty and that the inner mask | ||||
| * is also empty. If both conditions are true for any one of the 4 adjacent pixels | * is also empty. If both conditions are true for any one of the 4 adjacent pixels | ||||
| * then the current pixel is counted as being a true outer edge pixel. | * then the current pixel is counted as being a true outer edge pixel. | ||||
| */ | */ | ||||
| if ((!lomask[pix_nextCol] && !limask[pix_nextCol]) || | if ((!lomask[pix_nextCol] && !limask[pix_nextCol]) || | ||||
| (!lomask[pix_prevCol] && !limask[pix_prevCol]) || | (!lomask[pix_prevCol] && !limask[pix_prevCol]) || | ||||
| (!lomask[pix_nextRow] && !limask[pix_nextRow]) || | (!lomask[pix_nextRow] && !limask[pix_nextRow]) || | ||||
| (!lomask[pix_prevRow] && !limask[pix_prevRow])) { | (!lomask[pix_prevRow] && !limask[pix_prevRow])) { | ||||
| in_osz++; // increment the outer boundary pixel count | in_osz++; /* Increment the outer boundary pixel count. */ | ||||
| lres[a] = 3; // flag pixel as part of outer edge | lres[a] = 3; /* Flag pixel as part of outer edge. */ | ||||
| } | } | ||||
| else { // it's not a boundary pixel, but it is a gradient pixel | else { /* It's not a boundary pixel, but it is a gradient pixel. */ | ||||
| in_gsz++; // increment the gradient pixel count | in_gsz++; /* Increment the gradient pixel count. */ | ||||
| lres[a] = 2; // flag pixel as gradient | lres[a] = 2; /* Flag pixel as gradient. */ | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| if ((!limask[pix_nextCol] && lomask[pix_nextCol]) || | if ((!limask[pix_nextCol] && lomask[pix_nextCol]) || | ||||
| (!limask[pix_prevCol] && lomask[pix_prevCol]) || | (!limask[pix_prevCol] && lomask[pix_prevCol]) || | ||||
| (!limask[pix_nextRow] && lomask[pix_nextRow]) || | (!limask[pix_nextRow] && lomask[pix_nextRow]) || | ||||
| (!limask[pix_prevRow] && lomask[pix_prevRow])) { | (!limask[pix_prevRow] && lomask[pix_prevRow])) { | ||||
| in_isz++; // increment the inner boundary pixel count | in_isz++; /* Increment the inner boundary pixel count. */ | ||||
| lres[a] = 4; // flag pixel as part of inner edge | lres[a] = 4; /* Flag pixel as part of inner edge. */ | ||||
| } | } | ||||
| else { | else { | ||||
| res[a] = 1.0f; // pixel is part of inner mask, but not at an edge | res[a] = 1.0f; /* Pixel is part of inner mask, but not at an edge. */ | ||||
| } | } | ||||
| } | } | ||||
| a--; | a--; | ||||
| pix_prevRow--; // advance all four "surrounding" pixel pointers | pix_prevRow--; /* Advance all four "surrounding" pixel pointers. */ | ||||
| pix_nextRow--; | pix_nextRow--; | ||||
| pix_prevCol--; | pix_prevCol--; | ||||
| pix_nextCol--; | pix_nextCol--; | ||||
| } | } | ||||
| } | } | ||||
| rsize[0] = in_isz; // fill in our return sizes for edges + fill | rsize[0] = in_isz; /* Fill in our return sizes for edges + fill. */ | ||||
| rsize[1] = in_osz; | rsize[1] = in_osz; | ||||
| rsize[2] = in_gsz; | rsize[2] = in_gsz; | ||||
| } | } | ||||
| static void do_createEdgeLocationBuffer(unsigned int t, | static void do_createEdgeLocationBuffer(unsigned int t, | ||||
| unsigned int rw, | unsigned int rw, | ||||
| const unsigned int *lres, | const unsigned int *lres, | ||||
| float *res, | float *res, | ||||
| unsigned short *gbuf, | unsigned short *gbuf, | ||||
| unsigned int *innerEdgeOffset, | unsigned int *innerEdgeOffset, | ||||
| unsigned int *outerEdgeOffset, | unsigned int *outerEdgeOffset, | ||||
| unsigned int isz, | unsigned int isz, | ||||
| unsigned int gsz) | unsigned int gsz) | ||||
| { | { | ||||
| int x; // x = pixel loop counter | int x; /* Pixel loop counter. */ | ||||
| int a; // a = temporary pixel index buffer loop counter | int a; /* Temporary pixel index buffer loop counter. */ | ||||
| unsigned int ud; // ud = unscaled edge distance | unsigned int ud; /* Unscaled edge distance. */ | ||||
| unsigned int dmin; // dmin = minimum edge distance | unsigned int dmin; /* Minimum edge distance. */ | ||||
| unsigned int rsl; // long used for finding fast 1.0/sqrt | unsigned int rsl; /* Long used for finding fast `1.0/sqrt`. */ | ||||
| unsigned int gradientFillOffset; | unsigned int gradientFillOffset; | ||||
| /* For looping inner edge pixel indexes, represents current position from offset. */ | /* For looping inner edge pixel indexes, represents current position from offset. */ | ||||
| unsigned int innerAccum = 0; | unsigned int innerAccum = 0; | ||||
| /* For looping outer edge pixel indexes, represents current position from offset. */ | /* For looping outer edge pixel indexes, represents current position from offset. */ | ||||
| unsigned int outerAccum = 0; | unsigned int outerAccum = 0; | ||||
| /* For looping gradient pixel indexes, represents current position from offset. */ | /* For looping gradient pixel indexes, represents current position from offset. */ | ||||
| unsigned int gradientAccum = 0; | unsigned int gradientAccum = 0; | ||||
| Show All 13 Lines | static void do_createEdgeLocationBuffer(unsigned int t, | ||||
| * so if Blender starts doing renders greater than 65536 in either direction | * so if Blender starts doing renders greater than 65536 in either direction | ||||
| * this will need to allocate gbuf[] as unsigned int *and allocate 8 bytes | * this will need to allocate gbuf[] as unsigned int *and allocate 8 bytes | ||||
| * per flagged pixel. | * per flagged pixel. | ||||
| * | * | ||||
| * In general, the buffer on-screen: | * In general, the buffer on-screen: | ||||
| * | * | ||||
| * Example: 9 by 9 pixel block | * Example: 9 by 9 pixel block | ||||
| * | * | ||||
| * . = pixel non-white in both outer and inner mask | * `.` = Pixel non-white in both outer and inner mask. | ||||
| * o = pixel white in outer, but not inner mask, adjacent to "." pixel | * `o` = Pixel white in outer, but not inner mask, adjacent to "." pixel. | ||||
| * g = pixel white in outer, but not inner mask, not adjacent to "." pixel | * `g` = Pixel white in outer, but not inner mask, not adjacent to "." pixel. | ||||
| * i = pixel white in inner mask, adjacent to "g" or "." pixel | * `i` = Pixel white in inner mask, adjacent to "g" or "." pixel. | ||||
| * F = pixel white in inner mask, only adjacent to other pixels white in the inner mask | * `F` = Pixel white in inner mask, only adjacent to other pixels white in the inner mask. | ||||
| * | * | ||||
| * | * | ||||
| * ......... <----- pixel #80 | * ......... <----- pixel #80 | ||||
| * ..oooo... | * ..oooo... | ||||
| * .oggggo.. | * .oggggo.. | ||||
| * .oggiggo. | * .oggiggo. | ||||
| * .ogiFigo. | * .ogiFigo. | ||||
| * .oggiggo. | * .oggiggo. | ||||
| Show All 24 Lines | static void do_createEdgeLocationBuffer(unsigned int t, | ||||
| * | * | ||||
| * Ultimately we do need the pixel's memory buffer index to set the output | * Ultimately we do need the pixel's memory buffer index to set the output | ||||
| * pixel color, but it's faster to reconstruct the memory buffer location | * pixel color, but it's faster to reconstruct the memory buffer location | ||||
| * each iteration of the final gradient calculation than it is to deconstruct | * each iteration of the final gradient calculation than it is to deconstruct | ||||
| * a memory location into x,y pairs each round. | * a memory location into x,y pairs each round. | ||||
| */ | */ | ||||
| /* clang-format on */ | /* clang-format on */ | ||||
| gradientFillOffset = 0; // since there are likely "more" of these, put it first. :) | gradientFillOffset = 0; /* Since there are likely "more" of these, put it first. :). */ | ||||
| *innerEdgeOffset = gradientFillOffset + gsz; // set start of inner edge indexes | *innerEdgeOffset = gradientFillOffset + gsz; /* Set start of inner edge indexes. */ | ||||
| *outerEdgeOffset = (*innerEdgeOffset) + isz; // set start of outer edge indexes | *outerEdgeOffset = (*innerEdgeOffset) + isz; /* Set start of outer edge indexes. */ | ||||
| /* set the accumulators to correct positions */ // set up some accumulator variables for loops | /* Set the accumulators to correct positions */ /* Set up some accumulator variables for loops. | ||||
| gradientAccum = gradientFillOffset; // each accumulator variable starts at its respective | */ | ||||
| innerAccum = *innerEdgeOffset; // section's offset so when we start filling, each | gradientAccum = gradientFillOffset; /* Each accumulator variable starts at its respective. */ | ||||
| outerAccum = *outerEdgeOffset; // section fills up its allocated space in gbuf | innerAccum = *innerEdgeOffset; /* Section's offset so when we start filling, each. */ | ||||
| // uses dmin=row, rsl=col | outerAccum = *outerEdgeOffset; /* Section fills up its allocated space in gbuf. */ | ||||
| /* Uses `dmin=row`, `rsl=col`. */ | |||||
| for (x = 0, dmin = 0; x < t; x += rw, dmin++) { | for (x = 0, dmin = 0; x < t; x += rw, dmin++) { | ||||
| for (rsl = 0; rsl < rw; rsl++) { | for (rsl = 0; rsl < rw; rsl++) { | ||||
| a = x + rsl; | a = x + rsl; | ||||
| if (lres[a] == 2) { // it is a gradient pixel flagged by 2 | if (lres[a] == 2) { /* It is a gradient pixel flagged by 2. */ | ||||
| ud = gradientAccum << 1; // double the index to reach correct unsigned short location | ud = gradientAccum << 1; /* Double the index to reach correct unsigned short location. */ | ||||
| gbuf[ud] = dmin; // insert pixel's row into gradient pixel location buffer | gbuf[ud] = dmin; /* Insert pixel's row into gradient pixel location buffer. */ | ||||
| gbuf[ud + 1] = rsl; // insert pixel's column into gradient pixel location buffer | gbuf[ud + 1] = rsl; /* Insert pixel's column into gradient pixel location buffer. */ | ||||
| gradientAccum++; // increment gradient index buffer pointer | gradientAccum++; /* Increment gradient index buffer pointer. */ | ||||
| } | } | ||||
| else if (lres[a] == 3) { // it is an outer edge pixel flagged by 3 | else if (lres[a] == 3) { /* It is an outer edge pixel flagged by 3. */ | ||||
| ud = outerAccum << 1; // double the index to reach correct unsigned short location | ud = outerAccum << 1; /* Double the index to reach correct unsigned short location. */ | ||||
| gbuf[ud] = dmin; // insert pixel's row into outer edge pixel location buffer | gbuf[ud] = dmin; /* Insert pixel's row into outer edge pixel location buffer. */ | ||||
| gbuf[ud + 1] = rsl; // insert pixel's column into outer edge pixel location buffer | gbuf[ud + 1] = rsl; /* Insert pixel's column into outer edge pixel location buffer. */ | ||||
| outerAccum++; // increment outer edge index buffer pointer | outerAccum++; /* Increment outer edge index buffer pointer. */ | ||||
| res[a] = 0.0f; // set output pixel intensity now since it won't change later | res[a] = 0.0f; /* Set output pixel intensity now since it won't change later. */ | ||||
| } | } | ||||
| else if (lres[a] == 4) { // it is an inner edge pixel flagged by 4 | else if (lres[a] == 4) { /* It is an inner edge pixel flagged by 4. */ | ||||
| ud = innerAccum << 1; // double int index to reach correct unsigned short location | ud = innerAccum << 1; /* Double int index to reach correct unsigned short location. */ | ||||
| gbuf[ud] = dmin; // insert pixel's row into inner edge pixel location buffer | gbuf[ud] = dmin; /* Insert pixel's row into inner edge pixel location buffer. */ | ||||
| gbuf[ud + 1] = rsl; // insert pixel's column into inner edge pixel location buffer | gbuf[ud + 1] = rsl; /* Insert pixel's column into inner edge pixel location buffer. */ | ||||
| innerAccum++; // increment inner edge index buffer pointer | innerAccum++; /* Increment inner edge index buffer pointer. */ | ||||
| res[a] = 1.0f; // set output pixel intensity now since it won't change later | res[a] = 1.0f; /* Set output pixel intensity now since it won't change later. */ | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| static void do_fillGradientBuffer(unsigned int rw, | static void do_fillGradientBuffer(unsigned int rw, | ||||
| float *res, | float *res, | ||||
| const unsigned short *gbuf, | const unsigned short *gbuf, | ||||
| unsigned int isz, | unsigned int isz, | ||||
| unsigned int osz, | unsigned int osz, | ||||
| unsigned int gsz, | unsigned int gsz, | ||||
| unsigned int innerEdgeOffset, | unsigned int innerEdgeOffset, | ||||
| unsigned int outerEdgeOffset) | unsigned int outerEdgeOffset) | ||||
| { | { | ||||
| int x; // x = pixel loop counter | int x; /* Pixel loop counter. */ | ||||
| int a; // a = temporary pixel index buffer loop counter | int a; /* Temporary pixel index buffer loop counter. */ | ||||
| int fsz; // size of the frame | int fsz; /* Size of the frame. */ | ||||
| unsigned int rsl; // long used for finding fast 1.0/sqrt | unsigned int rsl; /* Long used for finding fast `1.0/sqrt`. */ | ||||
| float rsf; // float used for finding fast 1.0/sqrt | float rsf; /* Float used for finding fast `1.0/sqrt`. */ | ||||
| const float rsopf = 1.5f; // constant float used for finding fast 1.0/sqrt | const float rsopf = 1.5f; /* Constant float used for finding fast `1.0/sqrt`. */ | ||||
| unsigned int gradientFillOffset; | unsigned int gradientFillOffset; | ||||
| unsigned int t; | unsigned int t; | ||||
| unsigned int ud; // ud = unscaled edge distance | unsigned int ud; /* Unscaled edge distance. */ | ||||
| unsigned int dmin; // dmin = minimum edge distance | unsigned int dmin; /* Minimum edge distance. */ | ||||
| float odist; // odist = current outer edge distance | float odist; /* Current outer edge distance. */ | ||||
| float idist; // idist = current inner edge distance | float idist; /* Current inner edge distance. */ | ||||
| int dx; // dx = X-delta (used for distance proportion calculation) | int dx; /* X-delta (used for distance proportion calculation) */ | ||||
| int dy; // dy = Y-delta (used for distance proportion calculation) | int dy; /* Y-delta (used for distance proportion calculation) */ | ||||
| /* | /* | ||||
| * The general algorithm used to color each gradient pixel is: | * The general algorithm used to color each gradient pixel is: | ||||
| * | * | ||||
| * 1.) Loop through all gradient pixels. | * 1.) Loop through all gradient pixels. | ||||
| * A.) For each gradient pixel: | * A.) For each gradient pixel: | ||||
| * a.) Loop through all outside edge pixels, looking for closest one | * a.) Loop through all outside edge pixels, looking for closest one | ||||
| * to the gradient pixel we are in. | * to the gradient pixel we are in. | ||||
| * b.) Loop through all inside edge pixels, looking for closest one | * b.) Loop through all inside edge pixels, looking for closest one | ||||
| * to the gradient pixel we are in. | * to the gradient pixel we are in. | ||||
| * c.) Find proportion of distance from gradient pixel to inside edge | * c.) Find proportion of distance from gradient pixel to inside edge | ||||
| * pixel compared to sum of distance to inside edge and distance to | * pixel compared to sum of distance to inside edge and distance to | ||||
| * outside edge. | * outside edge. | ||||
| * | * | ||||
| * In an image where: | * In an image where: | ||||
| * . = blank (black) pixels, not covered by inner mask or outer mask | * `.` = Blank (black) pixels, not covered by inner mask or outer mask. | ||||
| * + = desired gradient pixels, covered only by outer mask | * `+` = Desired gradient pixels, covered only by outer mask. | ||||
| * * = white full mask pixels, covered by at least inner mask | * `*` = White full mask pixels, covered by at least inner mask. | ||||
| * | * | ||||
| * ............................... | * ............................... | ||||
| * ...............+++++++++++..... | * ...............+++++++++++..... | ||||
| * ...+O++++++..++++++++++++++.... | * ...+O++++++..++++++++++++++.... | ||||
| * ..+++\++++++++++++++++++++..... | * ..+++\++++++++++++++++++++..... | ||||
| * .+++++G+++++++++*******+++..... | * .+++++G+++++++++*******+++..... | ||||
| * .+++++|+++++++*********+++..... | * .+++++|+++++++*********+++..... | ||||
| * .++***I****************+++..... | * .++***I****************+++..... | ||||
| Show All 28 Lines | static void do_fillGradientBuffer(unsigned int rw, | ||||
| * the sums-of-squares against each other, since they are in the same | * the sums-of-squares against each other, since they are in the same | ||||
| * mathematical sort-order as if we did go ahead and take square roots | * mathematical sort-order as if we did go ahead and take square roots | ||||
| * | * | ||||
| * Loop through all gradient pixels. | * Loop through all gradient pixels. | ||||
| */ | */ | ||||
| for (x = gsz - 1; x >= 0; x--) { | for (x = gsz - 1; x >= 0; x--) { | ||||
| gradientFillOffset = x << 1; | gradientFillOffset = x << 1; | ||||
| t = gbuf[gradientFillOffset]; // calculate column of pixel indexed by gbuf[x] | t = gbuf[gradientFillOffset]; /* Calculate column of pixel indexed by `gbuf[x]`. */ | ||||
| fsz = gbuf[gradientFillOffset + 1]; // calculate row of pixel indexed by gbuf[x] | fsz = gbuf[gradientFillOffset + 1]; /* Calculate row of pixel indexed by `gbuf[x]`. */ | ||||
| dmin = 0xffffffff; // reset min distance to edge pixel | dmin = 0xffffffff; /* Reset min distance to edge pixel. */ | ||||
| for (a = outerEdgeOffset + osz - 1; a >= outerEdgeOffset; | for (a = outerEdgeOffset + osz - 1; a >= outerEdgeOffset; | ||||
| a--) { // loop through all outer edge buffer pixels | a--) { /* Loop through all outer edge buffer pixels. */ | ||||
| ud = a << 1; | ud = a << 1; | ||||
| dy = t - gbuf[ud]; // set dx to gradient pixel column - outer edge pixel row | dy = t - gbuf[ud]; /* Set dx to gradient pixel column - outer edge pixel row. */ | ||||
| dx = fsz - gbuf[ud + 1]; // set dy to gradient pixel row - outer edge pixel column | dx = fsz - gbuf[ud + 1]; /* Set dy to gradient pixel row - outer edge pixel column. */ | ||||
| ud = dx * dx + dy * dy; // compute sum of squares | ud = dx * dx + dy * dy; /* Compute sum of squares. */ | ||||
| if (ud < dmin) { // if our new sum of squares is less than the current minimum | if (ud < dmin) { /* If our new sum of squares is less than the current minimum. */ | ||||
| dmin = ud; // set a new minimum equal to the new lower value | dmin = ud; /* Set a new minimum equal to the new lower value. */ | ||||
| } | } | ||||
| } | } | ||||
| odist = (float)(dmin); // cast outer min to a float | odist = (float)(dmin); /* Cast outer min to a float. */ | ||||
| rsf = odist * 0.5f; // | rsf = odist * 0.5f; | ||||
| rsl = *(unsigned int *)&odist; // use some peculiar properties of the way bits are stored | rsl = *(unsigned int *)&odist; /* Use some peculiar properties of the way bits are stored. */ | ||||
| rsl = 0x5f3759df - (rsl >> 1); // in floats vs. unsigned ints to compute an approximate | rsl = 0x5f3759df - (rsl >> 1); /* In floats vs. unsigned ints to compute an approximate. */ | ||||
| odist = *(float *)&rsl; // reciprocal square root | odist = *(float *)&rsl; /* Reciprocal square root. */ | ||||
| odist = odist * (rsopf - (rsf * odist * | odist = odist * (rsopf - (rsf * odist * | ||||
| odist)); // -- ** this line can be iterated for more accuracy ** -- | odist)); /* -- This line can be iterated for more accuracy. -- */ | ||||
| dmin = 0xffffffff; // reset min distance to edge pixel | dmin = 0xffffffff; /* Reset min distance to edge pixel. */ | ||||
| for (a = innerEdgeOffset + isz - 1; a >= innerEdgeOffset; | for (a = innerEdgeOffset + isz - 1; a >= innerEdgeOffset; | ||||
| a--) { // loop through all inside edge pixels | a--) { /* Loop through all inside edge pixels. */ | ||||
| ud = a << 1; | ud = a << 1; | ||||
| dy = t - gbuf[ud]; // compute delta in Y from gradient pixel to inside edge pixel | dy = t - gbuf[ud]; /* Compute delta in Y from gradient pixel to inside edge pixel. */ | ||||
| dx = fsz - gbuf[ud + 1]; // compute delta in X from gradient pixel to inside edge pixel | dx = fsz - gbuf[ud + 1]; /* Compute delta in X from gradient pixel to inside edge pixel. */ | ||||
| ud = dx * dx + dy * dy; // compute sum of squares | ud = dx * dx + dy * dy; /* Compute sum of squares. */ | ||||
| if (ud < dmin) { // if our new sum of squares is less than the current minimum we've found | if (ud < | ||||
| dmin = ud; // set a new minimum equal to the new lower value | dmin) { /* If our new sum of squares is less than the current minimum we've found. */ | ||||
| dmin = ud; /* Set a new minimum equal to the new lower value. */ | |||||
| } | } | ||||
| } | } | ||||
| idist = (float)(dmin); // cast inner min to a float | |||||
| rsf = idist * 0.5f; // | /* Cast inner min to a float. */ | ||||
| rsl = *(unsigned int *)&idist; // | idist = (float)(dmin); | ||||
| rsl = 0x5f3759df - (rsl >> 1); // see notes above | rsf = idist * 0.5f; | ||||
| idist = *(float *)&rsl; // | rsl = *(unsigned int *)&idist; | ||||
| idist = idist * (rsopf - (rsf * idist * idist)); // | |||||
| /* | /* See notes above. */ | ||||
| * Note once again that since we are using reciprocals of distance values our | rsl = 0x5f3759df - (rsl >> 1); | ||||
| idist = *(float *)&rsl; | |||||
| idist = idist * (rsopf - (rsf * idist * idist)); | |||||
| /* NOTE: once again that since we are using reciprocals of distance values our | |||||
| * proportion is already the correct intensity, and does not need to be | * proportion is already the correct intensity, and does not need to be | ||||
| * subtracted from 1.0 like it would have if we used real distances. | * subtracted from 1.0 like it would have if we used real distances. */ | ||||
| */ | |||||
| /* | /* Here we reconstruct the pixel's memory location in the CompBuf by | ||||
| * Here we reconstruct the pixel's memory location in the CompBuf by | * `Pixel Index = Pixel Column + ( Pixel Row * Row Width )`. */ | ||||
| * Pixel Index = Pixel Column + ( Pixel Row * Row Width ) | |||||
| */ | |||||
| res[gbuf[gradientFillOffset + 1] + (gbuf[gradientFillOffset] * rw)] = | res[gbuf[gradientFillOffset + 1] + (gbuf[gradientFillOffset] * rw)] = | ||||
| (idist / (idist + odist)); // set intensity | (idist / (idist + odist)); /* Set intensity. */ | ||||
| } | } | ||||
| } | } | ||||
| // end of copy | /* End of copy. */ | ||||
| void DoubleEdgeMaskOperation::doDoubleEdgeMask(float *imask, float *omask, float *res) | void DoubleEdgeMaskOperation::doDoubleEdgeMask(float *imask, float *omask, float *res) | ||||
| { | { | ||||
| unsigned int *lres; // lres = unsigned int pointer to output pixel buffer (for bit operations) | unsigned int *lres; /* Pointer to output pixel buffer (for bit operations). */ | ||||
| unsigned int *limask; // limask = unsigned int pointer to inner mask (for bit operations) | unsigned int *limask; /* Pointer to inner mask (for bit operations). */ | ||||
| unsigned int *lomask; // lomask = unsigned int pointer to outer mask (for bit operations) | unsigned int *lomask; /* Pointer to outer mask (for bit operations). */ | ||||
| int rw; // rw = pixel row width | int rw; /* Pixel row width. */ | ||||
| int t; // t = total number of pixels in buffer - 1 (used for loop starts) | int t; /* Total number of pixels in buffer - 1 (used for loop starts). */ | ||||
| int fsz; // size of the frame | int fsz; /* Size of the frame. */ | ||||
| unsigned int isz = 0; // size (in pixels) of inside edge pixel index buffer | unsigned int isz = 0; /* Size (in pixels) of inside edge pixel index buffer. */ | ||||
| unsigned int osz = 0; // size (in pixels) of outside edge pixel index buffer | unsigned int osz = 0; /* Size (in pixels) of outside edge pixel index buffer. */ | ||||
| unsigned int gsz = 0; // size (in pixels) of gradient pixel index buffer | unsigned int gsz = 0; /* Size (in pixels) of gradient pixel index buffer. */ | ||||
| unsigned int rsize[3]; // size storage to pass to helper functions | unsigned int rsize[3]; /* Size storage to pass to helper functions. */ | ||||
| unsigned int innerEdgeOffset = | unsigned int innerEdgeOffset = | ||||
| 0; // offset into final buffer where inner edge pixel indexes start | 0; /* Offset into final buffer where inner edge pixel indexes start. */ | ||||
| unsigned int outerEdgeOffset = | unsigned int outerEdgeOffset = | ||||
| 0; // offset into final buffer where outer edge pixel indexes start | 0; /* Offset into final buffer where outer edge pixel indexes start. */ | ||||
| unsigned short *gbuf; // gradient/inner/outer pixel location index buffer | unsigned short *gbuf; /* Gradient/inner/outer pixel location index buffer. */ | ||||
| if (true) { // if both input sockets have some data coming in... | if (true) { /* If both input sockets have some data coming in... */ | ||||
| rw = this->getWidth(); // width of a row of pixels | rw = this->getWidth(); /* Width of a row of pixels. */ | ||||
| t = (rw * this->getHeight()) - 1; // determine size of the frame | t = (rw * this->getHeight()) - 1; /* Determine size of the frame. */ | ||||
| memset(res, | memset(res, | ||||
| 0, | 0, | ||||
| sizeof(float) * (t + 1)); // clear output buffer (not all pixels will be written later) | sizeof(float) * | ||||
| (t + 1)); /* Clear output buffer (not all pixels will be written later). */ | |||||
| lres = (unsigned int *)res; // unsigned int pointer to output buffer (for bit level ops) | lres = (unsigned int *)res; /* Pointer to output buffer (for bit level ops).. */ | ||||
| limask = (unsigned int *)imask; // unsigned int pointer to input mask (for bit level ops) | limask = (unsigned int *)imask; /* Pointer to input mask (for bit level ops).. */ | ||||
| lomask = (unsigned int *)omask; // unsigned int pointer to output mask (for bit level ops) | lomask = (unsigned int *)omask; /* Pointer to output mask (for bit level ops).. */ | ||||
| /* | /* | ||||
| * The whole buffer is broken up into 4 parts. The four CORNERS, the FIRST and LAST rows, the | * The whole buffer is broken up into 4 parts. The four CORNERS, the FIRST and LAST rows, the | ||||
| * LEFT and RIGHT edges (excluding the corner pixels), and all OTHER rows. | * LEFT and RIGHT edges (excluding the corner pixels), and all OTHER rows. | ||||
| * This allows for quick computation of outer edge pixels where | * This allows for quick computation of outer edge pixels where | ||||
| * a screen edge pixel is marked to be gradient. | * a screen edge pixel is marked to be gradient. | ||||
| * | * | ||||
| * The pixel type (gradient vs inner-edge vs outer-edge) tests change | * The pixel type (gradient vs inner-edge vs outer-edge) tests change | ||||
| Show All 10 Lines | if (true) { /* If both input sockets have some data coming in... */ | ||||
| * 3.) Inner Edge -> All | * 3.) Inner Edge -> All | ||||
| * Buffer Edge -> Keep Inside | * Buffer Edge -> Keep Inside | ||||
| * | * | ||||
| * 4.) Inner Edge -> All | * 4.) Inner Edge -> All | ||||
| * Buffer Edge -> Bleed Out | * Buffer Edge -> Bleed Out | ||||
| * | * | ||||
| * Each version has slightly different criteria for detecting an edge pixel. | * Each version has slightly different criteria for detecting an edge pixel. | ||||
| */ | */ | ||||
| if (this->m_adjacentOnly) { // if "adjacent only" inner edge mode is turned on | if (this->m_adjacentOnly) { /* If "adjacent only" inner edge mode is turned on. */ | ||||
| if (this->m_keepInside) { // if "keep inside" buffer edge mode is turned on | if (this->m_keepInside) { /* If "keep inside" buffer edge mode is turned on. */ | ||||
| do_adjacentKeepBorders(t, rw, limask, lomask, lres, res, rsize); | do_adjacentKeepBorders(t, rw, limask, lomask, lres, res, rsize); | ||||
| } | } | ||||
| else { // "bleed out" buffer edge mode is turned on | else { /* "bleed out" buffer edge mode is turned on. */ | ||||
| do_adjacentBleedBorders(t, rw, limask, lomask, lres, res, rsize); | do_adjacentBleedBorders(t, rw, limask, lomask, lres, res, rsize); | ||||
| } | } | ||||
| // set up inner edge, outer edge, and gradient buffer sizes after border pass | /* Set up inner edge, outer edge, and gradient buffer sizes after border pass. */ | ||||
| isz = rsize[0]; | isz = rsize[0]; | ||||
| osz = rsize[1]; | osz = rsize[1]; | ||||
| gsz = rsize[2]; | gsz = rsize[2]; | ||||
| // detect edges in all non-border pixels in the buffer | /* Detect edges in all non-border pixels in the buffer. */ | ||||
| do_adjacentEdgeDetection(t, rw, limask, lomask, lres, res, rsize, isz, osz, gsz); | do_adjacentEdgeDetection(t, rw, limask, lomask, lres, res, rsize, isz, osz, gsz); | ||||
| } | } | ||||
| else { // "all" inner edge mode is turned on | else { /* "all" inner edge mode is turned on. */ | ||||
| if (this->m_keepInside) { // if "keep inside" buffer edge mode is turned on | if (this->m_keepInside) { /* If "keep inside" buffer edge mode is turned on. */ | ||||
| do_allKeepBorders(t, rw, limask, lomask, lres, res, rsize); | do_allKeepBorders(t, rw, limask, lomask, lres, res, rsize); | ||||
| } | } | ||||
| else { // "bleed out" buffer edge mode is turned on | else { /* "bleed out" buffer edge mode is turned on. */ | ||||
| do_allBleedBorders(t, rw, limask, lomask, lres, res, rsize); | do_allBleedBorders(t, rw, limask, lomask, lres, res, rsize); | ||||
| } | } | ||||
| // set up inner edge, outer edge, and gradient buffer sizes after border pass | /* Set up inner edge, outer edge, and gradient buffer sizes after border pass. */ | ||||
| isz = rsize[0]; | isz = rsize[0]; | ||||
| osz = rsize[1]; | osz = rsize[1]; | ||||
| gsz = rsize[2]; | gsz = rsize[2]; | ||||
| // detect edges in all non-border pixels in the buffer | /* Detect edges in all non-border pixels in the buffer. */ | ||||
| do_allEdgeDetection(t, rw, limask, lomask, lres, res, rsize, isz, osz, gsz); | do_allEdgeDetection(t, rw, limask, lomask, lres, res, rsize, isz, osz, gsz); | ||||
| } | } | ||||
| // set edge and gradient buffer sizes once again... | /* Set edge and gradient buffer sizes once again... | ||||
| // the sizes in rsize[] may have been modified | * the sizes in rsize[] may have been modified | ||||
| // by the do_*EdgeDetection() function. | * by the `do_*EdgeDetection()` function. */ | ||||
| isz = rsize[0]; | isz = rsize[0]; | ||||
| osz = rsize[1]; | osz = rsize[1]; | ||||
| gsz = rsize[2]; | gsz = rsize[2]; | ||||
| // calculate size of pixel index buffer needed | /* Calculate size of pixel index buffer needed. */ | ||||
| fsz = gsz + isz + osz; | fsz = gsz + isz + osz; | ||||
| // allocate edge/gradient pixel index buffer | /* Allocate edge/gradient pixel index buffer. */ | ||||
| gbuf = (unsigned short *)MEM_callocN(sizeof(unsigned short) * fsz * 2, "DEM"); | gbuf = (unsigned short *)MEM_callocN(sizeof(unsigned short) * fsz * 2, "DEM"); | ||||
| do_createEdgeLocationBuffer( | do_createEdgeLocationBuffer( | ||||
| t, rw, lres, res, gbuf, &innerEdgeOffset, &outerEdgeOffset, isz, gsz); | t, rw, lres, res, gbuf, &innerEdgeOffset, &outerEdgeOffset, isz, gsz); | ||||
| do_fillGradientBuffer(rw, res, gbuf, isz, osz, gsz, innerEdgeOffset, outerEdgeOffset); | do_fillGradientBuffer(rw, res, gbuf, isz, osz, gsz, innerEdgeOffset, outerEdgeOffset); | ||||
| // free the gradient index buffer | /* Free the gradient index buffer. */ | ||||
| MEM_freeN(gbuf); | MEM_freeN(gbuf); | ||||
| } | } | ||||
| } | } | ||||
| DoubleEdgeMaskOperation::DoubleEdgeMaskOperation() | DoubleEdgeMaskOperation::DoubleEdgeMaskOperation() | ||||
| { | { | ||||
| this->addInputSocket(DataType::Value); | this->addInputSocket(DataType::Value); | ||||
| this->addInputSocket(DataType::Value); | this->addInputSocket(DataType::Value); | ||||
| this->addOutputSocket(DataType::Value); | this->addOutputSocket(DataType::Value); | ||||
| this->m_inputInnerMask = nullptr; | this->m_inputInnerMask = nullptr; | ||||
| this->m_inputOuterMask = nullptr; | this->m_inputOuterMask = nullptr; | ||||
| this->m_adjacentOnly = false; | this->m_adjacentOnly = false; | ||||
| this->m_keepInside = false; | this->m_keepInside = false; | ||||
| this->flags.complex = true; | this->flags.complex = true; | ||||
| is_output_rendered_ = false; | |||||
| } | } | ||||
| bool DoubleEdgeMaskOperation::determineDependingAreaOfInterest(rcti * /*input*/, | bool DoubleEdgeMaskOperation::determineDependingAreaOfInterest(rcti * /*input*/, | ||||
| ReadBufferOperation *readOperation, | ReadBufferOperation *readOperation, | ||||
| rcti *output) | rcti *output) | ||||
| { | { | ||||
| if (this->m_cachedInstance == nullptr) { | if (this->m_cachedInstance == nullptr) { | ||||
| rcti newInput; | rcti newInput; | ||||
| ▲ Show 20 Lines • Show All 48 Lines • ▼ Show 20 Lines | void DoubleEdgeMaskOperation::deinitExecution() | ||||
| this->m_inputOuterMask = nullptr; | this->m_inputOuterMask = nullptr; | ||||
| deinitMutex(); | deinitMutex(); | ||||
| if (this->m_cachedInstance) { | if (this->m_cachedInstance) { | ||||
| MEM_freeN(this->m_cachedInstance); | MEM_freeN(this->m_cachedInstance); | ||||
| this->m_cachedInstance = nullptr; | this->m_cachedInstance = nullptr; | ||||
| } | } | ||||
| } | } | ||||
| void DoubleEdgeMaskOperation::get_area_of_interest(int UNUSED(input_idx), | |||||
| const rcti &UNUSED(output_area), | |||||
| rcti &r_input_area) | |||||
| { | |||||
| r_input_area.xmax = this->getWidth(); | |||||
| r_input_area.xmin = 0; | |||||
| r_input_area.ymax = this->getHeight(); | |||||
| r_input_area.ymin = 0; | |||||
| } | |||||
| void DoubleEdgeMaskOperation::update_memory_buffer(MemoryBuffer *output, | |||||
| const rcti &UNUSED(area), | |||||
| Span<MemoryBuffer *> inputs) | |||||
| { | |||||
| if (!is_output_rendered_) { | |||||
| /* Ensure full buffers to work with no strides. */ | |||||
| MemoryBuffer *input_inner_mask = inputs[0]; | |||||
| MemoryBuffer *inner_mask = input_inner_mask->is_a_single_elem() ? input_inner_mask->inflate() : | |||||
| input_inner_mask; | |||||
| MemoryBuffer *input_outer_mask = inputs[1]; | |||||
| MemoryBuffer *outer_mask = input_outer_mask->is_a_single_elem() ? input_outer_mask->inflate() : | |||||
| input_outer_mask; | |||||
| BLI_assert(output->getWidth() == this->getWidth()); | |||||
| BLI_assert(output->getHeight() == this->getHeight()); | |||||
| /* TODO(manzanilla): Once tiled implementation is removed, use execution system to run | |||||
| * multi-threaded where possible. */ | |||||
| doDoubleEdgeMask(inner_mask->getBuffer(), outer_mask->getBuffer(), output->getBuffer()); | |||||
| is_output_rendered_ = true; | |||||
| if (inner_mask != input_inner_mask) { | |||||
| delete inner_mask; | |||||
| } | |||||
| if (outer_mask != input_outer_mask) { | |||||
| delete outer_mask; | |||||
| } | |||||
| } | |||||
| } | |||||
| } // namespace blender::compositor | } // namespace blender::compositor | ||||