import java.awt.geom.*; static Path2D.Float alphaToShape(BufferedImage img) { BWImage bw = getAlphaChannel(img); Image2B alpha = new Image2B(bw); int w = alpha.w(), h = alpha.h(); Path2D.Float path = new Path2D.Float(); int x = w/2; int y = -1; while (y < h && !alphaToShape_isInteresting(alphaToShape_getQuadrant(alpha, x, y))) ++y; int x1 = x, y1 = y; path.moveTo(x, y); new HashSet seen; while (seen.add(new Pt(x, y))) { int q = alphaToShape_getQuadrant(alpha, x, y); Pt next = null; for (Pt p : neighborhood8(x, y)) if (!seen.contains(p) && alphaToShape_isInteresting(alphaToShape_getQuadrant(alpha, p.x, p.y))) { next = p; break; } if (next == null) break; x = next.x; y = next.y; path.lineTo(x+1, y+1); } ret path; } sbool alphaToShape_isInteresting(int q) { ret q != 0 && q != 0x1111; } static int alphaToShape_getQuadrant(Image2B img, int x, int y) { ret (alphaToShape_getQuadrant_getPixel(img, x, y) ? 0x1000 : 0) + (alphaToShape_getQuadrant_getPixel(img, x+1, y) ? 0x0100 : 0) + (alphaToShape_getQuadrant_getPixel(img, x, y+1) ? 0x0010 : 0) + (alphaToShape_getQuadrant_getPixel(img, x+1, y+1) ? 0x0001 : 0); } static bool alphaToShape_getQuadrant_getPixel(Image2B img, int x, int y) { ret x >= 0 && x < img.w && y >= 0 && y < img.h && img.getPixel(x, y); }