Warning: session_start(): open(/var/lib/php/sessions/sess_aqlea4gd4kov33407q7smoa3f7, O_RDWR) failed: No space left on device (28) in /var/www/tb-usercake/models/config.php on line 51
Warning: session_start(): Failed to read session data: files (path: /var/lib/php/sessions) in /var/www/tb-usercake/models/config.php on line 51
srecord noeq BWImage_FastRegions(BWImage image) is Runnable {
int w, h, size, runner;
new IntBuffer stack; // locations as y*w+x
int[] regionMatrix; // for each pixel: region index (starting at 1)
// initialize these to use them
IntBuffer regionFirstPixel; // for each region: index of first pixel found
IntBuffer regionSize; // for each region: number of pixels
int regionCounter;
bool verbose;
double regionStep = .1; // for rendering in regionsImage
int x(int pos) { ret pos % w; }
int y(int pos) { ret pos / w; }
int pos(int x, int y) { ret y*w+x; }
Pt pt(int pos) { ret Pt(x(pos), y(pos)); }
int getColor(int pos) { ret image.getInt(x(pos), y(pos)); }
*(BufferedImage img) { this(toBWImage(img)); }
run {
w = image.getWidth(); h = image.getHeight();
size = w*h;
regionMatrix = new int[size];
regionFirstPixel?.add(0); // unused
while (runner < size) {
if (regionMatrix[runner] == 0) {
// make a new region, get color
int region = ++regionCounter;
regionFirstPixel?.add(runner);
stack.add(runner);
int color = getColor(runner);
int rsize = 0;
// flood-fill region
while (nempty(stack)) {
int pos = stack.popLast();
if (regionMatrix[pos] != 0) continue; // touching myself (or someone else)
if (getColor(pos) != color) continue; // wrong color
// new pixel found, mark as ours
regionMatrix[pos] = region;
++rsize;
// explore neighborhood
int x = x(pos), y = y(pos);
if (x > 0) stack.add(pos-1);
if (x < w-1) stack.add(pos+1);
if (y > 0) stack.add(pos-w);
if (y < h-1) stack.add(pos+w);
}
regionSize?.add(rsize);
}
++runner;
}
}
IBWImage regionsImage() {
ret iBWImageFromFunction((x, y) -> {
var region = regionMatrix[pos(x, y)];
ret ((region-1)*regionStep) % (1.0+regionStep-0.0001);
}, w, h);
}
int regionCount() { ret regionCounter; }
// returns points in no particular order
record noeq RegionIterator(int region) {
new IntBuffer stack; // locations as y*w+x
BitSet seen = new(size);
int pos;
{
int pos = regionFirstPixel.get(region);
seen.set(pos);
stack.add(pos);
}
// flood-fill region
bool next() {
if (empty(stack)) false;
pos = stack.popLast();
// explore neighborhood
int x = x(), y = y();
if (x > 0) tryPosition(pos-1);
if (x < w-1) tryPosition(pos+1);
if (y > 0) tryPosition(pos-w);
if (y < h-1) tryPosition(pos+w);
true;
}
private void tryPosition(int p) {
if (!seen.get(p) && regionMatrix[p] == region) {
seen.set(p);
stack.add(p);
}
}
int pos() { ret pos; }
int x() { ret BWImage_FastRegions.this.x(pos); }
int y() { ret BWImage_FastRegions.this.y(pos); }
}
int regionSize(int iRegion) { ret regionSize.get(iRegion); }
Pt samplePixel(int iRegion) { ret pt(regionFirstPixel.get(iRegion)); }
bool inRegion(int iRegion, int x, int y) {
ret regionMatrix[pos(x, y)] == iRegion;
}
}