Jump to content

Change image interpolation


Cybergon
 Share

Recommended Posts

Hey guys, sorry if this is a repeated or stupid question but I just couldn't find any on-spot topics to help me out.

I'm using GUICtrlCreatePic to place this tiny stretched out bmp inside a form, but I haven't the slightest idea on how to change the interpolation so it doesn't look blurry like the one on the left.

Posted Image

So please how can I do this?

To be honest this is more or less for cosmetic purposes, but it can't be that hard to change, can it?

Link to comment
Share on other sites

You can use GDI+ to scale the image using the _GDIPlus_GraphicsSetInterpolationMode() function (in ) to set the interpolation to nearest-neighbor interpolation.

Afterwards you can send the scaled image to the picture control.

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

Thanks for the help UEZ. So far this is what I got:

$display = GUICreate("imaeg",$newimagewidth,$newimageheight,int((@DesktopWidth-$newimagewidth)/2),Int((@DesktopHeight-$newimageheight)/2))
GUISetState()
_GDIPlus_Startup()
$grafix = _GDIPlus_GraphicsCreateFromHWND($display)
$hImage = _GDIPlus_ImageLoadFromFile($filename)
_GDIPlus_GraphicsDrawImageRect($grafix,$hImage,0,0,$newimagewidth,$newimageheight)
_GDIPlus_GraphicsSetInterpolationMode($grafix,5)

But how do I send the image to the GUICtrlCreatePic?

Edit: Actually that doesn't seem to change the interpolation at all. Help?

Edited by Cybergon
Link to comment
Share on other sites

Try this:

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

$filename = FileOpenDialog("Select an image", "", "Images (*.jpg;*.png*;*.bmp;*.gif)", 3)
If @error Then Exit
_GDIPlus_Startup()
$hImage = _GDIPlus_ImageLoadFromFile($filename)
$iW = _GDIPlus_ImageGetWidth($hImage)
$iH  = _GDIPlus_ImageGetHeight($hImage)
$scale = 0.4  ;40% from original size
$newimagewidth = Round($iW * $scale, 0)
$newimageheight = Round($iH * $scale, 0)
$display = GUICreate("imaeg", $newimagewidth, $newimageheight, Int((@DesktopWidth - $newimagewidth) / 2), Int((@DesktopHeight - $newimageheight) / 2))
GUISetBkColor(0x000000)
$idPic = GUICtrlCreatePic("", 0, 0, $newimagewidth, $newimageheight)
$hBmp = ScaleImage($hImage, $newimagewidth, $newimageheight)
$hHBmp = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBmp )
_WinAPI_DeleteObject(GUICtrlSendMsg($idPic, 0x0172, 0, $hHBmp))
GUISetState(@SW_SHOW)


While 1
$nMsg = GUIGetMsg()
Switch $nMsg
    Case $GUI_EVENT_CLOSE
        _WinAPI_DeleteObject($hHBmp)
        _GDIPlus_ImageDispose($hBmp)
        _GDIPlus_Shutdown()
        Exit
EndSwitch
WEnd

Func ScaleImage($hImage, $iWidth, $iHeight,  $iInterpolationMode = 5, $iStride = 0, $iPixelFormat = 0x0026200A, $pScan0 = 0) ;coded by UEZ 2011
    Local Const $aResult = DllCall($ghGDIPDll, "uint", "GdipCreateBitmapFromScan0", "int", $iWidth, "int", $iHeight, "int", $iStride, "int", $iPixelFormat, "ptr", $pScan0, "int*", 0)
    Local Const $hBitmap = $aResult[6]
    Local Const $hGfxContext= _GDIPlus_ImageGetGraphicsContext($hBitmap)
    DllCall($ghGDIPDll, "uint", "GdipSetInterpolationMode", "handle", $hGfxContext, "int", $iInterpolationMode)
    _GDIPlus_GraphicsDrawImageRect($hGfxContext, $hImage, 0, 0, $iWidth, $iHeight)
    _GDIPlus_GraphicsDispose($hGfxContext)
    Return $hBitmap
EndFunc

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

Sorry man, not looking good:

Posted Image

However I tried at my code again and it turns out the order was wrong:

$display = GUICreate("imaeg",$newimagewidth,$newimageheight,int((@DesktopWidth-$newimagewidth)/2),Int((@DesktopHeight-$newimageheight)/2))
GUISetState()
_GDIPlus_Startup()
$grafix = _GDIPlus_GraphicsCreateFromHWND($display)
_GDIPlus_GraphicsSetInterpolationMode($grafix,5);goes here
$hImage = _GDIPlus_ImageLoadFromFile($filename)
_GDIPlus_GraphicsDrawImageRect($grafix,$hImage,0,0,$newimagewidth,$newimageheight)
;not here

