Jump to content

Recommended Posts

Posted

I'm using GUICtrlCreatePic to show an image....it's a simple gui with only that control and it takes up the whole gui. It's many different  images that can show...different sizes. In order to make sure the whole image shows I of course set the size portion of GUICtrlCreatePic. My issue is I am not happy with the way some pics are displayed from simply setting the image size. Many look squashed. Is there a way to simply scale the image (quickly) to fit the size of the gui vs putting a fixed value that may go against the aspect ratio and stretches or squashes the image?

Posted
1 hour ago, Champak said:

Is there a way to simply scale the image (quickly) to fit the size of the gui vs putting a fixed value that may go against the aspect ratio and stretches or squashes the image?

In order for an image to cover the entire GUI without loss, i.e. without cutting off picture content, both must have an identical aspect ratio. Otherwise, distortions will inevitably occur. 

You probably know this effect when, for example, movies are displayed on a TV with different scaling. This causes right and left parts of the movie to be clipped and/or black bars. 

Musashi-C64.png

"In the beginning the Universe was created. This has made a lot of people very angry and been widely regarded as a bad move."

Posted (edited)

Right, but I was looking for a solution like photo editing software where you put in either the width OR the length and the other is automatically scaled to keep the proper ratio. I was hoping there was a way to do that here to remedy this issue.

 

EDIT:

It occurred to me this may be possible. 

1/ Get the image size

2/ Determine which of width or height is larger and work with that.

3/ Calculate percentage reduction to get to the width or height of the gui

4/ Apply that percentage reduction to the "other side" width/height

This should maintain the aspect ratio and have the image fit "perfectly" within the gui, no squishing/expansion.

Does this sound right to work? It's late and my mind is not working right now and the formula is not coming to me. If there is another way...or this wont work...let me know.

Edited by Champak
Posted (edited)

here is something I've borrowed  from @UEZ

#include <GDIPlus.au3>

_GDIPlus_Startup()
Local $hImage = _GDIPlus_ImageLoadFromFile(@ScriptDir & "\Torus.png")
Local $iScale = "your scaling factor here"

Local $B_Scaled = _GDIPlus_ImageScale($hImage, $iScale, $iScale)
Local $idPic = GUICtrlCreatePic("", 196, 82, _GDIPlus_ImageGetWidth($B_Scaled), _GDIPlus_ImageGetHeight($B_Scaled))
GUICtrlSendMsg($idPic, 0x0172, 0, _GDIPlus_BitmapCreateHBITMAPFromBitmap($B_Scaled))
_GDIPlus_BitmapDispose($B_Scaled)
_GDIPlus_Shutdown()

 

Edited by Shark007
Posted (edited)

This is what I came up with, if there is a better way let me know.

 

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

Example()

Func Example()
    _GDIPlus_Startup()
    Local Const $iW = 400, $iH = 400
    Global $WidthP = False, $HeightP = False

    $hBitmap = _GDIPlus_ImageLoadFromFile("image")

        ; Get the size of the original
        $iX1 = _GDIPlus_ImageGetWidth($hBitmap)
        $iY1 = _GDIPlus_ImageGetHeight($hBitmap)

        If $iX1 > $iY1 Then
            $Prime = $iX1
            $WidthP = True
        Else
            $Prime = $iY1
            $HeightP = True
        EndIf

        ; Calculate percentage decrease
        $x = ($Prime - 400) / $Prime
        $x = $x * 100
        $x = 100 - $x
        $x = $x/100

        ; Set percentage change
        Local $iScale = $x;1.0 is without any scaling
        Local $hBitmap_Scaled = _GDIPlus_ImageScale($hBitmap, $iScale, $iScale, $GDIP_INTERPOLATIONMODE_NEARESTNEIGHBOR) ;scale image by 275% (magnify)

        ; Get the width of new
        $iX1 = _GDIPlus_ImageGetWidth($hBitmap_Scaled)
        $iY1 = _GDIPlus_ImageGetHeight($hBitmap_Scaled)

        If $WidthP = True Then

            $adjustedY = (400 - $iY1) / 2
            $adjustedx = 0

        Else
            
            $adjustedX = (400 - $iX1) / 2
            $adjustedY = 0

        EndIf
        

    Local $hGUI = GUICreate("GDI+ test", $iW, $iH, -1, -1) ;create a test gui to display the resized image
    GUISetState(@SW_SHOW)

    Local $hGraphics = _GDIPlus_GraphicsCreateFromHWND($hGUI) ;create a graphics object from a window handle
    _GDIPlus_GraphicsDrawImage($hGraphics, $hBitmap_Scaled, $adjustedX, $adjustedY) ;display scaled image

    While 1
        Switch GUIGetMsg()
            Case $GUI_EVENT_CLOSE
                ExitLoop
        EndSwitch
    WEnd

    ;cleanup resources
    _GDIPlus_GraphicsDispose($hGraphics)
    _GDIPlus_BitmapDispose($hBitmap)
    _GDIPlus_BitmapDispose($hBitmap_Scaled)
    _GDIPlus_Shutdown()
    GUIDelete($hGUI)
