Sign in to follow this  
Followers 0
KaFu

[Solved] _GDIPlus, resize / scale a loaded picture and

14 posts in this topic

#1 ·  Posted (edited)

Hiho Community,

I'm looking for a way to load a JPG from disk, to resize it if it's larger then the screen resolution and then display it on a control... well, the script works except for the resize part :D , the math seems to fit, but somehow I don't seem to get the grasp for GDI.

Try the attached code with a JPG "test.jpg" larger then your desktop.

Best regards

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GDIPlus.au3>
#include <winapi.au3>

_GDIPlus_Startup()

Local $msg

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

$hImage = _GDIPlus_ImageLoadFromFile(@ScriptDir & '\test.jpg')

$iX_ImageDisplay = _GDIPlus_ImageGetWidth($hImage)
$iY_ImageDisplay = _GDIPlus_ImageGetHeight($hImage)

$iFactor_ImageDisplay = 1
If $iX_ImageDisplay > @DesktopWidth Or $iY_ImageDisplay > @DesktopHeight Then
    $iX_ImageDisplay = $iX_ImageDisplay * (@DesktopHeight / $iY_ImageDisplay)
    $iFactor_ImageDisplay = @DesktopHeight / $iY_ImageDisplay
    $iY_ImageDisplay = @DesktopHeight
    If $iX_ImageDisplay > @DesktopWidth Then
        $iY_ImageDisplay = $iY_ImageDisplay * (@DesktopWidth / $iX_ImageDisplay)
        $iFactor_ImageDisplay = @DesktopWidth / $iX_ImageDisplay
        $iX_ImageDisplay = @DesktopWidth
    EndIf
EndIf

$gui_image_display = GUICreate("My GUI", $iX_ImageDisplay, $iY_ImageDisplay, Default, Default, $WS_POPUP) ; will create a dialog box that when displayed is centered
$pic_image_display = GUICtrlCreatePic("", 0, 0, $iX_ImageDisplay, $iY_ImageDisplay)

If $iFactor_ImageDisplay <> 1 Then
    $hGraphic = _GDIPlus_GraphicsCreateFromHWND(GUICtrlGetHandle($pic_image_display))
    _GDIPlus_GraphicsDrawImageRect($hGraphic,$hImage,0,0,$iX_ImageDisplay,$iY_ImageDisplay)
    ConsoleWrite($iX_ImageDisplay & @tab & $iY_ImageDisplay & @crlf)
EndIf

$hBMP = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage)

$aBmp = DllCall("user32.dll", "hwnd", "SendMessage", "hwnd", GUICtrlGetHandle($pic_image_display), "int", $STM_SETIMAGE, "int", $IMAGE_BITMAP, "int", $hBMP)
_WinAPI_RedrawWindow($gui_image_display, "", "", BitOR($RDW_INVALIDATE, $RDW_UPDATENOW, $RDW_FRAME))

If $aBmp[0] <> 0 Then _WinAPI_DeleteObject($aBmp[0])

_GDIPlus_ImageDispose($hImage)
_WinAPI_DeleteObject($hBMP)

If $iFactor_ImageDisplay <> 1 Then
    _GDIPlus_GraphicsDispose($hGraphic)
endif

GUISetState(@SW_SHOW) ; will display an empty dialog box

; Run the GUI until the dialog is closed
While 1
    $msg = GUIGetMsg()

    If $msg = $GUI_EVENT_CLOSE Then ExitLoop
WEnd
GUIDelete()
Edited by KaFu

Share this post


Link to post
Share on other sites



If I understood right:

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GDIPlus.au3>
#include <winapi.au3>

_GDIPlus_Startup()

Local $msg

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

$hImage = _GDIPlus_ImageLoadFromFile(@ScriptDir & '\Pen.jpg')

$iX_ImageDisplay = _GDIPlus_ImageGetWidth($hImage)
$iY_ImageDisplay = _GDIPlus_ImageGetHeight($hImage)

$iFactor_ImageDisplay = 1