I tried looking at your code to see how to go from here, but I'm just not sure how to :D

By the way, the $filename simply comes from a fileopendialog. $newimagewidth and height are generated as the scaled down dimensions required to make the image fit in $form1 while mantaining the image's aspect ratio.

Edited by Cybergon
Link to comment
Share on other sites

I don't know what you exactly want but I updated the code post#4.

Is this what you are looking for?

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

Or maybe something more like this (tweaked UEZs excellent example)?

#include <GUIConstantsEx.au3>
#include <GDIPlus.au3>
$filename = FileOpenDialog("Select an image", "", "Images (*.jpg;*.png*;*.bmp;*.gif)", 3)
If @error Then Exit
_GDIPlus_Startup()
$hImage = _GDIPlus_ImageLoadFromFile($filename)
$iW = _GDIPlus_ImageGetWidth($hImage)
$iH = _GDIPlus_ImageGetHeight($hImage)
$hGUI = GUICreate("imaeg", 400, 400)
GUISetBkColor(0x000000)
$idPic = GUICtrlCreatePic("", 10, 10, 200, 200)
$hBmp = ScaleImage($hImage, $hGUI, $idPic)
$hHBmp = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBmp)
_WinAPI_DeleteObject(GUICtrlSendMsg($idPic, 0x0172, 0, $hHBmp))
GUISetState(@SW_SHOW)

While 1
 $nMsg = GUIGetMsg()
 Switch $nMsg
  Case $GUI_EVENT_CLOSE
   _WinAPI_DeleteObject($hHBmp)
   _GDIPlus_ImageDispose($hBmp)
   _GDIPlus_Shutdown()
   Exit
 EndSwitch
WEnd
Func ScaleImage($hImage, $hGUI, $iCtrl, $iInterpolationMode = 5, $iStride = 0, $iPixelFormat = 0x0026200A, $pScan0 = 0) ;coded by UEZ 2011
 Local $aControlPos = ControlGetPos($hGUI, "", $iCtrl)
 Local Const $aResult = DllCall($ghGDIPDll, "uint", "GdipCreateBitmapFromScan0", "int", $aControlPos[2], "int", $aControlPos[3], "int", $iStride, "int", $iPixelFormat, "ptr", $pScan0, "int*", 0)
 Local Const $hBitmap = $aResult[6]
 Local Const $hGfxContext = _GDIPlus_ImageGetGraphicsContext($hBitmap)
 DllCall($ghGDIPDll, "uint", "GdipSetInterpolationMode", "handle", $hGfxContext, "int", $iInterpolationMode)
 _GDIPlus_GraphicsDrawImageRect($hGfxContext, $hImage, 0, 0, $aControlPos[2], $aControlPos[3])
 _GDIPlus_GraphicsDispose($hGfxContext)
 Return $hBitmap
EndFunc   ;==>ScaleImage
Link to comment
Share on other sites

Thanks for all the input guys, I finally managed to get it on my GUI. I figured I'd just leave it as a GDIP graphics object. This is what it looks like:

Posted Image

Pretty good.

I'd leave it like that, but the thing bothering me now is the small gap between the arrows. What I could see from it is that the pixels are being rendered based on their center, rather than their top left corner, chopping out half a pixel from the top and left and at the same time leaving a little gap at the bottom right of the same distance.

The most practical way I could think of solving this was drawing the image 4 times to fill in those gaps.

This code is a bit lengthy, but I'll try to trim it down to the parts that matters:

#include <Array.au3>
#include <GDIP.au3>
#include <ButtonConstants.au3>
#include <EditConstants.au3>
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
#include <String.au3>
#Include <Math.au3>
Global Const $HX_REF="0123456789ABCDEF"

Local $filename, $aArr,$colors,$uniquecolors, $numberofcolors, $inputcolors[16], $Iinputcolors[16], $labelcolors[16], $Scale, $display, $imagewidth, $imageheight, $canvas[2], $centerpos[2]


$MainForm = GUICreate("CSV paint", 595, 372, Int((@DesktopWidth-595)/2),Int((@DesktopHeight-372)/2))
$newpatternbutton = GUICtrlCreateButton("Select new pattern", 384, 64, 105, 25)
$canvas[0] = GUICtrlCreateLabel("", 0, 0, 186, 372)
GUICtrlSetBkColor(-1, 0xF9F9F9)
$canvas[1] = GUICtrlCreateLabel("", 186, 0, 186, 372)
GUICtrlSetBkColor(-1, 0xF9F9F9)
GUISetState(@SW_SHOW)

If $CmdLine[0] > 0 Then
    WinSetState($MainForm,"",@SW_DISABLE)
    $filename = $CmdLine[1]
    goforit($colors,$uniquecolors)
    WinSetState($MainForm,"",@SW_ENABLE)
