# Stackoverflow

I’m using a fill algorithm in my pixel art project which gives an error “stackoverflow” only if I scale up the project. For example if i do a fill for a 64 64 image it doesn’t give me any error but if I go ahead to 170 170 it gives a stackoverflow error. I’m sure that the algorithm is not going in an infinite loop since it works for 64*64. So what is the limit before which codea gives a stackoverflow error? I’m using the algorithm from this page http://en.wikipedia.org/wiki/Flood_fill , the one at the bottom of the page under the heading Large scale behaviour (four way flood fill).

Can you post the code?i am fairly sure there is something wrong in it.

@Jmv38 Here’s the part related to the fill.
Pixelate is a function which sets the colour of the pixel. And (a,b) are the coordinates. And self.Image is the image. And self.r… Is the colour of the pixel chosen and self.rc…is colour of the adjacent pixel.

``````function Grid:Flood(a, b)

self:Pixelate(a, b)

if a + 1 <= self.Image.width and b <= self.Image.height and a + 1 >= 1 and b >= 1 then
self.rc, self.gc, self.bc, self.ac = self.Image:get(a + 1, b)
if self.rc == self.r and self.gc == self.g and self.bc == self.b and self.ac == self.a then
self:Pixelate(a + 1, b)
self:Flood(a + 1, b)
end
end

if a - 1 <= self.Image.width and b <= self.Image.height and a - 1 >= 1 and b >= 1 then
self.rc, self.gc, self.bc, self.ac = self.Image:get(a - 1, b)
if self.rc == self.r and self.gc == self.g and self.bc == self.b and self.ac == self.a then
self:Pixelate(a - 1, b)
self:Flood(a - 1, b)
end
end

if a <= self.Image.width and b + 1 <= self.Image.height and a >= 1 and b + 1 >= 1 then
self.rc, self.gc, self.bc, self.ac = self.Image:get(a, b + 1)
if self.rc == self.r and self.gc == self.g and self.bc == self.b and self.ac == self.a then
self:Pixelate(a, b + 1)
self:Flood(a, b + 1)
end
end

if a <= self.Image.width and b - 1 <= self.Image.height and a >= 1 and b - 1 >= 1 then
self.rc, self.gc, self.bc, self.ac = self.Image:get(a, b - 1)
if self.rc == self.r and self.gc == self.g and self.bc == self.b and self.ac == self.a then
self:Pixelate(a, b - 1)
self:Flood(a, b - 1)
end
end
end
``````

Flood() is calling Flood() calling Flood() etc… You clearly have a huge recursive loop. The ipad has limited memory, so no doubt you get a stackoverflow! You should rewrite Flood without the recursive loop. Like multiple passes until nothing changes anymore.

Thanks @Jmv38 finally got it working after some tweaking. But why is it that the above code worked for 64 by 64 and not for 170 by 170. There must be some reason?

@Saurabh - there may be a better way to do it, by using a table to store the cells you want to visit, instead of calling your function recursively. It looks something like this…

``````--first find the cell you want to start from, say cell (x,y)
tbl={vec2(x,y)}
--keep looping until we're done
while #tbl>0 do
--use the first table item, which has a location of tbl[1].x, tbl[1].y
local x,y=tbl[1].x, tbl[1].y
--look at the neighbour cells, and add them to the table if they need processing
--eg suppose cell x-1,y+1 needs processing, then you say
table.insert(tbl,vec2(x-1,y+1))
--finally we remove the cell we just processed
table.remove(tbl,1)
end
``````

So what we are doing is adding new cells at the end of the table, and examining cells at the beginning of the table. This is called a queue in computer science because we add to the end, and process the beginning, like a real queue.

The advantage is that this cannot overflow. And it’s easier to program than recursion. I hate recursion.

@Saurabh the reason why it works for 64x64 and not 128x128 is probably that: for each pixel you call the 4 neighbours (or so) which call the 4 neighbours, which etc… until you reach the border. So you create a huge number of contextual calls, but this number is not infinite, because you stop on the border. In the 64x64 you didnt reach the memory limit, and in 128x128 you did…

Wow coincidental I did the same thing. I added the ones I wanted to flood in a table and in the draw function I did a flood check for them and removed it from the table out there itself. But this has a disadvantage if there are too many values in the table like for large images. It drops the frame rate temporarily.

If you really need a good framerate, for catching user touch for instance, but have a big computation to do, you can put the computation in a coroutine and start the computation at every draw() but stop it after 10ms, then requme it at next draw() etc… The computation will be a little bit longer, but the frame rate will still feel like 60 Hz.

Thanks @Ignatz, @Jmv38 now only have to learn how to do the co routine stuff from Ignatz’ tutorials, i believe he has done something about them. Thanks!

Here is a working example

``````--# Main
-- test coroutine

-- Use this function to perform your initial setup
function setup()
print("trying to use coroutines")
x1=0
fps = FPS()
fps:progressBarInit("long fonction")
end

longFonc2 = coroutine.wrap(function()
local xmax=100000
local t0,dt = 0,0.003
local restart = true
local killMe = false
local x = xmax
local justFinished = false
while not killMe do
if restart then
x=0
--            print("t0")
restart = false
end
t0 = os.clock()+ dt
if x<xmax then
for i=1,xmax do
x = x + 1
if os.clock()>t0 then
fps:progressBarUpdate(x/xmax)
coroutine.yield(x,false)
t0 = os.clock()+ dt
end
end
justFinished = true
end
if justFinished then
fps:progressBarUpdate(x/xmax)
justFinished = false
end
restart,_,t0 = coroutine.yield(x,true)
end
end)

