Sign in to follow this  
Followers 0
UEZ

Recursion level limit

45 posts in this topic

#1 ·  Posted (edited)

Is there a way to increase max recursion level?

For example this code is using recursion to fill an area with a color but the job is interrupted because of reaching the recursion limit!

#include <GDIPlus.au3>

$sRegPath = "HKLM\SOFTWARE\AutoIt v3\AutoIt"
If StringInStr("X64IA64", @OSArch) Then $sRegPath = StringReplace($sRegPath, "SOFTWARE", "SOFTWARE\Wow6432Node")

_GDIPlus_Startup()
$hImage = _GDIPlus_ImageLoadFromFile(RegRead($sRegPath, "InstallDir") & "\Examples\GUI\logo4.gif")
$iW = _GDIPlus_ImageGetWidth($hImage)
$iH = _GDIPlus_ImageGetHeight($hImage)
$hGUI = GUICreate("Test", $iW, $iH)
GUISetState()
$hGfx = _GDIPlus_GraphicsCreateFromHWND($hGUI)
AdlibRegister("UpdateView", 10)

$iColor2Fill = 0xFFFFFFFF
;~ _GDIPlus_FloodFillRec($hImage, 0, 0, 0xFF000080, 0xFFFFFF00)
_GDIPlus_FloodFillRec($hImage, 82, 24, 0xFF000080, 0xFFFFFF00)
_GDIPlus_ImageSaveToFile($hImage, @ScriptDir & "\Filled.png")
;~ ShellExecute(@ScriptDir & "\Filled.png")
AdlibUnRegister("UpdateView")
ConsoleWrite("Done" & @LF)
Do
Until GUIGetMsg() = -3

_GDIPlus_ImageDispose($hImage)
_GDIPlus_GraphicsDispose($hGfx)
_GDIPlus_Shutdown()
Exit

Func _GDIPlus_FloodFillRec(ByRef $hBitmap, $iX, $iY, $iColorOld, $iColorNew) ;coded by UEZ 2013-01-12
    Local Static $iRec = 1
    Local $aResult = DllCall($ghGDIPDll, "uint", "GdipBitmapGetPixel", "handle", $hBitmap, "int", $iX, "int", $iY, "uint*", 0)
    If $aResult[4] = "0x" & Hex($iColorOld, 8) Then
        DllCall($ghGDIPDll, "uint", "GdipBitmapSetPixel", "handle", $hBitmap, "int", $iX, "int", $iY, "uint", $iColorNew)
    Else
        Return 0
    EndIf
    Local $iRecLimit = 3899
    $aResult = DllCall($ghGDIPDll, "uint", "GdipGetImageDimension", "handle", $hBitmap, "float*", 0, "float*", 0)
    If ($iX + 1) < $aResult[2] + 1 Then
        $iRec += 1
        If $iRec = $iRecLimit Then Return -1
        _GDIPlus_FloodFillRec($hBitmap, $iX + 1, $iY, $iColorOld, $iColorNew) ;go east
        $iRec -= 1
    EndIf
    If ($iY + 1) < $aResult[3] + 1 Then
        $iRec += 1
        If $iRec = $iRecLimit Then Return -1
        _GDIPlus_FloodFillRec($hBitmap, $iX, $iY + 1, $iColorOld, $iColorNew) ;go south
        $iRec -= 1
    EndIf
    If ($iX - 1) > -1 Then
        $iRec += 1
        If $iRec = $iRecLimit Then Return -1
        _GDIPlus_FloodFillRec($hBitmap, $iX - 1, $iY, $iColorOld, $iColorNew) ;go west
        $iRec -= 1
    EndIf
    If ($iY - 1) > -1 Then
        $iRec += 1
        If $iRec = $iRecLimit Then Return -1
        _GDIPlus_FloodFillRec($hBitmap, $iX, $iY - 1, $iColorOld, $iColorNew) ;go north
        $iRec -= 1
    EndIf
    Return 1
EndFunc   ;==>_GDIPlus_FloodFillRec

Func UpdateView()
    _GDIPlus_GraphicsDrawImage($hGfx, $hImage, 0, 0)
EndFunc

Br,

UEZ

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Share this post


Link to post
Share on other sites



Nothing wrong with recursion. Although generally not needed.

Just don't do it per pixel in this case. :blink:


"Straight_and_Crooked_Thinking" : A "classic guide to ferreting out untruths, half-truths, and other distortions of facts in political and social discussions."
"The Secrets of Quantum Physics" : New and excellent 2 part documentary on Quantum Physics by Jim Al-Khalili. (Dec 2014)

