Jump to content

Resizing images script


pixelsearch
 Share

Recommended Posts

Hi everybody :)
I just ended a script and wanted to share it with you.
It allows you to resize files and save them automatically, after you choose a whole folder (with or without recursion) or maybe you prefer to pick the files individually and you can do that too.
You decide what to do with the resized files (saving them with new names or overwriting the originals, be careful)
Just check the image types you need, so the filters will automatically be generated in the appropriate functions.
During the resizing & saving phase, you can press the Escape key if you want to pause or exit the script

736083765_resizeimagefiles.png.10796b3e705fd2cfb4a74258a532e36f.png

Your personal computation is to be placed in the function named _Calc_New_Size() so you can bring your own rules concerning the resizing process, based on width and height of the original images (that's why I wrote the script), skipping a file depending on certain conditions etc... In this example, I just divided width and length by 2, so it's an easy resizing method :)

Watch out if you check the gif image type, in case you got animated gifs and choose to overwrite them, the animation will be lost. That's why gif default is unchecked, but you can have it checked by default after changing ["GIF", 0, 999] to ["GIF", 1, 999] in the very beginning of the script.

There are comments in the script that may be useful if you decide to modify it to your needs. Also several _ArrayDisplay (and MsgBox) are left commented out, they were used for debug in case you need them.

Please be careful when choosing the "overwrite" option in case you don't get a copy of the originals. In all cases, just try the script on a sample folder the first times, to be secure.

Image quality of the resized files should be the best one as $GDIP_INTERPOLATIONMODE_HIGHQUALITYBICUBIC is the default in _GDIPlus_ImageResize() and I kept it that way.

Thanks to UEZ for his useful comments found here and there, that helps a lot.
Not forgetting our best friend... the help file.

If you guys got any ideas to improve this script, please be kind enough to share your thoughts so we can make it better :)

#include <Array.au3>
#include <ButtonConstants.au3>
#include <FileConstants.au3>
#include <GDIPlus.au3>
#include <GUIConstantsEx.au3>
#include <MsgBoxConstants.au3>
#include <WindowsConstants.au3>
#include <WinAPIDlg.au3>
#include <WinAPISysWin.au3>

; =======
; Gui checkboxes placed in an Array to avoid plenty of lines here and there in the script
Global $iMaxImageTypes = 8, $idCheckbox[$iMaxImageTypes]
Global $aContentCheckbox[$iMaxImageTypes][3] = _
    [["JPG", 1, 999], ["PNG", 1, 999], ["BMP", 1, 999], ["GIF", 0, 999], _
    ["TIFF", 0, 999], ["EXIF", 0, 999], ["WMF", 0, 999], ["EMF", 0, 999]]
    ; 1 = already checked in GUI. 999 = Checkboxes id's (updated during their creation)

Global $iHow_Choose_img = 1 ; 1 = folder, 2 = folder (recurse), 3 = pick them individually
Global $iNewname_or_Overwrite = 1 ; 1 = new name (ex ..._resized.jpg), 2 = Overwrite

F10()   ; displays the GUI so the user will choose :
        ; 1) how to select image files, using FileSelectFolder() or FileOpenDialog()
        ; 2) give a new name to resized images or overwrite ?
        ; 3) check the image types desired (at least 1 is mandatory)
; =======

; Both variables $sPath and $aListe_img will be updated in Select_img_folder OR Select_img()
Global $sPath ; will always end with a "\"
Global $aListe_img ; Array containing the list of images to resize (1-based)

If $iHow_Choose_img = 3 Then ; pick files individually
    Select_img()
Else ; 1 (folder, no recursion) or 2 (folder, with recursion)
    Select_img_folder()
EndIf
; =======

Global $aSummary[5][2] ; informative MsgBox when all is done
$aSummary[0][1] = (($iNewname_or_Overwrite = 1) ? ("new name") : ("overwritten"))
$aSummary[1][1] = " image(s) resized and saved (" & $aSummary[0][1] & ")"
$aSummary[2][1] = " image(s) skipped (due to calculation rules)"
$aSummary[3][1] = " image(s) skipped (name ended with '_resized.')"
$aSummary[4][1] = " image(s) skipped (not overwritten as read-only)"
For $i = 0 to 4
    $aSummary[$i][0] = 0 ; number of images related to each category
Next
; _ArrayDisplay($aSummary, "Debug $aSummary") ; note that [0][0] will be unused