caller = coroutine.wrap(function()
while true do
while a or not v do
u,v = longFonc2(a,b,c)
a,b,c = coroutine.yield(u,v)
end
a,b,c = coroutine.yield(u,v)
end
end)

-- This function gets called once every frame
function draw()
-- This sets a dark background color
background(40, 40, 50)

-- This sets the line thickness
strokeWidth(5)

local a,b

if math.floor(ElapsedTime/5)~=math.floor((ElapsedTime-DeltaTime)/5) then
a,b = caller(true,false,ElapsedTime)
print(ElapsedTime,a,b)
else a,b = caller() end

fps:draw()
-- write the x on the screen
fill(208, 208, 208, 255)
fontSize(100)
font("AmericanTypewriter-Bold")
rectMode(CENTER)
text(tostring(a),WIDTH/2,HEIGHT/2)

end

--# FPS
FPS = class()

-- this manages FPS and a progress bar
function FPS:init()
-- average fps
self.val = 60
self.t0 = ElapsedTime
-- min fps
self.min = 60
self.t1 = ElapsedTime
-- progress bar
self.frac = 0
self:progressBarInit()
end

function FPS:draw()
local vShift = 0
if self.progressBarActive then vShift = 30 end
-- update FPS value with some smoothing
local old = self.val
local frac = self.frac
--    local t1 = os.clock()
local t1 = ElapsedTime
local delta = t1 - self.t0
self.t0 = t1
local new = 1/delta or old
if new<self.min then self.min=new; self.t1=ElapsedTime+1 end
if self.t1<ElapsedTime then self.min=60 end
if new>65 then new=65 end
local ratio = new/old
if 0.5<ratio and ratio<2 then new = old*(1-frac)+ new*frac end
self.val = new

-- write the FPS on the screen
fill(208, 208, 208, 255)
fontSize(20)
font("AmericanTypewriter-Bold")
rectMode(CENTER)
text(math.floor(new).." fps (> "..math.floor(self.min)..")",70,HEIGHT-15-vShift)
-- draw progress bar
self:progressBarDraw()
end

function FPS:progressBarInit(txt)
self.frac = 0
self.txt = txt or "running"
self.img = self:progressBarCalcInfoImg(self.txt,WIDTH*0.19,30,"top")
self.progressBarActive = false
end

function FPS:progressBarUpdate(frac)
self.frac = frac
if frac>0 and frac<1 then self.progressBarActive = true
else self.progressBarActive = false end
end

-- image to show job progress
function FPS:progressBarCalcInfoImg(txt,w,h,rot)
local w0,h0
pushStyle() pushMatrix()
if rot=="left" or rot=="right"
then w0,h0 = h,w
else w0,h0 = w,h
end
local img0 = image(w0,h0)
setContext(img0)
font("AmericanTypewriter-Bold")
rectMode(CENTER)
textMode(CENTER)
strokeWidth(1)
background(255, 255, 255, 255)
fill(0, 0, 0, 255)
stroke(0, 0, 0, 255)
fontSize(20)
text(txt,w0/2,h0/2)
setContext()
local img = image(w,h)
setContext(img)
background(0, 0, 0, 255)
spriteMode(CENTER)
translate(w/2,h/2)
if rot=="left" then rotate(-90) end
if rot=="right" then rotate(90) end
sprite(img0,0,0)
setContext()
popStyle() popMatrix()
return img
end

function FPS:progressBarDraw()
if self.progressBarActive then
local img = self.img
pushStyle()
spriteMode(CORNER)
tint(128, 128, 128, 255)
sprite(img, 0, HEIGHT - img.height)
tint()
tint(255, 255, 255, 255)
clip(0,HEIGHT  - img.height,self.frac*img.width,img.height)
sprite(img, 0, HEIGHT - img.height)
clip()
popStyle()
end
end

``````

I was just working on coroutine. Why does this not work? It doesn’t go beyond 1

``````function setup()
cos = coroutine.create(Job)
end

function Job()
for i = 1,10000 do
print(i)
coroutine.yeild(Job)
end
end

function draw()
coroutine.resume(cos)
end
``````

though this one doesn’t need coroutine but yet…

:)) :)) :)>-
coroutine.yield(Job).

Dam it wasn’t that. Weird. As far as I remember it doesn’t work with coroutine.yield() also. I’ll check in the morning again and tell.

Yes it was. I ran your code and got 1. Then i corrected the syntax and got 1,2,3 etc…

Reading your code again i have a doubt. But since it worked directly i didnt try further. I’ll check tomorrow too

@saurabh no, finally it works fine. What i didnt like was the coroutine.yield(Job).
You shoul really write coroutine.yield() only, the pevious line returns the adress to call the class Job at each yield, which is not what you wanted, and you dont use it anyway because you dont read the output of the yield in this example.

I didn’t understand you @Jmv38 why shouldn’t I use coroutine out here. Or were you trying to say something else? And how did coroutine.yeild work?? It should have given an error…

@Saurabh read my text again. I didnt say you should not use coroutine. I just said you shouldnt pass the ‘Job’ parameter to the yield().

Oh okay thanks misunderstood it.