Alternative zu rekursiver Funktion

  • Hi,
    ich arbeite gerade an einem Programm, dass von einem bestimmten Pixel aus in einem Bild nach außen hin scannt (wie die Zauberstab Funktion in Paint.NET). Allerdings fällt mir keine Alternative zu meiner jetzigen Funktion ein:

    [autoit]

    Func _ScanColor($iX, $iY, $iW, $iH)
    Local $SetterPixelData, $GetterPixelData, $Color, $Red, $Green, $Blue, $RedDiff, $GreenDiff, $BlueDiff
    For $row = $iY - 1 To $iY + 1 ; Reihe für Reihe
    For $col = $iX - 1 To $iX + 1 ; Spalte für Spalte
    If $PixelChecked[($row * $iW) + $col] = '' Then
    $SetterPixelData = DllStructCreate("dword", $SetterScan0 + ($row * $Stride) + ($col * 4))
    $GetterPixelData = DllStructCreate("dword", $GetterScan0 + ($row * $Stride) + ($col * 4))
    $Color = DllStructGetData($GetterPixelData, 1)
    $Red = _ColorGetRed($Color)
    $Green = _ColorGetGreen($Color)
    $Blue = _ColorGetBlue($Color)
    $RedDiff = Abs($TargetColor[0] - $Red)
    $GreenDiff = Abs($TargetColor[1] - $Green)
    $BlueDiff = Abs($TargetColor[2] - $Blue)
    If $RedDiff <= $ColorTolerance And $GreenDiff <= $ColorTolerance And $BlueDiff <= $ColorTolerance Then
    DllStructSetData($SetterPixelData, 1, BitOR($Blue, BitShift($Green, -8), BitShift($Red, -16)))
    $Zaehler += 1
    $PixelChecked[($row * $iW) + $col] = True
    _ScanColor($col, $row, $iW, $iH)
    Else
    $PixelChecked[($row * $iW) + $col] = True
    EndIf
    EndIf
    Next
    Next
    If TimerDiff($OneSecondTimer) >= 1000 Then
    ConsoleWrite($Zaehler &" gefärbte Pixel. Letzte Differenzen: " &$RedDiff &" " &$GreenDiff &" " &$BlueDiff &@CRLF)
    $OneSecondTimer = TimerInit()
    EndIf
    EndFunc

    [/autoit]
  • Bei mir hängt der jezz leider in einer Endlosschleife, hab das Skript mal ein paar minuten laufen lassen:

    Spoiler anzeigen
    [autoit]

    Func _GDIPlus_FloodFillIter2(ByRef $hGetterBitmap, ByRef $hSetterBitmap, $iX, $iY) ;coded by UEZ 2013-01-13
    ConsoleWrite("Färbe mit Toleranz " &$Tolerance &"%..." &@CRLF)
    Local $KonvertingTimer = TimerInit()
    Local $OneSecondTimer = $KonvertingTimer
    Local $ColorTolerance = Round(($Tolerance / 100) * 255)
    Local $aResult = DllCall($ghGDIPDll, "uint", "GdipGetImageDimension", "handle", $hGetterBitmap, "float*", 0, "float*", 0)
    Local $iW = $aResult[2], $iH = $aResult[3]
    If BitOR($iX < 0, $iY < 0, $iX > $iW - 1, $iY > $iH - 1) Then Return SetError(1, 0, 0)
    Local $x, $y, $RedDiff, $GreenDiff, $BlueDiff,$i = 1, $Zaehler = 0
    Local $oD = ObjCreate('Scripting.Dictionary')
    $oD.Add($i, $iX & ";" & $iY) ;push
    $i += 1

    [/autoit] [autoit][/autoit] [autoit]

    $aResult = DllCall($ghGDIPDll, "uint", "GdipBitmapGetPixel", "handle", $hGetterBitmap, "int", $iX, "int", $iY, "uint*", 0)
    Local $Color = $aResult[4]
    Local $Red = _ColorGetRed($Color)
    Local $Green = _ColorGetGreen($Color)
    Local $Blue = _ColorGetBlue($Color)
    Local $TargetColor[3] = [$Red, $Green, $Blue]

    [/autoit] [autoit][/autoit] [autoit]

    While $oD.Count > 0
    $sPoint = $oD.Item($i - 1)
    $oD.Remove($i - 1) ;pop
    $i -= 1
    $x = Int(StringRegExpReplace($sPoint, "(\d+);\d+", "$1"))
    $y = Int(StringRegExpReplace($sPoint, "\d+;(\d+)", "$1"))
    If BitOR($x < 0, $y < 0, $x > $iW - 1, $y > $iH - 1) Then ContinueLoop
    $aResult = DllCall($ghGDIPDll, "uint", "GdipBitmapGetPixel", "handle", $hGetterBitmap, "int", $x, "int", $y, "uint*", 0)
    $Color = $aResult[4]
    $Red = _ColorGetRed($Color)
    $Green = _ColorGetGreen($Color)
    $Blue = _ColorGetBlue($Color)
    $RedDiff = Abs($TargetColor[0] - $Red)
    $GreenDiff = Abs($TargetColor[1] - $Green)
    $BlueDiff = Abs($TargetColor[2] - $Blue)
    If $RedDiff <= $ColorTolerance And $GreenDiff <= $ColorTolerance And $BlueDiff <= $ColorTolerance Then
    DllCall($ghGDIPDll, "uint", "GdipBitmapSetPixel", "handle", $hSetterBitmap, "int", $x, "int", $y, "uint", $Color)
    $oD.Add($i, $x + 1 & ";" & $y) ;push
    $i += 1
    $oD.Add($i, $x & ";" & $y + 1) ;push
    $i += 1
    $oD.Add($i, $x - 1 & ";" & $y) ;push
    $i += 1
    $oD.Add($i, $x & ";" & $y - 1) ;push
    $i += 1
    $Zaehler += 1
    EndIf
    If TimerDiff($OneSecondTimer) >= 1000 Then
    ConsoleWrite($Zaehler &" gefärbte Pixel. Letzte Differenzen: " &$RedDiff &" " &$GreenDiff &" " &$BlueDiff &@CRLF)
    $OneSecondTimer = TimerInit()
    EndIf
    WEnd
    ConsoleWrite("Fertig... Verstrichene Zeit: " &Round(TimerDiff($KonvertingTimer) / 1000, 2) &"s, gefärbte Pixel: " &$Zaehler &@CRLF)
    $oD = 0
    Return 1
    EndFunc ;==>_GDIPlus_FloodFillIter2

    [/autoit]