Jump to content

Image resize with mouse wheel


jcpetu
 Share

Recommended Posts

Hi people, I'm trying to change image size by using mouse Wheel. I managed to trap the message and increease or decrease the size but after resizing the image disapears.

Any help will be appreciated.

thanks a lot and regards.

#include <APIConstants.au3>
#include <GDIPlus.au3>
#include <GUIConstantsEx.au3>
#include <ScreenCapture.au3>
#include <WinAPI.au3>
;------------------------------------------------

Global $PWidth = 600, $PHeight = 384
Global $hGUI = GUICreate("Image Inverter", 615, 438, -1, -1)
Global $BLoadFile = GUICtrlCreateButton("Load Image File", 328, 400, 125, 25)
GUISetState(@SW_SHOW)

GUIRegisterMsg($WM_MOUSEWHEEL, "WM_MOUSEWHEEL") ;to resize image with mouse wheel

_GDIPlus_Startup() ;initialize GDI+
While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
        Case $GUI_EVENT_CLOSE
            _GDIPlus_Shutdown()
            GUIDelete($hGUI)
            Exit
        Case $BLoadFile
            $file = FileOpenDialog("Select image file", @ScriptDir, "Images (*.bmp;*.ico;*.jpg)")
            $hImage = _GDIPlus_ImageLoadFromFile($file)
            $Width = _GDIPlus_ImageGetWidth($hImage)
            $Height = _GDIPlus_ImageGetHeight($hImage)
            DrawImage()
    EndSwitch
WEnd

Func DrawImage()
    ;Resize image to fit in screen----------------------------------------------------------
    $P2Width = $PWidth
    If $Width <= $PWidth Then $P2Width = $Width
    $P2Height = $PHeight
    If $Height <= $PHeight Then $P2Height = $Height
    $hBitmap = _GDIPlus_ScaleImage($file, $P2Width, $P2Height)
    $hHBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBitmap)

    ;Prepare graphic context and invert colors----------------------------------------------
    Local $hGraphics = _GDIPlus_GraphicsCreateFromHWND(WinGetHandle($hGUI)) ;create a graphics object from a window handle
    Local $hIA = _GDIPlus_ImageAttributesCreate() ;create an ImageAttribute object
    Local $tColorMatrix = _GDIPlus_ColorMatrixCreateNegative() ;create negative color matrix
    _GDIPlus_ImageAttributesSetColorMatrix($hIA, 0, True, $tColorMatrix) ;set negative color matrix

    ;Delete previous image------------------------------------------------------------------
    _GDIPlus_GraphicsClear($hGraphics)

    ;Redraw the main GUI -------------------------------------------------------------------
    _WinAPI_RedrawWindow($hGUI)


    ;Show image ----------------------------------------------------------------------------
    _GDIPlus_GraphicsDrawImageRectRect($hGraphics, $hBitmap, 0, 0, $PWidth, $PHeight, 0, 0, $PWidth, $PHeight, $hIA) ;draw the bitmap while applying the color adjustment
    _WinAPI_DeleteObject($hImage) ;release GDI bitmap resource because not needed anymore
    _WinAPI_DeleteObject($hHBitmap)
    _GDIPlus_ImageAttributesDispose($hIA)
    _GDIPlus_GraphicsDispose($hGraphics)
    Return
EndFunc   ;==>DrawImage


Func WM_MOUSEWHEEL($hWnd, $iMsg, $wParam, $lParam)
    #forceref $iMsg, $wParam
    Switch $hWnd
        Case $hGUI
            If BitShift($wParam, 16) > 0 Then ;Wheel up
                $PWidth = $PWidth + 1
                $PHeight = $PHeight + 1
                DrawImage()
            Else ;-----------------------------Wheel down
                $PWidth = $PWidth - 1
                $PHeight = $PHeight - 1
                DrawImage()
            EndIf

    EndSwitch
    Return "GUI_RUNDEFMSG"
EndFunc   ;==>WM_MOUSEWHEEL


Func _GDIPlus_ScaleImage($sFile, $iW, $iH, $iInterpolationMode = 7) ;coded by UEZ 2012
    If Not FileExists($sFile) Then Return SetError(1, 0, 0)
    Local $hImage = _GDIPlus_ImageLoadFromFile($sFile)
    If @error Then Return SetError(2, 0, 0)
    Local $hBitmap = DllCall($__g_hGDIPDll, "uint", "GdipCreateBitmapFromScan0", "int", $iW, "int", $iH, "int", 0, "int", 0x0026200A, "ptr", 0, "int*", 0)
    If @error Then Return SetError(3, 0, 0)
    $hBitmap = $hBitmap[6]
    Local $hBmpCtxt = _GDIPlus_ImageGetGraphicsContext($hBitmap)
    DllCall($__g_hGDIPDll, "uint", "GdipSetInterpolationMode", "handle", $hBmpCtxt, "int", $iInterpolationMode)
    _GDIPlus_GraphicsDrawImageRect($hBmpCtxt, $hImage, 0, 0, $iW, $iH)
    _GDIPlus_ImageDispose($hImage)
    _GDIPlus_GraphicsDispose($hBmpCtxt)
    Return $hBitmap