If $iX_ImageDisplay > @DesktopWidth Or $iY_ImageDisplay > @DesktopHeight Then
    $iX_ImageDisplay = $iX_ImageDisplay * (@DesktopHeight / $iY_ImageDisplay)
    $iFactor_ImageDisplay = @DesktopHeight / $iY_ImageDisplay
    $iY_ImageDisplay = @DesktopHeight
    If $iX_ImageDisplay > @DesktopWidth Then
        $iY_ImageDisplay = $iY_ImageDisplay * (@DesktopWidth / $iX_ImageDisplay)
        $iFactor_ImageDisplay = @DesktopWidth / $iX_ImageDisplay
        $iX_ImageDisplay = @DesktopWidth
    EndIf
EndIf

$gui_image_display = GUICreate("My GUI", $iX_ImageDisplay, $iY_ImageDisplay, Default, Default, $WS_POPUP); will create a dialog box that when displayed is centered
$pic_image_display = GUICtrlCreatePic("", 0, 0, $iX_ImageDisplay, $iY_ImageDisplay)

;If $iFactor_ImageDisplay <> 1 Then
;   $hGraphic = _GDIPlus_GraphicsCreateFromHWND(GUICtrlGetHandle($pic_image_display))
;   _GDIPlus_GraphicsDrawImageRect($hGraphic, $hImage, 0, 0, $iX_ImageDisplay, $iY_ImageDisplay)
;   ConsoleWrite($iX_ImageDisplay & @TAB & $iY_ImageDisplay & @CRLF)
;EndIf

$hBMP = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage)
_WinAPI_DeleteObject(GUICtrlSendMsg($pic_image_display, $STM_SETIMAGE, $IMAGE_BITMAP, $hBMP))
;$aBmp = DllCall("user32.dll", "hwnd", "SendMessage", "hwnd", GUICtrlGetHandle($pic_image_display), "int", $STM_SETIMAGE, "int", $IMAGE_BITMAP, "int", $hBMP)
;_WinAPI_RedrawWindow($gui_image_display, "", "", BitOR($RDW_INVALIDATE, $RDW_UPDATENOW, $RDW_FRAME))

;If $aBmp[0] <> 0 Then _WinAPI_DeleteObject($aBmp[0])

_GDIPlus_ImageDispose($hImage)
_WinAPI_DeleteObject($hBMP)

;If $iFactor_ImageDisplay <> 1 Then
;   _GDIPlus_GraphicsDispose($hGraphic)
;EndIf

_GDIPlus_Shutdown()

GUICtrlSetPos($pic_image_display, 0, 0, $iX_ImageDisplay, $iY_ImageDisplay)

GUISetState(@SW_SHOW); will display an empty dialog box

; Run the GUI until the dialog is closed
While 1
    $msg = GUIGetMsg()

    If $msg = $GUI_EVENT_CLOSE Then ExitLoop
WEnd


GUIDelete()

♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites

Sadly this doesn't work as intended too :D . It does not resize pictures larger then desktop.

If the picture fits to the desktop display it 1:1 in GUI.

If the picture does not fit to the desktop (e.g. 1000x2000), resize it to max display size (keeping ratio) and display the resized picture in GUI.

The numbers in my first example seem to fit (checked with consolewrite), but I fail to resize the loaded image.

Share this post


Link to post
Share on other sites

Sadly this doesn't work as intended too :D . It does not resize pictures larger then desktop.

If the picture fits to the desktop display it 1:1 in GUI.

If the picture does not fit to the desktop (e.g. 1000x2000), resize it to max display size (keeping ratio) and display the resized picture in GUI.

The numbers in my first example seem to fit (checked with consolewrite), but I fail to resize the loaded image.

Are you sure it doesn't work? Can you check again? It works for me. I'm having 2000x2500 jpg and it's resized and displayed as 614.4x768 (my monitor here is 1024x768).

♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites

#6 ·  Posted (edited)

Core is StretchBlt API

Ah, already played with that one in the past, will try :D ...

Are you sure it doesn't work? Can you check again? It works for me. I'm having 2000x2500 jpg and it's resized and displayed as 614.4x768 (my monitor here is 1024x768).

Tested on work-notebook and @home (both XP), but sadly it crops the picture but does not shrink it. Edited by KaFu

Share this post


Link to post
Share on other sites

#include <GDIPlus.au3>
#include <WindowsConstants.au3>
#include <WinAPI.au3>
#include <Constants.au3>

_GDIPlus_Startup()