EndIf

While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
        Case $GUI_EVENT_CLOSE
            Exit
        Case $newpatternbutton
            goforit($colors,$uniquecolors)
            WinSetState($MainForm,"",@SW_ENABLE)
            WinActivate($MainForm)
    EndSwitch
WEnd

Func goforit(ByRef $colors,ByRef $uniquecolors)
    WinSetState($MainForm,"",@SW_DISABLE)
    $filename = FileOpenDialog("Get image",@DesktopDir,"Images(*.bmp;*.gif)")
    If @error = 1 Then Return
    WinActivate($MainForm)
    $return=0
    $return=_FileImageToArray($filename, $aArr, $return)
    if $return>0 then Return
    $imageheight = UBound($aArr, 1)
    $imagewidth = UBound($aArr, 2)
    Dim $colors[$imageheight * $imagewidth]

    $k = 0
    $numberofcolors = 0
    Local $sHold
    ProgressOn("Progress Bar", "Counting unique colors.", "0 percent",(@DesktopWidth/2)-150,(@DesktopHeight/2)-50,3)
    For $j = 0 to ($imageheight -1)
        ProgressSet(Int(100 * $j / ($imageheight -1)), Int(100 * $j / ($imageheight -1)) & " percent")
        For $i = 0 to ($imagewidth -1)
            If Not StringInStr("|" & $sHold, "|" & $aArr[$j][$i] & "|", 1) Then
                $sHold &= $aArr[$j][$i] & "|"
                $numberofcolors += 1
            EndIf
        Next
    Next
    ProgressOff()

    If $numberofcolors > 16 Then
        MsgBox(0,"Error","That's too many colors")
        Return
    EndIf

    If $sHold Then
        Dim $uniquecolors[$numberofcolors+1]
        $uniquecolors = StringSplit(StringTrimRight($sHold, 1), "|", 1)
    EndIf

    ;;;;;;;;;;;;;;;;
    ;;Modify Form1;;
    ;;;;;;;;;;;;;;;;

    For $i = 0 to 15
        GUICtrlDelete ($Iinputcolors[$i])
        GUICtrlDelete ($labelcolors[$i])
    Next
    For $i = 0 to $numberofcolors -1
        $labelcolors[$i] = GUICtrlCreateLabel("", 384, 96+(15*$i), 15, 15)
        GUICtrlSetBkColor(-1, "0x" & $uniquecolors[$i+1])
        $Iinputcolors[$i] = GUICtrlCreateInput("", 414, 96+(15*$i), 163, 15)
    Next
    $Scale = _Min(372 / $imagewidth, 372 / $imageheight)
    $newimagewidth = Int($imagewidth * $Scale)
    $newimageheight = Int($imageheight * $Scale)


    GUICtrlDelete ($canvas[0])
    GUICtrlDelete ($canvas[1])
    If $newimageheight > $newimagewidth Then
        $canvas[0] = GUICtrlCreateLabel("", 0, 0, Ceiling((372-$newimagewidth)/2), 372)
        GUICtrlSetBkColor(-1, 0xF9F9F9)
        $canvas[1] = GUICtrlCreateLabel("",Floor((372+$newimagewidth)/2), 0, Ceiling((372-$newimagewidth)/2), 372)
        GUICtrlSetBkColor(-1, 0xF9F9F9)
    Else
        $canvas[0] = GUICtrlCreateLabel("", 0, 0, 372, Ceiling((372-$newimageheight)/2))
        GUICtrlSetBkColor(-1, 0xF9F9F9)
        $canvas[1] = GUICtrlCreateLabel("", 0, Floor((372+$newimageheight)/2), 372, Ceiling((372-$newimageheight)/2))
        GUICtrlSetBkColor(-1, 0xF9F9F9)
    EndIf

    ;;;;;;;;;;;;;;;;;
    ;;Display Image;;
    ;;;;;;;;;;;;;;;;;
    _GDIPlus_Startup()
    $grafix = _GDIPlus_GraphicsCreateFromHWND($MainForm)
    _GDIPlus_GraphicsSetInterpolationMode($grafix,5)
    $hImage = _GDIPlus_ImageLoadFromFile($filename)
    If $newimageheight > $newimagewidth Then
        $littlegap = Int((372/$imageheight)/2)
    Else
        $littlegap = Int((372/$imagewidth)/2)
    EndIf
    _GDIPlus_GraphicsDrawImageRect($grafix,$hImage,(372-$newimagewidth)/2,(372-$newimageheight)/2,$newimagewidth,$newimageheight)
    _GDIPlus_GraphicsDrawImageRect($grafix,$hImage,(372-$newimagewidth)/2+$littlegap,(372-$newimageheight)/2,$newimagewidth,$newimageheight)
    _GDIPlus_GraphicsDrawImageRect($grafix,$hImage,(372-$newimagewidth)/2,(372-$newimageheight)/2+$littlegap,$newimagewidth,$newimageheight)
    _GDIPlus_GraphicsDrawImageRect($grafix,$hImage,(372-$newimagewidth)/2 +$littlegap,(372-$newimageheight)/2+$littlegap,$newimagewidth,$newimageheight)
    _GDIPlus_ImageDispose($hImage)
    _GDIPlus_GraphicsDispose($grafix)
    _GDIPlus_Shutdown()
