Lights_On Posted September 24, 2019 Share Posted September 24, 2019 (edited) Hi, I have a GUI that is able to resize. The GUI contains an Image. The image is refreshed at set intervals. My issue is image quality. I am using a .gif and the quality of the image displayed is not as good as if I open the image separately. I read it can be improved using GDI but not sure how to implement this even after some testing as I need resizing capabilities. I am happy to not use GDI if there are better ways to increase image quality. Below is a test script that can be used to replicate the issue. #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include <ScreenCapture.au3> Local $TESTQuality = GUICreate("TESTQuality", 1000, 590, -1, -1, BitOR($WS_SIZEBOX, $WS_MAXIMIZEBOX, $WS_MINIMIZEBOX)) _ScreenCapture_Capture(@DesktopDir & "\atestpic.jpg") Local $ImagePath = @DesktopDir & "\atestpic.jpg" Local $Image1 = GUICtrlCreatePic($ImagePath, 10, 30, 990, 580) GUICtrlSetResizing($Image1, $GUI_DOCKVCENTER) Local $time = TimerInit() GUISetState(@SW_SHOW) While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop EndSwitch ; Refresh the image If TimerDiff($time) > 500 Then GUICtrlSetImage($Image1, $ImagePath) Local $time = TimerInit() EndIf WEnd GUIDelete($TESTQuality) Any help appreciated. Edited September 24, 2019 by Lights_On Link to comment Share on other sites More sharing options...
UEZ Posted September 25, 2019 Share Posted September 25, 2019 Try something like this here; expandcollapse popup#include <Constants.au3> #include <GDIPlus.au3> #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> Global Const $STM_SETIMAGE = 0x0172 Global $sPathKey = "HKLM64\SOFTWARE\AutoIt v3\AutoIt\" If @OSArch = "x64" Then $sPathKey = "HKLM\SOFTWARE\Wow6432Node\AutoIt v3\AutoIt\" Global $sImage = RegRead($sPathKey, "InstallDir") & "\Examples\GUI\logo4.gif" _GDIPlus_Startup() Global $hBmp = _GDIPlus_BitmapCreateFromFile($sImage) Global $iW = _GDIPlus_ImageGetWidth($hBmp), $iH = _GDIPlus_ImageGetHeight($hBmp) Global $hGUI = GUICreate("Test", 235, 112, -1, -1, BitOR($GUI_SS_DEFAULT_GUI, $WS_SIZEBOX, $WS_THICKFRAME), $WS_EX_COMPOSITED) Global $idPic = GUICtrlCreatePic("", 32, 16, $iW, $iH) GUICtrlSetResizing(-1, $GUI_DOCKVCENTER + $GUI_DOCKHCENTER) Global $hHBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBmp) Global $hB = GUICtrlSendMsg($idPic, $STM_SETIMAGE, $IMAGE_BITMAP, $hHBitmap) If $hB Then _WinAPI_DeleteObject($hB) GUISetState(@SW_SHOW) GUIRegisterMsg($WM_SIZE, "WM_SIZE") While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE GUIRegisterMsg($WM_SIZE, "") _WinAPI_DeleteObject($hHBitmap) _GDIPlus_BitmapDispose($hBmp) _GDIPlus_Shutdown() GUIDelete() Exit EndSwitch WEnd Func WM_SIZE($hWnd, $Msg, $wParam, $lParam) #forceref $Msg, $wParam, $lParam Local $aSize = ControlGetPos($hWnd, "", $idPic) Local $hBitmap = _GDIPlus_BitmapCreateFromScan0($aSize[2], $aSize[3]) Local $hContext = _GDIPlus_ImageGetGraphicsContext($hBitmap) _GDIPlus_GraphicsSetInterpolationMode($hContext, 5) _GDIPlus_GraphicsDrawImageRect($hContext, $hBmp, 0, 0, $aSize[2], $aSize[3]) _GDIPlus_GraphicsDispose($hContext) Local $hHBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBitmap) Local $hB = GUICtrlSendMsg($idPic, $STM_SETIMAGE, $IMAGE_BITMAP, $hHBitmap) If $hB Then _WinAPI_DeleteObject($hB) _WinAPI_DeleteObject($hHBitmap) _GDIPlus_BitmapDispose($hBitmap) Return "GUI_RUNDEFMSG" EndFunc Please don't send me any personal message and ask for support! I will not reply! Selection of finest graphical examples at Codepen.io The own fart smells best! ✌Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!¯\_(ツ)_/¯ ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ Link to comment Share on other sites More sharing options...
Lights_On Posted September 25, 2019 Author Share Posted September 25, 2019 (edited) Hi UEZ, Thank you for taking the time to help me. I have had a play with your code to understand it better and as part of doing this made some changes so it was more familiar to my example. My code (yours amended) is below: expandcollapse popup#include <Constants.au3> #include <GDIPlus.au3> #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include <ScreenCapture.au3> Global Const $STM_SETIMAGE = 0x0172 ;Global $sPathKey = "HKLM64\SOFTWARE\AutoIt v3\AutoIt\" ;If @OSArch = "x64" Then $sPathKey = "HKLM\SOFTWARE\Wow6432Node\AutoIt v3\AutoIt\" ;Global $sImage = RegRead($sPathKey, "InstallDir") & "\Examples\GUI\logo4.gif" _ScreenCapture_Capture(@DesktopDir & "\atestpic.gif") Global $sImage = @DesktopDir & "\atestpic.gif" _GDIPlus_Startup() Global $hBmp = _GDIPlus_BitmapCreateFromFile($sImage) Global $iW = _GDIPlus_ImageGetWidth($hBmp), $iH = _GDIPlus_ImageGetHeight($hBmp) ;Global $hGUI = GUICreate("Test", 235, 112, -1, -1, BitOR($GUI_SS_DEFAULT_GUI, $WS_SIZEBOX, $WS_THICKFRAME), $WS_EX_COMPOSITED) Global $hGUI = GUICreate("Test", 1000, 590, -1, -1, BitOR($WS_SIZEBOX, $WS_MAXIMIZEBOX, $WS_MINIMIZEBOX)) ;Global $idPic = GUICtrlCreatePic("", 32, 16, $iW, $iH) Global $idPic = GUICtrlCreatePic("", 10, 30, $iW, $iH) GUICtrlSetResizing(-1, $GUI_DOCKVCENTER + $GUI_DOCKHCENTER) Global $hHBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBmp) Global $hB = GUICtrlSendMsg($idPic, $STM_SETIMAGE, $IMAGE_BITMAP, $hHBitmap) If $hB Then _WinAPI_DeleteObject($hB) Local $time = TimerInit() GUISetState(@SW_SHOW) GUIRegisterMsg($WM_SIZE, "WM_SIZE") While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE GUIRegisterMsg($WM_SIZE, "") _WinAPI_DeleteObject($hHBitmap) _GDIPlus_BitmapDispose($hBmp) _GDIPlus_Shutdown() GUIDelete() Exit EndSwitch ; Refresh the image If TimerDiff($time) > 500 Then GUICtrlSetImage($idPic, $sImage) Local $time = TimerInit() EndIf WEnd Func WM_SIZE($hWnd, $Msg, $wParam, $lParam) #forceref $Msg, $wParam, $lParam Local $aSize = ControlGetPos($hWnd, "", $idPic) Local $hBitmap = _GDIPlus_BitmapCreateFromScan0($aSize[2], $aSize[3]) Local $hContext = _GDIPlus_ImageGetGraphicsContext($hBitmap) _GDIPlus_GraphicsSetInterpolationMode($hContext, 5) _GDIPlus_GraphicsDrawImageRect($hContext, $hBmp, 0, 0, $aSize[2], $aSize[3]) _GDIPlus_GraphicsDispose($hContext) Local $hHBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBitmap) Local $hB = GUICtrlSendMsg($idPic, $STM_SETIMAGE, $IMAGE_BITMAP, $hHBitmap) If $hB Then _WinAPI_DeleteObject($hB) _WinAPI_DeleteObject($hHBitmap) _GDIPlus_BitmapDispose($hBitmap) Return "GUI_RUNDEFMSG" EndFunc Sadly however the quality, if comparing like for like, is in fact worse? So it would seem, and happy to be wrong, that for my example the GDI option is perhaps not he best way to go? To test if you run both scripts on the same image, or at least same capture, then it is easy to see the different in picture quality when resizing the window. Could it just be that the image needs to be a certain format for best res. or am I just not working with images correctly generally? Thank you again. Edited September 25, 2019 by Lights_On Link to comment Share on other sites More sharing options...
UEZ Posted September 25, 2019 Share Posted September 25, 2019 You have to change the value in line 61 -> _GDIPlus_GraphicsSetInterpolationMode(), e.g. to _GDIPlus_GraphicsSetInterpolationMode($hGraphics, $GDIP_INTERPOLATIONMODE_BILINEAR) But this will slow down the resizing! Please don't send me any personal message and ask for support! I will not reply! Selection of finest graphical examples at Codepen.io The own fart smells best! ✌Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!¯\_(ツ)_/¯ ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ Link to comment Share on other sites More sharing options...
Lights_On Posted September 25, 2019 Author Share Posted September 25, 2019 Thank you. Yes this has helped and it now is an improvement - it is still a little "granular" on colours but is better and now usable. I am now seeking to simply things so as to get the bare bones of what i need. I got rid of: ;Global $hBmp = _GDIPlus_BitmapCreateFromFile($sImage) ;Global $iW = _GDIPlus_ImageGetWidth($hBmp), $iH = _GDIPlus_ImageGetHeight($hBmp) and set size manual - this seemed to make no difference and on reading the help file i think i can do my way as below ;Global $idPic = GUICtrlCreatePic("", 32, 16, $iW, $iH) Global $idPic = GUICtrlCreatePic("", 10, 30, 990, 580) Please let me know if I am wrong and must not do this. Link to comment Share on other sites More sharing options...
UEZ Posted September 25, 2019 Share Posted September 25, 2019 Sure, you can do it that way if you know the image dimension. Please don't send me any personal message and ask for support! I will not reply! Selection of finest graphical examples at Codepen.io The own fart smells best! ✌Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!¯\_(ツ)_/¯ ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ Link to comment Share on other sites More sharing options...
Lights_On Posted November 6, 2019 Author Share Posted November 6, 2019 Hi, Sorry for the delay - I have only just been able to come back to this. I am sadly still struggling. The below is the latest code I have and if you resize the window from how it opens, to small, to full screen again the quality of the image just degrades and degrades: expandcollapse popup#include <Constants.au3> #include <GDIPlus.au3> #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include <ScreenCapture.au3> Global Const $STM_SETIMAGE = 0x0172 _ScreenCapture_Capture(@DesktopDir & "\atestpic.jpg") Global $sImage = @DesktopDir & "\atestpic.jpg" _GDIPlus_Startup() Global $hBmp = _GDIPlus_BitmapCreateFromFile($sImage) Global $hGUI = GUICreate("Test", 1000, 590, -1, -1, BitOR($WS_SIZEBOX, $WS_MAXIMIZEBOX, $WS_MINIMIZEBOX)) Global $idPic = GUICtrlCreatePic("", 10, 30, 990, 580) GUICtrlSetResizing(-1, $GUI_DOCKVCENTER + $GUI_DOCKHCENTER) Global $hHBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBmp) Global $hB = GUICtrlSendMsg($idPic, $STM_SETIMAGE, $IMAGE_BITMAP, $hHBitmap) If $hB Then _WinAPI_DeleteObject($hB) Local $time = TimerInit() GUISetState(@SW_SHOW) GUIRegisterMsg($WM_SIZE, "WM_SIZE") While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE GUIRegisterMsg($WM_SIZE, "") _WinAPI_DeleteObject($hHBitmap) _GDIPlus_BitmapDispose($hBmp) _GDIPlus_Shutdown() GUIDelete() Exit EndSwitch ; Refresh the image If TimerDiff($time) > 500 Then GUICtrlSetImage($idPic, $sImage) Local $time = TimerInit() EndIf WEnd Func WM_SIZE($hWnd, $Msg, $wParam, $lParam) #forceref $Msg, $wParam, $lParam Local $aSize = ControlGetPos($hWnd, "", $idPic) Local $hBitmap = _GDIPlus_BitmapCreateFromScan0($aSize[2], $aSize[3]) Local $hContext = _GDIPlus_ImageGetGraphicsContext($hBitmap) ;_GDIPlus_GraphicsSetInterpolationMode($hContext, 5) _GDIPlus_GraphicsSetInterpolationMode($hContext, 2) _GDIPlus_GraphicsDrawImageRect($hContext, $hBmp, 0, 0, $aSize[2], $aSize[3]) _GDIPlus_GraphicsDispose($hContext) Local $hHBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBitmap) Local $hB = GUICtrlSendMsg($idPic, $STM_SETIMAGE, $IMAGE_BITMAP, $hHBitmap) If $hB Then _WinAPI_DeleteObject($hB) _WinAPI_DeleteObject($hHBitmap) _GDIPlus_BitmapDispose($hBitmap) Return "GUI_RUNDEFMSG" EndFunc This all seems a lot of code just to refresh an image ensuring the image is the best quality it can be. Is there not a simpler way? or way to really get great quality of an image in a GUI? Thank you in advance. Link to comment Share on other sites More sharing options...
Lights_On Posted November 6, 2019 Author Share Posted November 6, 2019 Hi all, Further hours spent and this is my latest code (not much change): expandcollapse popup#include <Constants.au3> #include <GDIPlus.au3> #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include <ScreenCapture.au3> ; Create the GUI Global $hGUI = GUICreate("Test", 1000, 590, -1, -1, BitOR($WS_SIZEBOX, $WS_MAXIMIZEBOX, $WS_MINIMIZEBOX)) Global $idPic = GUICtrlCreatePic("", 10, 30, 320, 220) GUICtrlSetResizing($idPic, $GUI_DOCKVCENTER) ; Sart GDI+ _GDIPlus_Startup() Global Const $STM_SETIMAGE = 0x0172 _ScreenCapture_Capture(@DesktopDir & "\atestpic.jpg") Global $sImage = @DesktopDir & "\atestpic.jpg" Global $hBmp = _GDIPlus_BitmapCreateFromFile($sImage) Global $hHBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBmp) Global $hB = GUICtrlSendMsg($idPic, $STM_SETIMAGE, $IMAGE_BITMAP, $hHBitmap) ; The bit that ensures corect size? GUIRegisterMsg($WM_SIZE, "WM_SIZE") Local $time = TimerInit() GUISetState(@SW_SHOW) While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE GUIRegisterMsg($WM_SIZE, "") _WinAPI_DeleteObject($hHBitmap) _GDIPlus_BitmapDispose($hBmp) _GDIPlus_Shutdown() GUIDelete() Exit EndSwitch ; Refresh the image If TimerDiff($time) > 5000 Then _GDIPlus_BitmapDispose($hBmp) _ScreenCapture_Capture(@DesktopDir & "\atestpic.jpg") Global $sImage = @DesktopDir & "\atestpic.jpg" Global $hBmp = _GDIPlus_BitmapCreateFromFile($sImage) Global $hHBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBmp) Global $hB = GUICtrlSendMsg($idPic, $STM_SETIMAGE, $IMAGE_BITMAP, $hHBitmap) If $hB Then _WinAPI_DeleteObject($hB) ; The bit that ensures corect size? GUIRegisterMsg($WM_SIZE, "WM_SIZE") Local $time = TimerInit() EndIf WEnd Func WM_SIZE($hWnd, $Msg, $wParam, $lParam) #forceref $Msg, $wParam, $lParam Local $aSize = ControlGetPos($hWnd, "", $idPic) Local $hBitmap = _GDIPlus_BitmapCreateFromScan0($aSize[2], $aSize[3]) Local $hContext = _GDIPlus_ImageGetGraphicsContext($hBitmap) ;_GDIPlus_GraphicsSetInterpolationMode($hContext, 5) _GDIPlus_GraphicsSetInterpolationMode($hContext, 2) _GDIPlus_GraphicsDrawImageRect($hContext, $hBmp, 0, 0, $aSize[2], $aSize[3]) _GDIPlus_GraphicsDispose($hContext) Local $hHBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBitmap) Local $hB = GUICtrlSendMsg($idPic, $STM_SETIMAGE, $IMAGE_BITMAP, $hHBitmap) If $hB Then _WinAPI_DeleteObject($hB) _WinAPI_DeleteObject($hHBitmap) _GDIPlus_BitmapDispose($hBitmap) Return "GUI_RUNDEFMSG" EndFunc The issues i'm facing are: The image size does not get set to what it is set to in the scrip at the top (10, 30, 320, 220)? Instead it fills the GUI. The image should refresh every 5 seconds with a new image - but it does not, I thought disposing of the prior image would work but it has not? When the image refreshes every 5 seconds it does not remain the same size? the image is enlarged and a smaller area of the whole image is seen. 🤯. ...really trying here but seem to be going in circles Link to comment Share on other sites More sharing options...
Lights_On Posted November 6, 2019 Author Share Posted November 6, 2019 (edited) Small progress in putting: GUIRegisterMsg($WM_SIZE, "WM_SIZE") underneath: GUISetState(@SW_SHOW) Before I had moved it above. Now this is done i get the correct size image on first run and also when resizing, it is now just the refreshing of the image that is not working, in that it keeps the same image and also changes size. Edit: Image is changing, it is just not the correct size. Edited November 6, 2019 by Lights_On Link to comment Share on other sites More sharing options...
Lights_On Posted November 6, 2019 Author Share Posted November 6, 2019 I think i managed it, it seems to now do what i need: expandcollapse popup#include <Constants.au3> #include <GDIPlus.au3> #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include <ScreenCapture.au3> ; Create the GUI Global $hGUI = GUICreate("Test", 1000, 590, -1, -1, BitOR($WS_SIZEBOX, $WS_MAXIMIZEBOX, $WS_MINIMIZEBOX)) Global $idPic = GUICtrlCreatePic("", 10, 30, 320, 220) GUICtrlSetResizing($idPic, $GUI_DOCKVCENTER) ; Sart GDI+ _GDIPlus_Startup() Global Const $STM_SETIMAGE = 0x0172 _ScreenCapture_Capture(@DesktopDir & "\atestpic.jpg") Global $sImage = @DesktopDir & "\atestpic.jpg" Global $hBmp = _GDIPlus_BitmapCreateFromFile($sImage) Global $hHBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBmp) Global $hB = GUICtrlSendMsg($idPic, $STM_SETIMAGE, $IMAGE_BITMAP, $hHBitmap) Local $time = TimerInit() GUISetState(@SW_SHOW) ReSize() While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE GUIRegisterMsg($WM_SIZE, "") _WinAPI_DeleteObject($hHBitmap) _GDIPlus_BitmapDispose($hBmp) _GDIPlus_Shutdown() GUIDelete() Exit Case $GUI_EVENT_RESIZED, $GUI_EVENT_MAXIMIZE, $GUI_EVENT_RESTORE ReSize() EndSwitch ; Refresh the image If TimerDiff($time) > 5000 Then _GDIPlus_BitmapDispose($hBmp) _ScreenCapture_Capture(@DesktopDir & "\atestpic.jpg") Global $sImage = @DesktopDir & "\atestpic.jpg" Global $hBmp = _GDIPlus_BitmapCreateFromFile($sImage) ReSize() Local $time = TimerInit() EndIf WEnd Func ReSize() Local $aSize = ControlGetPos($hGUI, "", $idPic) Local $hBitmap = _GDIPlus_BitmapCreateFromScan0($aSize[2], $aSize[3]) Local $hContext = _GDIPlus_ImageGetGraphicsContext($hBitmap) ;_GDIPlus_GraphicsSetInterpolationMode($hContext, 5) _GDIPlus_GraphicsSetInterpolationMode($hContext, 2) _GDIPlus_GraphicsDrawImageRect($hContext, $hBmp, 0, 0, $aSize[2], $aSize[3]) _GDIPlus_GraphicsDispose($hContext) Local $hHBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBitmap) Local $hB = GUICtrlSendMsg($idPic, $STM_SETIMAGE, $IMAGE_BITMAP, $hHBitmap) If $hB Then _WinAPI_DeleteObject($hB) _WinAPI_DeleteObject($hHBitmap) _GDIPlus_BitmapDispose($hBitmap) EndFunc Is this as it should be? Improvements? 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