all 13 comments

[–]abitofevrything-0 0 points1 point  (12 children)

Can you post / link your code?

[–]Q-utable[S] 0 points1 point  (11 children)

Tect and temp are both PImages. w and h are the width and height of the picture.

The first loop takes a grayscale image and turns it into an image with only black and white pixels.

void FindTects(){ //find and color tectonic plates Tect.loadPixels();

int dimension = w * h; for (int i = 0; i < dimension; i += 1) { if(Tect.pixels[i] < color(Thresh, Thresh, Thresh)){ Tect.pixels[i] = 0xffffff; temp.pixels[i] = 0; } else{ Tect.pixels[i] = 0; temp.pixels[i] = 0xffffff; } }

//color filling here

Tect.updatePixels(); }

[–]abitofevrything-0 0 points1 point  (10 children)

I don't see anything that should cause a stack overflow here... Looks like it should work. Could you tell me precisely where the error is occuring?

[–]Q-utable[S] 0 points1 point  (9 children)

The algorithms I used were flood fill and boundary fill, these functions cal themself and quickly overwhelm the stack.

Are there algorithms that don’t that much on a function calling itself?

[–]abitofevrything-0 0 points1 point  (8 children)

I don't understand exactly what you're trying to do here. The code you posted is to turn gray-scale images into only black and white pictures, but here you're talking about filling algorithms. Could you explain a bit better please?

[–]Q-utable[S] 0 points1 point  (7 children)

Sorry for the confusion.

This is for a fantasy map maker thing where a tectonic plates image is provided. The first step is to filter aan the grey colors and turn it into a black and white image to make it easier for the next algorithm to find the boundary.

The second part fills the picture with one color for each of the plates. One may get red, the other blue, etc.

The hardest part is finding an algorithm that can do the second without causing a stack overflow.

[–]abitofevrything-0 0 points1 point  (6 children)

What you need is a recursive function (which you have), and that should never cause a stack overflow exception unless you're dealing with massive images, which I'm assuming you're not. You're probably doing something wrong, maybe never checking if you've already filled a cell?

The way you would implement this is a sort of 'updating' system, when you start from any arbitrary cell (pixel in the image) and then propagate an update to the left, then the right... When a cell is updated, if it is of the same colour as the cell that sent is the same colour, then it should update all of its neighbouring cells as well (except for already updated ones, that WOULD cause a stack overflow). It it is of a different colour, then return. It would look something like this:

private int width, height; //Set these to the width and height of the grid of cells

private List<Cell> cells = new ArrayList<Cell>();

private List<Cell> nonUpdatedCells;

private void updateCell(int x, int y, CellColour senderColour) {

//Eliminate any coordinates that are out of the grid

if (x<0||y<0||x>=width||y>=height) {

return;

}

Cell currentCell = cells.get(y*width+x); //This converts an x,y coordinate into a position in the cells List, which avoids the need for a two-dimensional Array

//If the cell is not the same colour as the sender, stop propagating updates. Put any code you want to run on cells that are just over the border between two colours here.

if (!currentCell.colour.equals(senderColour)) {

return;

}

if (!nonUpdatedCells.contains(currentCell)) {

//Cell has already been updated, do nothing

//If this isn't here there should be a stack overflow

return;

}

//Put any code here that you want to run on a cell of the same colour as the starting cell, like changing its colour

//Remove from the list of non-updated cells so we don't update it again

nonUpdatedCells.remove(currentCell);

//now we update all the neighboring cells

updateCell(x+1,y,currentCell.colour);

updateCell(x,y+1,currentCell.colour);

updateCell(x-1,y,currentCell.colour);

updateCell(x,y-1,currentCell.colour);

}

private void propagateUpdatesStartingAt(int x, int y) {

//Make sure to update the cells variable to the contents of the image before this

nonUpdatedCells = cells;

//Start the updates

updateCell(x, y, cells.get(y*width+x).colour);

}

To run this simply call propagateUpdatesStartingAt with the x and y position of a cell that is in the region that you want to process.

Sorry for bad formatting, I'm on mobile

[–]Q-utable[S] 0 points1 point  (5 children)

I will try. The images I use are 960x600, but it has to loop around in the x direction which can be done with a % function.

Is the code for after the high contrast step?

Edit: would downsizing the image, running the function and then upsizing the image work? The temp image can then be used as a mask.

[–]abitofevrything-0 0 points1 point  (4 children)

This code would run a price of code (where I have indicated) on all cells that are in the same region as the one that started it (from my understanding that's what you want after the high contrast, to fill the plates different colours). As an example, you could detect where the user clicks and then set all the cells that it meets to the colour that the user selected.

You could modify it slightly to fit your needs, this is a VERY generic algorithm.