Jump to content

[Solved] PNG scaled down to GUI, cropped


Go to solution Solved by cramaboule,

Recommended Posts

Posted (edited)

Here is an exemple of the PNG scaled down based on this script : https://www.autoitscript.com/forum/topic/200086-display-png-images/#findComment-1498721

Here is my script: but the png is cropped 1 or 2 px
The others looks bad any hint how to fix it ?
 

#include <GDIPlus.au3>
#include <GUIConstantsEx.au3>
#include <MsgBoxConstants.au3>
#include <WindowsConstants.au3>
#include <StaticConstants.au3>

Local $idPic, $idPic1

GUICreate('Test', 200, 500, 1050, 50)     ;Create a GUI
GUISetBkColor(0xFFFFFF)
$idPic = _GUICtrlCreatePngScale(@ScriptDir & "\big-green.png", 5, 5, .035)
$idPic1 = _GUICtrlCreatePngScale(@ScriptDir & "\big-green.png", 5, 200, 1)
$idPic2 = GUICtrlCreatePic(@ScriptDir & "\green.bmp", 5, 300, 100, 100)
GUICtrlSetPos($idPic1, 5, 150, 100, 100)
GUISetState(@SW_SHOW)

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
        Case $idPic
            MsgBox($MB_TOPMOST, "Information", "PNG 1 image was clicked")
        Case $idPic1
            MsgBox($MB_TOPMOST, "Information", "PNG 2 image was clicked")
        Case $idPic2
            MsgBox($MB_TOPMOST, "Information", "PNG 3 image was clicked")
    EndSwitch
WEnd

Func _GUICtrlCreatePngScale($_sName, $_left, $_top, $_iScale = 1)
    _GDIPlus_Startup()
    Local $_hImage = _GDIPlus_ImageLoadFromFile($_sName) ;The PNG image that you want to display
    Local $B_Scaled = _GDIPlus_ImageScale($_hImage, $_iScale, $_iScale)
    Local $_idPic = GUICtrlCreatePic("", $_left, $_top, 20, 20)
    GUICtrlSendMsg($_idPic, 0x0172, 0, _GDIPlus_BitmapCreateHBITMAPFromBitmap($B_Scaled))
    _WinAPI_DeleteObject($_hImage) ;some clean up
    _GDIPlus_ImageDispose($B_Scaled)
    _GDIPlus_Shutdown()
    Return $_idPic
EndFunc   ;==>_GUICtrlCreatePngScale

image.png.320a9c52aac9487501b91f4ae3c5b53c.png

green.PNG

green.BMP

Edited by cramaboule
Posted

Not sure if this helps - I was looking for an out by 1 error re the cropping, but the scaling function looks to be correct as far as I can tell. 🤷‍♂️

Below is the same scaling routine, but I've added a 1px box around the image to help find the edge. Then I've saved the bitmap using _GDIPlus_ImageSaveToFile to inspect it and verify the new dimensions etc. 

So with this you can play with adding +1s with the widths and heights etc  (just in case it helps)

Func _GDIPlus_ImageScale2($hImage, $iScaleW, $iScaleH, $iInterpolationMode = $GDIP_INTERPOLATIONMODE_HIGHQUALITYBICUBIC)
    Local $iWidth = _GDIPlus_ImageGetWidth($hImage)
    If @error Then Return SetError(1, 0, 0)
    Local $iHeight = _GDIPlus_ImageGetHeight($hImage)
    If @error Then Return SetError(2, 0, 0)
    Local $iNewWidth = $iWidth * $iScaleW
    Local $iNewHeight = $iHeight * $iScaleH
    Local $hBitmap = _GDIPlus_BitmapCreateFromScan0($iNewWidth, $iNewHeight)
    If @error Then Return SetError(3, 0, 0)
    Local $hBmpCtxt = _GDIPlus_ImageGetGraphicsContext($hBitmap)

    Local $hPen = _GDIPlus_PenCreate(0xFFAA00AA)
    _GDIPlus_GraphicsDrawRect($hBmpCtxt, 0, 0, $iNewWidth-1, $iNewHeight-1, $hPen)

    _GDIPlus_GraphicsSetInterpolationMode($hBmpCtxt, $iInterpolationMode)
    _GDIPlus_GraphicsSetPixelOffsetMode($hBmpCtxt, $GDIP_PIXELOFFSETMODE_HIGHQUALITY)
    Local $hIA = _GDIPlus_ImageAttributesCreate()
    __GDIPlus_ImageAttributesSetImageWrapMode($hIA)
    If @error Then
        _GDIPlus_ImageAttributesDispose($hIA)
        _GDIPlus_GraphicsDispose($hBmpCtxt)
        _GDIPlus_BitmapDispose($hBitmap)
        Return SetError(4, 0, 0)
    EndIf
    _GDIPlus_GraphicsDrawImageRectRect($hBmpCtxt, $hImage, 0, 0, $iWidth, $iHeight, 0, 0, $iNewWidth, $iNewHeight, $hIA)
    _GDIPlus_ImageAttributesDispose($hIA)
    _GDIPlus_GraphicsDispose($hBmpCtxt)
    Return $hBitmap
