Advertisement
UEZ

GDI+ Flood Fill

UEZ
Jul 15th, 2014
405
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
AutoIt 6.71 KB | None | 0 0
  1. #include-once
  2. #include <GDIPlus.au3>
  3.  
  4. Func _GDIPlus_FloodFillIter(ByRef $hBitmap, $iX, $iY, $iColorOld, $iColorNew) ;coded by UEZ 2013-01-12
  5.     Local $aResult = DllCall($__g_hGDIPDll, "uint", "GdipGetImageDimension", "handle", $hBitmap, "float*", 0, "float*", 0)
  6.     Local $iW = $aResult[2], $iH = $aResult[3]
  7.     If BitOR($iX < 0, $iY < 0, $iX > $iW - 1, $iY > $iH - 1) Then Return SetError(1, 0, 0)
  8.     Local $x, $y, $aPos, $sPoint, $c = 0
  9.     Local $aStack[16384] ;init stack
  10.     Local $iStack = 1
  11.     $iColorOld = "0x" & Hex($iColorOld, 8)
  12.     Push($aStack, $iX & ";" & $iY, $iStack)
  13.     While $iStack > 1
  14.         $sPoint = $aStack[$iStack - 1]
  15.         Pop($iStack) ;pop
  16.         $aPos = StringRegExp($sPoint, "(\d+);(\d+)", 3)
  17.         $x = $aPos[0] ;StringRegExpReplace($sPoint, "(\d+);\d+", "$1")
  18.         $y = $aPos[1] ;StringRegExpReplace($sPoint, "\d+;(\d+)", "$1")
  19.         If BitOR($x < 0, $y < 0, $x > $iW - 1, $y > $iH - 1) Then ContinueLoop
  20.         $aResult = DllCall($__g_hGDIPDll, "uint", "GdipBitmapGetPixel", "handle", $hBitmap, "int", $x, "int", $y, "uint*", 0)
  21.         If $aResult[4] = $iColorOld Then
  22.             DllCall($__g_hGDIPDll, "uint", "GdipBitmapSetPixel", "handle", $hBitmap, "int", $x, "int", $y, "uint", $iColorNew)
  23.             Push($aStack, $x + 1 & ";" & $y, $iStack)
  24.             Push($aStack, $x & ";" & $y + 1, $iStack)
  25.             Push($aStack, $x - 1 & ";" & $y, $iStack)
  26.             Push($aStack, $x & ";" & $y - 1, $iStack)
  27.             $c += 1
  28.         EndIf
  29.     WEnd
  30.     $aStack = 0
  31.     If Not $c Then Return SetError(2, 0, 0)
  32.     Return 1
  33. EndFunc   ;==>_GDIPlus_FloodFillIter
  34.  
  35. Func _GDIPlus_FloodFillIter2(ByRef $hBitmap, $iX, $iY, $iColorOld, $iColorNew) ;coded by UEZ 2013-01-12
  36.     Local $aResult = DllCall($__g_hGDIPDll, "uint", "GdipGetImageDimension", "handle", $hBitmap, "float*", 0, "float*", 0)
  37.     Local $iW = $aResult[2], $iH = $aResult[3]
  38.     If BitOR($iX < 0, $iY < 0, $iX > $iW - 1, $iY > $iH - 1) Then Return SetError(1, 0, 0)
  39.     Local $x, $y, $i = 1
  40.     Local $oD = ObjCreate('Scripting.Dictionary')
  41.     $oD.Add($i, $iX & ";" & $iY) ;push
  42.     $i += 1
  43.     While $oD.Count > 0
  44.         $sPoint = $oD.Item($i - 1)
  45.         $oD.Remove($i - 1) ;pop
  46.         $i -= 1
  47.         $x = Int(StringRegExpReplace($sPoint, "(\d+);\d+", "$1"))
  48.         $y = Int(StringRegExpReplace($sPoint, "\d+;(\d+)", "$1"))
  49.         If BitOR($x < 0, $y < 0, $x > $iW - 1, $y > $iH - 1) Then ContinueLoop
  50.         $aResult = DllCall($__g_hGDIPDll, "uint", "GdipBitmapGetPixel", "handle", $hBitmap, "int", $x, "int", $y, "uint*", 0)
  51.         If $aResult[4] = "0x" & Hex($iColorOld, 8) Then
  52.             DllCall($__g_hGDIPDll, "uint", "GdipBitmapSetPixel", "handle", $hBitmap, "int", $x, "int", $y, "uint", $iColorNew)
  53.             $oD.Add($i, $x + 1 & ";" & $y) ;push
  54.             $i += 1
  55.             $oD.Add($i, $x & ";" & $y + 1) ;push
  56.             $i += 1
  57.             $oD.Add($i, $x - 1 & ";" & $y) ;push
  58.             $i += 1
  59.             $oD.Add($i, $x & ";" & $y - 1) ;push
  60.             $i += 1
  61.         EndIf
  62.     WEnd
  63.     $oD = 0
  64.     Return 1
  65. EndFunc   ;==>_GDIPlus_FloodFillIter2
  66.  
  67. Func _GDIPlus_FloodFillIter3(ByRef $hBitmap, $iX, $iY, $iColorOld, $iColorNew, $iTolerance = 0) ;coded by UEZ 2014-07-20
  68.     Local $aResult = DllCall($__g_hGDIPDll, "uint", "GdipGetImageDimension", "handle", $hBitmap, "float*", 0, "float*", 0)
  69.     Local $iW = $aResult[2], $iH = $aResult[3]
  70.     If BitOR($iX < 0, $iY < 0, $iX > $iW - 1, $iY > $iH - 1) Then Return SetError(1, 0, 0)
  71.     $iTolerance = ($iTolerance < 0) ? 0 : $iTolerance > 255 ? 255: $iTolerance
  72.     Local $x, $y, $aPos, $sPoint, $c = 0
  73.     Local $aStack[16384] ;init stack
  74.     Local $iStack = 1
  75.     Push($aStack, $iX & ";" & $iY, $iStack)
  76.  
  77.     Local $tBitmapData = _GDIPlus_BitmapLockBits($hBitmap, 0, 0, $iW, $iH, BitOR($GDIP_ILMWRITE, $GDIP_ILMREAD), $GDIP_PXF32ARGB)
  78.  
  79.     Local $iScan0 = DllStructGetData($tBitmapData, "Scan0")
  80.     Local $tPixel = DllStructCreate("int[" & $iW * $iH & "];", $iScan0)
  81.     Local $aPixel, $iRowOffset
  82.  
  83.     While $iStack > 1
  84.         $sPoint = $aStack[$iStack - 1]
  85.         Pop($iStack) ;pop
  86.         $aPos = StringRegExp($sPoint, "(\d+|-\d+);(\d+|-\d+)", 3)
  87.         $x = $aPos[0] ;StringRegExpReplace($sPoint, "(\d+);\d+", "$1")
  88.         $y = $aPos[1] ;StringRegExpReplace($sPoint, "\d+;(\d+)", "$1")
  89.  
  90.         If BitOR($x < 0, $y < 0, $x > $iW - 1, $y > $iH - 1) Then ContinueLoop
  91.         $iRowOffset = $y * $iW + 1
  92.  
  93.         If GetColorTolerance($iColorOld, DllStructGetData($tPixel, 1, $iRowOffset + $x)) <= $iTolerance Then
  94.             DllStructSetData($tPixel, 1, $iColorNew, $iRowOffset + $x)
  95.             Push($aStack, $x + 1 & ";" & $y, $iStack)
  96.             Push($aStack, $x & ";" & $y + 1, $iStack)
  97.             Push($aStack, $x - 1 & ";" & $y, $iStack)
  98.             Push($aStack, $x & ";" & $y - 1, $iStack)
  99.             $c += 1
  100.         EndIf
  101.     WEnd
  102.  
  103.     _GDIPlus_BitmapUnlockBits($hBitmap, $tBitmapData)
  104.     $aStack = 0
  105.     If Not $c Then Return SetError(2, 0, 0)
  106.     Return 1
  107. EndFunc   ;==>_GDIPlus_FloodFillIter
  108.  
  109. Func GetColorTolerance($c1, $c2)
  110.     Local Const $a = (BitShift(BitAND($c1, 0xFF000000), 24) - BitShift(BitAND($c2, 0xFF000000), 24))^2
  111.     Local Const $r = (BitShift(BitAND($c1, 0x00FF0000), 16) - BitShift(BitAND($c2, 0x00FF0000), 16))^2
  112.     Local Const $g = (BitShift(BitAND($c1, 0x0000FF00), 8) - BitShift(BitAND($c2, 0x0000FF00), 8))^2
  113.     Local Const $b = (BitAND($c1, 0x000000FF) - BitAND($c2, 0x000000FF))^2
  114.     Return Floor(Sqrt($a + $r + $g + $b))
  115. EndFunc
  116.  
  117. Func _GDIPlus_FloodFillIter4(ByRef $hBitmap, $iX, $iY, $iColorNew) ;no alpha channel support but fast
  118.     Local $aResult = DllCall($__g_hGDIPDll, "uint", "GdipGetImageDimension", "handle", $hBitmap, "float*", 0, "float*", 0)
  119.     Local $iW = $aResult[2], $iH = $aResult[3]
  120.     If BitOR($iX < 0, $iY < 0, $iX > $iW - 1, $iY > $iH - 1) Then Return SetError(1, 0, 0)
  121.     Local $nCN = Hex($iColorNew, 8)
  122.     If StringLeft($nCN, 2) = "FF" Then
  123.         $nCN = StringTrimLeft($nCN, 2)
  124.         Local Const $hHBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBitmap)
  125.         Local Const $hDC = _WinAPI_GetDC(0)
  126.         Local Const $hBitmapDC = _WinAPI_CreateCompatibleDC($hDC)
  127.         Local Const $hObjOld = _WinAPI_SelectObject($hBitmapDC, $hHBitmap)
  128.         Local Const $hBrush = _WinAPI_CreateBrushIndirect($BS_SOLID, "0x" & $nCN)
  129.         Local Const $hObjOld2 = _WinAPI_SelectObject($hBitmapDC, $hBrush)
  130. ;~      _WinAPI_ExtFloodFill($hBitmapDC, $iX, $iY, "0x" & $nCN)
  131.         DllCall("gdi32.dll", "int", "FloodFill", "int", $hBitmapDC, "int", $iX,"int", $iY, "int", 0)
  132.         _WinAPI_SelectObject($hBitmapDC, $hObjOld2)
  133.         _WinAPI_DeleteObject($hBrush)
  134.         Local Const $hCtxt = _GDIPlus_ImageGetGraphicsContext($hBitmap)
  135.         Local Const $hBmp = _GDIPlus_BitmapCreateFromHBITMAP($hHBitmap)
  136.         _GDIPlus_GraphicsDrawImageRect($hCtxt, $hBmp, 0, 0, $iW, $iH)
  137.         _GDIPlus_GraphicsDispose($hCtxt)
  138.         _GDIPlus_BitmapDispose($hBmp)
  139.         _WinAPI_DeleteObject($hHBitmap)
  140.         _WinAPI_SelectObject($hBitmapDC, $hObjOld)
  141.         _WinAPI_ReleaseDC(0, $hDC)
  142.         Return 1
  143.     EndIf
  144.     Return SetError(2, 0, 0)
  145. EndFunc
  146.  
  147. Func Push(ByRef $aStack, $sVal, ByRef $iStack)
  148.     If $iStack + 2 > UBound($aStack) Then ReDim $aStack[$iStack + 500]
  149.     $aStack[$iStack] = $sVal
  150.     $iStack += 1
  151. EndFunc   ;==>Push
  152. ;
  153. Func Pop(ByRef $iStack)
  154.     $iStack -= 1
  155. EndFunc   ;==>Pop
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement