"Best of" Bilder Script

  • Guten Abend,
    nachdem ich mich heute wieder zum zigtem mal über diverse Fotosoftware aufregte, kam mir folgende Idee, welche ich gerne mit Autoit umsetzen würde.
    Ausgangssituation:

    • Ein Ordner mit vielen Unterordnern, wo diverse Bilder (*.jpg) abgelegt sind


    Ziel:
    Eine Autoit Anwendung, welche recursive alle Bilder einliest, dann Step by Step jedes einzelne Bild in der Autoit Anwendung anzeigt (also immer nur ein Bild).
    Als Navigation soll es einen VOR und ZURÜCK Button geben um zwischen den Bildern zu navigieren. Die Anwendung soll selbstständig in die verschiedenen Ordner wechseln, d.h. die Struktur "soll mich nicht interessieren". Und dann noch einen fetten runden "HOT" Knopf. Wenn dieser gedrückt wird, wird das Bild, welches sich ja "irgendwo" in der Struktur befindet, an einen 2. definierten Ordner kopiert.

    Ich habe z.B. ca. 2000 Bilder in der Struktur und möchte damit erreichen, das ich nur die Besten "auf Knopfdruck" rauskopiere.

    Hilfe brauche ich für folgende Funktionen:

    1.) Wie lese ich das alles recursiv ein, bzw. wie "wechselt" die Anwendung automatisch in die verschiedenen Unterordner rein und wieder raus ?
    2.) Wie stelle ich die Bilder dar (welche UDF oder was auch immer)
    3.) Wie baut man z.B. runde Schaltflächen

    Es werden sicherlich dann noch viele weitere Fragen kommen, aber ich mach jetzt erst mal Brainstorming :)

    Gruß Hassan

    2 Mal editiert, zuletzt von HassanMullah (8. April 2013 um 12:36) aus folgendem Grund: Nicht von mir gelöst, aber die Lösung wurde gleich veröffentlich. Vielen Dank nochmals an dieser Stelle Nochmals geöffnet, da noch eine kleine Bitte von mir.

  • zu:

    • such dir eine der _FileListToArrayRekursiv-Lösungen hier im Forum. Da im zurückgegebenen Array der komplette Pfad steht braucht es keinen Ordnerwechsel
    • [autoit]GUICtrlCreatePic
      GUICtrlSetImage[/autoit]genügen für JPG's
    • mit GDI+ bzw. mit der GUICtrlPic.au3 von Großvater

    mfg autoBert

    • Offizieller Beitrag

    Ich hatte gerade mal Lust sowas zu programmieren und weil ich einiges davon sowieso schonmal gebraucht hatte, ist bisher das hier fertig:

    Spoiler anzeigen
    [autoit]


    #include <EditConstants.au3>
    #include <GDIPlus.au3>
    #include <GUIConstantsEx.au3>
    #include <GuiStatusBar.au3>

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

    _GDIPlus_Startup()

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

    Global $iPreviewLeft = 10
    Global $iPreviewTop = 70
    Global $iPreviewMaxWidth = 800
    Global $iPreviewMaxHeight = 600
    Global $aPicFilenames[1] = [0], $iCount = 0, $pState = False, $aParts[3] = [$iPreviewMaxWidth / 2 + 100, $iPreviewMaxWidth / 2 + 250, $iPreviewMaxWidth / 2 + 350]
    Global $sSourcePath = '', $sDestPath = ''

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

    $hGui = GUICreate('Fotosortierer', $iPreviewMaxWidth + 20, $iPreviewMaxHeight + 140)
    GUISetFont(9, 400, 0, 'Verdana')
    GUICtrlCreateLabel('Quellverzeichnis:', 10, 12, 120, 25)
    GUICtrlSetFont(-1, 10, 400, 0, 'Verdana', 5)
    $ID_SourceDir = GUICtrlCreateInput('', 130, 10, $iPreviewMaxWidth - 170, 25, $ES_READONLY)
    GUICtrlSetBkColor(-1, 0xFFFFEE)
    $ID_SourceSel = GUICtrlCreateButton('...', $iPreviewMaxWidth - 38, 10, 32, 24)
    GUICtrlSetFont(-1, 10, 400, 0, 'Verdana', 5)

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

    GUICtrlCreateLabel('Zielverzeichnis:', 10, 42, 120, 25)
    GUICtrlSetFont(-1, 10, 400, 0, 'Verdana', 5)
    $ID_DestDir = GUICtrlCreateInput('', 130, 40, $iPreviewMaxWidth - 170, 25, $ES_READONLY)
    GUICtrlSetBkColor(-1, 0xFFFFEE)
    $ID_DestSel = GUICtrlCreateButton('...', $iPreviewMaxWidth - 38, 40, 32, 24)
    GUICtrlSetFont(-1, 10, 400, 0, 'Verdana', 5)

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

    $hPreviewGraphic = _GDIPlus_GraphicsCreateFromHWND($hGui)

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

    $ID_Prev = GUICtrlCreateButton('Vorheriges Bild', $iPreviewMaxWidth / 2 - 200, $iPreviewMaxHeight + 80, 110, 25)
    GUICtrlSetState(-1, $GUI_DISABLE)
    $ID_Copy = GUICtrlCreateButton('Bild kopieren', $iPreviewMaxWidth / 2 - 60, $iPreviewMaxHeight + 76, 130, 32)
    GUICtrlSetState(-1, $GUI_DISABLE)
    $ID_Next = GUICtrlCreateButton('Nächstes Bild', $iPreviewMaxWidth / 2 + 100, $iPreviewMaxHeight + 80, 110, 25)
    GUICtrlSetState(-1, $GUI_DISABLE)

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

    $hStatus = _GUICtrlStatusBar_Create($hGui)
    _GUICtrlStatusBar_SetParts($hStatus, $aParts)

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

    GUISetState()
    _GDIPlus_GraphicsFillRect($hPreviewGraphic, $iPreviewLeft, $iPreviewTop, $iPreviewMaxWidth, $iPreviewMaxHeight)

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

    While True
    Switch GUIGetMsg()
    Case $GUI_EVENT_CLOSE
    _GDIPlus_GraphicsDispose($hPreviewGraphic)
    _GDIPlus_Shutdown()
    Exit
    Case $ID_Prev
    $iCount -= 1
    _ShowStatus()
    _ShowImage($aPicFilenames[$iCount])
    $pState = False
    Case $ID_Next
    $iCount += 1
    _ShowStatus()
    _ShowImage($aPicFilenames[$iCount])
    $pState = False
    Case $ID_Copy
    GUICtrlSetState($ID_Copy, $GUI_DISABLE)
    _GUICtrlStatusBar_SetText($hStatus, 'Bitte Warten! Bild wird kopiert...', 0)
    If FileCopy($aPicFilenames[$iCount], $sDestPath) Then
    _GUICtrlStatusBar_SetText($hStatus, 'Das Bild wurde erfolgreich kopiert.', 0)
    Else
    _GUICtrlStatusBar_SetText($hStatus, 'Fehler beim kopieren!', 0)
    EndIf
    $pState = False
    Case $ID_SourceSel
    $sPath = FileSelectFolder('Bitte Quellverzeichnis auswählen', '', 6, $sSourcePath, $hGui)
    If $sPath <> '' Then
    If StringRight($sPath, 1) <> '\' Then $sPath &= '\'
    $sSourcePath = $sPath
    GUICtrlSetData($ID_SourceDir, $sPath)
    _GUICtrlStatusBar_SetText($hStatus, 'Bitte Warten! Verzeichnis wird eingelesen...', 0)
    $aPicFilenames = _RecursiveFileListToArray($sPath, '(?i).+\.(jpg|jpeg|gif|bmp)', 1)
    If $aPicFilenames[0] > 0 Then
    $iCount = 1
    _ShowStatus()
    _ShowImage($aPicFilenames[$iCount])
    Else
    $iCount = 0
    _GUICtrlStatusBar_SetText($hStatus, 'Keine Bilder im Quellverzeichnis vorhanden!', 0)
    EndIf
    $pState = False
    EndIf
    Case $ID_DestSel
    $sPath = FileSelectFolder('Bitte Zielverzeichnis auswählen', '', 6, $sDestPath, $hGui)
    If $sPath <> '' Then
    If StringRight($sPath, 1) <> '\' Then $sPath &= '\'
    $sDestPath = $sPath
    GUICtrlSetData($ID_DestDir, $sPath)
    $pState = False
    EndIf
    EndSwitch
    If Not $pState Then
    $pState = True
    If $aPicFilenames[0] > 0 Then
    If FileExists($sDestPath) Then
    If Not FileExists($sDestPath & StringRegExpReplace($aPicFilenames[$iCount], '.+\\(.+)', '$1')) Then
    GUICtrlSetState($ID_Copy, $GUI_ENABLE)
    Else
    GUICtrlSetState($ID_Copy, $GUI_DISABLE)
    EndIf
    Else
    GUICtrlSetState($ID_Copy, $GUI_DISABLE)
    EndIf
    If $iCount > 1 Then
    GUICtrlSetState($ID_Prev, $GUI_ENABLE)
    Else
    GUICtrlSetState($ID_Prev, $GUI_DISABLE)
    EndIf
    If $iCount < $aPicFilenames[0] Then
    GUICtrlSetState($ID_Next, $GUI_ENABLE)
    Else
    GUICtrlSetState($ID_Next, $GUI_DISABLE)
    EndIf
    Else
    GUICtrlSetState($ID_Prev, $GUI_DISABLE)
    GUICtrlSetState($ID_Copy, $GUI_DISABLE)
    GUICtrlSetState($ID_Next, $GUI_DISABLE)
    EndIf
    EndIf
    WEnd

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

    Func _ShowStatus()
    _GUICtrlStatusBar_SetText($hStatus, StringReplace($aPicFilenames[$iCount], $sSourcePath, '', 1), 0)
    _GUICtrlStatusBar_SetText($hStatus, StringFormat(' Bild %i von %i', $iCount, $aPicFilenames[0]), 1)
    EndFunc

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

    Func _ShowImage($sImgFile)
    Local $iVector, $iPreviewHeight, $iPreviewWidth, $aPixelFormat
    Local $hPreviewBitmap = _GDIPlus_BitmapCreateFromFile($sImgFile)
    If $hPreviewBitmap = 0 Then
    _GDIPlus_GraphicsFillRect($hPreviewGraphic, $iPreviewLeft, $iPreviewTop, $iPreviewMaxWidth, $iPreviewMaxHeight)
    _GDIPlus_BitmapDispose($hPreviewBitmap)
    Return
    EndIf
    $iPreviewWidth = _GDIPlus_ImageGetWidth($hPreviewBitmap)
    $iPreviewHeight = _GDIPlus_ImageGetHeight($hPreviewBitmap)
    $aPixelFormat = _GDIPlus_ImageGetPixelFormat($hPreviewBitmap)
    _GUICtrlStatusBar_SetText($hStatus, StringFormat(' %i x %i px , %i Bit', $iPreviewWidth, $iPreviewHeight, $aPixelFormat[1]), 2)
    If $iPreviewWidth > $iPreviewMaxWidth Or $iPreviewHeight > $iPreviewMaxHeight Then
    $iVector = $iPreviewWidth / $iPreviewHeight
    Do
    $iPreviewWidth -= $iVector
    $iPreviewHeight -= 1
    Until $iPreviewHeight <= $iPreviewMaxHeight And $iPreviewWidth <= $iPreviewMaxWidth
    EndIf
    _GDIPlus_GraphicsFillRect($hPreviewGraphic, $iPreviewLeft, $iPreviewTop, $iPreviewMaxWidth, $iPreviewMaxHeight)
    _GDIPlus_GraphicsDrawImageRect($hPreviewGraphic, $hPreviewBitmap, $iPreviewLeft + ($iPreviewMaxWidth - $iPreviewWidth) / 2, $iPreviewTop + ($iPreviewMaxHeight - $iPreviewHeight) / 2, $iPreviewWidth, $iPreviewHeight)
    _GDIPlus_BitmapDispose($hPreviewBitmap)
    EndFunc ;==>_PreviewShowImage

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

    Func _GuiCtrlSetPath($nID, $sPath, $iFit = 0)
    ;coded by funkey
    ;2011, Nov 24th
    Local $hCtrl = GUICtrlGetHandle($nID)
    Local $hDC = _WinAPI_GetDC($hCtrl)
    Local $tPath = DllStructCreate("char[260]")
    Local $pPath = DllStructGetPtr($tPath)
    DllStructSetData($tPath, 1, $sPath)
    Local $hFont = _SendMessage($hCtrl, 49, 0, 0, 0, "wparam", "lparam", "hwnd") ;WM_GETFONT
    Local $hFont_old = _WinAPI_SelectObject($hDC, $hFont)
    Local $aPos = ControlGetPos($hCtrl, "", "")
    DllCall("Shlwapi.dll", "BOOL", "PathCompactPath", "handle", $hDC, "ptr", $pPath, "int", $aPos[2] - $iFit)
    _WinAPI_SelectObject($hDC, $hFont_old)
    _WinAPI_DeleteDC($hDC)
    GUICtrlSetData($nID, DllStructGetData($tPath, 1))
    Return DllStructGetData($tPath, 1)
    EndFunc ;==>_GuiCtrlSetPath

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

    ;===============================================================================
    ; Function Name: _RecursiveFileListToArray($sPath[, $sPattern][, $iFlag][, $iFormat][, $fRecursion][, $sDelim])
    ; Description:: gibt Verzeichnisse (rekursiv) und/oder Dateien zurück, die einem RegExp-Pattern entsprechen
    ; Parameter(s): $sPath = Startverzeichnis
    ; $sPattern = ein beliebiges RexExp-Pattern für die Auswahl
    ; $iFlag = Auswahl
    ; 0 = Dateien & Verzeichnisse
    ; 1 = nur Dateien
    ; 2 = nur Verzeichnisse
    ; $iFormat = Rückgabeformat
    ; 0 = String
    ; 1 = Array mit [0] = Anzahl
    ; 2 = Nullbasiertes Array
    ; $fRecursion = Verzeichnisse rekursiv durchsuchen
    ; False = Nein
    ; True = Ja
    ; $sDelim = Trennzeichen für die String-Rückgabe
    ; Requirement(s): AutoIt 3.3.0.0
    ; Return Value(s): Array/String mit den gefundenen Dateien/Verzeichnissen
    ; Author(s): Oscar (http://www.autoit.de)
    ; Anregungen von: bernd670 (http://www.autoit.de)
    ; und: AspirinJunkie (http://www.autoit.de)
    ;===============================================================================
    Func _RecursiveFileListToArray($sPath, $sPattern = '', $iFlag = 0, $iFormat = 1, $fRecursion = True, $sDelim = @CRLF, $fOpenDLL = True)
    Local $hSearch, $sFile, $sReturn = '', $aD
    Local Static $hDll
    If StringRight($sPath, 1) <> '\' Then $sPath &= '\'
    $hSearch = FileFindFirstFile($sPath & '*')
    If @error Or $hSearch = -1 Then Return SetError(1, 0, $sReturn)
    If $fOpenDLL Then $hDll = DllOpen('kernel32.dll')
    While True
    $sFile = FileFindNextFile($hSearch)
    If @error Then ExitLoop
    If @extended Then
    $aD = DllCall($hDll, 'dword', 'GetFileAttributesW', 'wstr', $sPath & $sFile)
    If @error Or BitAND($aD[0], 0x400) Then ContinueLoop
    If StringRegExp($sPath & $sFile, $sPattern) And ($iFlag = 0 Or $iFlag = 2) Then $sReturn &= $sPath & $sFile & '\' & $sDelim
    If $fRecursion Then $sReturn &= _RecursiveFileListToArray($sPath & $sFile & '\', $sPattern, $iFlag, 0, True, $sDelim, False)
    ContinueLoop
    EndIf
    If StringRegExp($sFile, $sPattern) And ($iFlag = 0 Or $iFlag = 1) Then $sReturn &= $sPath & $sFile & $sDelim
    WEnd
    FileClose($hSearch)
    If $fOpenDLL Then DllClose($hDll)
    If $iFormat And $sReturn = '' Then Return SetError(0, 1, StringSplit($sReturn, '', $iFormat))
    If $iFormat Then Return SetError(0, 2, StringSplit(StringTrimRight($sReturn, StringLen($sDelim)), $sDelim, $iFormat))
    Return $sReturn
    EndFunc

    [/autoit]
  • Die Idee finde ich total genial. Ich habe mal die Variante von Oscar genutzt, jedoch funktioniert die Quellverzeichnisauswahl bei mir nicht so wie ich persönlich sie mir als Nutzer vorstellen würde...Wähle ich meinen Bilderordner aus ließt er scheinbar alle Bilder aus, auch wenn dort noch Ordner sind, wenn ich aber z.B. die Bibliotheken aus Windows auswähle crashed es:
    Zeile 80 : ==> Subscript used with non-Array variable.:
    If $aPicFilenames[0] > 0 Then
    If $aPicFilenames^ ERROR

    Grüße Yaerox

    Grüne Hölle

  • Tausche die Original _RecursiveFileListToArray gegen:

    Spoiler anzeigen
    [autoit]

    ;===============================================================================
    ; Function Name: _RecursiveFileListToArray($sPath[, $sPattern][, $iFlag][, $iFormat][, $fRecursion][, $sDelim])
    ; Description:: gibt Verzeichnisse (rekursiv) und/oder Dateien zurück, die einem RegExp-Pattern entsprechen
    ; Parameter(s): $sPath = Startverzeichnis
    ; $sPattern = ein beliebiges RexExp-Pattern für die Auswahl
    ; $iFlag = Auswahl
    ; 0 = Dateien & Verzeichnisse
    ; 1 = nur Dateien
    ; 2 = nur Verzeichnisse
    ; $iFormat = Rückgabeformat
    ; 0 = String
    ; 1 = Array mit [0] = Anzahl
    ; 2 = Nullbasiertes Array
    ; $fRecursion = Verzeichnisse rekursiv durchsuchen
    ; False = Nein
    ; True = Ja
    ; $sDelim = Trennzeichen für die String-Rückgabe
    ; Requirement(s): AutoIt 3.3.0.0
    ; Return Value(s): Array/String mit den gefundenen Dateien/Verzeichnissen
    ; Author(s): Oscar (http://www.autoit.de)
    ; Anregungen von: bernd670 (http://www.autoit.de)
    ; und: AspirinJunkie (http://www.autoit.de)
    ;===============================================================================
    Func _RecursiveFileListToArray($sPath, $sPattern = '', $iFlag = 0, $iFormat = 1, $fRecursion = True, $sDelim = @CRLF, $fOpenDLL = True)
    Local $hSearch, $sFile, $sReturn = '', $aD
    Local Static $hDll
    If StringRight($sPath, 1) <> '\' Then $sPath &= '\'
    $hSearch = FileFindFirstFile($sPath & '*')
    If @error Or $hSearch = -1 Then
    If $iFormat And $sReturn = '' Then Return SetError(1, 1, StringSplit($sReturn, '', $iFormat))
    If $iFormat Then Return SetError(1, 2, StringSplit(StringTrimRight($sReturn, StringLen($sDelim)), $sDelim, $iFormat))
    Return $sReturn
    EndIf
    If $fOpenDLL Then $hDll = DllOpen('kernel32.dll')
    While True
    $sFile = FileFindNextFile($hSearch)
    If @error Then ExitLoop
    If @extended Then
    $aD = DllCall($hDll, 'dword', 'GetFileAttributesW', 'wstr', $sPath & $sFile)
    If @error Or BitAND($aD[0], 0x400) Then ContinueLoop
    If StringRegExp($sPath & $sFile, $sPattern) And ($iFlag = 0 Or $iFlag = 2) Then $sReturn &= $sPath & $sFile & '\' & $sDelim
    If $fRecursion Then $sReturn &= _RecursiveFileListToArray($sPath & $sFile & '\', $sPattern, $iFlag, 0, True, $sDelim, False)
    ContinueLoop
    EndIf
    If StringRegExp($sFile, $sPattern) And ($iFlag = 0 Or $iFlag = 1) Then $sReturn &= $sPath & $sFile & $sDelim
    WEnd
    FileClose($hSearch)
    If $fOpenDLL Then DllClose($hDll)
    If $iFormat And $sReturn = '' Then Return SetError(0, 1, StringSplit($sReturn, '', $iFormat))
    If $iFormat Then Return SetError(0, 2, StringSplit(StringTrimRight($sReturn, StringLen($sDelim)), $sDelim, $iFormat))
    Return $sReturn
    EndFunc ;==>_RecursiveFileListToArray

    [/autoit]

    dann ist der Fehler in Zeie 80 behoben.

    mfg autoBert

  • Wobei er dann immer noch net die gesamte Bibliothek nimmt ... Er schmiert zwar nicht mehr ab, aber er findet scheinbar keine Bilder und als Pfad wird lediglich "Bilder/" eingetragen ...

    Schnellste Spontanlösung die mir da einfällt wäre die Standardbibliotheken abzufangen von wegen:

    If $sSourcePath = "Bilder" Then $sSourcePath = C:\User\username\Pictures

    Grüße Yaerox

    Grüne Hölle

  • Einen kleine Bitte hätte ich noch, da es mir "auf die Schnelle" noch schwer fällt, mich in den Code einzulesen.

    Mein erster Kurztest hat technisch funktioniert, mit dem echten Verzeichnis für ca. 2000 Bilder muss ich es noch testen.

    Schön wäre eine Speicherfunktion für den Verarbeitungsstand, d.h. wenn ich mir vermutlich mal 400 Bilder am Stück angeschaut habe, möchte ich ja eine Pause machen. Wenn ich dann die Anwendung schließe, wäre es schön, wenn sich diese die Einstellungen des Quell- und Zielpfades, sowie das letzte angezeigte Bild merken würde, damit ich da wieder weiter machen kann und nicht wieder komplett von Vorne anfangen muss.

    Ich hoffe es ist nicht zu unverschämt, wenn ich Euch bitte sowas noch einzubauen.

    Vorab mal vielen Dank

    Gruß Hassan

  • Ich denke der einzige Weg sowas zu realisieren wäre eine Datei anzulegen indem eine Art Index der Datei geschrieben wird bei dem gestartet werden kann ... üblicherweise wird sofern das Programm geschlossen wird ja alles an Speicher freigegeben ... falls ich im unrecht bin belehrt mich bitte :)

    Womit man dann u.U. sagen müsste es darf dann halt kein weiteres Bild dazu kommen da es sonst mit dem Index Probleme geben könnte ...

    Grüße

    Grüße Yaerox

    Grüne Hölle

    • Offizieller Beitrag

    Einen kleine Bitte hätte ich noch, da es mir "auf die Schnelle" noch schwer fällt, mich in den Code einzulesen.

    Ich hoffe es ist nicht zu unverschämt, wenn ich Euch bitte sowas noch einzubauen.


    Da stellt sich mir ernsthaft die Frage: Was treibst du hier im Forum? Bist du überhaupt gewillt deinen Wissensstand zu erweitern oder willst du nur auf die Betteltour die Arbeit von anderen erledigen lassen?

    Und ja, ich finde es verdammt unverschämt, wenn man andere für sich werkeln läßt!

    Aus diesem Grunde:

    Dieser Thread wird vorerst geschlossen, damit der TE die Muße hat, das Skript von Oscar zu lesen, zu verstehen und mit dem Plus an Wissen kann er auch ohne unsere Hilfe den Rest erledigen.
    Btw.: Tauchen in den nächsten Tagen Threads zur selben Thematik auf, kannst du sicher sein, dass diese geschlossen werden.

    [CLOSED]