Global $hImage = _GDIPlus_ImageLoadFromFile(@ScriptDir & "\test.jpg")
Global $nWidth = _GDIPlus_ImageGetWidth($hImage), $nHeight = _GDIPlus_ImageGetHeight($hImage)
Global $xScale = $nWidth / @DesktopWidth, $yScale = $nHeight / @DesktopHeight
Global $newWidth, $newHeight

If ($xScale > 1) Or ($yScale > 1) Then
    If $xScale > $yScale Then
        $newWidth = @DesktopWidth
        $newHeight = Int(@DesktopHeight / $xScale)
    Else
        $newWidth = Int(@DesktopWidth / $yScale)
        $newHeight = @DesktopHeight
    EndIf
Else
    $newWidth = $nWidth
    $newHeight = $nHeight
EndIf

Global $hWnd = GUICreate("", $newWidth, $newHeight, Default, Default, $WS_POPUP)
Global $hPic = GUICtrlGetHandle(GUICtrlCreatePic("", 0, 0, $newWidth, $newHeight))
GUISetState()
Global $hPicDC = _WinAPI_GetDC($hPic)
Global $hGraphics = _GDIPlus_GraphicsCreateFromHDC($hPicDC)
_GDIPlus_GraphicsDrawImageRect($hGraphics, $hImage, 0, 0, $newWidth, $newHeight)

While GUIGetMsg() <> -3
    Sleep(10)
Wend

_GDIPlus_GraphicsDispose($hGraphics)
_WinAPI_ReleaseDC($hPic, $hPicDC)
_GDIPlus_ImageDispose($hImage)

_GDIPlus_Shutdown()

Exit

Func _WinAPI_StretchBlt($hDestDC, $iXDest, $iYDest, $iWidth, $iHeight, _
                        $hSrcDC, $iXSrc, $iYSrc, $iWidthSrc, $iHeightSrc, $iROP)
    Local $aResult = DllCall("gdi32.dll", "int", "StretchBlt", "hwnd", $hDestDC, "int", $iXDest, "int", $iYDest, _
                                "int", $iWidth, "int", $iHeight, _
                                "hwnd", $hSrcDC, "int", $iXSrc, "int", $iYSrc, _
                                "int", $iWidthSrc, "int", $iHeightSrc, "int", $iROP)
    If @error Then Return SetError(@error, 0, False)
    Return $aResult[0] <> 0
EndFunc  ;==>_WinAPI_StretchBlt

Maybe?

WBD

Share this post


Link to post
Share on other sites

That's nice WideBoyDixon. No _WinAPI_StretchBlt().

I'm gonna just return to the version I posted.

It's not croping, it's resizing. Though there is style issue. See when I change GUI style:

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GDIPlus.au3>
#include <winapi.au3>

_GDIPlus_Startup()

Local $msg

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

$hImage = _GDIPlus_ImageLoadFromFile(@ScriptDir & '\test.jpg')

$iX_ImageDisplay = _GDIPlus_ImageGetWidth($hImage)
$iY_ImageDisplay = _GDIPlus_ImageGetHeight($hImage)
 ConsoleWrite($iX_ImageDisplay & " x "  & $iY_ImageDisplay & @CRLF)

$iFactor_ImageDisplay = 1

If $iX_ImageDisplay > @DesktopWidth Or $iY_ImageDisplay > @DesktopHeight Then
    $iX_ImageDisplay = $iX_ImageDisplay * (@DesktopHeight / $iY_ImageDisplay)
    $iFactor_ImageDisplay = @DesktopHeight / $iY_ImageDisplay
    $iY_ImageDisplay = @DesktopHeight
    If $iX_ImageDisplay > @DesktopWidth Then
        $iY_ImageDisplay = $iY_ImageDisplay * (@DesktopWidth / $iX_ImageDisplay)
        $iFactor_ImageDisplay = @DesktopWidth / $iX_ImageDisplay
        $iX_ImageDisplay = @DesktopWidth
    EndIf
EndIf
$iX_ImageDisplay = Int($iX_ImageDisplay)
$iY_ImageDisplay = Int($iY_ImageDisplay)

$gui_image_display = GUICreate("My GUI", $iX_ImageDisplay, $iY_ImageDisplay, Default, Default, $WS_OVERLAPPEDWINDOW); will create a dialog box that when displayed is centered
$pic_image_display = GUICtrlCreatePic("", 0, 0, $iX_ImageDisplay, $iY_ImageDisplay)