Global $iX, $iX_resized, $iY, $iY_resized, $hImage, $hImage_Resized ; for GDI+

Global $bTest_ReadOnly = True ; test read-only when savefile => @error = 10 And @extended = 7
Global $iTest_ReadOnly = 0 ; 2 if Overwrite all read-only files, 4 if Skip all read-only files
; =======

_ArrayDisplay($aListe_img, _
    $aListe_img[0] & " image(s) to resize", _
    "", 0, Default, "Image name")

If $iNewname_or_Overwrite = 2 Then ; 2 = Overwrite
    If MsgBox(BitOr($MB_TOPMOST, $MB_ICONWARNING, $MB_OKCANCEL, $MB_DEFBUTTON2), _
      "You choosed to OVERWRITE", "Original files will be lost." & @CRLF & _
      "Proceed anyway ?") = $IDCANCEL Then Exit
EndIf
; =======

HotKeySet("{ESC}", "_Wanna_Quit") ; user keys Esc while images are resizing

ProgressOn("Resizing images (Esc to abort)", "File in treatment...", "", -1, -1, 16)
    ; 16 = $DLG_MOVEABLE
AdlibRegister("AdlibProgressBar", 1000) ; each 1000ms (1s)

_GDIPlus_Startup()

For $iNum_img = 1 To $aListe_img[0]
    ; this sounds good : do not resize again a file already "_resized."
    If StringInStr($aListe_img[$iNum_img], "_resized.", 0, -1) <> 0 Then
        $aSummary[3][0] += 1 ; skipped (name ended with '_resized.')
        ContinueLoop
    EndIf

    ; full path is already included in file name only if recursion has been chosen
    ; if not, add path to filename
    $sFileName = (($iHow_Choose_img <> 2) ? ($sPath) : ("")) & $aListe_img[$iNum_img]

    $hImage = _GDIPlus_ImageLoadFromFile($sFileName)
    If @error Or Not $hImage  Then _
        _Exit("_GDIPlus_ImageLoadFromFile", $sFileName, @error, @extended)

    $iX = _GDIPlus_ImageGetWidth($hImage)
    If @error Then _Exit("_GDIPlus_ImageGetWidth", $sFileName, @error, @extended)

    $iY = _GDIPlus_ImageGetHeight($hImage)
    If @error Then _Exit("_GDIPlus_ImageGetHeight", $sFileName, @error, @extended)

    ; note that _GDIPlus_ImageGetDimension() could have been used instead
    ; $aDim = _GDIPlus_ImageGetDimension($hImage) ; $aDim[0] = width, $aDim[1] = height

    If _Calc_New_Size() = False Then ; False = skip image, True = resize and save
        _GDIPlus_ImageDispose($hImage)
        $aSummary[2][0] += 1 ; skipped (due to calculation rules)
        ContinueLoop
    EndIf

    $hImage_Resized = _GDIPlus_ImageResize($hImage, $iX_resized, $iY_resized)
    If @error Then _Exit("_GDIPlus_ImageResize", $sFileName, @error, @extended)

    _GDIPlus_ImageDispose($hImage) ; place it here, needed if file will be overwritten

    If $iNewname_or_Overwrite = 1 Then ; 1 = save with new file name (ex ..._resized.jpg)
        $iLastDot = StringInStr($sFileName, ".", 0, -1) ; -1 = search 1st dot from right side
        If $iLastDot = 0 Then _Exit("StringInStr (no extension dot found)", _
            $sFileName, @error, @extended) ; impossible
        $sFileName = StringLeft($sFileName, $iLastDot - 1) & _
            "_resized" &  StringMid($sFileName, $iLastDot) ; ex. "image01_resized.jpg"
    Endif

    _GDIPlus_ImageSaveToFile($hImage_Resized, $sFileName)
    If @error Then ; could be a read-only file error (tried it: @error = 10 and @extended =7)
        $iKeep_error = @error
        $iKeep_extended = @extended
        If Not ($iKeep_error = 10 And $iKeep_extended = 7) Then
            _Exit("_GDIPlus_ImageSaveToFile", $sFileName, $iKeep_error, $iKeep_extended)
        Else ; $iKeep_error = 10 And $iKeep_extended = 7 : maybe a read-only file ?
            _Treat_SaveToFile($hImage_Resized, $sFileName, $iKeep_error, $iKeep_extended)
        EndIf
    Else
        $aSummary[1][0] += 1 ; resized & saved
    EndIf

    _GDIPlus_ImageDispose($hImage_Resized)
