Jump to content

Resize Image and display centered in control


KaFu
 Share

Recommended Posts

Hiho Forum,

I'm still not that good using GDI, but this should be no problem for the real pros :oops:.

I want to load a picture of any size, resize it while maintaining the aspect ratio and display it centered in a 320x240 control. Anyone got a hint for me what I'm doing wrong?

#include <GDIPlus.au3>
#include <WinAPI.au3>
HotKeySet("{ESC}", "_Exit")
_GDIPlus_Startup()
Global Const $STM_SETIMAGE = 0x0172
Global Const $IMAGE_BITMAP = 0
GUICreate("Test", 340, 260)
$c_Pic = GUICtrlCreatePic("", 10, 10, 320, 240)
$h_Pic = GUICtrlGetHandle($c_Pic)
GUISetState()
_SetPicture($h_Pic, @ScriptDir & "\test.jpg")
While 1
 Sleep(10)
WEnd
Func _SetPicture($hWnd, $sFile)
 Local $hDC = _WinAPI_GetWindowDC($hWnd)
 Local $hDC_Sub = _WinAPI_CreateCompatibleDC($hDC)
 _WinAPI_ReleaseDC($hWnd, $hDC)
 Local $hGraphic = _GDIPlus_GraphicsCreateFromHDC($hDC)
 Local $hImage = _GDIPlus_ImageLoadFromFile($sFile)
 Local $_PC_iX = _GDIPlus_ImageGetWidth($hImage)
 Local $_PC_iY = _GDIPlus_ImageGetHeight($hImage)
 Local $_PC_aScale = _GetScale($_PC_iX, $_PC_iY, 320)
 Local $_PC_iX_New = (320 - $_PC_aScale[2] / 2) - (320 / 2)
 Local $_PC_iY_New = (240 - $_PC_aScale[3] / 2) - (240 / 2)
 _GDIPlus_GraphicsDrawImageRect($hGraphic, $hImage, $_PC_iX_New, $_PC_iY_New, $_PC_aScale[2], $_PC_aScale[3])
 $hbmp = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage)
 _WinAPI_DeleteObject(GUICtrlSendMsg($hWnd, $STM_SETIMAGE, $IMAGE_BITMAP, $hbmp))
 _WinAPI_DeleteObject($hbmp)
 _GDIPlus_ImageDispose($hImage)
 _GDIPlus_GraphicsDispose($hGraphic)
 _WinAPI_DeleteDC($hDC_Sub)
EndFunc   ;==>_SetPicture
Func _Exit()
 _GDIPlus_Shutdown()
 Exit
EndFunc   ;==>_Exit
Func _GetScale($iW, $iH, $i_TargetWidth)
 Local $aRet[4]
 If $iW <= $i_TargetWidth And $iH <= $i_TargetWidth Then
  $aRet[2] = $iW
  $aRet[3] = $iH
  $aRet[0] = ($i_TargetWidth - $aRet[2]) / 2
  $aRet[1] = ($i_TargetWidth - $aRet[3]) / 2
 ElseIf $iW > $iH Then
  $aRet[2] = $i_TargetWidth
  $aRet[3] = $iH / ($iW / $i_TargetWidth)
  $aRet[0] = 0
  $aRet[1] = ($i_TargetWidth - $aRet[3]) / 2
 ElseIf $iW < $iH Then
  $aRet[2] = $iW / ($iH / $i_TargetWidth)
  $aRet[3] = $i_TargetWidth
  $aRet[0] = ($i_TargetWidth - $aRet[2]) / 2
  $aRet[1] = 0
 ElseIf $iW = $iH Then
  $aRet[2] = $i_TargetWidth
  $aRet[3] = $i_TargetWidth
  $aRet[0] = 0
  $aRet[1] = 0
 EndIf
 Return $aRet
EndFunc   ;==>_GetScale
Link to comment
Share on other sites

Hmmm, not quite what I was looking for. This does what I want... except that I can't get the $STM_SETIMAGE part to work properly. On XP and Vista+ with DWM disabled the image is lost on redraw (e.g. another window covers the pic) :oops:...

#include <GDIPlus.au3>
#include <WinAPI.au3>
HotKeySet("{ESC}", "_Exit")
_GDIPlus_Startup()
Global Const $STM_SETIMAGE = 0x0172
Global Const $IMAGE_BITMAP = 0
GUICreate("Test", 340, 260)
$c_Pic = GUICtrlCreatePic("", 10, 10, 320, 240)
$h_Pic = GUICtrlGetHandle($c_Pic)
GUISetState()
_SetPicture($h_Pic, @ScriptDir & "test.jpg")
While 1
    Sleep(10)