"Believing what you know ain't so" ...

Knock Knock ...
 

Share this post


Link to post
Share on other sites

On your original question. Probably not, as hitting a recursion limit is general a case of bad coding.


"Straight_and_Crooked_Thinking" : A "classic guide to ferreting out untruths, half-truths, and other distortions of facts in political and social discussions."
"The Secrets of Quantum Physics" : New and excellent 2 part documentary on Quantum Physics by Jim Al-Khalili. (Dec 2014)

"Believing what you know ain't so" ...

Knock Knock ...
 

Share this post


Link to post
Share on other sites

I could be wrong, but isn't recursion limited by available memory? I am able to reach 3899 recursions on one machine, and only 1899 on another. Shutting down my email allows me to reach 5848 on the first system.

Share this post


Link to post
Share on other sites

#6 ·  Posted (edited)

In some cases recursion is very easy to implement to get the wanted result, e.g. as shown in the example above.

So it is legitime to use / prefer recursion rather than iteration in some cases. I cannot say anything about the AutoIt internal procedure how recursion (stacks) are handled but in this particualar simple example to fill a small image (169x68) fails which I cannot understand.

I don't know how to optimize the code not to reach any limits.

When I run the code it will increase the memory consumption from 5 MB to 10 MB until it reaches the limit.

Br,

UEZ

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Share this post


Link to post
Share on other sites

Recursion limit is artificial. Jon did some testings and concluded that in order for AutoIt to function correctly in low memory coditions it would be good to use the numbers willichan shows. It's not machine specific, it's related to the bitness of the interpretter. x86 have one limit and x64 other.

The problem with the numbers used before is that undrelying API couldn't load string resource (as docummented by MSDN) used for displaying the "error". This means that in reality these numbers could be set higher if the strings wouldn't be loaded from resources. Still the limit would also be reached at some point, so the question is really why to change it. :)

2 people like this

♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites

#8 ·  Posted (edited)

is this way just slower, or not the intended effect at all? Because it seems the implementation is equally easy.

#include <GDIPlus.au3>

$sRegPath = "HKLM\SOFTWARE\AutoIt v3\AutoIt"
If StringInStr("X64IA64", @OSArch) Then $sRegPath = StringReplace($sRegPath, "SOFTWARE", "SOFTWARE\Wow6432Node")

_GDIPlus_Startup()
$hImage = _GDIPlus_ImageLoadFromFile(RegRead($sRegPath, "InstallDir") & "\Examples\GUI\logo4.gif")

_GDIPlus_FloodFill($hImage, 0, 0, 0xFF000080, 0xFFFFFF00)
_GDIPlus_ImageSaveToFile($hImage, @ScriptDir & "\Filled.png")
_GDIPlus_ImageDispose($hImage)
_GDIPlus_Shutdown()
ShellExecute(@ScriptDir & "\Filled.png")
Exit

Func _GDIPlus_FloodFill(ByRef $hBitmap, $iX, $iY, $iColorOld, $iColorNew) ;coded by UEZ 2013-01-11
$aResult = DllCall($ghGDIPDll, "uint", "GdipGetImageDimension", "handle", $hBitmap, "float*", 0, "float*", 0)

For $x = 1 to $aResult[2]
For $y = 1 to $aResult[3]
Local $aResult = DllCall($ghGDIPDll, "uint", "GdipBitmapGetPixel", "handle", $hBitmap, "int", $X, "int", $Y, "uint*", 0)
If $aResult[4] = "0x" & Hex($iColorOld, 8) Then
DllCall($ghGDIPDll, "uint", "GdipBitmapSetPixel", "handle", $hBitmap, "int", $X, "int", $Y, "uint", $iColorNew)
EndIf

Next
Next

EndFunc
Edited by boththose