EndFunc
  • Solution
Posted

After digging into my script I found a small bug or improvement in the code of @UEZ in the UDF of GDI+ _GDIPlus_ImageScale() : I added 

Floor($iNewWidth), Floor($iNewHeight)

Here is my script working nicely 😄

#include <GDIPlus.au3>
#include <GUIConstantsEx.au3>
#include <MsgBoxConstants.au3>
#include <WindowsConstants.au3>
#include <StaticConstants.au3>

Local $idPic, $idPic1

GUICreate('Test', 200, 500, 1050, 50)     ;Create a GUI
GUISetBkColor(0xFFFFFF)
$idPic = _GUICtrlCreatePngScale(@ScriptDir & "\big-green.png", 5, 5, .035)
$idPic1 = _GUICtrlCreatePngScale(@ScriptDir & "\big-green.png", 5, 200, 1)
$idPic2 = GUICtrlCreatePic(@ScriptDir & "\green.bmp", 5, 300, 100, 100)
GUICtrlSetPos($idPic1, 5, 150, 100, 100)
GUISetState(@SW_SHOW)

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
        Case $idPic
            MsgBox($MB_TOPMOST, "Information", "PNG 1 image was clicked")
        Case $idPic1
            MsgBox($MB_TOPMOST, "Information", "PNG 2 image was clicked")
        Case $idPic2
            MsgBox($MB_TOPMOST, "Information", "PNG 3 image was clicked")
    EndSwitch
WEnd

Func _GUICtrlCreatePngScale($_sName, $_left, $_top, $_iScale = 1)
    _GDIPlus_Startup()
    Local $_hImage = _GDIPlus_ImageLoadFromFile($_sName) ;The PNG image that you want to display
    Local $B_Scaled = _GDIPlus_ImageScaleNew($_hImage, $_iScale, $_iScale)
    Local $_idPic = GUICtrlCreatePic("", $_left, $_top, 20, 20)
    GUICtrlSendMsg($_idPic, 0x0172, 0, _GDIPlus_BitmapCreateHBITMAPFromBitmap($B_Scaled))
    _WinAPI_DeleteObject($_hImage) ;some clean up
    _GDIPlus_ImageDispose($B_Scaled)
    _GDIPlus_Shutdown()
    Return $_idPic
EndFunc   ;==>_GUICtrlCreatePngScale