WEnd
Func _SetPicture($hWnd, $sFile)
    Local $hGraphic = _GDIPlus_GraphicsCreateFromHWND($hWnd)
    Local $hImage = _GDIPlus_ImageLoadFromFile($sFile)
    Local $_PC_iX = _GDIPlus_ImageGetWidth($hImage)
    Local $_PC_iY = _GDIPlus_ImageGetHeight($hImage)

    If $_PC_iX > $_PC_iY Then
        Local $_PC_aScale = _GetScale($_PC_iX, $_PC_iY, 320)
    Else
        Local $_PC_aScale = _GetScale($_PC_iX, $_PC_iY, 240)
    EndIf

    ConsoleWrite($_PC_aScale[0] & @TAB & $_PC_aScale[1] & @TAB & $_PC_aScale[2] & @TAB & $_PC_aScale[3] & @CRLF)
    Local $_PC_iX_New = (320 - $_PC_aScale[2] / 2) - (320 / 2)
    Local $_PC_iY_New = (240 - $_PC_aScale[3] / 2) - (240 / 2)
    _GDIPlus_GraphicsDrawImageRect($hGraphic, $hImage, $_PC_iX_New, $_PC_iY_New, $_PC_aScale[2], $_PC_aScale[3])

    #cs
        $hbmp = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage)
        _WinAPI_DeleteObject(GUICtrlSendMsg($hWnd, $STM_SETIMAGE, $IMAGE_BITMAP, $hbmp))
        _WinAPI_DeleteObject($hbmp)
    #ce
    _GDIPlus_ImageDispose($hImage)
    _GDIPlus_GraphicsDispose($hGraphic)
EndFunc   ;==>_SetPicture

Func _Exit()
    _GDIPlus_Shutdown()
    Exit
EndFunc   ;==>_Exit
Func _GetScale($iW, $iH, $i_TargetWidth)
    Local $aRet[4]
    If $iW <= $i_TargetWidth And $iH <= $i_TargetWidth Then
        $aRet[2] = $iW
        $aRet[3] = $iH
        $aRet[0] = ($i_TargetWidth - $aRet[2]) / 2
        $aRet[1] = ($i_TargetWidth - $aRet[3]) / 2
    ElseIf $iW > $iH Then
        $aRet[2] = $i_TargetWidth
        $aRet[3] = $iH / ($iW / $i_TargetWidth)
        $aRet[0] = 0
        $aRet[1] = ($i_TargetWidth - $aRet[3]) / 2
    ElseIf $iW < $iH Then
        $aRet[2] = $iW / ($iH / $i_TargetWidth)
        $aRet[3] = $i_TargetWidth
        $aRet[0] = ($i_TargetWidth - $aRet[2]) / 2
        $aRet[1] = 0
    ElseIf $iW = $iH Then
        $aRet[2] = $i_TargetWidth
        $aRet[3] = $i_TargetWidth
        $aRet[0] = 0
        $aRet[1] = 0
    EndIf
    Return $aRet
EndFunc   ;==>_GetScale
Link to comment
Share on other sites

You have to repaint the GDI+ stuff when the window gets repaint message:

#include <windowsconstants.au3>
#include <gdiplus.au3>

HotKeySet("{ESC}", "_Exit")

_GDIPlus_Startup()
Global Const $STM_SETIMAGE = 0x0172
Global Const $IMAGE_BITMAP = 0
GUICreate("Test", 340, 260)
$c_Pic = GUICtrlCreatePic("", 10, 10, 320, 240)
$h_Pic = GUICtrlGetHandle($c_Pic)
GUISetState()

Global $aRet = _SetPicture($h_Pic, @ScriptDir & "test.jpg")
GUIRegisterMsg($WM_ERASEBKGND, "RePaint")

While 1
    Sleep(10)
WEnd

Func RePaint($hWnd, $msg, $wParam, $lParam)
    ; The sequencial order of these two commands is important.
    _GDIPlus_GraphicsDrawImageRect($aRet[0], $aRet[1], $aRet[2], $aRet[3], $aRet[4], $aRet[5])
    _WinAPI_RedrawWindow($hWnd, "", "", BitOR($RDW_INVALIDATE, $RDW_UPDATENOW, $RDW_FRAME)); , $RDW_ALLCHILDREN
    Return 1
EndFunc ;==>MY_PAINT