Next

_GDIPlus_Shutdown()
AdlibStop()

$sMsgBoxText = ""
For $i = 1 to 4
    If $aSummary[$i][0] <> 0 Then
        $sMsgBoxText &= $aSummary[$i][0] & @TAB & $aSummary[$i][1] & @CRLF & @CRLF
    EndIf
Next

MsgBox(BitOr($MB_TOPMOST, $MB_ICONINFORMATION), _
    "Summary of " & $aListe_img[0] & " processed image(s)", _
    StringTrimRight($sMsgBoxText, 2)) ; remove last @CRLF

; ====================================================
Func _Treat_SaveToFile($hImage_Resized, $sFileName, $iKeep_error, $iKeep_extended)
    ; always $iKeep_error = 10 And $iKeep_extended = 7 : maybe a read-only file ?

    ; test on possible read-only file as Save => @error = 10 And @extended = 7
    If $bTest_ReadOnly = True Then
        If StringInStr(FileGetAttrib($sFileName), "R") = 0 Then ; NOT a Read only file
            _Exit("_GDIPlus_ImageSaveToFile", _
              $sFileName & @CRLF & "(NOT read-only)", _
              $iKeep_error, $iKeep_extended)

        Else ; read-only File

            ; hide this window temporarily (too crowded with Splash & GUI coming)
            WinSetState("Resizing images (Esc to abort)", "", @SW_HIDE)

            ; display the image in a Splash window, create a 5-buttons GUI to ask user.
            Local $sExt = StringTrimLeft($sFileName, StringInStr($sFileName, ".", 0, -1))
            If $sExt = "jpg" Or $sExt = "jpeg" Or $sExt = "bmp" Or $sExt = "gif"  Then ; no png
                Local $iX_splash, $iY_splash
                If $iX <= 800 And $iY <= 600 Then ; max Splash image size will be 800 x 600
                    $iX_splash = $iX ; keep real width as <= 800
                    $iY_splash = $iY ; keep real height as <= 600
                Else ; $iX > 800 OR $iY > 600
                    $iRatio = $iX / $iY
                    If $iRatio <= 4/3 Then ; height forced to 600 will always have width <= 800
                        $iY_splash = 600
                        $iX_splash = $iX * $iY_splash / $iY
                    Else ; > 4/3 then any width forced to 800 will always have height < 600
                        $iX_splash = 800
                        $iY_splash = $iY * $iX_splash / $iX
                    EndIf
                EndIf
                SplashImageOn(StringTrimLeft($sFileName, StringInStr($sFileName, "\", 0, -1)), _
                    $sFileName, $iX_splash, $iY_splash, Default, Default, 2+16)
            EndIf

            HotKeySet("{ESC}") ; unset the Esc Hotkey to control Escape behavior in the GUI
            Opt("GUICloseOnESC", 0) ;1=ESC  closes, 0=ESC won't close

            Local $hGUI = GUICreate("Read-only file", 500, 150, -1, -1, _
                BitOR($WS_CAPTION, $WS_POPUP, $WS_SYSMENU), @SW_SHOWDEFAULT)

            ; 40 = large height in case of 2 lines (very long file name & path)
            GUICtrlCreateLabel($sFileName, 10, 10, 480, 40)
            GUICtrlCreateLabel("This file is read-only. What do you want to do ?", _
                10, 55, 480, 20)
            Local $idButton1 = GUICtrlCreateButton("Overwrite it", 10, 100, 80, 40)
            Local $idButton2 = GUICtrlCreateButton("Overwrite all" & @CRLF & "read-only files", _
                110, 100, 80, 40, $BS_MULTILINE)
            Local $idButton3 = GUICtrlCreateButton("Skip it", 210, 100, 80, 40)
            Local $idButton4 = GUICtrlCreateButton("Skip all" & @CRLF & "read-only files", _
                310, 100, 80, 40, $BS_MULTILINE)
            Local $idButton5 = GUICtrlCreateButton("Exit script", 410, 100, 80, 40)

            GUISetState()

            While 1
                Switch GUIGetMsg()
                    Case $GUI_EVENT_CLOSE ; Red X, as Escape key deact by Opt("GUICloseOnESC", 0)
                        MsgBox($MB_TOPMOST, "", "Please check a button to make your choice")

                    Case $idButton1 ; Overwrite it (re-ask if another read-only is found)
                        FileSetAttrib($sFileName, "-R")
                        _GDIPlus_ImageSaveToFile($hImage_Resized, $sFileName)
                        $aSummary[1][0] += 1 ; resized & saved
                        ExitLoop

                    Case $idButton2 ; Overwrite all read-only files
                        FileSetAttrib($sFileName, "-R")
                        _GDIPlus_ImageSaveToFile($hImage_Resized, $sFileName)
                        $aSummary[1][0] += 1 ; resized & saved
                        $bTest_ReadOnly = False ; don't ask if others read-only files encountered
                        $iTest_ReadOnly = 2 ; (2 because of $idButton2, for fun)
                        ExitLoop

                    Case $idButton3 ; Skip it (re-ask if another read-only is found)
                        $aSummary[4][0] += 1 ; not overwritten as read-only
                        ExitLoop

                    Case $idButton4 ; Skip all read-only files
                        $aSummary[4][0] += 1 ; not overwritten as read-only
                        $bTest_ReadOnly = False ; don't ask if others read-only files encountered
                        $iTest_ReadOnly = 4 ; (4 because of $idButton4, for fun)
                        ExitLoop

                    Case $idButton5 ; Exit script
                        GUIDelete($hGui)
                        SplashOff()
                        AdlibStop()
                        ; _GDIPlus_ImageDispose($hImage) ; already disposed before Save in main
                        _GDIPlus_ImageDispose($hImage_Resized)
                        _GDIPlus_Shutdown()
                        Exit
                EndSwitch
            WEnd

            GUIDelete($hGui)
            SplashOff()
            WinSetState("Resizing images (Esc to abort)", "", @SW_SHOW)
            Opt("GUICloseOnESC", 1) ;1=ESC  closes, 0=ESC won't close
            HotKeySet("{ESC}", "_Wanna_Quit")
        Endif

    Else ; $bTest_ReadOnly = False (means already tested for 1 read-only file encountered)
        Switch $iTest_ReadOnly
            Case 2 ; Overwrite all read-only files
                FileSetAttrib($sFileName, "-R")
                _GDIPlus_ImageSaveToFile($hImage_Resized, $sFileName)
                $aSummary[1][0] += 1 ; resized & saved

            Case 4 ; Skip all read-only files
                $aSummary[4][0] += 1 ; not overwritten as read-only

            Case Else
                MsgBox($MB_TOPMOST, "Impossible error", _
                    "$iTest_ReadOnly = " & $iTest_ReadOnly)
                AdlibStop()
                ; _GDIPlus_ImageDispose($hImage) ; already disposed before Save in main
                _GDIPlus_ImageDispose($hImage_Resized)
                _GDIPlus_Shutdown()
                Exit
        EndSwitch
    EndIf

EndFunc ; _Treat_SaveToFile()

; ====================================================
Func _Calc_New_Size() ; user's function to calculate new width & height, compute etc...

    ; Return True  => will resize the image and save  <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    ; Return False => won't do anything (no resize and no save) <<<<<<<<<<<<<<<<<<<<<<

    ; example for Forum
    $iX_resized = $iX / 2
    $iY_resized = $iY / 2
    Return True

;~  ; personal example
;~  If $iX = 1024 OR $iY = 768 Then Return False ; skip image (in case already reworked)
;~  $iRatio = $iX / $iY

;~  If $iRatio <= 4/3 Then ; then any height forced to 768 will always have width <= 1024
;~      If $iY > 768 Then
;~          $iY_resized = 768
;~      Else ; $iY < 768
;~          If $iY * 4/3 < 768 Then ; 4/3 = arbitrary 33pc, more would be too pixelized
;~              $iY_resized = $iY * 4/3
;~          Else
;~              $iY_resized = 768
;~          EndIf
;~      EndIf
;~      $iX_resized = $iX * $iY_resized / $iY

;~  Else ; > 4/3 then any width forced to 1024 will always have height < 768
;~      If $iX > 1024 Then
;~          $iX_resized = 1024
;~      Else ; $iX < 1024
;~          If $iX * 4/3 < 1024 Then ; 4/3 = arbitrary 33pc, more would be too pixelized
;~              $iX_resized = $iX * 4/3
;~          Else
;~              $iX_resized = 1024
;~          EndIf
;~      EndIf
;~      $iY_resized = $iY * $iX_resized / $iX
;~  EndIf

;~  Return True ; True will resize & save

EndFunc ; _Calc_New_Size()

; ====================================================
Func AdlibProgressBar() ; updated each second

    ; Update the progress value of the progress bar window
    ProgressSet($iNum_img / $aListe_img[0] * 100, $iNum_img & " / " & $aListe_img[0])

EndFunc ; AdlibProgressBar()

; ====================================================
Func AdlibStop() ; called before exiting the script

    AdlibUnRegister("AdlibProgressBar")
    ProgressOff()

EndFunc ; AdlibStop()

; ====================================================
Func _Exit($sError_title, $sError_msg, $iKeep_error, $iKeep_extended) ; bad error

    AdlibStop()
    MsgBox($MB_TOPMOST, "Error : " & $sError_title, _
        $sError_msg & @CRLF & @CRLF & _
        "@error = " & $iKeep_error & "    @extended = " & $iKeep_extended)
    _GDIPlus_ImageDispose($hImage)
    _GDIPlus_ImageDispose($hImage_Resized)
    _GDIPlus_Shutdown()
    Exit

EndFunc ; _Exit()

; ====================================================
Func _Wanna_Quit() ; user keys Esc while images are resizing

    HotKeySet("{ESC}")
    If MsgBox(BitOr($MB_TOPMOST, $MB_OKCANCEL, $MB_DEFBUTTON2), _
      "Esc was keyed", "Quit script ?") = $IDOK Then
        AdlibStop()
        _GDIPlus_ImageDispose($hImage)
        _GDIPlus_ImageDispose($hImage_Resized)
        _GDIPlus_Shutdown()
        Exit
    EndIf
    HotKeySet("{ESC}", "_Wanna_Quit")

EndFunc ; _Wanna_Quit()

; ====================================================
Func Select_img_folder() ; user wants to choose a whole folder

    Local $iRecursion = 0, $sRecursion_Msg = "" ; no recursion by default
    If $iHow_Choose_img = 2 Then  ; user choosed folder and all subfolders
        $iRecursion = 1
        $sRecursion_Msg = " (WITH recursion)"
    EndIf

    ; Create a variable in Local scope of the message to display in FileSelectFolder
    Local $sMessage = "Resize images - Choose folder to convert" & $sRecursion_Msg

    ; FileSelectFolder on top is great, so use @SW_SHOWDEFAULT in an invisible GUI
    Local $hGui = GUICreate("", 0, 0, 0, 0, Default, @SW_SHOWDEFAULT)

    ; Display an open dialog to select a folder : $sPath updated here or in Select_img()
    $sPath = FileSelectFolder( _
        $sMessage, _
        "", _
        2+4, _
        "", _
        $hGui)  ; On Top (because of last parameter $hGui)
                ; 2+4 : 2 = Use New Dialog Style and 4 = Show Edit Control (XP only)

    Local $iKeep_error = @error
    GUIDelete($hGui)

    If $iKeep_error <> 0 Then
        MsgBox(BitOr($MB_TOPMOST, $MB_ICONWARNING), "End of script", _
            "No folder selected   ") ; Cancel, Red X or Esc key in FileSelectFolder()
        Exit
    Else
        ; Display the selected chosen folder
        ; MsgBox($MB_TOPMOST, "", "You chose the following folder:" & @CRLF & $sPath)

        If StringRight($sPath, 1) <> "\" Then
            $sPath &= "\" ; "C:\" => "C:\"  "C:\Temp" => "C:\Temp\"
        EndIf

        Local $Path_and_Filter = "", $sTypeImageName, $sFilter

        For $i = 0 To $iMaxImageTypes - 1
            If $aContentCheckbox[$i][1] = 1 Then ; 1 = image type is checked
                $sTypeImageName = StringLower($aContentCheckbox[$i][0]) ; ex. "jpg"
                $sFilter = "*." & $sTypeImageName
                $Path_and_Filter &= chr(34) & $sPath & $sFilter & chr(34) & " "
                If $sTypeImageName = "jpg" Then
                    $Path_and_Filter &= chr(34) & $sPath & "*.jpeg" & chr(34) & " "
                EndIf
            EndIf
        Next
        $Path_and_Filter = StringTrimRight($Path_and_Filter, 1) ; remove last " "

        ; MsgBox($MB_TOPMOST, "$Path_and_Filter", $Path_and_Filter)

        $aListe_img = _FileListFromDir($Path_and_Filter, $iRecursion)
        ; when Recursion (1), all files names have full path included in array.
        ; if no Recursion (0 or no 2nd parameter) then no full path is included.

        Switch @error
            Case 0 ; all good
            Case 1
                Exit MsgBox($MB_TOPMOST, "_FileListFromDir", _
                    "error 1 : No files found")
            Case 2
                Exit MsgBox($MB_TOPMOST, "_FileListFromDir", _
                    "error 2 : Strange, no @CRLF at end !")
            Case Else
                Exit MsgBox($MB_TOPMOST, "_FileListFromDir", _
                    "unknown error = " & @error)
        EndSwitch

        ; Display the results returned by _FileListFromDir
        ; _ArrayDisplay($aListe_img, "Debug _FileListFromDir")

    EndIf

    ; @WorkingDir not changed by FileSelectFolder()

EndFunc ; Select_img_folder()

; ====================================================
Func _FileListFromDir($sMask, $iRecurse = 0) ; called by Select_img_folder()

    Local $sList = "", $sCommand = " /c dir /a-d /b /o "
    If $iRecurse = 1 Then $sCommand = " /c dir /a-d /b /o /s "

    Local $iPid = Run(@ComSpec & $sCommand & $sMask, $sPath, @SW_HIDE, $STDOUT_CHILD)

    ProcessWaitClose($iPid)
    Local $sList = StdoutRead($iPid)

    If $sList = "" Then Return SetError(1) ; no files found
    If StringRight($sList, 2) <> @CRLF Then Return SetError(2) ; shouldn't happen
    $sList = StringTrimRight($sList, 2) ; delete last @CRLF

    Local $aList = StringSplit($sList, @CRLF, 1)

    Switch @error
        Case 0 ; ok (at least 2 files found)
            ; _ArrayDisplay($aList, "0 => $aList")

        Case 1 ; no delimiters found in $sList during StringSplit => 1 file
            ; _ArrayDisplay($aList, "1 => $aList")

        Case Else
            Exit MsgBox($MB_TOPMOST, "StringSplit", "unknown error = " & @error)
    EndSwitch

    Return $aList

EndFunc  ; _FileListFromDir()

; ====================================================
Func Select_img() ; user wants to pick images individually

    Local $sTypeImageName, $sFilter = "Image files ("

    For $i = 0 To $iMaxImageTypes - 1
        If $aContentCheckbox[$i][1] = 1 Then ; 1 = image type is checked
            $sTypeImageName = StringLower($aContentCheckbox[$i][0]) ; ex. "jpg"
            $sFilter &= "*." & $sTypeImageName & ";"
            If $sTypeImageName = "jpg" Then $sFilter &= "*.jpeg;"
        EndIf
    Next
    $sFilter = StringTrimRight($sFilter, 1) & ")" ; remove last ";" then add ")"

    ; Create a variable in Local scope of the message to display in FileOpenDialog
    Local $sMessage = "Resize images - Select image file(s) individually"

    ; FileOpenDialog on top is great, so use @SW_SHOWDEFAULT in an invisible GUI
    Local $hGui = GUICreate("", 0, 0, 0, 0, Default, @SW_SHOWDEFAULT)

    ; Display an open dialog to select a list of file(s)
    Local $sFileOpenDialog = FileOpenDialog( _
        $sMessage, _
        @ScriptDir, _
        $sFilter, _
        BitOR($FD_FILEMUSTEXIST, $FD_PATHMUSTEXIST, $FD_MULTISELECT), _
        "", _
        $hGui) ; On Top (because of last parameter $hGui)

    Local $iKeep_error = @error
    GUIDelete($hGui)

    If $iKeep_error <> 0 Then
        MsgBox(BitOr($MB_TOPMOST, $MB_ICONWARNING), "End of script", _
            "No file(s) selected   ") ; Cancel, Red X or Esc key in FileOpenDialog()
        Exit
    Else
        $aListe_img = StringSplit($sFileOpenDialog, "|")
        ; _ArrayDisplay($aListe_img, "1") ; for debug

        ; $sPath updated here or in Select_img_folder()
        Switch $aListe_img[0]
            Case 0, 2
                MsgBox(BitOr($MB_TOPMOST, $MB_ICONERROR), "End of script", _
                    "Impossible value of $aListe_img[0] = " & $aListe_img[0] & "   ")
                Exit

            Case 1 ; 1 selected image
                Local $iPos_AntiSlash = StringInStr($aListe_img[1], "\", 0, -1)
                If $iPos_AntiSlash = 0 Then
                    MsgBox(BitOr($MB_TOPMOST, $MB_ICONERROR), "End of script", _
                        "No antislash (\) found in " & $aListe_img[1] & "   ") ; impossible !
                    Exit
                Else
                    $sPath = StringLeft($aListe_img[1], $iPos_AntiSlash)
                    $aListe_img[1] = StringMid($aListe_img[1], $iPos_AntiSlash + 1)
                EndIf

            Case Else ; 3+ when at least 2 images have been selected
                $sPath = $aListe_img[1] & ((StringRight($aListe_img[1], 1) = "\") ? ("") : ("\"))
                ; "C:\" => "C:\"  "C:\Temp" => "C:\Temp\"

                _ArrayDelete($aListe_img, 1)
                $aListe_img[0] -= 1
                ; _ArrayDisplay($aListe_img, "2") ; for debug

                _ArraySort($aListe_img, 0, 1) ; 0 = ascending sort, 1 = start from 1st element
                ; _ArrayDisplay($aListe_img, "2a") ; for debug
        EndSwitch

    EndIf

   ; change the working directory (@WorkingDir) back to the location of the script directory
   ; as FileOpenDialog sets it to the last accessed folder.
   FileChangeDir(@ScriptDir)

EndFunc ; Select_img()

; ====================================================
Func F10() ; create and displays the GUI for user to choose 3 kind of options

    Local $hGUI = GUICreate("Resize image files", 400, 274, -1, -1, _
        BitOR($WS_CAPTION, $WS_POPUP, $WS_SYSMENU), @SW_SHOWDEFAULT)

    GUICtrlCreateGroup(" How to select image files ? ", 13, 8, 193, 97)
    $idRadio_1 = GUICtrlCreateRadio("Choose a folder", 29, 33, 153, 17)
    GUICtrlSetState(-1, $GUI_CHECKED)
    $idRadio_2 = GUICtrlCreateRadio("Choose a folder + all subfolders", 28, 58, 169, 17)
    $idRadio_3 = GUICtrlCreateRadio("Pick them individually", 29, 83, 169, 17)
    GUICtrlCreateGroup("", -99, -99, 1, 1)

    GUICtrlCreateGroup(" How to save resized files ? ", 12, 136, 193, 81)
    $idRadio_11 = GUICtrlCreateRadio("New names (ex ..._resized.jpg)", 28, 161, 169, 17)
    GUICtrlSetState(-1, $GUI_CHECKED)
    $idRadio_12 = GUICtrlCreateRadio("Overwrite", 28, 186, 161, 17)
    GUICtrlCreateGroup("", -99, -99, 1, 1)

    GUICtrlCreateGroup(" Which image types ? ", 224, 8, 161, 209)
    ; comment out Checkbox id's lines generated by Koda as we'll use an array instead
;~  $idCheckbox_jpg = GUICtrlCreateCheckbox("JPG", 240, 32, 97, 17)
;~  GUICtrlSetState(-1, $GUI_CHECKED)
;~  $idCheckbox_png = GUICtrlCreateCheckbox("PNG", 240, 54, 97, 17)
;~  GUICtrlSetState(-1, $GUI_CHECKED)
;~  $idCheckbox_bmp = GUICtrlCreateCheckbox("BMP", 240, 76, 97, 17)
;~  GUICtrlSetState(-1, $GUI_CHECKED)
;~  $idCheckbox_gif = GUICtrlCreateCheckbox("GIF", 240, 99, 97, 17)
;~  $idCheckbox_tiff = GUICtrlCreateCheckbox("TIFF", 240, 121, 97, 17)
;~  $idCheckbox_exif = GUICtrlCreateCheckbox("EXIF", 240, 143, 97, 17)
;~  $idCheckbox_wmf = GUICtrlCreateCheckbox("WMF", 240, 166, 97, 17)
;~  $idCheckbox_emf = GUICtrlCreateCheckbox("EMF", 240, 188, 97, 17)

    Local $iRow = 10 ; to be incremented in For loop, Koda's coordinates
    For $i = 0 To $iMaxImageTypes - 1
        $iRow += 22
        $idCheckbox[$i] = GUICtrlCreateCheckbox($aContentCheckbox[$i][0], 240, $iRow, 97, 17)
        If $aContentCheckbox[$i][1] = 1 Then GUICtrlSetState(-1, $GUI_CHECKED)
        $aContentCheckbox[$i][2] = $idCheckbox[$i] ; keep id's in Checkbox's array
    Next
    GUICtrlCreateGroup("", -99, -99, 1, 1)

    $idButton_OK = GUICtrlCreateButton("OK", 123, 235, 75, 25, $BS_DEFPUSHBUTTON)
    $idButton_Cancel = GUICtrlCreateButton("Cancel", 228, 235, 75, 25)

    GUISetState(@SW_SHOW)

    While 1
        Switch GUIGetMsg()
            Case $GUI_EVENT_CLOSE, $idButton_Cancel ; or Esc
                GUIDelete($hGui)
                MsgBox(BitOr($MB_TOPMOST, $MB_ICONWARNING), "End of script", _
                    "You choosed to Cancel   ")
                Exit
            Case $idRadio_1
                $iHow_Choose_img = 1 ; a whole folder (no recursion) using FileSelectFolder()
            Case $idRadio_2
                $iHow_Choose_img = 2 ; a whole folder + subfolders, using  FileSelectFolder()
            Case $idRadio_3
                $iHow_Choose_img = 3 ; pick files individually, using FileOpenDialog()
            Case $idRadio_11
                $iNewname_or_Overwrite = 1 ; New files names (add _resized at the end)
            Case $idRadio_12
                $iNewname_or_Overwrite = 2 ; Overwrite

            Case $idCheckbox[0] To $idCheckbox[$iMaxImageTypes - 1]
                Local $idFocus = _WinAPI_GetDlgCtrlID(_WinAPI_GetFocus()) ; handle => id
                Local $iIndex = _ArrayBinarySearch($aContentCheckbox, $idFocus, 0, 0, 2)
                If @error Then Exit MsgBox($MB_TOPMOST, "_ArrayBinarySearch", _
                    "impossible error = " &  @error)
                $aContentCheckbox[$iIndex][1] = _
                    ((GUICtrlRead($idFocus) = $GUI_CHECKED) ? (1) : (0))
                ; _ArrayDisplay($aContentCheckbox, "Debug", "", 0, Default, _
                ;   "Image type|Checked|Id")

            Case $idButton_OK
                For $i = 0 To $iMaxImageTypes - 1
                    If $aContentCheckbox[$i][1] = 1 Then ; at least 1 image type checked
                        GUIDelete($hGui)
                        Return
                    EndIf
                Next
                MsgBox(BitOr($MB_TOPMOST, $MB_ICONWARNING), "Which image types ?", _
                    "You need to check at least 1 of them   ")
        EndSwitch
    WEnd

EndFunc ; F10()

; https://www.autoitscript.com/forum/topic/199830-resizing-images-script/

August 6, 2019
* User is now asked what to do when read-only images are found.
* Add a warning display when the Overwrite option is ticked :

resize image files 2.png

August 7, 2019
* Added SplashImageOn to show the read-only image in case the user is gonna overwrite it. Works for jpg, bmp and gif (no png)
* Filenames ending with ..._resized.(ext) won't be treated again, in case the user runs the script a 2nd time choosing the same folder.

August 9, 2019
* Added a final summary showing the details of what has been processed :

332970205_Resizesummary.png.ce036da8fdc87dd47916f9db8a8a6e10.png

 

Edited by pixelsearch
Details of what changed (with date) just above
Link to comment
Share on other sites

  • 10 months later...

Hello ,@pixelsearch

Thanks for the script, it's very useful and very well developed.

I was looking for something like your script. I have tried to do it by myself and i found a mistake that neither your script solves. In my case, there are images manualy rotated by users in win10, but when those are resized, them are rotated to the original orientation.

I have tried to check image orientation in EXIF properties but some of them don´t have any.

Have it been also a problem to you?

Link to comment
Share on other sites

  • 2 weeks later...

Hello PixelSearch,

Thank's for your script ! I like it.

To overwrite original files, I tried to use in my own script :

_GDIPlus_ImageDispose($oImageObject)     ; place it here, needed if file will be overwritten

It works but, If I use it with many files (> 100), Autoit stops working without prompt.

An idea ?

 

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...