Func _GDIPlus_ImageScaleNew($hImage, $iScaleW, $iScaleH, $iInterpolationMode = $GDIP_INTERPOLATIONMODE_HIGHQUALITYBICUBIC)
    Local $iWidth = _GDIPlus_ImageGetWidth($hImage)
    If @error Then Return SetError(1, 0, 0)
    Local $iHeight = _GDIPlus_ImageGetHeight($hImage)
    If @error Then Return SetError(2, 0, 0)
    Local $iNewWidth = $iWidth * $iScaleW
    Local $iNewHeight = $iHeight * $iScaleH
    Local $hBitmap = _GDIPlus_BitmapCreateFromScan0($iNewWidth, $iNewHeight)
    If @error Then Return SetError(3, 0, 0)
    Local $hBmpCtxt = _GDIPlus_ImageGetGraphicsContext($hBitmap)
    _GDIPlus_GraphicsSetInterpolationMode($hBmpCtxt, $iInterpolationMode)
    _GDIPlus_GraphicsSetPixelOffsetMode($hBmpCtxt, $GDIP_PIXELOFFSETMODE_HIGHQUALITY)
    Local $hIA = _GDIPlus_ImageAttributesCreate()
    __GDIPlus_ImageAttributesSetImageWrapMode($hIA)
    If @error Then
        _GDIPlus_ImageAttributesDispose($hIA)
        _GDIPlus_GraphicsDispose($hBmpCtxt)
        _GDIPlus_BitmapDispose($hBitmap)
        Return SetError(4, 0, 0)
    EndIf
    _GDIPlus_GraphicsDrawImageRectRect($hBmpCtxt, $hImage, 0, 0, $iWidth, $iHeight, 0, 0, Floor($iNewWidth), Floor($iNewHeight), $hIA)
    _GDIPlus_ImageAttributesDispose($hIA)
    _GDIPlus_GraphicsDispose($hBmpCtxt)
    Return $hBitmap
EndFunc   ;==>_GDIPlus_ImageScale

image.png.598a45fcd5dd3e3faf46c9d8802dc98c.png

Posted
3 minutes ago, MattyD said:

Not sure if this helps - I was looking for an out by 1 error re the cropping, but the scaling function looks to be correct as far as I can tell. 🤷‍♂️

Below is the same scaling routine, but I've added a 1px box around the image to help find the edge. Then I've saved the bitmap using _GDIPlus_ImageSaveToFile to inspect it and verify the new dimensions etc. 

So with this you can play with adding +1s with the widths and heights etc  (just in case it helps)

Func _GDIPlus_ImageScale2($hImage, $iScaleW, $iScaleH, $iInterpolationMode = $GDIP_INTERPOLATIONMODE_HIGHQUALITYBICUBIC)
    Local $iWidth = _GDIPlus_ImageGetWidth($hImage)
    If @error Then Return SetError(1, 0, 0)
    Local $iHeight = _GDIPlus_ImageGetHeight($hImage)
    If @error Then Return SetError(2, 0, 0)
    Local $iNewWidth = $iWidth * $iScaleW
    Local $iNewHeight = $iHeight * $iScaleH
    Local $hBitmap = _GDIPlus_BitmapCreateFromScan0($iNewWidth, $iNewHeight)
    If @error Then Return SetError(3, 0, 0)
    Local $hBmpCtxt = _GDIPlus_ImageGetGraphicsContext($hBitmap)

    Local $hPen = _GDIPlus_PenCreate(0xFFAA00AA)
    _GDIPlus_GraphicsDrawRect($hBmpCtxt, 0, 0, $iNewWidth-1, $iNewHeight-1, $hPen)

    _GDIPlus_GraphicsSetInterpolationMode($hBmpCtxt, $iInterpolationMode)
    _GDIPlus_GraphicsSetPixelOffsetMode($hBmpCtxt, $GDIP_PIXELOFFSETMODE_HIGHQUALITY)
    Local $hIA = _GDIPlus_ImageAttributesCreate()
    __GDIPlus_ImageAttributesSetImageWrapMode($hIA)
    If @error Then
        _GDIPlus_ImageAttributesDispose($hIA)
        _GDIPlus_GraphicsDispose($hBmpCtxt)
        _GDIPlus_BitmapDispose($hBitmap)
        Return SetError(4, 0, 0)
    EndIf
    _GDIPlus_GraphicsDrawImageRectRect($hBmpCtxt, $hImage, 0, 0, $iWidth, $iHeight, 0, 0, $iNewWidth, $iNewHeight, $hIA)
    _GDIPlus_ImageAttributesDispose($hIA)
    _GDIPlus_GraphicsDispose($hBmpCtxt)
    Return $hBitmap
EndFunc

Thanks,
yes it is playing around... but I think my solution works with upscale and downscale

  • cramaboule changed the title to [Solved] PNG scaled down to GUI, cropped
Posted
Quote

I guess some of those GDI funcs deal with floats hey? I suppose that's where the inconsistency stems from.

the _GDIPlus_ImageScale() can have some floats... soooo yeeeee this is why!

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...