package Algorithms; import Utils.IntVector; import java.util.Arrays; public class Outline { static final int[] firstPointIsTopLeft = new int[] { 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, -1, -1, 0, -1, 0 }; static final int[] firstPointIsTopRight = new int[] { 0, 0, 0, 0, -1, -1, -1, -1, 0, 0, 0, 0, 0, -1, 0, 0 }; static final int[] firstPointIsBottomLeft = new int[] { 0, -1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static final int[] firstPointIsBottomRight = new int[] { 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static final int[] secondPointIsTopRight = new int[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0 }; static final int[] secondPointIsBottomRight = new int[] { 0, 0, 0, -1, 0, 0, -1, 0, 0, 0, -1, -1, 0, 0, -1, 0 }; static final int[] secondPointIsBottomLeft = new int[] { 0, 0, 0, 0, 0, -1, 0, -1, 0, -1, 0, 0, 0, -1, 0, 0 }; public static void drawOutline( int[] outline, int[] outlineScratch1, int[] outlineScratch2, int rgbColor, double strokeWidth, byte[] image, int width, int height ) { int area = width * height; int iterations = (int)Math.ceil(strokeWidth); int[] readingScratch = outlineScratch1; int[] writingScratch = outlineScratch2; Arrays.fill(readingScratch, 0, area, 0); Arrays.fill(writingScratch, 0, area, 0); byte firstInputPixel = image[0]; int firstOutputPixel = outline[0]; image[0] = 0; outline[0] = 0; readingScratch[0] = 0; for (int i = 0; i < iterations; i++) { int shouldReadMask = -i >> 31; for (int y = -1; y < height; y++) { int topLeft = 0, topRight = 0, bottomLeft = 0, bottomRight = 0; int topLeftIdx = 0, topRightIdx = 0, bottomLeftIdx = 0, bottomRightIdx = 0; readingScratch[0] = 0; for (int x = -1; x < width; x++) { topLeft = topRight; topLeftIdx = topRightIdx; bottomLeft = bottomRight; bottomLeftIdx = bottomRightIdx; topRightIdx = (x < width-1 && y >= 0) ? (x+1) + width * y : 0; bottomRightIdx = (x < width-1 && y < height-1) ? (x+1) + width * (y+1) : 0; topRight = (image[topRightIdx] ^ (-readingScratch[topRightIdx] & shouldReadMask)) >> 31; bottomRight = (image[bottomRightIdx] ^ (-readingScratch[bottomRightIdx] & shouldReadMask)) >> 31; int type = (topLeft & 8) | (topRight & 4) | (bottomRight & 2) | (bottomLeft & 1); if (type == 0 || type == 15) continue; int p1 = (topLeftIdx & firstPointIsTopLeft[type]) | (topRightIdx & firstPointIsTopRight[type]) | (bottomRightIdx & firstPointIsBottomRight[type]) | (bottomLeftIdx & firstPointIsBottomLeft[type]); int p2 = (topRightIdx & secondPointIsTopRight[type]) | (bottomRightIdx & secondPointIsBottomRight[type]) | (bottomLeftIdx & secondPointIsBottomLeft[type]); int p3 = (topLeftIdx & (-(((type - 13) | (13 - type)) >> 31) - 1)) | (topRightIdx & (-(((type - 14) | (14 - type)) >> 31) - 1)) | (bottomRightIdx & (-(((type - 7) | (7 - type)) >> 31) - 1)) | (bottomLeftIdx & (-(((type - 11) | (11 - type)) >> 31) - 1)); outline[p1] = rgbColor; outline[p2] = rgbColor; outline[p3] = rgbColor; writingScratch[p1] = 1; writingScratch[p2] = 1; writingScratch[p3] = 1; } } int[] temp = readingScratch; readingScratch = writingScratch; writingScratch = temp; } image[0] = firstInputPixel; outline[0] = firstOutputPixel; } }