EndFunc   ;==>_GDIPlus_ScaleImage

 

Link to comment
Share on other sites

Not really sure why you're trying to reinvent the _GDIPlus_ImageScale function.

#include <APIConstants.au3>
#include <GDIPlus.au3>
#include <GUIConstantsEx.au3>
#include <ScreenCapture.au3>
#include <WinAPI.au3>
;------------------------------------------------

Global $PWidth = 600, $PHeight = 384
Global $fScale = 1.0
Global $hGUI = GUICreate("Image Inverter: " & $fScale * 100 & "%", 615, 438, -1, -1)
Global $BLoadFile = GUICtrlCreateButton("Load Image File", 328, 400, 125, 25)
Global $hImage
Global $hWnd_buffer
GUISetState(@SW_SHOW)

GUIRegisterMsg($WM_MOUSEWHEEL, "WM_MOUSEWHEEL") ;to resize image with mouse wheel

_GDIPlus_Startup() ;initialize GDI+

Global $hGraphics = _GDIPlus_GraphicsCreateFromHWND($hGUI)

While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
        Case $GUI_EVENT_CLOSE
            _GDIPlus_GraphicsDispose($hGraphics)
            _GDIPlus_Shutdown()
            GUIDelete($hGUI)
            Exit
        Case $BLoadFile
            $file = FileOpenDialog("Select image file", @ScriptDir, "Images (*.bmp;*.ico;*.jpg)")
            ; Dispose in case there is already an image loaded)
            If ($hImage) Then _GDIPlus_ImageDispose($hImage)
            $hImage = _GDIPlus_ImageLoadFromFile($file)
            ; Reset scale
            $fScale = 1.0
            WinSetTitle($hGUI, "", "Image Inverter: " & $fScale * 100 & "%")
            DrawImage()
    EndSwitch
WEnd

Func DrawImage()
    Local $hBitmap_Scaled = _GDIPlus_ImageScale($hImage, $fScale, $fScale, $GDIP_INTERPOLATIONMODE_NEARESTNEIGHBOR)
    Local $hIA = _GDIPlus_ImageAttributesCreate() ;create an ImageAttribute object
    Local $tColorMatrix = _GDIPlus_ColorMatrixCreateNegative() ;create negative color matrix
    _GDIPlus_ImageAttributesSetColorMatrix($hIA, 0, True, $tColorMatrix) ;set negative color matrix

    _GDIPlus_GraphicsClear($hGraphics)
    _GDIPlus_GraphicsDrawImageRectRect($hGraphics, $hBitmap_Scaled, 0, 0, _GDIPlus_ImageGetWidth($hImage), _GDIPlus_ImageGetWidth($hImage), 0, 0, _GDIPlus_ImageGetWidth($hBitmap_Scaled), _GDIPlus_ImageGetWidth($hBitmap_Scaled), $hIA)

    _GDIPlus_BitmapDispose($hBitmap_Scaled)
    _GDIPlus_ImageAttributesDispose($hIA)
EndFunc   ;==>DrawImage

Func WM_MOUSEWHEEL($hWnd, $iMsg, $wParam, $lParam)
    #forceref $iMsg, $wParam
    ; If no image is currently loaded)
    If (Not $hImage) Then Return $GUI_RUNDEFMSG

    Switch $hWnd
        Case $hGUI
            If BitShift($wParam, 16) > 0 Then ;Wheel up
                $fScale += .1
                DrawImage()
            Else ;-----------------------------Wheel down
                $fScale -= .1
                DrawImage()
            EndIf

    EndSwitch

    WinSetTitle($hGUI, "", "Image Inverter: " & $fScale * 100 & "%")

    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_MOUSEWHEEL

Also, the reason it disappeared was because _WinAPI_RedrawWindow($hGUI). Forcing a redraw does weird things sometimes, especially with GUI's that have graphic objects. In my experience at least.

Link to comment
Share on other sites

Hi InunoTaishou and thanks a lot for your help,

In the example you attached when you scale the image it appears a black background that also erase the button, that the reason why I'm using _WinAPI_RedrawWindow($hGUI) to redraw the button. On the other hand, when you scale the image with _GDIPlus_ImageScale() it flickers in every scale operation.  

 

Link to comment
Share on other sites

It flickers because that's how GDI+ works. It's clearing the graphic object and then drawing it again. If you want to avoid that you use a buffer. A buffer is really a bitmap created from a graphic object. Instead of drawing directly to your graphic, you draw on the bitmap and then draw the bitmap.

