* Adds sub-pixel resolution EdgeOffsets for the outline if the supplied * pix is 8-bit. Does nothing otherwise. * Operation: Consider the following near-horizontal line: * @verbatim * _________ * |________ * |________ * @endverbatim * At *every* position along this line, the gradient direction will be close * to vertical. Extrapoaltion/interpolation of the
| 740 | * direction can be used to ignore the vertical steps. |
| 741 | */ |
| 742 | void C_OUTLINE::ComputeEdgeOffsets(int threshold, Pix* pix) { |
| 743 | if (pixGetDepth(pix) != 8) return; |
| 744 | const l_uint32* data = pixGetData(pix); |
| 745 | int wpl = pixGetWpl(pix); |
| 746 | int width = pixGetWidth(pix); |
| 747 | int height = pixGetHeight(pix); |
| 748 | bool negative = flag(COUT_INVERSE); |
| 749 | delete [] offsets; |
| 750 | offsets = new EdgeOffset[stepcount]; |
| 751 | ICOORD pos = start; |
| 752 | ICOORD prev_gradient; |
| 753 | ComputeGradient(data, wpl, pos.x(), height - pos.y(), width, height, |
| 754 | &prev_gradient); |
| 755 | for (int s = 0; s < stepcount; ++s) { |
| 756 | ICOORD step_vec = step(s); |
| 757 | TPOINT pt1(pos); |
| 758 | pos += step_vec; |
| 759 | TPOINT pt2(pos); |
| 760 | ICOORD next_gradient; |
| 761 | ComputeGradient(data, wpl, pos.x(), height - pos.y(), width, height, |
| 762 | &next_gradient); |
| 763 | // Use the sum of the prev and next as the working gradient. |
| 764 | ICOORD gradient = prev_gradient + next_gradient; |
| 765 | // best_diff will be manipulated to be always positive. |
| 766 | int best_diff = 0; |
| 767 | // offset will be the extrapolation of the location of the greyscale |
| 768 | // threshold from the edge with the largest difference, relative to the |
| 769 | // location of the binary edge. |
| 770 | int offset = 0; |
| 771 | if (pt1.y == pt2.y && abs(gradient.y()) * 2 >= abs(gradient.x())) { |
| 772 | // Horizontal step. diff_sign == 1 indicates black above. |
| 773 | int diff_sign = (pt1.x > pt2.x) == negative ? 1 : -1; |
| 774 | int x = MIN(pt1.x, pt2.x); |
| 775 | int y = height - pt1.y; |
| 776 | int best_sum = 0; |
| 777 | int best_y = y; |
| 778 | EvaluateVerticalDiff(data, wpl, diff_sign, x, y, height, |
| 779 | &best_diff, &best_sum, &best_y); |
| 780 | // Find the strongest edge. |
| 781 | int test_y = y; |
| 782 | do { |
| 783 | ++test_y; |
| 784 | } while (EvaluateVerticalDiff(data, wpl, diff_sign, x, test_y, height, |
| 785 | &best_diff, &best_sum, &best_y)); |
| 786 | test_y = y; |
| 787 | do { |
| 788 | --test_y; |
| 789 | } while (EvaluateVerticalDiff(data, wpl, diff_sign, x, test_y, height, |
| 790 | &best_diff, &best_sum, &best_y)); |
| 791 | offset = diff_sign * (best_sum / 2 - threshold) + |
| 792 | (y - best_y) * best_diff; |
| 793 | } else if (pt1.x == pt2.x && abs(gradient.x()) * 2 >= abs(gradient.y())) { |
| 794 | // Vertical step. diff_sign == 1 indicates black on the left. |
| 795 | int diff_sign = (pt1.y > pt2.y) == negative ? 1 : -1; |
| 796 | int x = pt1.x; |
| 797 | int y = height - MAX(pt1.y, pt2.y); |
| 798 | const l_uint32* line = pixGetData(pix) + y * wpl; |
| 799 | int best_sum = 0; |
no test coverage detected