Func _SetPicture($hWnd, $sFile)
    Local $hGraphic = _GDIPlus_GraphicsCreateFromHWND($hWnd)
    Local $hImage = _GDIPlus_ImageLoadFromFile($sFile)
    Local $_PC_iX = _GDIPlus_ImageGetWidth($hImage)
    Local $_PC_iY = _GDIPlus_ImageGetHeight($hImage)

    If $_PC_iX > $_PC_iY Then
        Local $_PC_aScale = _GetScale($_PC_iX, $_PC_iY, 320)
    Else
        Local $_PC_aScale = _GetScale($_PC_iX, $_PC_iY, 240)
    EndIf

    ConsoleWrite($_PC_aScale[0] & @TAB & $_PC_aScale[1] & @TAB & $_PC_aScale[2] & @TAB & $_PC_aScale[3] & @CRLF)
    Local $_PC_iX_New = (320 - $_PC_aScale[2] / 2) - (320 / 2)
    Local $_PC_iY_New = (240 - $_PC_aScale[3] / 2) - (240 / 2)
    _GDIPlus_GraphicsDrawImageRect($hGraphic, $hImage, $_PC_iX_New, $_PC_iY_New, $_PC_aScale[2], $_PC_aScale[3])

    #cs
        $hbmp = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage)
        _WinAPI_DeleteObject(GUICtrlSendMsg($hWnd, $STM_SETIMAGE, $IMAGE_BITMAP, $hbmp))
        _WinAPI_DeleteObject($hbmp)
    #ce
    Local $aReturn[6] = [$hGraphic, $hImage, $_PC_iX_New, $_PC_iY_New, $_PC_aScale[2], $_PC_aScale[3]]
    Return $aReturn
EndFunc   ;==>_SetPicture

Func _Exit()
    _GDIPlus_ImageDispose($aRet[1])
    _GDIPlus_GraphicsDispose($aRet[0])
    _GDIPlus_Shutdown()
    Exit
EndFunc   ;==>_Exit

Func _GetScale($iW, $iH, $i_TargetWidth)
    Local $aRet[4]
    If $iW <= $i_TargetWidth And $iH <= $i_TargetWidth Then
        $aRet[2] = $iW
        $aRet[3] = $iH
        $aRet[0] = ($i_TargetWidth - $aRet[2]) / 2
        $aRet[1] = ($i_TargetWidth - $aRet[3]) / 2
    ElseIf $iW > $iH Then
        $aRet[2] = $i_TargetWidth
        $aRet[3] = $iH / ($iW / $i_TargetWidth)
        $aRet[0] = 0
        $aRet[1] = ($i_TargetWidth - $aRet[3]) / 2
    ElseIf $iW < $iH Then
        $aRet[2] = $iW / ($iH / $i_TargetWidth)
        $aRet[3] = $i_TargetWidth
        $aRet[0] = ($i_TargetWidth - $aRet[2]) / 2
        $aRet[1] = 0
    ElseIf $iW = $iH Then
        $aRet[2] = $i_TargetWidth
        $aRet[3] = $i_TargetWidth
        $aRet[0] = 0
        $aRet[1] = 0
    EndIf
    Return $aRet
EndFunc   ;==>_GetScale

Tested on Win7 x64 + Aero enabled.

Br,

UEZ

Edited by UEZ

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

The problem occurs on XP and Vista+ with Aero disabled.

With Aero enabled my example above works fine too, yours of course too.

But with Aero disabled my example does not work at all and yours adds parts of the underlying background to the GUI for me :oops: ...

Link to comment
Share on other sites

I would do something like this (only because yours looks so complicated):

#include "GifAnimation.au3"
#include <WindowsConstants.au3>
Opt("GUICloseOnESC", 1); ESC to exit
Opt("MustDeclareVars", 1)
Global $sPic = @ScriptDir & "test.jpg"
Global $hGUI = GUICreate("", 700, 500)
Global $hPic = BzzThatThingDone($sPic, 10, 10, 320, 240)
GUISetState()

While 1
    Switch GUIGetMsg()
        Case -3
            Exit
        Case $hPic
            MsgBox(32, "", "OK?", 0, $hGUI)
    EndSwitch
WEnd

Func BzzThatThingDone($sPic, $iX, $iY, $iWidth, $iHeight)
    Local $aSize = _GIF_GetDimension($sPic)
    Local $nScaleX = $iWidth / $aSize[0]
    Local $nScaleY = $iHeight / $aSize[1]
    Local $nScale = $nScaleX
    If $nScale > $nScaleY Then $nScale = $nScaleY
    Local $iWidthNew = $aSize[0] * $nScale
    Local $iHeightNew = $aSize[1] * $nScale
    Return _GUICtrlCreateGIF($sPic, "", $iX + ($iWidth - $iWidthNew) / 2, $iY + $iY + ($iHeight - $iHeightNew) / 2, $iWidthNew, $iHeightNew)
