darkDrakee Posted July 15, 2018 Share Posted July 15, 2018 (edited) Hello guys, I am relatively new to AutoIt. I want to practise and always think of programs I can use for myself in my everyday life. So currently, I am working on a script that lets you sort a collection of photos. It is supposed to seperate the pictures within a folder you have selected via the FileSelectFolder() Function into a subfolder of pictures you want to keep and a subfolder of pictures you do not want to keep. Maybe you decide otherwise later. That is why they should not be deleted instantly. I needed to use GDI Plus to keep the aspect ratio of every picture while making it fit into a defined area of the GUI. Also I needed to use the _FileListToArray() script below, because the program should only put files into the array which are image files (.jpg, .jpeg, .png, .gif and .bmp, which are the most common formats). The script is the least work intensive method of doing that. Everything is working to my liking, except for the fact that I am unable to move Files instead of just copying them. I have tried disposing the image, the graphics and even closing the file, all at once, even shutting down GDI Plus before attempting to move. Nope, simply does not work. I have looked into so many other threads now, but my problem seems to be a bit more specific. I am sure it has something to do with GDI Plus using the picture, which is because it is not possible to move or delete the file. But, I am not able to find out how I can fix that. So, here is my script: expandcollapse popup;~ #RequireAdmin ;thought this would be needed for moving files, maybe, but nah, it's not #NoTrayIcon #include <ColorConstantS.au3> #include <GUIConstantsEx.au3> #include <GDIPlus.au3> #include <_FileListToArrayEx.au3> #include <Array.au3> $inputFolder = FileSelectFolder("Open Input Folder", "\input"); ;Create the GUI $hGui = GUICreate("Quick Photo Sorter", 1200, 910) GUISetBkColor($COLOR_GRAY) $butOk = GUICtrlCreateButton("Favourite", 5, 875, 327, 30) $butPrev = GUICtrlCreateButton("<<", 337, 875, 163, 30) $butRel = GUICtrlCreateButton("Reload", 505, 875, 192, 30) ;reload button needed, because image is not being refreshed by itself $butNext = GUICtrlCreateButton(">>", 702, 875, 163, 30) $butNah = GUICtrlCreateButton("Sort out", 868, 875, 327, 30) $imgField_size_x = 1180 $imgField_size_y = 850 Local $labelNo, $pic, $height, $width, $ratio GUISetState(@SW_SHOW, $hGui) $arr = _FileListToArrayEx($inputFolder, '*.jpg;*.jpeg;*.png;*.gif;*.bmp', 1) ;TODO: figure out how to exclude subfolders While UBound($arr) = 0 ;check if selected folder contains photo files, if not, let the user retry (or abort) $getmsg = MsgBox(1, "No Photos", "The folder you have selected contains no image files.") Switch $getmsg Case 1 $inputFolder = FileSelectFolder("Open Input Folder", "\input"); $arr = _FileListToArrayEx($inputFolder, '*.jpg;*.jpeg;*.png;*.gif;*.bmp',1) Case 2 Exit EndSwitch WEnd ;~ _ArrayDisplay($arr, "$aFileList") ;debugging purpose $iterator = 1 _GDIPlus_Startup() $graphics = _GDIPlus_GraphicsCreateFromHWND($hgui) displayImage() While 1 $msg = GUIGetMsg() Switch $msg Case $GUI_EVENT_CLOSE Exit Case $butOk keep() nextImage() Case $butNah sort_out() nextImage() Case $butNext nextImage() Case $butPrev prevImage() Case $butRel _GDIPlus_ImageDispose($pic) displayImage() EndSwitch WEnd Func nextImage() ;shows the next image without removing the current one from the array GUICtrlDelete($labelNo) GUISetBkColor($COLOR_GRAY) _GDIPlus_ImageDispose($pic) increaseIterator() displayImage() EndFunc Func prevImage();shows the previous image without removing the current one from the array GUICtrlDelete($labelNo) GUISetBkColor($COLOR_GRAY) _GDIPlus_ImageDispose($pic) decreaseIterator() displayImage() EndFunc Func getFileName() $Str = StringSplit($arr[$iterator], "\") return $Str[UBound($Str)-1] EndFunc Func keep() ;copies the picture to keep into the subfolder "_keep" (wanted: move the picture, but does not work) ;~ FileMove($arr[$iterator], "\_Favourites\" & getFileName(), 9) ;Why doesn't this work? FileCopy($arr[$iterator], $inputFolder & "\_Favourites\", $FC_OVERWRITE + $FC_CREATEPATH) removeImageFromArray() EndFunc Func sort_out() ;simply skips the current picture, but removes it from the array (wanted: move the picture to a folder called "unwanted" or sth like this, but does not work) removeImageFromArray() EndFunc Func removeImageFromArray() ;removes the image from the array and adjusts the iterator If NOT (checkArrayEnd()) Then _ArrayDelete($arr, $iterator) $iterator = $iterator - 1 Else MsgBox(1,"Work is done","You have finished sorting your collection, so there is nothing more to display.") EndIf EndFunc Func displayImage() ;display the image fittingly into the gui ;read height and width and calculate the ascpet ratio ;~ $pic = _GDIPlus_ImageLoadFromFile($inputFolder & $arr[$iterator]) ;use this with standard FileListToArrayFunction $pic = _GDIPlus_ImageLoadFromFile($arr[$iterator]) $height = _GDIPlus_ImageGetHeight($pic) $width = _GDIPlus_ImageGetWidth($pic) $ratio = $width/$height ;~ $labelx = GUICtrlCreateLabel("X: " & $width, 0, 0) ;~ $labely = GUICtrlCreateLabel("Y: " & $height, 50, 0) ;~ $labelRatio = GUICtrlCreateLabel("R: " & $ratio, 100, 0) $labelNo = GUICtrlCreateLabel("File: " & $iterator & "/" & (Ubound($arr)-1) & " File name: " & $arr[$iterator], 0, 0) ;resize if $width > $height Then $width = $imgField_size_x $height = $width/$ratio ElseIf $height > $width OR $height = $width Then $height = $imgField_size_y $width = $height*$ratio EndIf ;after resize check if the boundaries are exeeded and resize again if $width > $imgField_size_x Then $width = $imgField_size_x $height = $width/$ratio ElseIf $height > $imgField_size_y Then $height = $imgField_size_y $width = $height*$ratio EndIf $pic = _GDIPlus_ImageResize ($pic, $width, $height) ;now calculate the center position $posX = 10 + ($imgField_size_x/2) - ($width/2) $posY = 20 + ($imgField_size_y/2) - ($height/2) ;display the picture _GDIPlus_GraphicsDrawImage($graphics, $pic, $posX, $posY) EndFunc Func increaseIterator() ;for displaying the next picture if NOT (checkArrayEnd()) Then If $iterator < Ubound($arr) - 1 Then $iterator = $iterator + 1 Else $iterator = 1 EndIf EndIf EndFunc Func decreaseIterator() ;for displaying the previous picture if NOT (checkArrayEnd()) Then If $iterator > 1 Then $iterator = $iterator - 1 Else $iterator = Ubound($arr) - 1 EndIf EndIf EndFunc Func checkArrayEnd() ;preventing crashes, because the array gets empty after skipping all pictures If (UBound($arr)-1) = 0 Then Return true Else Return False EndIf EndFunc QuickPhotoSorter.au3 Edited July 16, 2018 by darkDrakee Link to comment Share on other sites More sharing options...
rudi Posted July 15, 2018 Share Posted July 15, 2018 Hello, without having done any tests I could imagine, that the files are kept opened, so that you cannot move them. So you could give it a try to copy your images to a temporary location to open them with your gui. By that the originals will remain closed and it should be possible to move them. The tempory copies of your images can be deleted later on. Regards, Rudi. Earth is flat, pigs can fly, and Nuclear Power is SAFE! Link to comment Share on other sites More sharing options...
AutoBert Posted July 15, 2018 Share Posted July 15, 2018 with $arr = _FileListToArrayRec($inputFolder, "*.jpg;*.jpeg;*.png;*.gif;*.bmp||", $FLTAR_FILES, $FLTAR_RECUR, $FLTAR_NOSORT, $FLTAR_FULLPATH) there is no need for _FileListToArrayEx(). Link to comment Share on other sites More sharing options...
darkDrakee Posted July 16, 2018 Author Share Posted July 16, 2018 (edited) @AutoBert Thanks! @Rudi Yes, the file is kept opened. When I try to move the files manually within Windows Exporer it will say that the file is being used by AutoItv3.exe, but only, if the file has been opened by GDI Plus. So, normally _GDIPlus_ImageDispose($pic) should close the file, but it does not. EDIT: Creating copies from the source files as temporary files is not a solution at all, because that causes more problems than just directly loading the source pictures. It makes displaying the pictures very buggy and also, the temporary files cannot be deleted. Edited July 16, 2018 by darkDrakee Link to comment Share on other sites More sharing options...
darkDrakee Posted July 22, 2018 Author Share Posted July 22, 2018 I have found the error. Seems like this line $pic= _GDIPlus_ImageResize ($pic, $width, $height) makes it impossible for GDIPlus to close the file loaded into $pic, as it creates a new object handle, so the other one remains in memory, but is not disposable anymore, because the pointer has changed. So I needed to make a new pointer: $resized = _GDIPlus_ImageResize ($pic, $width, $height) _GDIPlus_ImageDispose($pic) _GDIPlus_GraphicsDrawImage($graphics, $resized, $posX, $posY) _GDIPlus_ImageDispose($resized) So the file is being closed now upon using _GDIPlus_ImageDispose() Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now