EndFunc   ;==>Example

 

Edited by Champak
Posted (edited)

I made an example with different modes of fitting an image to a container. It's CSS like object-fit property:

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

Global $hMain, $cPic
Global $aFitObject = ['Fill', 'Contain', 'Cover']

$hMain = GUICreate('Sample GUI', 400, 400)
GUISetState(@SW_SHOW, $hMain)

For $Mode = 0 To 2
    $cPic = GUICtrlCreatePic('', 0, 0, 400, 400)
    SetImage('image.jpg', $cPic, $aFitObject[$Mode])
    Sleep(3000)
    GUICtrlDelete($cPic)
Next

Func SetImage($sImage, $cCtrl, $sFitType)
    If Not FileExists($sImage) Then Return
    Local $aPos = ControlGetPos($hMain, '', $cCtrl)
    _GDIPlus_Startup()
    Local $hResizedImage = Null, $hContext = Null
    Local $hImage = _GDIPlus_ImageLoadFromFile($sImage)
    If @error Then
        _GDIPlus_Shutdown()
        Return
    EndIf
    Local $aDim = _GDIPlus_ImageGetDimension($hImage)
    Local $iRW = $aPos[2] / $aDim[0]
    Local $iRH = $aPos[3] / $aDim[1]
    Switch $sFitType
        Case 'Contain'
            Local $iSR = ($iRW < $iRH ? $iRW : $iRH)
            Local $iX = Int(($aPos[2] - ($aDim[0] * $iSR)) / 2)
            Local $iY = Int(($aPos[3] - ($aDim[1] * $iSR)) / 2)
            $hResizedImage = _GDIPlus_BitmapCreateFromScan0($aPos[2], $aPos[3])
            $hContext = _GDIPlus_ImageGetGraphicsContext($hResizedImage)
            _GDIPlus_GraphicsDrawImageRectRect($hContext, $hImage, 0, 0, $aDim[0], $aDim[1], $iX, $iY, $aDim[0] * $iSR, $aDim[1] * $iSR)
        Case 'Cover'
            Local $iLR = ($iRW > $iRH ? $iRW : $iRH)
            Local $iX = Int(($aPos[2] - ($aDim[0] * $iLR)) / 2)
            Local $iY = Int(($aPos[3] - ($aDim[1] * $iLR)) / 2)
            $hResizedImage = _GDIPlus_BitmapCreateFromScan0($aPos[2], $aPos[3])
            $hContext = _GDIPlus_ImageGetGraphicsContext($hResizedImage)
            _GDIPlus_GraphicsDrawImageRectRect($hContext, $hImage, 0, 0, $aDim[0], $aDim[1], $iX, $iY, $aDim[0] * $iLR, $aDim[1] * $iLR)
        Case 'Fill'
            $hResizedImage = _GDIPlus_BitmapCreateFromScan0($aPos[2], $aPos[3])
            $hContext = _GDIPlus_ImageGetGraphicsContext($hResizedImage)
            _GDIPlus_GraphicsDrawImageRectRect($hContext, $hImage, 0, 0, $aDim[0], $aDim[1], 0, 0, $aDim[0] * $iRW, $aDim[1] * $iRH)
    EndSwitch
    If $hResizedImage <> Null Then
        Local $hHBITMAP = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hResizedImage)
        _WinAPI_DeleteObject(GUICtrlSendMsg($cCtrl, 0x0172, 0, $hHBITMAP))
        _WinAPI_DeleteObject($hHBITMAP)
    EndIf
    If $hContext <> Null Then _GDIPlus_GraphicsDispose($hContext)
    If $hResizedImage <> Null Then _GDIPlus_BitmapDispose($hResizedImage)
    _GDIPlus_ImageDispose($hImage)
    _GDIPlus_Shutdown()
EndFunc

 

Edited by Andreik

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
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...