EndFunc

GifAnimation.au3 is something I wrote once. Can be found in examples. Uses Gdip too.

♡♡♡

.

eMyvnE

Link to comment
Share on other sites

Sorry, did not read your post carefully!

Can you try this here please?

#include <windowsconstants.au3>
#include <gdiplus.au3>

_GDIPlus_Startup()
Global Const $STM_SETIMAGE = 0x0172
Global Const $IMAGE_BITMAP = 0
GUICreate("Test", 340, 260)
$c_Pic = GUICtrlCreatePic("", 10, 10, 320, 240)
$h_Pic = GUICtrlGetHandle($c_Pic)
GUISetState()

Global $aRet = _SetPicture($h_Pic, @ScriptDir & "test.jpg")
If @OSBuild < 6000 Then
    GUIRegisterMsg($WM_PAINT, "WM_REDRAW_XP")
Else
    GUIRegisterMsg($WM_PAINT, "WM_REDRAW")
EndIf

HotKeySet("{ESC}", "_Exit")

While 1
    Sleep(10)
WEnd

Func WM_REDRAW($hWnd, $msg, $wParam, $lParam)
    #forceref $msg, $wParam, $lParam
    _WinAPI_RedrawWindow($hWnd, 0, 0, $RDW_UPDATENOW + $RDW_NOINTERNALPAINT)
    _GDIPlus_GraphicsDrawImageRect($aRet[0], $aRet[1], $aRet[2], $aRet[3], $aRet[4], $aRet[5])
    Return "GUI_RUNDEFMSG"
EndFunc ;==>MY_PAINT

Func WM_REDRAW_XP($hWnd, $msg, $wParam, $lParam)
    #forceref $msg, $wParam, $lParam
    _WinAPI_RedrawWindow($hWnd, 0, 0, BitOR($RDW_INVALIDATE, $RDW_UPDATENOW))
    _GDIPlus_GraphicsDrawImageRect($aRet[0], $aRet[1], $aRet[2], $aRet[3], $aRet[4], $aRet[5])
    Return "GUI_RUNDEFMSG"
EndFunc ;==>MY_PAINT

Func _SetPicture($hWnd, $sFile)
    Local $hGraphic = _GDIPlus_GraphicsCreateFromHWND($hWnd)
    Local $hImage = _GDIPlus_ImageLoadFromFile($sFile)
    Local $_PC_iX = _GDIPlus_ImageGetWidth($hImage)
    Local $_PC_iY = _GDIPlus_ImageGetHeight($hImage)

    If $_PC_iX > $_PC_iY Then
        Local $_PC_aScale = _GetScale($_PC_iX, $_PC_iY, 320)
    Else
        Local $_PC_aScale = _GetScale($_PC_iX, $_PC_iY, 240)
    EndIf

    ConsoleWrite($_PC_aScale[0] & @TAB & $_PC_aScale[1] & @TAB & $_PC_aScale[2] & @TAB & $_PC_aScale[3] & @CRLF)
    Local $_PC_iX_New = (320 - $_PC_aScale[2] / 2) - (320 / 2)
    Local $_PC_iY_New = (240 - $_PC_aScale[3] / 2) - (240 / 2)
    _GDIPlus_GraphicsDrawImageRect($hGraphic, $hImage, $_PC_iX_New, $_PC_iY_New, $_PC_aScale[2], $_PC_aScale[3])

    #cs
        $hbmp = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage)
        _WinAPI_DeleteObject(GUICtrlSendMsg($hWnd, $STM_SETIMAGE, $IMAGE_BITMAP, $hbmp))
        _WinAPI_DeleteObject($hbmp)
    #ce
    Local $aReturn[6] = [$hGraphic, $hImage, $_PC_iX_New, $_PC_iY_New, $_PC_aScale[2], $_PC_aScale[3]]
    Return $aReturn
EndFunc   ;==>_SetPicture

Func _Exit()
    GUIRegisterMsg($WM_PAINT, "")
    _GDIPlus_ImageDispose($aRet[1])
    _GDIPlus_GraphicsDispose($aRet[0])
    _GDIPlus_Shutdown()
    Exit
EndFunc   ;==>_Exit