The background is from clearing the graphic object. The second parameter, of GraphicsClear, is an ARGB value you can pass that will fill the empty area with that color. By default the color is black.

As for your button, I would suggest designating a graphic area where the image can be drawn and leave the button out of that area. Like how photoshop or paint does it.

Here is an example without the flickering, without the black background, and the button out of the graphic area.

#include <APIConstants.au3>
#include <GDIPlus.au3>
#include <GUIConstantsEx.au3>
#include <ScreenCapture.au3>
#include <WinAPI.au3>
;------------------------------------------------

Global $PWidth = 600, $PHeight = 384
Global $fScale = 1.0
Global $hGUI = GUICreate("Image Inverter: " & $fScale * 100 & "%", 615, 438, -1, -1)
Global $BLoadFile = GUICtrlCreateButton("Load Image File", 328, 400, 125, 25)
Global $hImage
Global $hWnd_buffer
GUISetState(@SW_SHOW)

GUIRegisterMsg($WM_MOUSEWHEEL, "WM_MOUSEWHEEL") ;to resize image with mouse wheel

_GDIPlus_Startup() ;initialize GDI+

Global $hGraphics = _GDIPlus_GraphicsCreateFromHWND($hGUI)
Global $hWnd_bitmap = _GDIPlus_BitmapCreateFromGraphics(615, 395, $hGraphics)
Global $hWnd_gdi_buffer = _GDIPlus_ImageGetGraphicsContext($hWnd_bitmap)

_GDIPlus_GraphicsSetSmoothingMode($hGraphics, $GDIP_SMOOTHINGMODE_HIGHQUALITY)
_GDIPlus_GraphicsSetTextRenderingHint($hGraphics, $GDIP_TEXTRENDERINGHINT_ANTIALIASGRIDFIT)

While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
        Case $GUI_EVENT_CLOSE
            _GDIPlus_GraphicsDispose($hGraphics)
            _GDIPlus_BitmapDispose($hWnd_bitmap)
            _GDIPlus_Shutdown()
            GUIDelete($hGUI)
            Exit
        Case $BLoadFile
            $file = FileOpenDialog("Select image file", @ScriptDir, "Images (*.bmp;*.ico;*.jpg)")
            ; Dispose in case there is already an image loaded)
            If ($hImage) Then _GDIPlus_ImageDispose($hImage)
            $hImage = _GDIPlus_ImageLoadFromFile($file)
            ; Reset scale
            $fScale = 1.0
            WinSetTitle($hGUI, "", "Image Inverter: " & $fScale * 100 & "%")
            DrawImage()
    EndSwitch
WEnd

Func DrawImage()
    Local $hBitmap_Scaled = _GDIPlus_ImageScale($hImage, $fScale, $fScale, $GDIP_INTERPOLATIONMODE_NEARESTNEIGHBOR)
    Local $hIA = _GDIPlus_ImageAttributesCreate() ;create an ImageAttribute object
    Local $tColorMatrix = _GDIPlus_ColorMatrixCreateNegative() ;create negative color matrix
    _GDIPlus_ImageAttributesSetColorMatrix($hIA, 0, True, $tColorMatrix) ;set negative color matrix

    _GDIPlus_GraphicsClear($hWnd_gdi_buffer, 0xFFF0F0F0)
    _GDIPlus_GraphicsDrawImageRectRect($hWnd_gdi_buffer, $hBitmap_Scaled, 0, 0, _GDIPlus_ImageGetWidth($hImage), _GDIPlus_ImageGetWidth($hImage), 0, 0, _GDIPlus_ImageGetWidth($hBitmap_Scaled), _GDIPlus_ImageGetWidth($hBitmap_Scaled), $hIA)
    _GDIPlus_GraphicsDrawImage($hGraphics, $hWnd_bitmap, 0, 0)

    _GDIPlus_BitmapDispose($hBitmap_Scaled)
    _GDIPlus_ImageAttributesDispose($hIA)
EndFunc   ;==>DrawImage

Func WM_MOUSEWHEEL($hWnd, $iMsg, $wParam, $lParam)
    #forceref $iMsg, $wParam
    ; If no image is currently loaded)
    If (Not $hImage) Then Return $GUI_RUNDEFMSG

    Switch $hWnd
        Case $hGUI
            If BitShift($wParam, 16) > 0 Then ;Wheel up
                $fScale += .1
                DrawImage()
            Else ;-----------------------------Wheel down
                $fScale -= .1
                DrawImage()
            EndIf

    EndSwitch

    WinSetTitle($hGUI, "", "Image Inverter: " & $fScale * 100 & "%")

    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_MOUSEWHEEL

 

Edited by InunoTaishou
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...