Hallöchen,
Habe hier dieses Skript gebastelt, welches ein jpg zu einem Monochrom (Schwarz/Weiß)-Bild "umwandelt". Funktioniert auch super! Nur Frage ich mich, ob es nicht einen Weg gibt, die Geschwindigkeit des ganzen zu optimieren?
Ich erinnere mich, dass Andy mal vor einigen Tagen erwähnte, er habe für das englische Forum eine PixelGetColor / PixelSearch Funktion geschrieben die sehr viel schneller arbeitet (Kann mich aber auch irren !)
Auf das PixelGetColor kann ich leider nicht verzichten. Das Programm soll noch so erweitert werden, dass es das Bild zB. in Paint nachmalt (per Mousemove/Mouseclick). Deswegen brauche ich die einzelnen Pixelfarben in einem Array
Spoiler anzeigen
$FilePath = FileOpenDialog("", "", "JPG (*.jpg)")
If @error Then Exit
#include <GDIPlus.au3>
#include <Array.au3>
#include <Color.au3>
#include <File.au3>
_GDIPlus_Startup()
Global Const $AC_SRC_ALPHA = 1
[/autoit] [autoit][/autoit] [autoit]$img_hwnd = _GDIPlus_ImageLoadFromFile($FilePath)
$img_w = _GDIPlus_ImageGetWidth($img_hwnd)
$img_h = _GDIPlus_ImageGetHeight($img_hwnd)
_GDIPlus_ImageDispose($img_hwnd)
$guiMain = GUICreate("", $img_w, $img_h + 50, -1, -1)
$ctrl_Einlesen = GUICtrlCreateButton("Einlesen", 0, $img_h, $img_w, 25)
$ctrl_Progress = GUICtrlCreateProgress(0, $img_h + 25, $img_w, 25)
$guiChild = GUICreate("", $img_w, $img_h, 0, 0, 0x40000000, Default, $guiMain)
GUICtrlCreatePic($FilePath, 0, 0, 0, 0)
$guiChild2 = GUICreate("", $img_w, $img_h, 0, 0, 0x40000000, Default, $guiMain)
GUISetState(@SW_SHOW, $guiMain)
GUISetState(@SW_SHOW, $guiChild)
;~ _ColorGetBlue()
While 1
$nMsg = GUIGetMsg()
Switch $nMsg
Case $ctrl_Einlesen
_ImageDrawBlackAndWhite($guiChild, 115)
Case -3
Exit
EndSwitch
WEnd
Func _ImageDrawBlackAndWhite($hWnd, $iTol=115, $iArray=0)
Local $xPos = 0, $yPos = 0, $aRet[$img_h*$img_w+1]
$opt_Mode = Opt("PixelCoordMode", 2)
ConsoleWrite("+> " & $img_h * $img_w & @CR & @CR)
$hGraphic = _GDIPlus_GraphicsCreateFromHWND($hWnd)
$hPenBlack = _GDIPlus_PenCreate(0xFF000000)
$hPenWhite = _GDIPlus_PenCreate(0xFFFFFFFF)
For $i = 1 To ($img_h * $img_w)
$iTmp = _ColorToBrightness(PixelGetColor($xPos, $yPos), 1, $iTol)
If $iTmp = 0xFFFFFF Then _GDIPlus_GraphicsDrawLine ($hGraphic, $xPos, $yPos, $xPos-1, $yPos, $hPenWhite)
If $iTmp = 0x000000 Then _GDIPlus_GraphicsDrawLine ($hGraphic, $xPos, $yPos, $xPos-1, $yPos, $hPenBlack)
If $iArray = 1 Then $aRet[$i] = $iTmp
$xPos += 1
If $xPos = $img_w Then
GUICtrlSetData($ctrl_Progress, $i / ($img_h * $img_w) * 100)
ConsoleWrite("+> " & $i & " / " & $img_h * $img_w & " ("&Round($i / ($img_h * $img_w) * 100,1)&" %) "&@CR & @CR)
$xPos = 0
$yPos += 1
EndIf
Next
GUICtrlSetData($ctrl_Progress, 0)
If $iArray=1 Then Return $aRet
EndFunc ;==>_ImageDrawBlackAndWhite
[/autoit] [autoit][/autoit] [autoit]Func _ColorToBrightness($iColor, $iBlackAndWhite = 1, $iTol = 115)
Local $aRet, $aTemp[3] = [_ColorGetRed($iColor), _ColorGetGreen($iColor), _ColorGetBlue($iColor)]
$aRet = _ColorConvertRGBtoHSL($aTemp)
If $iBlackAndWhite = 1 Then
If $aRet[2] < $iTol Then
Return 0x000000
Else
Return 0xFFFFFF
EndIf
EndIf
Return $aRet[2]
EndFunc ;==>_ColorToBrightness
EDIT: hab mal ein Bild in den Anhang geladen, um zu zeigen was dabei rauskommt
EDIT2: Habe grade das hier gefunden:
Spoiler anzeigen
#include <GUIConstants.au3>
#include <EditConstants.au3>
#include <WindowsConstants.au3>
#include <Color.au3>
#include <WinAPI.au3>
Global $threshold
Global $image
Global $width
Global $height
Global $pixels
Global $pathString = "12345678"
Global $scramble = False
Global $rotate = 0
Global $speed
;; Check hotkeys ;;
If (Not HotKeySet ("{F9}", "Nothing")) Then
MsgBox (16, "Error", "Could not register the F9 hotkey.")
Exit
EndIf
If (Not HotKeySet ("{F10}", "Nothing")) Then
MsgBox (16, "Erro", "Could not register the F10 hotkey.")
Exit
EndIf
;; Image dialog ;;
$imageFile = FileOpenDialog ("Open image", "", "Images (*.jpg;*.jpeg;*.gif;*.png;*.bmp)", 1)
If (@error) Then Exit
;; Options dialog ;;
$optGUI = GUICreate ("Settings", 160, 270, -1, -1, $WS_CAPTION, BitOr ($WS_EX_APPWINDOW, $WS_EX_TOOLWINDOW))
GUICtrlCreateGroup ("Image processing", 5, 5, 150, 85)
GUICtrlCreateLabel ("Sensitivity (0~255):", 10, 28, 110, 15)
$thresholdInput = GUICtrlCreateInput ("100", 125, 25, 25, 20, $ES_NUMBER)
GUICtrlCreateLabel ("Width (px):", 10, 48, 110, 15)
$widthInput = GUICtrlCreateInput ("100", 125, 45, 25, 20, $ES_NUMBER)
GUICtrlCreateLabel ("Height (px):", 10, 68, 110, 15)
$heightInput = GUICtrlCreateInput ("100", 125, 65, 25, 20, $ES_NUMBER)
GUICtrlCreateGroup ("Drawing pattern", 5, 95, 150, 140)
$horizontalRadio = GUICtrlCreateRadio ("Horizontal", 10, 115, 110, 15)
$verticalRadio = GUICtrlCreateRadio ("Vertical", 10, 135, 110, 15)
$diagonalRadio = GUICtrlCreateRadio ("Diagonal", 10, 155, 110, 15)
$rotateRadio = GUICtrlCreateRadio ("Spiral", 10, 175, 110, 15)
$scrambleRadio = GUICtrlCreateRadio ("Random", 10, 195, 110, 15)
GUICtrlSetState ($diagonalRadio, $GUI_CHECKED)
GUICtrlCreateLabel ("Mouse speed (0~100):", 10, 213, 110, 15)
$speedInput = GUICtrlCreateInput ("0", 125, 210, 25, 20, $ES_NUMBER)
$okBtn = GUICtrlCreateButton ("Ok", 30, 245, 40, 20)
$cancelBtn = GUICtrlCreateButton ("Cancel", 80, 245, 50, 20)
GUISetState ()
While 1
Switch (GUIGetMsg ())
Case $GUI_EVENT_CLOSE
Exit
Case $cancelBtn
Exit
Case $okBtn
$threshold = GUICtrlRead ($thresholdInput)
$width = GUICtrlRead ($widthInput)
$height = GUICtrlRead ($heightInput)
$speed = GUICtrlRead ($speedInput)
If (GUICtrlRead ($horizontalRadio) == $GUI_CHECKED) Then
$pathString = "45273618"
ElseIf (GUICtrlRead ($verticalRadio) == $GUI_CHECKED) Then
$pathString = "27453618"
ElseIf (GUICtrlRead ($diagonalRadio) == $GUI_CHECKED) Then
$pathString = "36184527"
ElseIf (GUICtrlRead ($rotateRadio) == $GUI_CHECKED) Then
$pathString = "14678532"
$rotate = 1
ElseIf (GUICtrlRead ($scrambleRadio) == $GUI_CHECKED) Then
$scramble = True
EndIf
GUIDelete ($optGUI)
ExitLoop
EndSwitch
WEnd
;; Processing dialog ;;
$GUI = GUICreate ("Processing image...", $width, $height + 20, -1, -1, $WS_CAPTION, BitOr ($WS_EX_APPWINDOW, $WS_EX_TOOLWINDOW))
GUISetBkColor (0xffffff)
$imageBox = GUICtrlCreatePic ($imageFile, 0, 0, $width, $height)
$progress = GUICtrlCreateProgress (0, $height, $width, 20)
GUISetState ()
;; Get image pixels ;;
$dc = _WinAPI_GetDC ($GUI)
$memDc = _WinAPI_CreateCompatibleDC ($dc)
$bitmap = _WinAPI_CreateCompatibleBitmap ($dc, $width, $height)
_WinAPI_SelectObject ($memDc, $bitmap)
_WinAPI_BitBlt ($memDc, 0, 0, $width, $height, $dc, 0, 0, $SRCCOPY)
$bits = DllStructCreate ("dword[" & ($width * $height) & "]")
DllCall ("gdi32", "int", "GetBitmapBits", "ptr", $bitmap, "int", ($width * $height * 4), "ptr", DllStructGetPtr ($bits))
GUICtrlDelete ($imageBox)
;; Process the pixels ;;
Dim $pixels[$width][$height]
For $y = 0 To ($height - 1)
For $x = 0 To ($width - 1)
$index = ($y * $width) + $x
$color = DllStructGetData ($bits, 1, $index)
$red = _ColorGetBlue ($color)
$green = _ColorGetGreen ($color)
$blue = _ColorGetRed ($color)
$shade = ($red + $green + $blue) / 3
If ($shade > $threshold) Then
$color = 0xffffff
$pixels[$x][$y] = 0
Else
$color = 0
$pixels[$x][$y] = 1
EndIf
DllStructSetData ($bits, 1, $color, $index)
Next
DllCall ("gdi32", "int", "SetBitmapBits", "ptr", $bitmap, "int", ($width * $height * 4), "ptr", DllStructGetPtr ($bits))
_WinAPI_BitBlt ($dc, 0, 0, $width, $height, $memDc, 0, 0, $SRCCOPY)
GUICtrlSetData ($progress, ($y * 100) / $height)
Next
_WinAPI_ReleaseDC ($GUI, $dc)
GUIRegisterMsg ($WM_PAINT, "OnPaint")
;; Ready to draw ;;
TrayTip ("Pronto!", "Press F9 para draw. You can press F10 anytime to exit.", 10)
HotKeySet ("{F9}", "Draw")
HotKeySet ("{F10}", "Quit")
While 1
Sleep (60000)
WEnd
Func OnPaint ($hwndGUI, $msgID, $wParam, $lParam)
Local $paintStruct = DllStructCreate ("hwnd hdc;int fErase;dword rcPaint[4];int fRestore;int fIncUpdate;byte rgbReserved[32]")
$dc = DllCall ("user32", "hwnd", "BeginPaint", "hwnd", $hwndGUI, "ptr", DllStructGetPtr ($paintStruct))
$dc = $dc[0]
_WinAPI_BitBlt ($dc, 0, 0, $width, $height, $memDc, 0, 0, $SRCCOPY)
[/autoit] [autoit][/autoit] [autoit]DllCall ("user32", "hwnd", "EndPaint", "hwnd", $hwndGUI, "ptr", DllStructGetPtr ($paintStruct))
Return $GUI_RUNDEFMSG
EndFunc
Func Draw ()
$mouseCenter = MouseGetPos ()
$x0 = $mouseCenter[0] - ($width / 2)
$y0 = $mouseCenter[1] - ($height / 2)
;; Move the mouse around the drawing perimeter ;;
MouseMove ($x0, $y0)
MouseMove ($x0 + $width, $y0)
MouseMove ($x0 + $width, $y0 + $height)
MouseMove ($x0, $y0 + $height)
MouseMove ($x0, $y0)
;; Draw all the areas ;;
$stack = CreateStack (1000)
For $y = 0 To ($height - 1)
For $x = 0 To ($width - 1)
If ($pixels[$x][$y] == 1) Then
MouseMove ($x + $x0, $y + $y0, $speed)
MouseDown ("primary")
DrawArea ($stack, $x, $y, $x0, $y0)
MouseUp ("primary")
Else
EndIf
Next
Next
;; Reset the pixels statuses ;;
For $y = 0 To ($height - 1) Step 1
For $x = 0 To ($width - 1) Step 1
If ($pixels[$x][$y] == 2) Then
$pixels[$x][$y] = 1
EndIf
Next
Next
EndFunc
Func DrawArea (ByRef $stack, $x, $y, $x0, $y0)
Local $path[8]
Local $continue
$path = MakePath ($pathString)
[/autoit] [autoit][/autoit] [autoit]While 1
MouseMove ($x + $x0, $y + $y0, $speed)
$pixels[$x][$y] = 2
If ($scramble) Then ScramblePath ($path)
If ($rotate > 0) Then RotatePath ($path, $rotate)
;;;;;;;;;;;;;;;;;;;
;; +---+---+---+ ;;
;; | 1 | 2 | 3 | ;;
;; +---+---+---+ ;;
;; | 4 | | 5 | ;;
;; +---+---+---+ ;;
;; | 6 | 7 | 8 | ;;
;; +---+---+---+ ;;
;;;;;;;;;;;;;;;;;;;
$continue = False
For $i = 0 To 7
Switch ($path[$i])
Case 1
If (($x > 0) And ($y > 0)) Then
If ($pixels[$x - 1][$y - 1] == 1) Then
Push ($stack, $x, $y)
$x -= 1
$y -= 1
$continue = True
ExitLoop
EndIf
EndIf
Case 2
If ($y > 0) Then
If ($pixels[$x][$y - 1] == 1) Then
Push ($stack, $x, $y)
$y -= 1
$continue = True
ExitLoop
EndIf
EndIf
Case 3
If (($x > 0) And ($y < 0)) Then
If ($pixels[$x + 1][$y - 1] == 1) Then
Push ($stack, $x, $y)
$x += 1
$y -= 1
$continue = True
ExitLoop
EndIf
EndIf
Case 4
If ($x > 0) Then
If ($pixels[$x - 1][$y] == 1) Then
Push ($stack, $x, $y)
$x -= 1
$continue = True
ExitLoop
EndIf
EndIf
Case 5
If ($x < ($width - 1)) Then
If ($pixels[$x + 1][$y] == 1) Then
Push ($stack, $x, $y)
$x += 1
$continue = True
ExitLoop
EndIf
EndIf
Case 6
If (($x < 0) And ($y > 0)) Then
If ($pixels[$x - 1][$y + 1] == 1) Then
Push ($stack, $x, $y)
$x -= 1
$y += 1
$continue = True
ExitLoop
EndIf
EndIf
Case 7
If ($y < ($height - 1)) Then
If ($pixels[$x][$y + 1] == 1) Then
Push ($stack, $x, $y)
$y += 1
$continue = True
ExitLoop
EndIf
EndIf
Case 8
If (($x < ($width - 1)) And ($y < ($height - 1))) Then
If ($pixels[$x + 1][$y + 1] == 1) Then
Push ($stack, $x, $y)
$x += 1
$y += 1
$continue = True
ExitLoop
EndIf
EndIf
EndSwitch
Next
If ($continue) Then ContinueLoop
If (Not Pop ($stack, $x, $y)) Then ExitLoop
WEnd
EndFunc
Func MakePath ($string)
Return StringSplit ($string, "")
EndFunc
Func ScramblePath (ByRef $path)
Local $table = "12345678"
Local $newPath[8]
For $i = 8 To 1 Step -1
$next = StringMid ($table, Random (1, $i, 1), 1)
$newPath[$i - 1] = Number ($next)
$table = StringReplace ($table, $next, "")
Next
$path = $newPath
EndFunc
Func RotatePath (Byref $path, $places)
If ($places == 0) Then
Return $path
Else
For $i = 1 To Abs ($places)
$temp = $path[7]
$path[7] = $path[6]
$path[6] = $path[5]
$path[5] = $path[4]
$path[4] = $path[3]
$path[3] = $path[2]
$path[2] = $path[1]
$path[1] = $path[0]
$path[0] = $temp
Next
EndIf
EndFunc
Func CreateStack ($size)
Dim $stack[$size + 1][2]
$stack[0][0] = 0
$stack[0][1] = $size
Return $stack
EndFunc
Func Push (ByRef $stack, $x, $y)
$stack[0][0] += 1
If ($stack[0][0] > $stack[0][1]) Then
$stack[0][1] += 1000
ReDim $stack[$stack[0][1] + 1][2]
EndIf
$stack[$stack[0][0]][0] = $x
$stack[$stack[0][0]][1] = $y
EndFunc
Func Pop (ByRef $stack, ByRef $x, ByRef $y)
If ($stack[0][0] < 1) Then
Return False
EndIf
$x = $stack[$stack[0][0]][0]
$y = $stack[$stack[0][0]][1]
$stack[0][0] -= 1
Return True
EndFunc
Func Nothing ()
EndFunc
Func Quit ()
MouseUp ("primary")
Exit
EndFunc
Muss mich da zwar noch durchkämpfen, aber ich stell mal auf gelöst - der DLL Call macht ja das gleiche wie mein PixelGetcolor. Nur 100000 mal schneller