;If $iFactor_ImageDisplay <> 1 Then
;   $hGraphic = _GDIPlus_GraphicsCreateFromHWND(GUICtrlGetHandle($pic_image_display))
;   _GDIPlus_GraphicsDrawImageRect($hGraphic, $hImage, 0, 0, $iX_ImageDisplay, $iY_ImageDisplay)
    ConsoleWrite($iX_ImageDisplay & @TAB & $iY_ImageDisplay & @CRLF)
;EndIf

$hBMP = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage)
_WinAPI_DeleteObject(GUICtrlSendMsg($pic_image_display, $STM_SETIMAGE, $IMAGE_BITMAP, $hBMP))
;$aBmp = DllCall("user32.dll", "hwnd", "SendMessage", "hwnd", GUICtrlGetHandle($pic_image_display), "int", $STM_SETIMAGE, "int", $IMAGE_BITMAP, "int", $hBMP)
;_WinAPI_RedrawWindow($gui_image_display, "", "", BitOR($RDW_INVALIDATE, $RDW_UPDATENOW, $RDW_FRAME))

;If $aBmp[0] <> 0 Then _WinAPI_DeleteObject($aBmp[0])

_GDIPlus_ImageDispose($hImage)
_WinAPI_DeleteObject($hBMP)

;If $iFactor_ImageDisplay <> 1 Then
;   _GDIPlus_GraphicsDispose($hGraphic)
;EndIf

_GDIPlus_Shutdown()

GUICtrlSetPos($pic_image_display, 0, 0, $iX_ImageDisplay, $iY_ImageDisplay)


GUIRegisterMsg(522, "_ResizePic"); WM_MOUSEWHEEL

GUISetState(@SW_SHOW); will display an empty dialog box

; Run the GUI until the dialog is closed
While 1
    $msg = GUIGetMsg()

    If $msg = $GUI_EVENT_CLOSE Then ExitLoop
WEnd


GUIDelete()


Func _ResizePic($hWnd, $iMsg, $wParam, $lParam)

    If BitShift($wParam, 16) > 0 Then
        $iX_ImageDisplay *= 1.1
        $iY_ImageDisplay *= 1.1
    Else
        $iX_ImageDisplay /= 1.1
        $iY_ImageDisplay /= 1.1
    EndIf

    GUICtrlSetPos($pic_image_display, 0, 0, $iX_ImageDisplay, $iY_ImageDisplay)

EndFunc  ;==>_ResizePic

Use mouse wheel to resize it additionally.


♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites

Were coming really close :D ...

WideBoyDixon's example is not double-buffered (change windows focus will erase picture) and the aspect ratio is not maintained.

trancexx's example does not seem to allow $WS_POPUP.

Will throw both examples together and am sure that I'll get the desired effect :D , thanks to both of you!

Best Regards

Share this post


Link to post
Share on other sites

Were coming really close :D ...

WideBoyDixon's example is not double-buffered (change windows focus will erase picture) and the aspect ratio is not maintained.

trancexx's example does not seem to allow $WS_POPUP.

Will throw both examples together and am sure that I'll get the desired effect :D , thanks to both of you!

Best Regards

It allows, you just have to shake it a bit to awake it. Do this initially, before GUISetState(@SW_SHOW), and you have it:

GUICtrlSetPos($pic_image_display, 0, 0, $iX_ImageDisplay-1, $iY_ImageDisplay-1)
GUICtrlSetPos($pic_image_display, 0, 0, $iX_ImageDisplay, $iY_ImageDisplay)

♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites

#12 ·  Posted (edited)

I have seen some examples on the forum using _GDIPlus_GraphicsDrawImageRectRect() for painting resized images.

Did some research on that too... and failed :D , thanks for the hint!

It allows, you just have to shake it a bit to awake it.

LOL, okay, got it :D , thanks a lot for your help, works as intended now!

Thanks to all other repliers too!

Best Regards

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GDIPlus.au3>
#include <winapi.au3>

_GDIPlus_Startup()

Local $msg

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

$hImage = _GDIPlus_ImageLoadFromFile(@ScriptDir & '\test.jpg')

$iX_ImageDisplay = _GDIPlus_ImageGetWidth($hImage)
$iY_ImageDisplay = _GDIPlus_ImageGetHeight($hImage)
ConsoleWrite($iX_ImageDisplay & " x "  & $iY_ImageDisplay & @CRLF)