EndFunc

;convert images to hex array, by malkey
Func _FileImageToArray($sFileName, ByRef $aArray, $Ireturn)
    Local $Reslt, $stride, $format, $Scan0, $iIW, $iIH, $hImage
    Local $v_Buffer, $width, $height
    _GDIPlus_Startup()
    $hImage = _GDIPlus_ImageLoadFromFile($sFileName)
    $iIW = _GDIPlus_ImageGetWidth($hImage)
    $iIH = _GDIPlus_ImageGetHeight($hImage)
    If ($iIW > 766) or ($iIH > 766) Then
        $warning = MsgBox(1,"Warning","This pattern is way too big, it won't even fit on the largest possible embark. Are you sure about this?")
        if $warning = 2 then
            Return 1
        EndIf
    EndIf

    ProgressOn("Progress Bar", "Filling a " & $iIW & " x " & $iIH & " size array.", "0 percent",(@DesktopWidth/2)-150,(@DesktopHeight/2)-50,3)
    $Reslt = _GDIPlus_BitmapLockBits($hImage, 0, 0, $iIW, $iIH, $GDIP_ILMREAD, $GDIP_PXF32ARGB)

    ;Get the returned values of _GDIPlus_BitmapLockBits ()
    $width = DllStructGetData($Reslt, "width")
    $height = DllStructGetData($Reslt, "height")
    $stride = DllStructGetData($Reslt, "stride")
    $format = DllStructGetData($Reslt, "format")
    $Scan0 = DllStructGetData($Reslt, "Scan0")

    Dim $aArray[$height][$width]
    For $j = 0 To $iIH - 1
        For $i = 0 To $iIW - 1
            $v_Buffer = DllStructCreate("dword", $Scan0 + ($j * $stride) + ($i * 4))
            $aArray[$j][$i] = Hex(DllStructGetData($v_Buffer, 1), 6)
        Next
        ProgressSet(Int(100 * $j / ($iIH)), Int(100 * $j / ($iIH)) & " percent")
    Next
    _GDIPlus_BitmapUnlockBits($hImage, $Reslt)
    ProgressOff()
    _GDIPlus_ImageDispose($hImage)
    _GDIPlus_Shutdown()
    Return
EndFunc

; #FUNCTION# ==============================================================
; Function Name..: _HexToDec ( "expression" )
; Description ...: Returns decimal expression of a hexadecimal string.
; Parameters ....: expression   - String representation of a hexadecimal expression to be converted to decimal.
; Return values .: Success    - Returns decimal expression of a hexadecimal string.
;                 Failure     - Returns "" (blank string) and sets @error to 1 if string is not hexadecimal type.
; Author ........: jennico (jennicoattminusonlinedotde)
; Remarks .......: working input format: "FFFF" or "0xFFFF" (string format), do NOT pass 0xFFFF without quotation marks (number format).
;              current AutoIt Dec() limitation: 0x7FFFFFFF (2147483647).
; Related .......: Hex(), Dec(), _DecToHex()
; =======================================================================
Func _HexToDecimal($hx_hex)
    If StringLeft($hx_hex, 2) = "0x" Then $hx_hex = StringMid($hx_hex, 3)
    If StringIsXDigit($hx_hex) = 0 Then
        SetError(1)
        MsgBox(0,"Error","Wrong input, try again ...")
        Return ""
    EndIf
    Local $ret="", $hx_count=0, $hx_array = StringSplit($hx_hex, ""), $Ii, $hx_tmp
    For $Ii = $hx_array[0] To 1 Step -1
        $hx_tmp = StringInStr($HX_REF, $hx_array[$Ii]) - 1
        $ret += $hx_tmp * 16 ^ $hx_count
        $hx_count += 1
    Next
    Return $ret
EndFunc

I know I didn't use UEZ's code, but still thanks again for the help. Let me know what you guys think and if there is a more elegant way of doing it. I'll be busy finishing this little app (if you're wondering what it is, it's a utility for the Lazy Newb Pack, to replace Chromafort, please don't ban me). I'll post it on example scripts, if you guys have no problem with that.

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