Hi,
ich arbeite momentan an einem Skript, dass bestimmte Pixel ausliest und bei Bedarf färbt. Meine Funktion arbeitet mit einer While Schleife, weil meine vorherige Rekursive Funktion nicht funktioniert hat. Die Schleifen Funktion funktionert leider nur teilweise. Ich habe momentan 2 Probleme mit ihr:
-Der nicht eingefärbte Bereich ist danach komplett schwarz, obwohl vorher ein Bild darauf geladen war und diese Pixel garnicht verändert wurden
-An einer Stelle vom gefärbten Bereich "reißt" er einfach ab => Schnitt obwohl die Funktion dort weiter Färben sollte
Die problematische Funktion ist _PaintRecursiv()
Spoiler anzeigen
#include <GUIConstants.au3>
#Include <GDIPlus.au3>
#include <Color.au3>
#include <Misc.au3>
_GDIPlus_Startup()
[/autoit] [autoit][/autoit] [autoit]Dim $hBitmap[4]
Global $BrushSize = 10
Global $Tolerance = 10
$PrimaryDown = False
$SecondaryDown = False
$PlusDown = False
$MinusDown = False
$UpArrowDown = False
$DownArrowDown = False
$sFile = FileOpenDialog("Bild öffnen", @DesktopDir, "Bilder (*.jpg;*.bmp;*.png)")
;~ $sFile = @DesktopDir &"\Foto.jpg"
AutoItSetOption("MouseCoordMode", 2)
If $sFile <> "" Then
$MiscDLL = DllOpen("user32.dll")
ConsoleWrite("->Lädt Bild..." &@CRLF)
$hBitmap[1] = _GDIPlus_ImageLoadFromFile($sFile)
$hBitmap[2] = _GDIPlus_ImageLoadFromFile($sFile)
$hBitmap[3] = _GDIPlus_ImageLoadFromFile($sFile)
$hBuffer3 = _GDIPlus_ImageGetGraphicsContext($hBitmap[3])
ConsoleWrite("+>Geladen..." &@CRLF)
$iWidth = _GDIPlus_ImageGetWidth($hBitmap[1])
$iHeight = _GDIPlus_ImageGetHeight($hBitmap[1])
_GreyScale($hBitmap[1], 0, 0, $iWidth, $iHeight) ; Bereich wird in Graustufen umberechnet
_GDIPlus_GraphicsDrawImageRect($hBuffer3, $hBitmap[1], 0, 0, $iWidth, $iHeight)
$hGui = GUICreate("", $iWidth, $iHeight)
$hGraphics = _GDIPlus_GraphicsCreateFromHWND($hGui)
$hBitmap[0] = _GDIPlus_BitmapCreateFromGraphics($iWidth, $iHeight, $hGraphics)
$hBuffer = _GDIPlus_ImageGetGraphicsContext($hBitmap[0])
GUISetState()
While 1
$FPSTimer = TimerInit()
$GUIMsg = GUIGetMsg()
$MouseX = MouseGetPos(0)
$MouseY = MouseGetPos(1)
Switch $GUIMsg
Case $GUI_EVENT_CLOSE
ExitLoop
Case $GUI_EVENT_PRIMARYDOWN
$PrimaryDown = True
Case $GUI_EVENT_PRIMARYUP
$PrimaryDown = False
Case $GUI_EVENT_SECONDARYDOWN
$SecondaryDown = True
Case $GUI_EVENT_SECONDARYUP
$SecondaryDown = False
EndSwitch
If _IsPressed("6B", $MiscDLL) Then
If Not $PlusDown Then $BrushSize += 5
$PlusDown = True
Else
$PlusDown = False
EndIf
If _IsPressed("6D", $MiscDLL) Then
If Not $MinusDown And $BrushSize >= 5 Then $BrushSize -= 5
$MinusDown = True
Else
$MinusDown = False
EndIf
If _IsPressed("26", $MiscDLL) Then
If Not $UpArrowDown And $Tolerance <= 95 Then $Tolerance += 5
$UpArrowDown = True
Else
$UpArrowDown = False
EndIf
If _IsPressed("28", $MiscDLL) Then
If Not $DownArrowDown And $Tolerance >= 5 Then $Tolerance -= 5
$DownArrowDown = True
Else
$DownArrowDown = False
EndIf
If _IsPressed("53", $MiscDLL) Then
_PaintRecursiv($hBitmap[2], $hBitmap[3], $MouseX, $MouseY, $iWidth, $iHeight)
_GDIPlus_GraphicsDrawImageRect($hBuffer, $hBitmap[3], 0, 0, $iWidth, $iHeight)
EndIf
If $PrimaryDown Then
_GDIPlus_GraphicsDrawImageRectRect($hBuffer, $hBitmap[2], $MouseX, $MouseY, $BrushSize, $BrushSize, $MouseX, $MouseY, $BrushSize, $BrushSize)
ElseIf $SecondaryDown Then
_GDIPlus_GraphicsDrawImageRectRect($hBuffer, $hBitmap[1], $MouseX, $MouseY, $BrushSize, $BrushSize, $MouseX, $MouseY, $BrushSize, $BrushSize)
EndIf
_GDIPlus_GraphicsDrawImageRect($hBuffer, $hBitmap[3], 0, 0, $iWidth, $iHeight)
_GDIPlus_GraphicsDrawString($hBuffer, "FPS: " &Round(1000 / TimerDiff($FPSTimer)) &" Pinselgröße: " &$BrushSize &" Toleranz: " &$Tolerance &"%", 10, 10, "Arial", 12)
_GDIPlus_GraphicsDrawImageRect($hGraphics, $hBitmap[0], 0, 0, $iWidth, $iHeight) ;zeichne auf die GUI
WEnd
_GDIPlus_GraphicsDispose($hGraphics) ; gibt Grafikhandle wieder frei
_GDIPlus_ImageSaveToFile($hBitmap[0], @DesktopDir &"\Test.jpg") ; speichere fertiges Bild
For $i = 0 To UBound($hBitmap) - 1
_GDIPlus_BitmapDispose($hBitmap[$i])
Next
_GDIPlus_GraphicsDispose($hBuffer)
_GDIPlus_GraphicsDispose($hBuffer3)
_GDIPlus_Shutdown()
DllClose($MiscDLL)
EndIf
Func _PaintRecursiv($hGetterBitmap, $hSetterBitmap, $iX, $iY, $iW, $iH)
Local $KonvertingTimer = TimerInit()
Local $OneSecondTimer = $KonvertingTimer
Local $ColorTolerance = Round(($Tolerance / 100) * 255)
Local $SetterBitmapData = _GDIPlus_BitmapLockBits($hSetterBitmap, 0, 0, $iW, $iH, $GDIP_ILMWRITE, $GDIP_PXF32RGB)
Local $GetterBitmapData = _GDIPlus_BitmapLockBits($hGetterBitmap, 0, 0, $iW, $iH, $GDIP_ILMREAD, $GDIP_PXF32RGB)
Local $SetterScan0 = DllStructGetData($SetterBitmapData, "Scan0")
Local $GetterScan0 = DllStructGetData($GetterBitmapData, "Scan0")
Local $Stride = DllStructGetData($SetterBitmapData, "Stride") ; Anzahl der Pixel in einer Reihe
Local $Color, $Red, $Green, $Blue, $RedDiff, $GreenDiff, $BlueDiff, $GetterPixelData, $PixelChecked[$iW * $iH], $PixelToCheck[2][2] = [[1, ''], [$iX, $iY]], $Zaehler = 0
$GetterPixelData = DllStructCreate("dword", $GetterScan0 + ($iY * $Stride) + ($iX * 4))
$SetterPixelData = DllStructCreate("dword", $SetterScan0 + ($iY * $Stride) + ($iX * 4))
$Color = DllStructGetData($GetterPixelData, 1)
$Red = _ColorGetRed($Color)
$Green = _ColorGetGreen($Color)
$Blue = _ColorGetBlue($Color)
Local $TargetColor[3] = [$Red, $Green, $Blue]
ConsoleWrite("->Sucht rekursiv nach Pixeln... " &@CRLF &">Zielfarbe: " &$TargetColor[0] &" " &$TargetColor[1] &" " &$TargetColor[2] &" von " &$iX &"|" &$iY &", die Zielfarbe darf um " &$ColorTolerance &" abweichen." &@CRLF)
DllStructSetData($SetterPixelData, 1, BitOR($Blue, BitShift($Green, -8), BitShift($Red, -16)))
$Zaehler += 1
While $PixelToCheck[0][0] > 0
$iX = $PixelToCheck[$PixelToCheck[0][0]][0]
$iY = $PixelToCheck[$PixelToCheck[0][0]][1]
If $iX >= 0 And $iX < $iW And $iY >= 0 And $iY < $iH And $PixelChecked[($iY * $iW) + $iX] = '' Then
$SetterPixelData = DllStructCreate("dword", $SetterScan0 + ($iY * $Stride) + ($iX * 4))
$GetterPixelData = DllStructCreate("dword", $GetterScan0 + ($iY * $Stride) + ($iX * 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)))
$PixelToCheck[0][0] += 7
ReDim $PixelToCheck[$PixelToCheck[0][0] + 1][2]
$i = -7
For $x = $iX To $iX + 1
For $y = $iY - 1 To $iY + 1
If $y <> $iY Or $x <> $iX Then
If $PixelChecked[($y * $iW) + $x] = '' Then
$PixelToCheck[$PixelToCheck[0][0] + $i][0] = $x
$PixelToCheck[$PixelToCheck[0][0] + $i][1] = $y
Else
ReDim $PixelToCheck[$PixelToCheck[0][0]][2]
$PixelToCheck[0][0] -= 1
EndIf
$i += 1
EndIf
Next
Next
$Zaehler += 1
Else
ReDim $PixelToCheck[$PixelToCheck[0][0]][2]
$PixelToCheck[0][0] -= 1
EndIf
$PixelChecked[($iY * $iW) + $iX] = True
Else
ReDim $PixelToCheck[$PixelToCheck[0][0]][2]
$PixelToCheck[0][0] -= 1
EndIf
If TimerDiff($OneSecondTimer) >= 1000 Then
ConsoleWrite(">" &$Zaehler &" gefärbte Pixel. Letzte Differenzen: " &$RedDiff &" " &$GreenDiff &" " &$BlueDiff &", zu prüfende Pixel: " &$PixelToCheck[0][0] &@CRLF)
$OneSecondTimer = TimerInit()
EndIf
WEnd
_GDIPlus_BitmapUnlockBits($hSetterBitmap, $SetterBitmapData)
_GDIPlus_BitmapUnlockBits($hGetterBitmap, $GetterBitmapData)
ConsoleWrite("+>Fertig... Verstrichene Zeit: " &Round(TimerDiff($KonvertingTimer) / 1000, 2) &"s, gefärbte Pixel: " &$Zaehler &@CRLF)
EndFunc
Func _GreyScale($hBitmap, $iX, $iY, $iW, $iH)
ConsoleWrite("->Konvertiert in Grautöne..." &@CRLF)
Local $KonvertingTimer = TimerInit()
Local $OneSecondTimer = $KonvertingTimer
Local $BitmapData = _GDIPlus_BitmapLockBits($hBitmap, $iX, $iY, $iW, $iH, BitOR($GDIP_ILMREAD, $GDIP_ILMWRITE), $GDIP_PXF32RGB)
Local $Stride = DllStructGetData($BitmapData, "Stride") ; Stride ist der Offset von einer Reihe zur nächsten
Local $Width = DllStructGetData($BitmapData, "Width") ; Anzahl der Spalten
Local $Height = DllStructGetData($BitmapData, "Height") ; Anzahl der Reihen
Local $Scan0 = DllStructGetData($BitmapData, "Scan0") ; Die Bilddaten im Speicher
Local $PixelData, $Color, $Luma
For $row = 0 To $Height - 1 ; Reihe für Reihe
For $col = 0 To $Width - 1 ; Spalte für Spalte
; lese Farbinformation des aktuellen Pixels(Spalte,Reihe) aus
$PixelData = DllStructCreate("dword", $Scan0 + ($row * $Stride) + ($col * 4))
$Color = DllStructGetData($PixelData, 1)
; berechne Grauwert
$Luma = _ColorGetRed($Color) * 0.3 + _ColorGetGreen($Color) * 0.59 + _ColorGetBlue($Color) * 0.11
; Rot Grün und Blau wert werden jeweils auf den berechneten Grauwert gesetzt
DllStructSetData($PixelData, 1, BitOR($Luma, BitShift($Luma, -8), BitShift($Luma, -16)))
Next
If TimerDiff($OneSecondTimer) >= 1000 Then
ConsoleWrite(">" &Round(($row + 1) / ($Height / 100)) &"%" &@CRLF)
$OneSecondTimer = TimerInit()
EndIf
Next
_GDIPlus_BitmapUnlockBits($hBitmap, $BitmapData)
ConsoleWrite("+>Fertig... Verstrichene Zeit: " &Round(TimerDiff($KonvertingTimer) / 1000, 2) &"s" &@CRLF)
EndFunc ;==>_GreyScale