,-. .--. ________ .-. .-. ,---. ,-. .-. .-. .-.
|(| / /\ \ |\ /| |__ __||| | | || .-' | |/ / \ \_/ )/
(_) / /__\ \ |(\ / | )| | | `-' | | `-. | | / __ \ (_)
| | | __ | (_)\/ | (_) | | .-. | | .-' | | \ |__| ) (
| | | | |)| | \ / | | | | | |)| | `--. | |) \ | |
`-' |_| (_) | |\/| | `-' /( (_)/( __.' |((_)-' /(_|
'-' '-' (__) (__) (_) (__)

Share this post


Link to post
Share on other sites

#9 ·  Posted (edited)

@boththose: this is not same! You change every color in the image not the area of the color.

Try _GDIPlus_FloodFill($hImage, 73, 22, 0xFFFFFFFF, 0xFFFFFF00) in the recursive example to see the difference!

Br,

UEZ

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Share this post


Link to post
Share on other sites

#10 ·  Posted (edited)

fair enough, then. Same questions using $iX and $iY instead of 1 to ....

is there an advantage going with recursion instead of for loops?

#include <GDIPlus.au3>

$sRegPath = "HKLM\SOFTWARE\AutoIt v3\AutoIt"
If StringInStr("X64IA64", @OSArch) Then $sRegPath = StringReplace($sRegPath, "SOFTWARE", "SOFTWARE\Wow6432Node")

_GDIPlus_Startup()
$hImage = _GDIPlus_ImageLoadFromFile(RegRead($sRegPath, "InstallDir") & "\Examples\GUI\logo4.gif")

_GDIPlus_FloodFill($hImage, 73, 22, 0xFFFFFFFF, 0xFFFFFF00)
_GDIPlus_ImageSaveToFile($hImage, @ScriptDir & "\Filled.png")
_GDIPlus_ImageDispose($hImage)
_GDIPlus_Shutdown()
ShellExecute(@ScriptDir & "\Filled.png")
Exit

Func _GDIPlus_FloodFill(ByRef $hBitmap, $iX, $iY, $iColorOld, $iColorNew) ;coded by UEZ 2013-01-11
$aResult = DllCall($ghGDIPDll, "uint", "GdipGetImageDimension", "handle", $hBitmap, "float*", 0, "float*", 0)

For $x = $ix to $aResult[2]
For $y = $iY to $aResult[3]
Local $aResult = DllCall($ghGDIPDll, "uint", "GdipBitmapGetPixel", "handle", $hBitmap, "int", $X, "int", $Y, "uint*", 0)
If $aResult[4] = "0x" & Hex($iColorOld, 8) Then
DllCall($ghGDIPDll, "uint", "GdipBitmapSetPixel", "handle", $hBitmap, "int", $X, "int", $Y, "uint", $iColorNew)
EndIf

Next
Next

EndFunc
Edited by boththose

,-. .--. ________ .-. .-. ,---. ,-. .-. .-. .-.
|(| / /\ \ |\ /| |__ __||| | | || .-' | |/ / \ \_/ )/
(_) / /__\ \ |(\ / | )| | | `-' | | `-. | | / __ \ (_)
| | | __ | (_)\/ | (_) | | .-. | | .-' | | \ |__| ) (
| | | | |)| | \ / | | | | | |)| | `--. | |) \ | |
`-' |_| (_) | |\/| | `-' /( (_)/( __.' |((_)-' /(_|
'-' '-' (__) (__) (_) (__)

Share this post


Link to post
Share on other sites

#11 ·  Posted (edited)

In some cases recursion is very easy to implement to get the wanted result, e.g. as shown in the example above.

So it is legitime to use / prefer recursion rather than iteration in some cases. I cannot say anything about the AutoIt internal procedure how recursion (stacks) are handled but in this particualar simple example to fill a small image (169x68) fails which I cannot understand.

I don't know how to optimize the code not to reach any limits.

When I run the code it will increase the memory consumption from 5 MB to 10 MB until it reaches the limit.

Br,

UEZ

Use a loop with a stack, it will be just like recursion, but you will not hit any recursion depth limits.

Example:

Put initial pixel in stack.

While there are data on stack:

Pop stack and process the pixel

If pixel to left is same color: put on stack

if pixel to right is same color: put on stack

if pixel above is same color: put on stack

if pixel below is same color: put on stack

Done.

Funny thing with this aproach is that if you visualize the process and use something else instead of a stack (like a queue) the results are very interesting to watch!

Edited by monoceres

Broken link? PM me and I'll send you the file!

Share this post


Link to post
Share on other sites

There are some non-recursive C++ implementations posted here

http://stackoverflow.com/questions/1257117/does-anyone-have-a-working-non-recursive-floodfill-algorithm-written-in-c

that you might be able to translate into AI code.

Share this post


Link to post
Share on other sites

boththose: simplicity. Try to convert this into iteration.

Br,

UEZ


Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Share this post


Link to post
Share on other sites

@monoceres: thanks for the hint. It looks like the code from the link willichan has provided.

@willichan: thanks for the link.

Br,

UEZ


Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Share this post


Link to post
Share on other sites

#15 ·  Posted (edited)

Try to convert this into iteration.

I apologize, if there is something following that statement (like a pretty picture) it is getting websensed, if not then i dont understand how my previous posts are not iterative. Thanks for trying to educate me!

Edited by boththose

,-. .--. ________ .-. .-. ,---. ,-. .-. .-. .-.
|(| / /\ \ |\ /| |__ __||| | | || .-' | |/ / \ \_/ )/
(_) / /__\ \ |(\ / | )| | | `-' | | `-. | | / __ \ (_)
| | | __ | (_)\/ | (_) | | .-. | | .-' | | \ |__| ) (
| | | | |)| | \ / | | | | | |)| | `--. | |) \ | |
`-' |_| (_) | |\/| | `-' /( (_)/( __.' |((_)-' /(_|
'-' '-' (__) (__) (_) (__)

Share this post


Link to post
Share on other sites

@boththose: your version is iterative but it replaces all colors within the image not only a region of colors!

Try with your code to replace only white color (0xFFFFFFFF) within the AutoIt logo for all letters.

Br,

UEZ


Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Share this post


Link to post
Share on other sites

#17 ·  Posted (edited)

This only changes the letters from white to yellow, and is just an adjustment of x value you supplied in your func from post #9, I have a feeling I may be missing something completely...

#include <GDIPlus.au3>

$sRegPath = "HKLM\SOFTWARE\AutoIt v3\AutoIt"
If StringInStr("X64IA64", @OSArch) Then $sRegPath = StringReplace($sRegPath, "SOFTWARE", "SOFTWARE\Wow6432Node")

_GDIPlus_Startup()
$hImage = _GDIPlus_ImageLoadFromFile(RegRead($sRegPath, "InstallDir") & "\Examples\GUI\logo4.gif")

_GDIPlus_FloodFill($hImage, 63, 22, 0xFFFFFFFF, 0xFFFFFF00)
_GDIPlus_ImageSaveToFile($hImage, @ScriptDir & "\Filled.png")
_GDIPlus_ImageDispose($hImage)
_GDIPlus_Shutdown()
ShellExecute(@ScriptDir & "\Filled.png")
Exit

Func _GDIPlus_FloodFill(ByRef $hBitmap, $iX, $iY, $iColorOld, $iColorNew) ;coded by UEZ 2013-01-11
$aResult = DllCall($ghGDIPDll, "uint", "GdipGetImageDimension", "handle", $hBitmap, "float*", 0, "float*", 0)

For $x = $ix to $aResult[2]
For $y = $iY to $aResult[3]
Local $aResult = DllCall($ghGDIPDll, "uint", "GdipBitmapGetPixel", "handle", $hBitmap, "int", $X, "int", $Y, "uint*", 0)
If $aResult[4] = "0x" & Hex($iColorOld, 8) Then
DllCall($ghGDIPDll, "uint", "GdipBitmapSetPixel", "handle", $hBitmap, "int", $X, "int", $Y, "uint", $iColorNew)
EndIf

Next
Next

EndFunc

post-59031-0-72540800-1357924261_thumb.p

Edited by boththose

,-. .--. ________ .-. .-. ,---. ,-. .-. .-. .-.
|(| / /\ \ |\ /| |__ __||| | | || .-' | |/ / \ \_/ )/
(_) / /__\ \ |(\ / | )| | | `-' | | `-. | | / __ \ (_)
| | | __ | (_)\/ | (_) | | .-. | | .-' | | \ |__| ) (
| | | | |)| | \ / | | | | | |)| | `--. | |) \ | |
`-' |_| (_) | |\/| | `-' /( (_)/( __.' |((_)-' /(_|
'-' '-' (__) (__) (_) (__)

Share this post


Link to post
Share on other sites

#18 ·  Posted (edited)

This fills the letters but it fills in a defined rectangle area all colors whereas a flood fill algorithm fills the area where the color is bounded by other colors.

E.g. _GDIPlus_FloodFill($hImage, 88, 27, 0xFFFFFFFF, 0xFFFFFF00) should fill only the left part of the U.

Br,

UEZ

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Share this post


Link to post
Share on other sites

#19 ·  Posted (edited)

but in this particualar simple example to fill a small image (169x68) fails which I cannot understand.

The recursion seems to work like this:

- go north until there is no more north. (possible one recursion level dropped.)

- than go east, until there is no more east. (possible one recursion level dropped.)

- than go south, until there is no more south. (possible one recursion level dropped.)

- than go west, until there is no more west. (possible one recursion level dropped.)

So that code seem to be allowed to make a full circle(square one) while its collection recursion levels.

That still not explains it totally. so it probably run's in multiple, smaller and smaller, circles, while ranking up its recursion level.

If you make the added color depending on the recursion level (gradiant's), It should me more easy to see what path is taken.

Edited by MvGulik

"Straight_and_Crooked_Thinking" : A "classic guide to ferreting out untruths, half-truths, and other distortions of facts in political and social discussions."
"The Secrets of Quantum Physics" : New and excellent 2 part documentary on Quantum Physics by Jim Al-Khalili. (Dec 2014)

"Believing what you know ain't so" ...

Knock Knock ...
 

Share this post


Link to post
Share on other sites

@MvGulik: sorry for misunderstanding (my fault) but with ...fails which I cannot understand. I mean why the recursion limit is choosen so low but trancexx has already answered it.

Maybe I will update the code to show in realtime how the alg. works.

Br,

UEZ


Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0

  • Similar Content

    • gononono64
      By gononono64
      Hey there,
      I'm having some issues quick-sorting my 2d array imported from a database. Im trying to sort the array based on the name that would be returned in $array[$n][2]. The code i posted works for smaller arrays but for some reason when i try to sort my imported array (around 9000 indexes), I get "Recursion level has been exceeded". I understand that this is maybe due to lack of returns but i couldn't find an ideal spot to stick em and again it seems to work with smaller bits of code. Could it be that 9000 is too much?
      I would normally just trial and error it until i figured it out but due to the length of time to load and buffer my array it's become too time consuming. Really I'm just hoping there is a quick fix that someone with more experience happens to know.
      Thank you
       
      ;;---------------------------------------------This Works---------------------------------------------------- Local $a[7][2] = [ _ ["1", "asdfashks"], _ ["2", "SubStrlkghjing1"], _ ["3", "jdfghjsergh"], _ ["4", "nertynert"], _ ["5", "cvbncvjkrt"], _ ["6", "avbncvjkrt"], _ ["7", "oytuoyuop"]] Quicksort($a,1,0,6) _ArrayDisplay($a) ;;------------------------------------------This Does Not--------------------------------------------------------- Quicksort($aLargeData, 1, 0, Ubound($aLargeData) - 1) _ArrayDisplay($aLargeData) ;;----------------------------------------Quicksort Function------------------------------------------------------ Func Quicksort(ByRef $Array, $secondIndex, $First, $Last) Local $pivot, $i, $j, $temp If $First < $Last Then $pivot = $First $i = $First $j = $Last While ($i < $j) While (StringCompare($Array[$i][$secondIndex], $Array[$pivot][$secondIndex]) <= 0) And ($i < $Last) $i += 1 WEnd While (StringCompare($Array[$j][$secondIndex], $Array[$pivot][$secondIndex]) > 0) $j -= 1 WEnd If ($i < $j) Then _ArraySwap($Array, $i, $j) _ArraySwap($Array,$pivot,$j) Quicksort($Array, $secondIndex, $First,$j-1) Quicksort($Array, $secondIndex, $j+1,$Last) WEnd EndIf EndFunc  
    • rm4453
      By rm4453
      How would I get this code to work? If not possible/If there is a better way... How would I do it? I can't seem to get it to work properly...
       
      Func Go() ;Do stuff Re-Go() EndFunc Func Re-Go() Go() EndFunc  
    • TheAutomator
      By TheAutomator
      Hi, simple question actually:
      How to disable the character limit for an edit control?
      Want unlimited-length (or as much as possible)
      I know the GUICtrlSetLimit() function but i want to disable the limit, not set one...
      Any ideas?
      I thought there was some sort of autoit constant for this or something but cant find what i'm looking for.
    • Andreik
      By Andreik
      I use a DateTimePicker control and now I saw the minimum value for the year it's 1601. Know anyone how can be changed this limit?
    • Anne
      By Anne
      Hi everyone.
      I have a question and wasn't able to find any answer for this.
      What is the maximum value/limit for TimerInit & TimerDiff.
      I mean, If I use TimerInit() in my script, how long can it 'last'? How long will I be able to read it with TimerDiff()?
      I realize that the result of TimerDiff isn't an Integer. It's a floating number and I am not sure what the maximum value is.
      I would like my program to use $Time = TimerInit() today, and then I'll be able to use TimerDiff($Time) tomorrow or even the day after. Is this possible? and what happens if TimerDiff exceeds the maximum value (if there is any)?