Libraryless. Click here for Pure Java version (9070L/50K).
srecord noeq G22RegionThinner_v2<Img extends WidthAndHeight>(IImageRegion<Img> originalRegion) is Steppable { Rect bounds; IImageRegion<Img> region; bool phase1done; // 0 = outside of region // 1 = inner pixel // 2 = border pixel // index is in bounds coordinates byte[] pixels; int idx(int x, int y) { ret (y-bounds.y)*bounds.w+x-bounds.x; } int idx(Pt p) { ret idx(p.x, p.y); } Pt idxToPt(int idx) { ret pt(bounds.x+(idx % bounds.w), bounds.y+idx/bounds.w); } byte getPixel(Pt p) { ret !containsPt(bounds, p) ? 0 : pixels[idx(p)]; } byte getPixel(int x, int y) { ret !containsPt(bounds, x, y) ? 0 : pixels[idx(x, y)]; } bool contains(int x, int y) { ret getPixel(x, y) != 0; } bool clearPixel(int x, int y) { if (!region.contains(x, y)) false; pixels[idx(x, y)] = 0; true; } void init { if (bounds != null) ret; bounds = originalRegion.bounds(); pixels = new byte[area(bounds)]; for (Pt p : originalRegion.pixelIterator()) pixels[idx(p.x, p.y)] = 1; region = new ThinnedRegion; } class ThinnedRegion is IImageRegion<Img> { public Img image() { ret originalRegion.image(); } public Rect bounds() { ret bounds; } public bool contains(int x, int y) { ret containsPt(bounds, x, y) && pixels[idx(x, y)] > 0; } public ItIt<Pt> pixelIterator() { ret iff_null(new IF0<Pt> { int idx = 0; public Pt get() { for (; idx < pixels.length; idx++) if (pixels[idx] > 0) ret idxToPt(idx++); null; } }); } } public bool step() { init(); if (phase1done) ret finalStep(); L<PtBuffer> traces = g22_allBorderTraces_withDiagonals(region); for (points : traces) for (p : points) pixels[idx(p)] = 2; new PtBuffer toDelete; for (points : traces) { int nPoints = l(points); BitSet deletable = emptyBitSet(nPoints); for i to nPoints: { ping(); if (deletableBorderPoint(points, i)) deletable.set(i); } // handle special cases for (int i = 1; i < nPoints-1; i++) if (deletable.get(i-1) && !deletable.get(i) && deletable.get(i+1)) { Pt p = points.get(i); Pt prev = ptMinus(points.get(i-1), p); Pt next = ptMinus(points.get(i+1), p); int dir1 = onePathLookupDirection(prev); int dir2 = onePathLookupDirection(next); int diff = mod(dir2-dir1, 8); printVars ifdef G22RegionThinner_debug(+p, +prev, +next, +dir1, +dir2, +diff); if (diff == 1 || diff == 7) deletable.set(i); } for i to nPoints: if (deletable.get(i)) toDelete.add(points.get(i)); } for (p : toDelete) pixels[idx(p)] = 0; if (empty(toDelete)) set phase1done; true; } bool deletableBorderPoint(PtBuffer points, int i) { L<Pt> range = cyclicSubList_incl(points, i-3, i+3); Pt p = points.get(i); // special case if (eq(range.get(1), p) || eq(range.get(5), p)) false; int surroundingBorderPixels = 0, surroundingInnerPixels = 0; for (int dir = 1; dir <= 8; dir++) { Pt p2 = ptPlus(p, onePathDirection(dir)); byte value = getPixel(p2); if (value == 2 && !range.contains(p2)) surroundingBorderPixels++; else if (value == 1) surroundingInnerPixels++; } bool deletable = surroundingInnerPixels > 0 && surroundingBorderPixels == 0; printVars ifdef G22RegionThinner_debug(+p, +surroundingInnerPixels, +surroundingBorderPixels, +deletable, +range); ret deletable; } IImageRegion region aka get() { ret or(region, originalRegion); } // go from 2 pixels wide to 1 pixel wide (TODO) bool finalStep() { false; } }
Began life as a copy of #1034983
download show line numbers debug dex old transpilations
Travelled to 3 computer(s): bhatertpkbcr, mowyntqkapby, mqqgnosmbjvj
No comments. add comment
Snippet ID: | #1035003 |
Snippet name: | G22RegionThinner_v2 - thin a region to 2 pixel wide [OK backup without final thinning] |
Eternal ID of this version: | #1035003/1 |
Text MD5: | 20538f6b51376f6e420242aa39130a5c |
Transpilation MD5: | 77cf4d8750bb0e2968fac7c8940b3160 |
Author: | stefan |
Category: | javax |
Type: | JavaX fragment (include) |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2022-03-22 18:34:55 |
Source code size: | 4099 bytes / 151 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 131 / 182 |
Referenced in: | [show references] |