$iFactor_ImageDisplay = 1

If $iX_ImageDisplay > @DesktopWidth Or $iY_ImageDisplay > @DesktopHeight Then
    $iX_ImageDisplay = $iX_ImageDisplay * (@DesktopHeight / $iY_ImageDisplay)
    $iFactor_ImageDisplay = @DesktopHeight / $iY_ImageDisplay
    $iY_ImageDisplay = @DesktopHeight
    If $iX_ImageDisplay > @DesktopWidth Then
        $iY_ImageDisplay = $iY_ImageDisplay * (@DesktopWidth / $iX_ImageDisplay)
        $iFactor_ImageDisplay = @DesktopWidth / $iX_ImageDisplay
        $iX_ImageDisplay = @DesktopWidth
    EndIf
EndIf
$iX_ImageDisplay = Int($iX_ImageDisplay)
$iY_ImageDisplay = Int($iY_ImageDisplay)

$gui_image_display = GUICreate("My GUI", $iX_ImageDisplay,$iY_ImageDisplay, @DesktopWidth /2 - $iX_ImageDisplay /2 ,@DesktopHeight /2 - $iY_ImageDisplay /2 , $WS_POPUP); will create a dialog box that when displayed is centered
$pic_image_display = GUICtrlCreatePic("", 0, 0, $iX_ImageDisplay, $iY_ImageDisplay)

ConsoleWrite($iX_ImageDisplay & @TAB & $iY_ImageDisplay & @CRLF)

$hBMP = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage)
_WinAPI_DeleteObject(GUICtrlSendMsg($pic_image_display, $STM_SETIMAGE, $IMAGE_BITMAP, $hBMP))

_GDIPlus_ImageDispose($hImage)
_WinAPI_DeleteObject($hBMP)

_GDIPlus_Shutdown()

GUICtrlSetPos($pic_image_display, 0, 0, $iX_ImageDisplay, $iY_ImageDisplay)

GUIRegisterMsg(522, "_ResizePic"); WM_MOUSEWHEEL

GUICtrlSetPos($pic_image_display, 0, 0, $iX_ImageDisplay-1, $iY_ImageDisplay-1)
GUICtrlSetPos($pic_image_display, 0, 0, $iX_ImageDisplay, $iY_ImageDisplay)

GUISetState(@SW_SHOW); will display an empty dialog box

; Run the GUI until the dialog is closed
While 1
    $msg = GUIGetMsg()

    If $msg = $GUI_EVENT_CLOSE Then ExitLoop
WEnd


GUIDelete()


Func _ResizePic($hWnd, $iMsg, $wParam, $lParam)

    If BitShift($wParam, 16) > 0 Then
        $iX_ImageDisplay *= 1.1
        $iY_ImageDisplay *= 1.1
    Else
        $iX_ImageDisplay /= 1.1
        $iY_ImageDisplay /= 1.1
    EndIf

    WinMove($gui_image_display,"",@DesktopWidth /2 - $iX_ImageDisplay /2 ,@DesktopHeight /2 - $iY_ImageDisplay /2 ,$iX_ImageDisplay,$iY_ImageDisplay)

    GUICtrlSetPos($pic_image_display, 0, 0, $iX_ImageDisplay, $iY_ImageDisplay)

    ;ConsoleWrite($iX_ImageDisplay & @TAB & $iY_ImageDisplay & @CRLF)

    ConsoleWrite(@DesktopWidth /2 - $iX_ImageDisplay /2 & ";" & @DesktopHeight /2 - $iY_ImageDisplay /2  & @tab & @tab & $iX_ImageDisplay & @TAB & $iY_ImageDisplay & @crlf)

EndFunc  ;==>_ResizePic
Edited by KaFu
1 person likes this

Share this post


Link to post
Share on other sites

Nice.

I must say that ResourcesViewerAndCompiler.au3 uses this method to allow resizing of previewed images. You just have to click on it and while the cursor is over it you can resize the image with mouse wheel.

I had to say it :D . But don't tell anyone, it's a secret.


♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites

#14 ·  Posted (edited)

I had to say it :D . But don't tell anyone, it's a secret.

It's save with me m8 :D ... but for sure will take a deeper look into that one ;) ... Thanks for your help! Edited by KaFu

Share this post


Link to post
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
Sign in to follow this  
Followers 0