Func _GetScale($iW, $iH, $i_TargetWidth)
    Local $aRet[4]
    If $iW <= $i_TargetWidth And $iH <= $i_TargetWidth Then
        $aRet[2] = $iW
        $aRet[3] = $iH
        $aRet[0] = ($i_TargetWidth - $aRet[2]) / 2
        $aRet[1] = ($i_TargetWidth - $aRet[3]) / 2
    ElseIf $iW > $iH Then
        $aRet[2] = $i_TargetWidth
        $aRet[3] = $iH / ($iW / $i_TargetWidth)
        $aRet[0] = 0
        $aRet[1] = ($i_TargetWidth - $aRet[3]) / 2
    ElseIf $iW < $iH Then
        $aRet[2] = $iW / ($iH / $i_TargetWidth)
        $aRet[3] = $i_TargetWidth
        $aRet[0] = ($i_TargetWidth - $aRet[2]) / 2
        $aRet[1] = 0
    ElseIf $iW = $iH Then
        $aRet[2] = $i_TargetWidth
        $aRet[3] = $i_TargetWidth
        $aRet[0] = 0
        $aRet[1] = 0
    EndIf
    Return $aRet
EndFunc   ;==>_GetScale

Br,

UEZ

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

Couldn't stop tinkering myself :oops:, thanks for all your input!

#include <GUIConstantsEx.au3>
#include <GDIPlus.au3>
#include <WinAPI.au3>

_GDIPlus_Startup()

Global Const $STM_SETIMAGE = 0x0172
Global Const $IMAGE_BITMAP = 0

GUICreate("Test", 340, 260)
GUICtrlCreateLabel("", 10, 10, 320, 240)
GUICtrlSetBkColor(-1, 0x000000)
GUICtrlSetState(-1, $GUI_DISABLE)
$c_Pic = GUICtrlCreatePic("", 10, 10, 320, 240)
GUICtrlSetState(-1, $GUI_DISABLE)
GUISetState()

Sleep(2000)
_GUIPicCtrl_SetFile($c_Pic, @ScriptDir & "test.jpg")
Sleep(2000)
_WinAPI_DeleteObject(GUICtrlSendMsg($c_Pic, $STM_SETIMAGE, $IMAGE_BITMAP, 0))
Sleep(2000)
_GUIPicCtrl_SetFile($c_Pic, @ScriptDir & "test2.jpg")

While 1
    $msg = GUIGetMsg()
    If $msg = $GUI_EVENT_CLOSE Then ExitLoop
WEnd

_GDIPlus_Shutdown()
Exit

Func _GUIPicCtrl_SetFile($iCtrlId, $sFile)

    Local $hWnd = GUICtrlGetHandle($iCtrlId)

    Local $hImage = _GDIPlus_ImageLoadFromFile($sFile)
    Local $iX_Input = _GDIPlus_ImageGetWidth($hImage)
    Local $iY_Input = _GDIPlus_ImageGetHeight($hImage)

    Local $iRatio = $iX_Input / $iY_Input, $iX_Output, $iY_Output, $iX_Output_Offset, $iY_Output_Offset

    If $iRatio > 1 Then
        $iX_Output = 320
        $iY_Output = 320 / $iRatio
        $iX_Output_Offset = 0
        $iY_Output_Offset = (240 / 2) - ($iY_Output / 2)
    Else
        $iX_Output = 240 * $iRatio
        $iY_Output = 240
        $iX_Output_Offset = (320 / 2) - ($iX_Output / 2)
        $iY_Output_Offset = 0
    EndIf

    Local $hHBITMAP = _WinAPI_CreateBitmap(320, 240, 1, 32)
    Local $hCDC = _WinAPI_CreateCompatibleDC(0)
    _WinAPI_SelectObject($hCDC, $hHBITMAP)
    Local $hGraphic = _GDIPlus_GraphicsCreateFromHDC($hCDC)
    _GDIPlus_GraphicsDrawImageRect($hGraphic, $hImage, $iX_Output_Offset, $iY_Output_Offset, $iX_Output, $iY_Output)
    _GDIPlus_ImageDispose($hImage)
    _GDIPlus_GraphicsDispose($hGraphic)
    _WinAPI_DeleteDC($hCDC)

    _WinAPI_DeleteObject(GUICtrlSendMsg($iCtrlId, $STM_SETIMAGE, $IMAGE_BITMAP, $hHBITMAP)) ; works with $iCtrlId, fails with control handle!
    _WinAPI_DeleteObject($hHBITMAP)

    _WinAPI_RedrawWindow($hWnd)

EndFunc   ;==>_SetPicture
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

×
×
  • Create New...